<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>The Open App Library Project</title>
    <description></description>
    <link>https://openapplibrary.org/</link>
    <atom:link href="https://openapplibrary.org/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>Building an Open-Source Evernote Alternative: January 2019 Update</title>
        <description>&lt;div class=&quot;video-responsive&quot;&gt;
    &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/e7iCC8Q2fSg&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;h2 id=&quot;the-desktop-app&quot;&gt;The Desktop App&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Demo video: This video shows various features of the desktop app. Music by Kevin MacLeod (incompetech.com) under Creative Commons 3.0. Please excuse any flicking in the recording. I should’ve used SimpleScreenRecorder to avoid that problem.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There have been many improvements made in the desktop app. Let’s go over them.&lt;/p&gt;

&lt;h3 id=&quot;big-performance-upgrade&quot;&gt;Big performance upgrade&lt;/h3&gt;

&lt;p&gt;One change that I am very excited about is not actually noticeable - which is a good thing! The note list widget used to use a custom widget for each note in the list - via Qt’s &lt;a href=&quot;http://doc.qt.io/qt-5/qabstractitemview.html#setIndexWidget&quot;&gt;setIndexWidget&lt;/a&gt; function.&lt;/p&gt;

&lt;p&gt;This wouldn’t cause a major problem until you have hundreds of notes. At that point the app would use more memory (Still way, way less than an Electron app following best practices, haha.) and you would notice a delay when switching between different filtered note views - “All Notes”, “Favorited”, “Notebooks”, “Tags”.&lt;/p&gt;

&lt;p&gt;Thanks to the helpful people at the &lt;a href=&quot;https://forum.qt.io&quot;&gt;Qt forum&lt;/a&gt; I found out that it wouldn’t be too hard to migrate my code to a much more efficient display model - By sub-classing &lt;code class=&quot;highlighter-rouge&quot;&gt;QStyledItemDelegate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, instead of creating custom widgets which take time initializing, the note list items are painted using &lt;strong&gt;QPainter&lt;/strong&gt;, which “performs low-level painting on widgets and other paint devices.”, according to &lt;a href=&quot;http://doc.qt.io/qt-5/qpainter.html&quot;&gt;the docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/Open-App-Library/vibrato-notes-desktop/commit/c139b8244d496e7000bd0bf11ae026b77cecdccc&quot;&gt;Commit c139b824&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;a-c-api-to-interact-with-the-back-end-api&quot;&gt;A C++ API to interact with the back-end API&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/Open-App-Library/Qt-Vibrato-Cloud-API&quot;&gt;Qt-Vibrato-Cloud-API-Library&lt;/a&gt; was created to provide a C++ API for connecting to the &lt;a href=&quot;https://github.com/Open-App-Library/Vibrato-Notes-Back-End&quot;&gt;Note Sync Server&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is essentially complete minus the code for client-side encryption and decryption. That will come soon.&lt;/p&gt;

&lt;p&gt;Now I am focusing on using the Qt-Vibrato-Cloud-API-Library in conjunction with the desktop app to sync notes to the cloud.&lt;/p&gt;

&lt;h2 id=&quot;the-back-end-api--sync-server-has-a-lot-more-functionality&quot;&gt;The back-end API / sync-server has a lot more functionality&lt;/h2&gt;

&lt;p&gt;A ton of progress was made on &lt;a href=&quot;https://github.com/Open-App-Library/Vibrato-notes-Back-End&quot;&gt;the back-end&lt;/a&gt;. When the server runs, there is now API documentation available at &lt;code class=&quot;highlighter-rouge&quot;&gt;{SERVER_URL}/docs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to the &lt;a href=&quot;https://django-rest-framework.org/&quot;&gt;Django Rest Framework&lt;/a&gt; it was quite easy to add useful features to the REST API such as sorting &amp;amp; filtering - As an example, you can sort by notes from oldest-to-newest using the URL &lt;code class=&quot;highlighter-rouge&quot;&gt;{SERVER_URL}/notes?ordering=date_created&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The supported authentication types are token authentication and OAuth2. You could generate a token for your account via the URL, &lt;code class=&quot;highlighter-rouge&quot;&gt;{SERVER_URL}/users/login&lt;/code&gt; and use HTTP Basic Authentication with your user credentials. Tokens last for 30 days. You also can use the URL &lt;code class=&quot;highlighter-rouge&quot;&gt;{SERVER_URL}/users/logoutall&lt;/code&gt; to delete all of your tokens.&lt;/p&gt;

&lt;p&gt;Various changes were made to the &lt;a href=&quot;https://github.com/Open-App-Library/Vibrato-notes-Back-End/blob/master/notes/models.py&quot;&gt;database model&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;sync_hash&lt;/code&gt; was added to provide a unique “fingerprint” to all of your notes, notebooks and tags. Why not just use the database’s built-in &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt; field you might ask? It is very easy to run into &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt; conflicts when you have multiple devices that can create notes offline, saving to a SQLite database, and then sending them up to the cloud eventually. The back-end API gives notes, notebooks and tags a unique fingerprint, called a &lt;code class=&quot;highlighter-rouge&quot;&gt;sync_hash&lt;/code&gt; which is just a &lt;a href=&quot;https://en.wikipedia.org/wiki/Universally_unique_identifier&quot;&gt;UUID&lt;/a&gt;. With this, you can easily check if an object exists in the cloud.&lt;/p&gt;

&lt;p&gt;Currently, the &lt;code class=&quot;highlighter-rouge&quot;&gt;sync_hash&lt;/code&gt; is read-only and is only set by the back-end server when objects are initially synced to the cloud. But perhaps there are benefits to generating these on the clients too and also using these as “IDs” in foreignkeys as well. This could potentially improve reliability and require less hand-holding (additional code) to sync objects.&lt;/p&gt;

&lt;p&gt;The sync server will use Postgres as a database back-end by default. It’s currently using SQLite just for ease of development purposes but that will be changed. However, the desktop and mobile app will still use SQLite as I believe it is the right tool for the job for that particular case.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;row&lt;/code&gt; column in the Notebook table allows you to specify a custom ordering of your notebooks. The back-end will also normalize whatever row number you provide to keep things neat &amp;amp; simple. Here’s a quick little text diagram that shows how rows are represented. They represent the current index number of the current hierarchy level.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0 - Recipes
1 - Journaling
2 - CompSci
0   - Python
1   - C++
3 Fitness Tracking
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Qt uses the same row concept for their TreeModel. Here is their diagram to explain the concept (Ignore the root item):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019-01-21-progress/qttree.png&quot; alt=&quot;Tree diagram with row concept&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-status-of-the-web-app&quot;&gt;The status of the web app?&lt;/h2&gt;

&lt;p&gt;The web app will be put on hold for now as the desktop app and back-end server are top priority.&lt;/p&gt;

&lt;p&gt;Likely, the next big thing I will be working on is the mobile app, created in Qt.&lt;/p&gt;

&lt;p&gt;The web app has a lot of progress already but I suspect the majority of the users will use the desktop and mobile app, only occasionally using the web app. For that reason it is on hold - but not forgotten or abandoned.&lt;/p&gt;

&lt;h2 id=&quot;thank-you-for-the-support&quot;&gt;Thank you for the support!&lt;/h2&gt;

&lt;p&gt;I have received a good amount of encouragement from reddit and greatly appreciate it. Please &lt;a href=&quot;https://vibrato.app/&quot;&gt;sign up for the waiting list&lt;/a&gt; to get a notification as soon as the app is released if you are interested.&lt;/p&gt;

&lt;h2 id=&quot;upcoming-project-goals&quot;&gt;Upcoming project goals&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Connecting the desktop app to the sync server.&lt;/li&gt;
  &lt;li&gt;Ironing out text-editor bugs and adding a more complete feature set to it.&lt;/li&gt;
  &lt;li&gt;Client-side encryption!&lt;/li&gt;
  &lt;li&gt;Launching a pre-alpha program.&lt;/li&gt;
  &lt;li&gt;Plenty of usability and design tweaks.&lt;/li&gt;
  &lt;li&gt;Creating the mobile application.&lt;/li&gt;
  &lt;li&gt;Implement the plugin system, using a lisp-like scripting language - likely Chicken Scheme.&lt;/li&gt;
  &lt;li&gt;Implementing image &amp;amp; file upload support.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;useful-links&quot;&gt;Useful links&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://openapplibrary.org/about/&quot;&gt;About the Open App Library Project&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://vibrato.app&quot;&gt;Vibrato Notes website&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://features.vibrato.aapp/&quot;&gt;Feature Requests&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://t.me/joinchat/FslNFBYI88kLFXU5TJFJag&quot;&gt;Telegram Group&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Open-App-Library&quot;&gt;Source Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 22 Jan 2019 11:30:00 +0000</pubDate>
        <link>https://openapplibrary.org/news/january-2019-progress</link>
        <guid isPermaLink="true">https://openapplibrary.org/news/january-2019-progress</guid>
      </item>
    
      <item>
        <title>Embeddable GUIs – A plan for the ultimate software productivity suite</title>
        <description>&lt;p&gt;Something real great about using a framework like Qt is the ability to create “widgets” that are very portable and can be embedded in all sorts of other Qt applications.&lt;/p&gt;

&lt;p&gt;An example of this is Escriba, our hybrid Rich-text/Markdown editor. This editor can be embedded in any Qt project you wish to create. Vibrato Notes embeds it.&lt;/p&gt;

&lt;p&gt;There are two main benefits from the text-editor widget being separated from Vibrato Notes. First, it’s easier to develop. When a developer wants to add features to it, they don’t have to compile the entire Vibrato Notes application. They just compile Escriba, which is a much smaller program. Another benefit is that the project will catch more interest. It being a general-use text-editor embeddable in any Qt app makes it attractive for all sorts of applications. This enables developers who never have heard of Vibrato Notes – or don’t even care to for that matter – to contribute to Escriba. Anyone contributing to Escriba indirectly (Or directly depending on how you look at it) helps Vibrato Notes become a better piece of software.&lt;/p&gt;

&lt;p&gt;Now, let’s say I create a todo-list application. I can make it easily embedable and very flexible. This will allow me to both embed it into Vibrato Notes and create a standalone todo-list application. This could help the software appeal to two audiences – those who want todo-list capabilities in Vibrato Notes and those who just simply want a todo-list app. This could even appeal to a third audience depending on how flexible the app is created: Developers who want todo-list capabilities in their software.&lt;/p&gt;

&lt;p&gt;There are a lot of productivity apps to be created; maybe not all of them need to be embed in Vibrato Notes. However, creating all sorts of embeddable widgets and creating helper libraries to add features such as a scripting language can make for a set of apps that are extremely customizable and useful.&lt;/p&gt;
</description>
        <pubDate>Tue, 15 Jan 2019 16:28:00 +0000</pubDate>
        <link>https://openapplibrary.org/ideas/software-productivity-suite</link>
        <guid isPermaLink="true">https://openapplibrary.org/ideas/software-productivity-suite</guid>
      </item>
    
      <item>
        <title>Dev Log Week #4 - January 1-6</title>
        <description>&lt;h2 id=&quot;the-changes&quot;&gt;The Changes:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;You can now save notes!&lt;/li&gt;
  &lt;li&gt;Notes load &amp;amp; sync locally using SQLite3&lt;/li&gt;
  &lt;li&gt;Created SQLManager class and unit-tests for it.&lt;/li&gt;
  &lt;li&gt;You can change the hierarchy of notebooks&lt;/li&gt;
  &lt;li&gt;File»New - a new way to create notes, notebooks and tags&lt;/li&gt;
  &lt;li&gt;Creation shortcut keys - New Note (Ctrl+n), New Notebook (Ctrl+Shift+n), New Tag (Ctrl+Alt+n).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This marks a very important milestone&lt;/strong&gt;. The main functionality in the desktop app is complete. I will now begin working on connecting the back-end API with the desktop app.&lt;/p&gt;

&lt;p&gt;After that is complete I only really have to iron out some bugs and add a settings page.&lt;/p&gt;

&lt;p&gt;As for bugs, it’s mainly all on improving the reliability of the Escriba text editor. This means creating more unit-tests to ensure that bi-directional rich-text/markdown conversion is consistent.&lt;/p&gt;

&lt;p&gt;As for the settings page, I would like to provide some useful features for users to customize the desktop app. There won’t be a ton of customization in the first version of the app but will be more in-depth later on.&lt;/p&gt;

&lt;p&gt;Stay tuned for a pre-alpha release - where you can start playing around with Escriba and sending over feature requests.&lt;/p&gt;
</description>
        <pubDate>Sun, 06 Jan 2019 15:37:00 +0000</pubDate>
        <link>https://openapplibrary.org/weekly-dev-log/week-4</link>
        <guid isPermaLink="true">https://openapplibrary.org/weekly-dev-log/week-4</guid>
      </item>
    
      <item>
        <title>Dev Log Week #3 - Decemember 23-31</title>
        <description>&lt;h2 id=&quot;the-changes&quot;&gt;The Changes:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Fuzzy searching!&lt;/li&gt;
  &lt;li&gt;Added auto-completion when tagging notes&lt;/li&gt;
  &lt;li&gt;Added API for search results&lt;/li&gt;
  &lt;li&gt;Added note-searching UI&lt;/li&gt;
  &lt;li&gt;Made notebook and tags labels not selectable.&lt;/li&gt;
  &lt;li&gt;Fixed a segfault bug when user is deleting a tag/notebook they are viewing.&lt;/li&gt;
  &lt;li&gt;Fixed bug where title in note list wouldn’t update properly.&lt;/li&gt;
  &lt;li&gt;Fixed bugs while renaming tags&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 31 Dec 2018 22:49:00 +0000</pubDate>
        <link>https://openapplibrary.org/weekly-dev-log/week-3</link>
        <guid isPermaLink="true">https://openapplibrary.org/weekly-dev-log/week-3</guid>
      </item>
    
      <item>
        <title>Dev Log Week #2 - Decemember 16-22</title>
        <description>&lt;h2 id=&quot;the-changes&quot;&gt;The Changes:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Added a ‘trash note’ functionality!&lt;/li&gt;
  &lt;li&gt;Created a new UI for trashing notes - with bulk-trash/restore!&lt;/li&gt;
  &lt;li&gt;Polished tagging functions&lt;/li&gt;
  &lt;li&gt;Added “favorite note” functionality!&lt;/li&gt;
  &lt;li&gt;Added solid yellow star icon to indicate favorited notes (resources/icons/vibrato-default/icons/vibrato-draw-star-solid.svg)&lt;/li&gt;
  &lt;li&gt;Added “favorite note” icon to the Escriba text editor toolbar.&lt;/li&gt;
  &lt;li&gt;Made favorites view update when you un-favorite a note&lt;/li&gt;
  &lt;li&gt;Added “trashed” property to Note class&lt;/li&gt;
  &lt;li&gt;Updated the Note class to utilize the updateModifiedDate boolean&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 24 Dec 2018 18:09:00 +0000</pubDate>
        <link>https://openapplibrary.org/weekly-dev-log/week-2</link>
        <guid isPermaLink="true">https://openapplibrary.org/weekly-dev-log/week-2</guid>
      </item>
    
      <item>
        <title>Dev Log Week #1 - Decemember 10-15</title>
        <description>&lt;p&gt;Welcome to the first weekly dev log of Vibrato Notes! This week I was not massively productive but managed to crank away various important changes in the desktop app.&lt;/p&gt;

&lt;h2 id=&quot;the-changes&quot;&gt;The Changes:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Added various tag operations (add tag, delete tag, rename tag)&lt;/li&gt;
  &lt;li&gt;Created a ‘Manager’ class to hold all of the UI Managers. This makes it easy to access each of the UI Manager instances in all of the UI Manager classes.&lt;/li&gt;
  &lt;li&gt;Improved the ux of the ‘New Note’ feature.&lt;/li&gt;
  &lt;li&gt;Made the notelist sidebar properly refresh when a notebook is renamed.&lt;/li&gt;
  &lt;li&gt;Fixed bug where imported notebooks in ‘Default Notebook’ weren’t properly set.&lt;/li&gt;
  &lt;li&gt;Improved the ux when modifying note data. Most notably, when you right click the notebook tree and create a new notebook, it will immediately got into edit mode. (Saves you the step of having to right click again and edit.)&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 17 Dec 2018 20:00:00 +0000</pubDate>
        <link>https://openapplibrary.org/weekly-dev-log/week-1</link>
        <guid isPermaLink="true">https://openapplibrary.org/weekly-dev-log/week-1</guid>
      </item>
    
      <item>
        <title>Vibrato Notes: The Development Progress So Far</title>
        <description>&lt;p&gt;In this post I would like to cover the current progress of Vibrato Notes.&lt;/p&gt;

&lt;p&gt;There is &lt;a href=&quot;https://vibrato.app&quot;&gt;now a website&lt;/a&gt; for Vibrato Notes, btw!&lt;/p&gt;

&lt;p&gt;Creating the first version of this app has taken much longer than I initially thought. It’s common to go into software projects thinking that an idea is very easy to implement and then you keep encountering new design problems you hadn’t thought of and the scope of the project keeps increasing.&lt;/p&gt;

&lt;p&gt;There were a few problems in the beginning of the development of Vibrato Notes that caused me to spend a lot of time, not neccesarily building the core app, but instead building libraries that would be needed for the app. Examples of those include &lt;a href=&quot;https://github.com/Open-App-Library/markdownpanda&quot;&gt;Markdown Panda&lt;/a&gt; and &lt;a href=&quot;https://github.com/Open-App-Library/QBasicHtmlExporter&quot;&gt;QBasicHtmlExporter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/Open-App-Library/escriba&quot;&gt;Escriba&lt;/a&gt; is another library I had to spend a decent amount of time on. It is quite important as it is the hybrid text-editor used in the desktop application.&lt;/p&gt;

&lt;p&gt;Throughout the experience, I have drastically increased my ability to work with C and C++. It has been a lot of fun even in the most challenging parts, fighting off mysterious segfault after segfault.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is a rough overview of the progress&lt;/strong&gt;:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Component&lt;/th&gt;
      &lt;th&gt;Progress&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Back-end API&lt;/td&gt;
      &lt;td&gt;Functional, needs slight adjustments.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Web app&lt;/td&gt;
      &lt;td&gt;Close to completion. On hold while I finish the desktop app.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Desktop app&lt;/td&gt;
      &lt;td&gt;Good progress but a lot to do.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Mobile app&lt;/td&gt;
      &lt;td&gt;Not started.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;the-journey-so-far&quot;&gt;The journey so far.&lt;/h2&gt;

&lt;p&gt;The whole project started with me creating a bare-minimal API in Django that provided just enough functionality. After that, I started work on the web app.&lt;/p&gt;

&lt;p&gt;However, I took a break developing the web app to move onto the desktop app. I was progressing through the web app at quite a fast pace and that is because working with web technologies can be easy. VueJS in particular helped a lot.&lt;/p&gt;

&lt;p&gt;…However, C++ isn’t as easy. I was worried I would complete the web app, move onto the desktop app and just completely struggle with it. I like to do the hard things first, saving the easy stuff for last.&lt;/p&gt;

&lt;p&gt;C++ (and plain C for MarkdownPanda!) did involve quite a lot of additional learning as I was primarily familiar with languages with garbage collectors.&lt;/p&gt;

&lt;p&gt;Working with plain C in particular has improved my documentation-reading skills. There are times where a library has no other documentation other than the code itself and the few comments left within the header files. There are also times where a library that does a specific task does not exist. I needed an HTML to Markdown converter and had to write one myself, with the help of &lt;a href=&quot;https://github.com/lexborisov/myhtml&quot;&gt;MyHTML&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Qt5 has been an incredibly powerful framework to use. It saves a ton of effort and really makes cross-platform development a breeze. Still, with having to worry about memory management and the header-source-file workflow of C++, it’s still not that quick to prototype applications when you are used to being spoiled with web technologies.&lt;/p&gt;

&lt;p&gt;I look forward to implementing a scripting language into Vibrato Notes later on. It will allow me to decouple some non-performance-effecting C++ from the project as well as provide the users with a versatile extension system to use. This is a rough idea now - not set in stone - and will be further explored in the future.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-12-10-update/desktop.png&quot; alt=&quot;The Desktop app&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;desktop-app-features&quot;&gt;Desktop App Features&lt;/h2&gt;

&lt;p&gt;In this section I’ll go over a few cool features of the desktop app.&lt;/p&gt;

&lt;h3 id=&quot;hybrid-rich-textmarkdown-editor&quot;&gt;Hybrid rich-text/markdown editor&lt;/h3&gt;

&lt;p&gt;You can edit in both rich-text and markdown. Switching between the two is easy! I plan on improving and writing more unit-tests to improve the reliability of the bi-directional conversion.&lt;/p&gt;

&lt;video src=&quot;/images/2018-12-10-update/bidirectional.webm&quot; controls=&quot;&quot;&gt;
&lt;/video&gt;

&lt;h3 id=&quot;editing-notebooks-in-a-tree-based-hierarchial-fashion&quot;&gt;Editing notebooks in a tree-based, hierarchial fashion&lt;/h3&gt;

&lt;video src=&quot;/images/2018-12-10-update/notebook-tree.webm&quot; controls=&quot;&quot;&gt;
&lt;/video&gt;

&lt;h3 id=&quot;modify-the-notebook-and-tags-of-a-note&quot;&gt;Modify the notebook and tags of a note&lt;/h3&gt;

&lt;video src=&quot;/images/2018-12-10-update/tag-notebook-manipulation.webm&quot; controls=&quot;&quot;&gt;
&lt;/video&gt;

&lt;h3 id=&quot;layout-switching&quot;&gt;Layout switching&lt;/h3&gt;

&lt;p&gt;There are three different layout presets. The default one, one that hides the leftmost sidebar, and one that hides both sidebars, leaving you with the text editor.&lt;/p&gt;

&lt;video src=&quot;/images/2018-12-10-update/layouts.webm&quot; controls=&quot;&quot;&gt;
&lt;/video&gt;

&lt;h3 id=&quot;fairly-efficient-note-filtering-allowing-you-to-quickly-navigate-through-hundreds-of-notes&quot;&gt;Fairly efficient note filtering, allowing you to quickly navigate through hundreds of notes&lt;/h3&gt;

&lt;video src=&quot;/images/2018-12-10-update/filtering.webm&quot; controls=&quot;&quot;&gt;
&lt;/video&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018-12-10-update/webapp.png&quot; alt=&quot;Web app screenshot&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;web-app&quot;&gt;Web App&lt;/h2&gt;

&lt;p&gt;The web app is pretty - indeed - however you may notice it lacks a few features of the desktop app. Like I mentioned earlier, I took a break from the web app to build the desktop app. I haven’t touched the code of the web app for a few month and plan to return to it after the desktop app is complete.&lt;/p&gt;

&lt;p&gt;Here is a video I took of it a while ago:&lt;/p&gt;

&lt;blockquote class=&quot;reddit-card&quot; data-card-created=&quot;1544486919&quot;&gt;&lt;a href=&quot;https://www.reddit.com/r/UsabilityPorn/comments/99j657/kde_a_notetaking_app_im_building_emacs_and_my/&quot;&gt;[KDE] A note-taking app I'm building, Emacs, and my minimal KDE tweaks&lt;/a&gt; from &lt;a href=&quot;http://www.reddit.com/r/UsabilityPorn&quot;&gt;r/UsabilityPorn&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//embed.redditmedia.com/widgets/platform.js&quot; charset=&quot;UTF-8&quot;&gt;&lt;/script&gt;

&lt;h2 id=&quot;weekly-updates&quot;&gt;Weekly updates&lt;/h2&gt;

&lt;p&gt;Something new I will be doing is creating a new post every week on OpenAppLibrary.org detailing progress made in the app.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;
</description>
        <pubDate>Mon, 10 Dec 2018 16:40:00 +0000</pubDate>
        <link>https://openapplibrary.org/news/december-2018-progress</link>
        <guid isPermaLink="true">https://openapplibrary.org/news/december-2018-progress</guid>
      </item>
    
      <item>
        <title>A Guide to Using Icon Themes in Qt on All Platforms</title>
        <description>&lt;p&gt;This guide will attempt to demystify the usage of icon themes in Qt applications.&lt;/p&gt;

&lt;p&gt;Icon themes are standard on the Linux desktop but seem to be a foreign concept on Mac and Windows. Lucky for us, Qt has integrated icon themes quite seamlessly no matter what operating system you are using.&lt;/p&gt;

&lt;p&gt;To see a working example of icon theme usage that uses a variety of techniques from this article, check out our “&lt;a href=&quot;https://github.com/DougBeney/Qt5-Icon-Themes-Example&quot;&gt;Qt5 Cross-Platform Icon Themes&lt;/a&gt;” repo.&lt;/p&gt;

&lt;h2 id=&quot;what-is-an-icon-theme&quot;&gt;What is an “icon theme”?&lt;/h2&gt;

&lt;p&gt;FreeDesktop.org created &lt;a href=&quot;https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html&quot;&gt;the spec&lt;/a&gt; on how icon themes should work in free software desktop environments.&lt;/p&gt;

&lt;p&gt;They define an icon theme as the following:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;An icon theme is a set of icons that share a common look and feel. The user can then select the icon theme that they want to use, and all applications will use icons from the theme.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;adding-your-own-icons-to-the-default-theme&quot;&gt;Adding your own icons to the default theme&lt;/h2&gt;

&lt;p&gt;An easy way to add “cross-platform support” is to:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.)&lt;/strong&gt; create a folder in your project. (ex. “custom-icons”)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.)&lt;/strong&gt; Add all of your icons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.)&lt;/strong&gt; Use the following code to define a fallback icon search pack:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;QIcon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setFallbackSearchPaths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QIcon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fallbackSearchPaths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;:custom-icons&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;4.)&lt;/strong&gt; Create a new resources and add your custom icons. Your qrc file’s structure should look similar to the following:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/qt5-icons/custom-icons-structure.png&quot; alt=&quot;QRC file structure for custom icons&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now, you can reference any icons in that folder by their filename (minus the file extension). So, in the example of the above screenshot, I would reference the icon as “open-app-library”.&lt;/p&gt;

&lt;p&gt;To reference the icons, you can either use Qt Designer or enter it programatically.&lt;/p&gt;

&lt;p&gt;Here is how I changed a button’s icon from &lt;a href=&quot;https://github.com/DougBeney/Qt5-Icon-Themes-Example/blob/master/main.cpp&quot;&gt;the example repo&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;b2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setIcon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QIcon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromTheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;open-app-library&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If it is important to you that the icons should first try to obey the user’s system icons, please make sure to follow &lt;a href=&quot;https://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html&quot;&gt;the naming conventions defined by FreeDesktop.org&lt;/a&gt;. However, if your icon is something truly unique (Like the Open App Library logo I used in this example) you can of course deviate from the specification.&lt;/p&gt;

&lt;h2 id=&quot;configuring-a-new-icon-theme-in-qt&quot;&gt;Configuring a new icon theme in Qt&lt;/h2&gt;

&lt;p&gt;You might want to completely overwrite the system icon theme and use your own.&lt;/p&gt;

&lt;p&gt;You could either create your icon theme from scratch or use the &lt;a href=&quot;https://www.gnome-look.org/browse/cat/132/&quot;&gt;many existing themes&lt;/a&gt;. I personally like &lt;a href=&quot;https://github.com/KDE/breeze-icons&quot;&gt;KDE’s Breeze icons&lt;/a&gt; and &lt;a href=&quot;https://github.com/elementary/icons&quot;&gt;Elementary OS’s icons&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Be aware that not all icon themes include every single icon detailed in the FreeDesktop specification. I’ve found that KDE’s Breeze icons contain the widest selection of icons - I believe they even offer additional icons outside of the specification.&lt;/p&gt;

&lt;h3 id=&quot;how-icon-themes-work&quot;&gt;How icon themes work&lt;/h3&gt;

&lt;p&gt;Here is the file structure of a very minimal icon theme:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;└── my-theme/
  └── actions/
    └── 16/
      └── hello-world.png
    └── 24/
      └── hello-world.png
    └── index.theme
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It could be even simpler than that! (Note that this structure, while it works, deviates from the specification.)&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;└── my-theme/
  └── my-special-ui-icons
    └── hello-world.png
  └── index.theme
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The most important file is that index.theme. Here is an example of what an index.theme may look like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Icon Theme]
Name=My Theme
Comment=An example icon theme

[actions/16]
Size=16
Context=Actions
Type=Fixed

[actions/24]
Size=24
Context=Actions
Type=Fixed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are all sorts of things you could do in this index.theme file. You could even inherit icons from another theme! Once again, to learn more about how this all works, check out &lt;a href=&quot;https://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html&quot;&gt;the official specification&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;where-does-qt-search-for-icon-themes&quot;&gt;Where does Qt search for icon themes?&lt;/h3&gt;

&lt;p&gt;Now that we have either downloaded an icon pack or have created our own, how can we actually load it?&lt;/p&gt;

&lt;p&gt;First, let’s figure out where Qt is searching for icons. Run the following C++ code (Make sure to include QIcon and QDebug):&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;qDebug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QIcon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;themeSearchPaths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Depending on your operating system, you will get different output. Here are the different paths the command returned for me:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;/home/doug/.icons&lt;/li&gt;
  &lt;li&gt;/var/lib/flatpak/exports/share/icons&lt;/li&gt;
  &lt;li&gt;/usr/share/icons&lt;/li&gt;
  &lt;li&gt;:/icons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What’s important to know is that while the theme search paths will vary from operating system to operating system, the &lt;code class=&quot;highlighter-rouge&quot;&gt;:icons/&lt;/code&gt; resource path will always be present.&lt;/p&gt;

&lt;p&gt;This is where we will place our icon paths.&lt;/p&gt;

&lt;h3 id=&quot;adding-the-icon-pack-as-a-resource&quot;&gt;Adding the icon pack as a resource&lt;/h3&gt;

&lt;p&gt;If you’re in Qt Creator, the process is quite painless. After you create a new resource file, right click on it and choose “Add existing directory”.&lt;/p&gt;

&lt;p&gt;Now, it might be tempting to add EVERY file from your icon pack but that is not the most efficient way.&lt;/p&gt;

&lt;p&gt;Instead, only add the &lt;code class=&quot;highlighter-rouge&quot;&gt;index.theme&lt;/code&gt; and icons that you plan on using.&lt;/p&gt;

&lt;p&gt;For this example project, I decided to use &lt;a href=&quot;https://www.opendesktop.org/p/1209330/&quot;&gt;the Zafiro&lt;/a&gt; icon pack. Here is what my resources file structure looks like after adding the one icon I wanted:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/qt5-icons/zafiro-structure.png&quot; alt=&quot;Zafiro icon pack resource structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In case you want to see what my Qt resource file looks like after adding Zafiro, here it is:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;RCC&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;qresource&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;prefix=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;file&amp;gt;&lt;/span&gt;icons/zafiro/index.theme&lt;span class=&quot;nt&quot;&gt;&amp;lt;/file&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;file&amp;gt;&lt;/span&gt;icons/zafiro/places/48/folder-alt.svg&lt;span class=&quot;nt&quot;&gt;&amp;lt;/file&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/qresource&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/RCC&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;loading-the-icon-theme-programatically&quot;&gt;Loading the icon theme programatically&lt;/h3&gt;

&lt;p&gt;There very well may be a way to do this directly in Qt Designer but I have not yet found it.&lt;/p&gt;

&lt;p&gt;Here is how you would load your icon theme in C++:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;QIcon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setThemeName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;zafiro&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Easy peasy!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Button 1 is showing Zafiro’s folder-alt icon.&lt;/li&gt;
  &lt;li&gt;Button 2 is showing the custom open-app-library icon.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/images/qt5-icons/result.png&quot; alt=&quot;The Result&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;bonus-tip-keep-hidpi-support-in-mind&quot;&gt;Bonus tip: Keep HiDPI support in mind&lt;/h2&gt;

&lt;p&gt;If you ran the example project on a Mac with a retina display or any other device with a HiDPI display, you might have noticed the icons were a little bit blurry.&lt;/p&gt;

&lt;p&gt;You can fix this with a single magical line of C++:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;QGuiApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Qt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AA_UseHighDpiPixmaps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Before and after:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/qt5-icons/hidpi.png&quot; alt=&quot;Before and after: HiDPI icons&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;note-for-qt-deployment&quot;&gt;Note for qt deployment&lt;/h2&gt;

&lt;p&gt;Be aware that you have to deploy a plugin in case of svg images. You find the SVG + QIconEnginePlugin (as described under https://doc.qt.io/qt-5/qicon.html) plugins/iconengines. Otherwise the theme switch doesn’t work.&lt;/p&gt;

&lt;h2 id=&quot;did-i-miss-anything-about-icon-packs&quot;&gt;Did I miss anything about icon packs?&lt;/h2&gt;

&lt;p&gt;Hope you have enjoyed this article. If you have any further questions or have any ideas to improve this guide, don’t hesitate to drop a comment below.&lt;/p&gt;

&lt;p&gt;You may also edit this page by clicking the “Edit this page” button below and submitting a pull request.&lt;/p&gt;
</description>
        <pubDate>Wed, 14 Nov 2018 16:03:00 +0000</pubDate>
        <link>https://openapplibrary.org/dev-tutorials/qt-icon-themes</link>
        <guid isPermaLink="true">https://openapplibrary.org/dev-tutorials/qt-icon-themes</guid>
      </item>
    
      <item>
        <title>Converting markdown to HTML with Github's CMark-GFM library in C + How to use extensions!</title>
        <description>&lt;p&gt;Today, I was working on &lt;a href=&quot;https://github.com/Open-App-Library/markdownpanda&quot;&gt;MarkdownPanda&lt;/a&gt;, a bi-directiona HTML/Markdown conversion library that will be very important to &lt;a href=&quot;https://vibrato.app&quot;&gt;Vibrato Notes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With MarkdownPanda, I have gone through quite the number of Markdown parsers. I started my decision with Sundown and Discount. Then decided to go with Hoedown. I was happy with Hoedown up until the point where I noticed super strange behavior in my unit tests where previous markdown-&amp;gt;HTML operations would concatenate onto new ones…Super weird and just made me want to find something new. Came across CMark and found it absolutely perfect..Until I realized tables and strikethroughs were not implemented. &lt;strong&gt;And then I found Github’s own CMark-GFM&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At a surface level, the library is super simple and hardly any different than CMark.&lt;/p&gt;

&lt;h2 id=&quot;example-program&quot;&gt;Example Program&lt;/h2&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;cmark-gfm.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;markdown&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;# Welcome&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmark_markdown_to_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;markdown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;markdown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CMARK_OPT_DEFAULT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Easy, right? Must be smooth sailing from here! Well..we do have a bit of a problem. Tables and strikethroughs are not supported by default. There are also &lt;a href=&quot;https://github.com/github/cmark-gfm/tree/master/extensions&quot;&gt;other&lt;/a&gt; extensions you may find useful.&lt;/p&gt;

&lt;h2 id=&quot;using-extensions&quot;&gt;Using extensions&lt;/h2&gt;

&lt;p&gt;In order to use extensions you must first make sure to link against &lt;code class=&quot;highlighter-rouge&quot;&gt;libcmark-gfm-extensions&lt;/code&gt;. It is an additional library that is created while building CMark-GFM.&lt;/p&gt;

&lt;p&gt;Here is an example program that uses markdown extensions:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;cmark-gfm.h&amp;gt;
#include &amp;lt;cmark-gfm-core-extensions.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// This is a function that will make enabling extensions easier later on.&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addMarkdownExtension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmark_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;cmark_syntax_extension&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmark_find_syntax_extension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ext&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cmark_parser_attach_syntax_extension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// A function to convert HTML to markdown&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;markdown_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CMARK_OPT_DEFAULT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// You can also use CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE to enforce double tilde.&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;cmark_gfm_core_extensions_ensure_registered&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Modified version of cmark_parse_document in blocks.c&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;cmark_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmark_parser_new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;///////////////////////&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;/// Add extensions here&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;///////////////////////&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;addMarkdownExtension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;strikethrough&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;addMarkdownExtension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;table&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;cmark_node&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;cmark_parser_feed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;markdown_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;markdown_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmark_parser_finish&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;cmark_parser_free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Render&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmark_render_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;cmark_node_free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// MAIN FUNCTION&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;markdown&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;# Welcome&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;markdown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hope this saved you some time! You can check out how we implemented this in MarkdownPanda by viewing &lt;a href=&quot;https://github.com/Open-App-Library/markdown-panda/blob/master/src/markdownpanda_md2html.c&quot;&gt;markdownpanda_md2html.c&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you enjoyed, feel free to &lt;a href=&quot;/projects/&quot;&gt;browse our open-source software&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Fri, 26 Oct 2018 22:25:00 +0000</pubDate>
        <link>https://openapplibrary.org/dev-tutorials/cmark-gfm-extensions</link>
        <guid isPermaLink="true">https://openapplibrary.org/dev-tutorials/cmark-gfm-extensions</guid>
      </item>
    
      <item>
        <title>Announcing WideGuy!</title>
        <description>&lt;p&gt;Today I am very happy to announce &lt;a href=&quot;http://openapplibrary.org/project/wideguy&quot;&gt;WideGuy&lt;/a&gt;! A simple tool that solves a Linux gaming problem I came across.&lt;/p&gt;

&lt;p&gt;It makes switching your monitors to a wide-picture mode (Xinerama) as easy as a click of a button.&lt;/p&gt;

&lt;p&gt;Definitely give it a try if multi-monitor gaming is your thing.&lt;/p&gt;
</description>
        <pubDate>Mon, 08 Oct 2018 16:34:00 +0000</pubDate>
        <link>https://openapplibrary.org/news/announcing-wideguy</link>
        <guid isPermaLink="true">https://openapplibrary.org/news/announcing-wideguy</guid>
      </item>
    
  </channel>
</rss>
