<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Mardy (Articoli su maemo)</title><link>http://mardy.it/</link><description></description><atom:link href="http://mardy.it/it/categories/maemo.xml" rel="self" type="application/rss+xml"></atom:link><language>it</language><copyright>Contents © 2026 &lt;a href="mailto:info@mardy.it"&gt;Alberto Mardegan&lt;/a&gt; </copyright><lastBuildDate>Sat, 11 Apr 2026 13:54:08 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Back to Maemo!</title><link>http://mardy.it/it/blog/2023/01/back-to-maemo.html</link><dc:creator>Alberto Mardegan</dc:creator><description>&lt;p&gt;New year, new job. After &lt;a href="http://mardy.it/it/blog/2022/12/leaving-canonical-again.html"&gt;leaving
Canonical&lt;/a&gt; I'm back to working on the same
software platform on which I started working back in 2006: &lt;a href="http://mardy.it/it/blog/2023/01/maemo.org"&gt;Maemo&lt;/a&gt;.
Well, not exactly the vanilla Maemo, but rather its evolution known as &lt;a href="https://en.wikipedia.org/wiki/Aurora_OS_(Russian_Open_mobile_platform)"&gt;Aurora
OS&lt;/a&gt;,
which is based on &lt;a href="https://sailfishos.org/"&gt;Sailfish OS&lt;/a&gt;. This means I'm
actually back to fixing the very same bugs I introduced back then when I was
working in Nokia, since a lot of the middleware has remained the same.&lt;/p&gt;
&lt;p&gt;At the moment OMP (the company developing Aurora OS) is mostly (or even
&lt;em&gt;exclusively&lt;/em&gt;, AFAIK) targeting business customers, meaning corporations such
as the Russian posts and the railway company, whereas the consumer market is
seen as something in the far away future. Just in case you were curious whether
there were any devices on sale with Aurora OS.&lt;/p&gt;
&lt;p&gt;I should also explain why I've refused several very well paying job
opportunities from Western companies: it's actually for a reason that has been
bothering me since last March, and it's a very simple one. The fact is that
because of the sanctions against Russia I already had to change bank once (as
the one I was using fell under sanctions), and in these months I've always been
working with the fear of not being able to receive my salary, since new
sanctions are introduced every month and more and more banks are being added to
the blacklist. That's why I've restricted my job search to companies having an
official presence in Russia; and to my surprise (and from some point of view, I
could even say &lt;em&gt;disappointment&lt;/em&gt;) the selection and hiring processes were so
quick that I received three concrete offers while I was still working my last
weeks at Canonical, and I joined OMP on that very Monday after my last Friday
at Canonical.&lt;/p&gt;
&lt;p&gt;I mean, I could have rested a bit, at least until the Christmas holidays, but
no. ☺  Anyway, I'm so far very happy with my new job, and speaking Russian at
work is something totally new for me, both challenging and rewarding at the
same time.&lt;/p&gt;</description><guid>http://mardy.it/it/blog/2023/01/back-to-maemo.html</guid><pubDate>Sun, 08 Jan 2023 19:48:52 GMT</pubDate></item><item><title>Qbs and code coverage reports</title><link>http://mardy.it/it/blog/2019/07/qbs-and-code-coverage-reports.html</link><dc:creator>Alberto Mardegan</dc:creator><description>&lt;p&gt;You know that I'm not an &lt;em&gt;early adopter&lt;/em&gt;. That's why it was only a couple of
weeks ago when I decided to give &lt;a href="https://doc.qt.io/qbs/"&gt;Qbs&lt;/a&gt; a try, by using
the good old &lt;a href="https://www.mardy.it/mappero/"&gt;Mappero&lt;/a&gt; (and its spin-off,
&lt;a href="https://www.mardy.it/mappero-geotagger/"&gt;Mappero Geotagger&lt;/a&gt;) as a test bench.
Yes, I know that the Qt company is not going to maintain Qbs anymore in the
future, but the little I knew about Qbs was enough to convince me that it's a
project worth supporting. So, better late than never -- and hopefully the
community (me included) will do a good job in keeping Qbs thriving.&lt;/p&gt;
&lt;p&gt;Having Mappero build with Qbs was the simplest thing ever. The only issue I met
was in building the unit tests, because I'm used to set the &lt;code&gt;rpath&lt;/code&gt; on test
executables in order to make it easy to run them uninstalled, and with &lt;code&gt;qmake&lt;/code&gt;
I achieved that with this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nv"&gt;QMAKE_RPATHDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;QMAKE_LIBDIR&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In turns out that with Qbs you can do it in almost the same way, but for some
reason I couldn't figure it out and I even &lt;a href="https://bugreports.qt.io/browse/QBS-1455"&gt;reported a
bug&lt;/a&gt; to which I got some nice
suggestions, before eventually settling on this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;qbs&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;

&lt;span class="nx"&gt;Test&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"path-test"&lt;/span&gt;

    &lt;span class="k"&gt;files:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"path-test.cpp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"path-test.h"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"paths.qrc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="nx"&gt;Depends&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"Mappero"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;cpp.rpaths:&lt;/span&gt; &lt;span class="nx"&gt;cpp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;libraryPaths&lt;/span&gt;    &lt;span class="c1"&gt;// &amp;lt;-- this does the trick!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It's surprisingly similar to how it's done in qmake, so it's not clear even to
me why I didn't guess that immediately. Anyway, that was literally my only
problem, and you can see the whole set of Qbs files I wrote by having a look at
&lt;a href="https://gitlab.com/mardy/mappero/commit/2a19b59f018cd0517d37eadd24d1aa1780140e4b"&gt;this
commit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Given how easy the migration was, I thought I should also try to add a code
coverage report; that's not something I had in my qmake build either, but it's
something I really want to have in all my newer projects.&lt;/p&gt;
&lt;h3&gt;Teaching Qbs to make a code coverage report&lt;/h3&gt;
&lt;p&gt;Unfortunately, my search for examples on how to have Qbs prepare a coverage
report was mostly insuccessful, but thanks to some amazing help from Christian
in the #qbs IRC channel, this was not hard to achieve. So, I hope to be of some
help myself too, by sharing how this works.&lt;/p&gt;
&lt;p&gt;First of all, it must be said that Qbs doesn't know anything about code
coverage, at all. However, it's possible (and often easy) to extend Qbs by
adding your own &lt;code&gt;Product&lt;/code&gt; with its own set of build rules, so here's the
&lt;code&gt;CoverageReport&lt;/code&gt; item for Mappero (though, it should be general enough to be
reusable in your own project):&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;qbs&lt;/span&gt;

&lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"coverage"&lt;/span&gt;

    &lt;span class="nx"&gt;property&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="k"&gt;outputDirectory:&lt;/span&gt; &lt;span class="s2"&gt;"coverage-html"&lt;/span&gt;
    &lt;span class="nx"&gt;property&lt;/span&gt; &lt;span class="nx"&gt;stringList&lt;/span&gt; &lt;span class="k"&gt;extractPatterns:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;builtByDefault:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="k"&gt;files:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"**"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;type:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"coverage.html"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="nx"&gt;Depends&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;productTypes:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"autotest-result"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;Rule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;multiplex:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="k"&gt;explicitlyDependsOnFromDependencies:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"autotest-result"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;outputFileTags:&lt;/span&gt; &lt;span class="s2"&gt;"coverage.html"&lt;/span&gt;
        &lt;span class="k"&gt;requiresInputs:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
        &lt;span class="k"&gt;prepare:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;commands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;captureCmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"lcov"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;"--directory"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"--capture"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"--output-file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"coverage.info"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"--no-checksum"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"--compat-libtool"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="nx"&gt;captureCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Collecting coverage data"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;captureCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;highlight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"coverage"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;captureCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;silent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;captureCmd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;extractArgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extractPatterns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;extractArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"--extract"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;extractArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"coverage.info"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;extractArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extractPatterns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extractPatterns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;extractArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"-o"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;extractArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"coverage.info"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;extractCmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"lcov"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;extractArgs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;extractCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Extracting coverage data"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nx"&gt;extractCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;highlight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"coverage"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nx"&gt;extractCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;silent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extractCmd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;filterCmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"lcov"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;"--remove"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"coverage.info"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'moc_*.cpp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"--remove"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"coverage.info"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'qrc_*.cpp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"--remove"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"coverage.info"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'*/tests/*'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"-o"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"coverage.info"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="nx"&gt;filterCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Filtering coverage data"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;filterCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;highlight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"coverage"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;filterCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;silent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filterCmd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;genhtmlCmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"genhtml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;"--prefix"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"--output-directory"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outputDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"--title"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Code coverage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"--legend"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"--show-details"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"coverage.info"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="nx"&gt;genhtmlCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Generate HTML coverage report"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;genhtmlCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;highlight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"coverage"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;genhtmlCmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;silent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;genhtmlCmd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The most important thing here are the references to the &lt;code&gt;autotest-result&lt;/code&gt; tag:
this is the tag used by the &lt;code&gt;AutotestRunner&lt;/code&gt; Qbs item, which is responsible for
running the unit tests. Referencing its product's tag in the &lt;code&gt;Depends&lt;/code&gt; item and
in the &lt;code&gt;explicitlyDependsOnFromDependencies&lt;/code&gt; properties ensures that "building"
our product will cause the unit tests to run. Other needed bits are the
&lt;code&gt;requiresInputs: false&lt;/code&gt; property, which means that our rule doesn't have any
required inputs, and the &lt;code&gt;builtByDefault: false&lt;/code&gt; property, which says that our
coverage report should not be generated when just typing &lt;code&gt;qbs&lt;/code&gt;. Instead, to run
the tests and get the code coverage report one will have to request it
explicitly, by typing&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;qbs -p coverage
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;prepare&lt;/code&gt; property of the &lt;code&gt;Rule&lt;/code&gt; is where the commands to generate the code
coverage report are defined. Here we can use the &lt;code&gt;Command&lt;/code&gt; item to invoke
external programs, and we return a list of such items, so that the commands
will be executed in sequence. Note that here I'm using &lt;code&gt;lcov&lt;/code&gt; and expecting to
find the coverage data produced by &lt;code&gt;gcov&lt;/code&gt;, so this is probably not portable
outside of Linux/gcc.&lt;/p&gt;
&lt;p&gt;Using the &lt;code&gt;CoverageReport&lt;/code&gt; item is quite easy: you just need to declare it, and
specify which paths contain the coverage data that you are interested in
(otherwise, lcov will collect data from all object files that it find under the
build directory, which might not be what you desire):&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;    &lt;span class="nx"&gt;CoverageReport&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;condition:&lt;/span&gt; &lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enableCoverage&lt;/span&gt;
        &lt;span class="k"&gt;extractPatterns:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'*/src/*.cpp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'*/lib/*.cpp'&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There's little more than that to be done. Of course, you need to find a way to
pass the &lt;code&gt;--coverage&lt;/code&gt; option to gcc when building your products, and for this I
created a small &lt;code&gt;buildconfig&lt;/code&gt; module in
&lt;code&gt;qbs/modules/buildconfig/BuildConfig.qbs&lt;/code&gt; which I depend on in all products
which I wish to build with coverage enabled:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;qbs&lt;/span&gt;

&lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;cpp.cxxFlags:&lt;/span&gt; &lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enableCoverage&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"--coverage"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
    &lt;span class="k"&gt;cpp.dynamicLibraries:&lt;/span&gt; &lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enableCoverage&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"gcov"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;

    &lt;span class="nx"&gt;Depends&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"cpp"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If all this looks scary, you should probably have a look at the diff which
shows &lt;a href="https://gitlab.com/mardy/mappero/commit/ee04f6a453a935db653095c45bfe57af6a0ce508"&gt;how I added code coverage reporting to
qbs&lt;/a&gt;:
hopefully you'll find that it's not that complex, after all.&lt;/p&gt;
&lt;p&gt;I hope that Qbs users will find this interesting, and possibly improving my
setup. Ideally we should try to get something like this part of Qbs itself, but
portability outside of Linux / gcc is going to be an issue.&lt;/p&gt;</description><guid>http://mardy.it/it/blog/2019/07/qbs-and-code-coverage-reports.html</guid><pubDate>Mon, 01 Jul 2019 13:42:20 GMT</pubDate></item><item><title>Ubports at the LinuxPiter conference</title><link>http://mardy.it/it/blog/2019/03/ubports-at-the-linuxpiter-conference.html</link><dc:creator>Alberto Mardegan</dc:creator><description>&lt;p&gt;Last November I was invited to talk at the &lt;a class="reference external" href="https://linuxpiter.com/"&gt;LinuxPiter&lt;/a&gt; conference. I held a presentation of the &lt;a class="reference external" href="https://ubports.com/"&gt;Ubports
project&lt;/a&gt;, to which I still contribute in my little
spare time.&lt;/p&gt;
&lt;p&gt;The video recording from the conference has finally been published:&lt;/p&gt;
&lt;div class="youtube-video align-center"&gt;
&lt;iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/_gWTiVPahT0?rel=0&amp;amp;wmode=transparent" frameborder="0" allow="encrypted-media" allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;p&gt;(there's also a &lt;a class="reference external" href="https://www.youtube.com/watch?v=pYiqOzZZg-w"&gt;version in Russian&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;There was not a big audience, to be honest, but those that were there expressed
a lot of interest in the project.&lt;/p&gt;</description><guid>http://mardy.it/it/blog/2019/03/ubports-at-the-linuxpiter-conference.html</guid><pubDate>Wed, 13 Mar 2019 16:07:23 GMT</pubDate></item><item><title>Introducing Mappero Geotagger</title><link>http://mardy.it/it/blog/2012/08/introducing-mappero-geotagger.html</link><dc:creator>Alberto Mardegan</dc:creator><description>&lt;div style="float: right;"&gt;&lt;a href="http://www.mardy.it/archivos/imagines/mappero-geotagger.png"&gt;&lt;img src="http://www.mardy.it/archivos/imagines/mappero-geotagger.png" width="400px"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;A few days ago I published the first version of &lt;a href="http://www.mardy.it/mappero-geotagger"&gt;Mappero Geotagger&lt;/a&gt;, an open source geotagging application for Linux, Mac OS X and Windows.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Geotagging&lt;/em&gt; a file means assigning a geographic location to it, and it's an action typically performed on picture files, so that the geotagged photo can be shown on a map at the location where it was taken. Many photo-sharing websites, like for instance &lt;a href="http://flickr.com"&gt;flickr&lt;/a&gt; and &lt;a href="http://picasa.google.com/"&gt;picasa&lt;/a&gt;, will show your pictures on a map, as you can see for example &lt;a href="http://www.flickr.com/photos/mardytardi/2915024236/in/set-72157607758948089"&gt;in this picture&lt;/a&gt; of mine. Some services also allow you to view all photos taken in a certain area; for instance, here are some nice pictures taken in &lt;a href="http://www.flickr.com/map?&amp;amp;fLat=60.3834&amp;amp;fLon=25.6776&amp;amp;zl=13"&gt;Porvoo&lt;/a&gt;, Finland.&lt;/p&gt;

&lt;p&gt;Mappero Geotagger is a simple graphical tool to geotag your photos. You can manually move pictures on the map to set or change their location (removing the geotag is also possible) or, if you happened to record your way with a GPS while you took the pictures, the program can automatically correlate the time of the photos with the time of the GPS signal, and therefore establish with a certain precision where the pictures where taken. Since the time of the GPS receiver and the time of your camera might differ (and usually they do, especially if you travel to a different time-zone and forget to update the time in one of your devices), Mappero Geotagger has some controls to allow you to smoothly adjust the time difference and provides you an immediate feedback as you'll see the images being laid out on the map along the GPS track. The video below should give you a better idea of how this works:&lt;/p&gt;

&lt;div style="text-align: center; margin: 0 auto;"&gt;&lt;iframe width="560" height="315" src="http://www.youtube.com/embed/b1J84dISuNk?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br&gt;&lt;small&gt;See Mappero Geotagger in action&lt;/small&gt;&lt;/div&gt;

&lt;p&gt;I'm selling the application &lt;a href="http://www.mardy.it/mappero-geotagger"&gt;from my website&lt;/a&gt; for 15€, but if you hurry up and either &lt;a href="http://twitter.com"&gt;tweet&lt;/a&gt; or mention it in &lt;a href="http://plus.google.com"&gt;Google+&lt;/a&gt; you can have it for 5€ only — and &lt;b&gt;if you blog about it, you'll get it for free&lt;/b&gt;. Detailed info on the promotion are &lt;a href="http://www.mardy.it/mappero-geotagger#promotions"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Incidentally, if you own a Nokia N9 or N900, the source code which you will get when purchasing Mappero Geotagger can also be compiled for these phones, into an application (still under heavy development, but already usable) which lets you record a GPX track usable with Mappero Geotagger.&lt;/p&gt;</description><guid>http://mardy.it/it/blog/2012/08/introducing-mappero-geotagger.html</guid><pubDate>Thu, 23 Aug 2012 15:05:00 GMT</pubDate></item><item><title>From G to Q</title><link>http://mardy.it/it/blog/2012/05/from-g-to-q.html</link><dc:creator>Alberto Mardegan</dc:creator><description>&lt;p&gt;I decided to blog about my experience of transitioning from being a GLib and GObject enthusiast to a Qt (and QML) fanboy. :-) I'm not writing this with any specific goals, other than sharing my own experience and hopefully making the life of those developers who are forced to learn and use Qt less painful and a bit more rosy; in particular, I'm not trying to be a Qt evangelist here and convince you, hardcore GObject developer, to switch to Qt: I'm indeed sure that if my current self tried to talk my 3 years younger self into Qt, it would be a useless and tiresome (and maybe violent ;-)) discussion.&lt;/p&gt;

&lt;p&gt;Just a bit of background on myself: I've been developing on Linux and Unix for more than 10 years now, mostly using GObject based libraries, such as Gtk+. I had a short encounter with Qt in about 2004, just for a few weeks, which left me with a bad impression (mostly because of the &lt;a href="http://qt-project.org/doc/uic.html"&gt;uic&lt;/a&gt;). Other than that, I was simply not interested in Qt, mostly because I hate C++ and love C and anyway all my needs were perfectly met by GLib, GObject and Gtk+. I remember that the first time when I read about GObject, I was fascinated: the power of OO programming on top of my favorite language, all open source and hackable. In autumn 2006 I started a new job in Nokia, in the &lt;a href="http://maemo.org"&gt;maemo&lt;/a&gt; team, working on a middleware component in the &lt;a href="http://telepathy.freedesktop.org/wiki/"&gt;Telepathy&lt;/a&gt; VoIP framework; I enjoyed it a lot, and (if possible) grew even more fond of GObject and GLib. On early 2008, the big news: Nokia acquires Trolltech (the SW house developing Qt); for me, as for most of the people working in the &lt;i&gt;maemo&lt;/i&gt; team, this came as a complete surprise, and not as a really good one. Indeed, we were afraid that we would have to abandon the C/Gtk+ work and switch to C++/Qt — perhaps not coincidentally, several GNOME developers working in Nokia even left the company around that time. Luckily though, nothing really changed for us for more than one year, and even later, when more people joined to work on Qt-related stuff and I moved to another project, I could still avoid touching Qt code and continue using only my beloved GObject. However, &lt;em&gt;like all good dreams, this also came to an end&lt;/em&gt;: eventually, I had to refresh my C++ knowledge and change my most typed character from "g" to the hated "q".&lt;br&gt;
So, here my Q story begins.&lt;/p&gt;

&lt;h3&gt;The first prolonged exposure to Qt&lt;/h3&gt;

&lt;p&gt;It was painful. My first task was to create Qt-bindings for the GLib-based library I was developing. There was no UI involved, so on the tools front the experience was not as bad as I remembered; but on the pure programming side, I was horrified: I felt extremely limited, many programming paradigms I was used too couldn't be applied, or I was just told (by people more expert in Qt) that “you shouldn't do like that, it's not the Qt way!”. Urgh.&lt;/p&gt;
&lt;p&gt;The biggest issues I had were the lack of reference counting in QObject (!!) and the veto on using C-style function callbacks for asynchronous operations (you &lt;em&gt;should&lt;/em&gt; use Qt &lt;i&gt;slots&lt;/i&gt;, and in order to have a slot you &lt;em&gt;must&lt;/em&gt; have a receiving QObject). How could I take Qt seriously? Sure, there were also a few nice things about it, like the fact that QObject comes with child-parent lifetime handling out of the box (when a parent object dies, all of its children are automatically deleted), and that signal connections are automatically broken when either the emitter or the &lt;em&gt;receiver&lt;/em&gt; object dies (yay, no more explicit signal disconnections — or random crashes!). But still, this could in no way compensate for the lack of the other low-level features I was used to.&lt;/p&gt;
&lt;p&gt;I cannot really say that I enjoyed the first months of using Qt. I was still trying to work as much as possible on the GLib-based parts of the project, and twisting my head around to figure out what was “the Qt way” of doing all the things that I was used to do almost instinctively with GLib/GObject.&lt;/p&gt;

&lt;h3&gt;From hate to love&lt;/h3&gt;

&lt;p&gt;Now that I think back and try to find the moment of time when I finally started liking Qt (or just not dislike it too much), I cannot really point out a definite time. It was a very slow process, that surely wouldn't have completed if I hadn't been forced to use Qt because of my work. But indeed, the moment when I realized that Qt was not so bad after all is when I started writing new original code with it. In retrospection, I would say that my experience with Qt was so bad because I started with a completely wrong task: as an inexperienced Qt developer, creating binding for a GObject-based library couldn't possibly make me appreciate Qt; I was just bound to notice all the GObject features that were not present in Qt, and suffer their absence. And I wouldn't notice almost any of the niceties that Qt offers to application developers, because there is not much code you can write in a wrapper library other than some trivial glue code.&lt;br&gt;
So, my first suggestion for those GObject developers who start using Qt is: &lt;b&gt;do not write a Qt wrapper to your favorite GObject library!&lt;/b&gt;, you are going to hate it. Leave it to someone who is more experienced than you in Qt; it can be a very pedagogic task, indeed, but chances are that it will be the last time you are going to use Qt. If you can, start with writing new code.&lt;/p&gt;

&lt;p&gt;That said, there is a big difference between not disliking something and loving it. But again, I cannot tell when I started loving Qt. What I surely can tell is when I &lt;em&gt;realized&lt;/em&gt; that I loved it: and that was when I started porting some GObject-based code to Qt (not as a line-by-line port, but more like a functional rewrite) and found out that the resulting code was not only more compact and easier to write, but — and especially — easier to &lt;em&gt;read&lt;/em&gt;. And of course, when I realized that my enthusiasm was not the same as before, whenever I had to do some programming in C+GObject.&lt;/p&gt;

&lt;h3&gt;What I find cute in Qt&lt;/h3&gt;

&lt;p&gt;Let me begin with a couple of statements which could dispel some myths or anyway clarify some doubts that the Qt-virgin might hold:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;It's not C++&lt;/b&gt;. This is a bold (and false) statement, but it's probably the most effective to convey the idea: if you — like me — hate C++, you won't necessarily hate Qt. Qt's C++ is a subset of C++: although you can use whatever C++ feature you might like, developing with Qt does not involve using exceptions, templates, RTTI and the STL. In a similar way to how GLib and GObject “extend” the C language, Qt uses a preprocessor (called &lt;tt&gt;moc&lt;/tt&gt;) to add its own run-time type information (think of GType) and implement the signals/slots mechanism. In the end, you don't need to know all the details of C++ to develop Qt; instead, it's somehow similar to developing Vala code — it's like a programming language of its own.
&lt;/li&gt;&lt;li&gt;&lt;b&gt;It's not just GUI&lt;/b&gt;. As you might have noticed, this post is not about Qt vs. Gtk+, not at all. There are many other articles on the web where you can find comparisons and opinions of the two, but what I'm focusing on here is my experience with Qt programming and GNOME programming, and not just at the UI level. So, yes, the point is that you can develop whatever code with Qt (except maybe kernel drivers): I've personally written D-Bus services, command line tools and embedded software using just Qt.
&lt;/li&gt;&lt;li&gt;&lt;b&gt;There &lt;em&gt;really&lt;/em&gt; is a Qt way&lt;/b&gt;. My disappointment about the lack of reference counting in QObject is now history: apart from the fact that indeed there is one class in Qt which lets you implement reference counting for QObjects, I cannot recall any case where reference counting would have been useful. I know, coming from GObject this might sound hard to believe (especially to my three years younger self, who used to mess up with cross references everywhere in the code), but it's a fact: after some initial struggle, I always managed to design the software with clear ownership of objects, so that the reference counting ended up to be totally superfluous. And in fact, my code is designed better now. The same can be said of any other feature that I initially missed: if it's not there, you can do without it: just restructure your code in a different way — the Qt way — and there's a good chance that while reworking your classes you'll clear up some mess. :-)
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;That said, here's a list of things that I came to like about Qt; I'm obviously not mentioning those things that are also in GLib/GObject, unless there are significant differences.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;QObject automatic destruction of children&lt;/b&gt;. I already mentioned it before, but it's worth expanding a bit. Quite often I had to use reference counting in my GObject subclasses to keep track of the child-parent relationships; QObject already does that for you: whenever you create a QObject, you can specify one parent object which will “watch” its lifetime and destroy it in its destructor. This leads to a nice programming paradigm where you can create all the objects that your class needs and just use the &lt;tt&gt;this&lt;/tt&gt; pointer as parent object: then you don't need to remember destroying them explicitly in your destructor.
&lt;/li&gt;&lt;li&gt;&lt;b&gt;Automatic disconnection of signals when receiver object dies&lt;/b&gt;. I also mentioned this before, but &lt;i&gt;repetita iuvant&lt;/i&gt;: if you are an experienced C + GObject developer, you &lt;em&gt;must&lt;/em&gt; have seen at least once in your programming career one crash due to a signal callback invoked when the objects it operated on had already been destroyed. Of course I know that it never happened to &lt;em&gt;you&lt;/em&gt; personally, but you surely saw this in someone else's software. ;-) Well, in Qt this is very unlikely to happen, because (at least till Qt4) it's impossible to bind signals to C callbacks: you must bind them to a QObject method (called “slot”), and the QObject system takes care of disconnecting the signal for you when either the emitter or the receiver object are destroyed.
&lt;/li&gt;&lt;li&gt;&lt;b&gt;QString&lt;/b&gt;. I'm sometimes a bit maniacal with micro-optimizations, and one thing I was always trying to optimize in my early GLib days was avoiding string allocations. It really hurts me to write a g_strdup() in a library method's implementation when I could rather write "Please, don't destroy or change @string_param while this object is still alive" in the documentation string for the method. But that's not &lt;em&gt;the GLib way&lt;/em&gt; (and indeed, not my way anymore when I write GLib code): you can never know what happens with the string, so it's way safer to incur the small penalty of a g_strdup() than run the risk of a crash which is likely to be very hard to debug. So, C/GLib code is often full with g_strdup() and g_free() (not to speak about valac-generated code!). Enter QString! QString is not only a class that provides a ton of useful string methods, it is an &lt;em&gt;implicitly shared&lt;/em&gt; class. That means that the QString structure itself is very small (size of a pointer?), and that the string data is reference counted; then if/when you modify a string which has a reference count higher than 1, the string data is copied and your QString is now pointing at the modified copy. So you never have to worry about copying strings! How cool is that? :-)
&lt;/li&gt;&lt;li&gt;&lt;b&gt;Awesome container classes&lt;/b&gt;. Qt comes with a few container classes which you'll surely get to like: &lt;tt&gt;QMap&lt;/tt&gt;, &lt;tt&gt;QList&lt;/tt&gt; are those that you'll use the most, but then there's also &lt;tt&gt;QSet&lt;/tt&gt;, &lt;tt&gt;QQueue&lt;/tt&gt;, &lt;tt&gt;QHash&lt;/tt&gt;, &lt;tt&gt;QVector&lt;/tt&gt; and others. These are template classes, so you can write &lt;tt&gt;QMap&amp;lt;QString,QVariant&amp;gt;&lt;/tt&gt; and get the equivalent of a &lt;tt&gt;GHashtable&lt;/tt&gt; whose keys are strings and values are &lt;tt&gt;GValue&lt;/tt&gt;s. Inserting items is as easy as writing
&lt;pre&gt;
QMap&amp;lt;QString,QVariant&amp;gt; map;
map.insert("string", "string value");
map.insert("integer", 12);
&lt;/pre&gt;
while to iterate the values you have the handy &lt;tt&gt;foreach&lt;/tt&gt; macro, which lets you write
&lt;pre&gt;
foreach (const QVariant &amp;amp;value, map) {
    QDebug() &amp;lt;&amp;lt; "Value:" &amp;lt;&amp;lt; value;
}
&lt;/pre&gt;
And if you remember what I wrote above about QString: Qt container classes are implicitly shared too!

&lt;/li&gt;&lt;li&gt;&lt;b&gt;Reduced usage of pointers&lt;/b&gt;. This follows in part from the above: QString handles all string pointers for you, and the ease of implementing implicit sharing of container classes makes it so that you will be often passing them by value or by reference. Also, implementing implicit sharing for your own data structures is very easy, and you might prefer investing a little time doing that rather than using raw pointers.
&lt;/li&gt;&lt;li&gt;&lt;b&gt;Class and API offering&lt;/b&gt;. Even excluding the GUI classes, the functionality provided by the Qt classes will satisfy the most demanding developer: whether you want to deal with date/time, with network resources, with graphics/images, HTML (webkit), SQL databases, D-Bus, plugins, regular expressions, etc., it's all there, and everything works perfectly together. The APIs are intuitive and clean: you won't find duplicate classes offering the same functionality (unless one is deprecated), and the documentation is excellent.
&lt;/li&gt;&lt;li&gt;&lt;b&gt;Compact and clean code&lt;/b&gt;. Qt application code is likely to be much mode compact and clean than GObject code. Just like Vala, imagine removing all GObject casts and using class namespaces to shorten your method names and fit your code in a 80 chars wide editor. :-) Use &lt;tt&gt;const&lt;/tt&gt; effectively to mark your class methods and finally be able to pass constant objects and structures around your code, minimizing the risk of incorrect usage.
&lt;/li&gt;&lt;li&gt;&lt;b&gt;QML&lt;/b&gt;. This would deserve a chapter on its own, but since there has been quite a lot of buzz around it on the internet I won't spend many words on describing it. Instead, I'll focus on how I came to like it so much. As it often happens with new things, my first impression was not so great; sure, all the QML demos you can find in the internet are extremely captivating, and it's impressive how much you can achieve with very little code — which doesn't even look like real code, but more like a static description. And this was indeed my first doubt: what is the limit of QML? It's a nice language for moving graphics items around, but does it let me do anything more than that? Or: if it really allows me to write complex UIs for big applications, won't the code become a horrible mess to maintain? Again, time and hands-on experience is what changed my mind. I'm porting one map application from Gtk+/Clutter to Qt and of course the map widget and its animations has been my first item in the list. &lt;a href="http://www.clutter-project.org/"&gt;Clutter&lt;/a&gt; is a fantastic toolkit for producing animated UIs in the GNOME world; the Qt equivalent is QGraphicsView, whose APIs luckily match very close the Clutter ones; so, the porting wasn't that difficult at all, and it didn't took long until I had my widget working. However, for implementing the animations (zoom, panning and rotation of the map) I didn't use the &lt;a href="http://qt-project.org/doc/qt-4.8/animation-overview.html"&gt;Qt Animation Framework&lt;/a&gt;, which would be the natural equivalent to Clutter animation classes, but instead went for QML: exposing the map properties to QML enables implementing animations in a much easier and enjoyable way. QML property bindings, together with property animation descriptions, empower your application to any kind of smooth animations with almost no effort on your side. You don't have to take care of starting/stopping animations, changing the direction of animations while they are running, or combining zooming/panning/rotation at overlapping moments: no matter how crazily the user plays with your UI, all animations happen as expected, without any need for you to special code them. I couldn't help falling in love with QML. :-)&lt;br&gt;
So, my answers to the above questions are that, first of all, QML is a language especially designed for developing UIs and UI logics. There's not much else that you can do beside that; in order to write algorithms and implement the rest of application (all what is non-UI) you have to resort to either Javascript or C++ (or Python, etc.); the only difference on how you use these languages is that it's possible to write the Javascript code in the &lt;tt&gt;.qml&lt;/tt&gt; file itself, which is very convenient but also, in my humble opinion, something that you shouldn't do. So, while you could say that it is possible to write an entire application in QML, I heartily discourage you from doing so; if you really like Javascript (why would you, by the way?) and want to write your application with it and QML, it's much better to write the code of your application logic in a &lt;tt&gt;.js&lt;/tt&gt; file and import that from QML. About QML code becoming a maze when writing complex applications, I disagree; of course, it's possible, but it's the same in all other languages (which I know of). If you split your code into smaller QML files (per UI component or groups of components) and avoid creating cross dependencies between components, everything will go smoothly — my golden rule when writing QML code is that &lt;em&gt;a &lt;tt&gt;.qml&lt;/tt&gt; file should never refer to identifiers which are not defined in the file itself&lt;/em&gt;. The reason why I'm getting so down in technicalities here is that, if you are a developer who has some experience with QML but finds it messy, you should go and check your code against this rule. :-) Indeed, QML is not a panacea which let everyone who is not a developer write über-complex applications; it's easier and more effective than all other languages (which I know of, again), but the rules of good software development still apply.
&lt;/li&gt;&lt;/ul&gt;

&lt;h3&gt;How you can start liking Qt&lt;/h3&gt;

&lt;p&gt;No way you will. ;-) Joke aside, there is some truth in that answer: first of all, you will never like Qt until you try it; and you won't try it unless you are forced to, or have some very good reasons to start looking into it. In my case, in fact, I was forced to, and — at that time — I had absolutely no reason to try Qt on my own: I already had some bad memories with it, I didn't like KDE, the skype Linux client and, most importantly, I was totally happy and satisfied with coding C and GObject.&lt;/p&gt;
&lt;p&gt;However, I believe that nowadays there might be two reasons why even a hardcore GNOME developer could, in an unforgivable moment of weakness, decide to try programming with Qt: QML and application portability. QML is &lt;i&gt;the new cool stuff&lt;/i&gt; (it was not there when I started with Qt), there are plenty of nice demos and examples out there, and they do pretty amazing things. Especially given that setting up the environment is an easy task (just install the Qt packages from your Linux distribution) and running the demos is in most cases just a matter of typing &lt;tt&gt;qmlviewer &amp;lt;file&amp;gt;.qml&lt;/tt&gt;, and that you are a very curious geek, it's not so unlikely that you'll want to have a closer look to the demos; and since the source code consists in most cases of just a few lines of JSON-like text, it won't take long for you to understand it and maybe start playing with it. Especially because I &lt;a href="http://mail.gnome.org/archives/desktop-devel-list/2011-April/msg00174.html"&gt;still&lt;/a&gt; believe that GNOME developers deserve something as cool as QML. :-)&lt;br&gt;
The other reason why trying Qt nowadays is not so absurd as it might seem is portability. Yes, Qt has always made portability his flag, but who does really care about Windows and Mac? However, what you might care about is &lt;b&gt;Android&lt;/b&gt;! What has changed here in the last couple of years is that &lt;a href="http://www.youtube.com/watch?v=IzhFscWXs_w"&gt;Qt and QML run on Android&lt;/a&gt;, with GL acceleration and multitouch support, enabling you to develop modern applications which can be run on millions of devices; you can also target &lt;a href="http://swipe.nokia.com/"&gt;the best smartphone ever&lt;/a&gt;, Symbian smartphones and whatever devices Nokia will come up with for &lt;a href="http://www.developer.nokia.com/Community/Blogs/blog/nokia-developer-news/2011/06/21/future-of-qt-bringing-apps-to-next-billion"&gt;the next billion&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I don't think there is much more I can write to stimulate you to try out Qt or, if you have already started using it, to support your efforts to master it. What I can tell you, with no fear of being contradicted, is that &lt;em&gt;eventually you will like it&lt;/em&gt;; there is no way that this won't happen, if you continue learning it. At some point you will realize that going back to C (or even Vala) and GObject is not going to make your programming more productive, or even more enjoyable than how it has become with Qt. It's just a matter of enduring the difficulties and unpleasantness for a long enough time; which can be even several full months if you are, like me, one who takes technologies, programming languages and libraries next to your heart.&lt;/p&gt;</description><guid>http://mardy.it/it/blog/2012/05/from-g-to-q.html</guid><pubDate>Fri, 18 May 2012 13:33:00 GMT</pubDate></item><item><title>The Meego Accounts &amp; Single Sign On project</title><link>http://mardy.it/it/blog/2011/08/meego-accounts-single-sign-on-project.html</link><dc:creator>Alberto Mardegan</dc:creator><description>&lt;p&gt;One of the new features of the upcoming &lt;a href="http://swipe.nokia.com/"&gt;Nokia N9&lt;/a&gt; is the unified accounts UI  and the Single Sign On (SSO) framework. The developer website hosts a &lt;a href="http://www.developer.nokia.com/swipe/ux/pages/Accounts.html"&gt;page describing this feature&lt;/a&gt; in high level terms — a highly recommended reading — and offers a picture of the account creation flow (the orange circle representing the  finger tapping is a bit off target in the pictures, bummer):&lt;/p&gt;
&lt;div style="margin: 0 auto; width: 626px;"&gt;
&lt;img src="http://www.developer.nokia.com/swipe/ux/images/integrate_your_app/addaccount-thumb.png"&gt;
&lt;/div&gt;

&lt;p&gt;The  UX designers of the N9 decided to create a centralized place where all  the user’s accounts would be managed: all the account providers will be  listed in this application, and once the user chooses the provider and  enters his credentials (only once), he’ll be prompted to select which  services he intends to use on this account, in case the provider account  gives access to more than one. Once this is done, all the applications  interested in the selected services which have been enabled for the new  account will start using it.&lt;/p&gt;

&lt;p&gt;This design removes the need to implement account management in every  application, because all the accounts and their settings are handled in  the accounts UI application. Of course, applications can invoke the  accounts UI when an account needs to be created, and they can directly  embed the account configuration plugin when a specific account needs to  be edited.&lt;br&gt;
The accounts UI provides most of its functionality through &lt;b&gt;account plugins&lt;/b&gt;. There are &lt;em&gt;provider&lt;/em&gt; plugins, whose task is to create the account and handle those settings  that are shared through all the account’s services (such as a global  option to enable or disable the account), and &lt;em&gt;service&lt;/em&gt; plugins, which add support for a specific service within the account  and provide a configuration for its settings (at the very least, a  toggle switch to enable or disable the service). This plugin based way  of operate on accounts brings the possibility to extend the support for  new online services, with plugins possibly coming from different  sources, from the OS platform vendor to a user’s community, as well as  from a hardware vendor, third party software companies and application  stores. And all the new services can be directly accessible from the  same applications the user is already familiar with, instead of  requiring the installation of one additional stand-alone application.&lt;/p&gt;

&lt;p&gt;On the other hand, the &lt;b&gt;Single Sign On&lt;/b&gt; framework  is mostly transparent to the user (indeed, that’s the goal of any SSO  implementation): once the password for one service has been entered, all  applications operating on the same account should be able to login  without bothering the user with password dialogs. And if the password  turns out to be wrong, the SSO framework will ask for it &lt;em&gt;only once&lt;/em&gt;, no matter how many applications are using the account.&lt;br&gt;

Security  is also tightly bound to the MeeGo SSO implementation: at account  creation time it’s possible to specify which applications are allowed to  use a certain account (or, more technically, which resource tokens an  application must possess in order to be granted access to a certain  account’s credentials), and what authentication methods are allowed. For  instance, for security reasons we might not want to allow an account to  be used with any authentication method where the password is disclosed  in plain text to the applications or sent over the network.&lt;br&gt;
Last  but not least, the account passwords are stored on the device in  encrypted form, and the encrypted storage can be dynamically  activated/deactivated by providing/removing a master key, which could be  configured to be the user password, or a fingerprint or other biometric  checksum, some hardware key (such as a SIM card), or pretty much  anything else. When the encrypted password storage is unavailable and  some applications need to login to a service, the user will be prompted  for the needed service password (again not more than once per account);  all this being totally transparent to the application.&lt;/p&gt;

&lt;h4&gt;Using the framework in other devices/platforms&lt;/h4&gt;

&lt;p&gt;The  UI design for the Accounts &amp;amp; SSO components described above is just  one of the possible ways of integrating the MeeGo Accounts &amp;amp; SSO  framework into a user device. The framework itself has been written to  be flexible and support any UI workflow we could think of, without  compromises to performance or security. The deployment of the Accounts  &amp;amp; SSO framework in other devices and platforms has also been taken  into consideration during the architecture and implementation  development and several actions were taken towards this goal.&lt;/p&gt;

&lt;p&gt;The core software driving the Accounts &amp;amp; SSO frameworks is all open source (LGPL), and can be found in &lt;a href="https://gitorious.org/accounts-sso"&gt;gitorious.org&lt;/a&gt;. The most interesting components are:
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="http://gitorious.org/accounts-sso/accounts-glib"&gt;libaccounts-glib&lt;/a&gt;: &lt;a href="http://en.wikipedia.org/wiki/GLib"&gt;Glib&lt;/a&gt;-based API for account management. Depends on &lt;a href="http://www.sqlite.org/"&gt;SQLite&lt;/a&gt; and &lt;a href="http://www.freedesktop.org/wiki/Software/dbus"&gt;D-Bus&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gitorious.org/accounts-sso/accounts-qt"&gt;libaccounts-qt&lt;/a&gt;: Qt API for account management. Thin wrapper of libaccounts-glib APIs.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gitorious.org/accounts-sso/signon"&gt;signon&lt;/a&gt;: the SSO daemon (written with Qt), which provides a D-Bus API. In the  same source tree there’s also the libsignon-qt library, for Qt-based  clients.&lt;/li&gt;
&lt;li href="http://gitorious.org/accounts-sso/signon-glib"&gt;libsignon-glib: Glib-based client API for SSO.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most  of the other repositories in the project are probably not very useful  outside of MeeGo, and they are not that interesting anyway. What might  be more interesting to know, is the list of components that are missing  from the gitorious project (because they are not open source), and that  another platform/vendor would have to reimplement in order to provide  all the functionalities described above. Luckily, there’s not much in  this list. Apart from a couple of SSO authentication plugins for  specific services, the rest is all about UI parts (because of Nokia’s  general policy of not releasing the source code of its UI applications):  we &lt;i&gt;don’t&lt;/i&gt; have the account application and the account plugins, and the SSO UI  daemon serving the password dialogs. This is not a big loss because in  the UI would have had to be rewritten anyways to run in other platforms  (and for MeeGo as well, as the MeeGoTouch UI library which is used in  these Nokia UIs has been deprecated).&lt;/p&gt;

&lt;p&gt;Having  spent quite a considerable amount of (pleasant) time and energy on this  project, I feel rather bound to it even though my employment in Nokia  has ended. Therefore, I’m willing to continue to dedicate some of my  free time (which, I have to say, is not much) to contribute to it and  help its deployment in MeeGo and other Linux based platforms. Don’t  hesitate to &lt;a href="mailto:mardy@users.sourceforge.net"&gt;contact me&lt;/a&gt; if you are interested in getting the Accounts &amp;amp; SSO powering the OS you love and would like to know more about it.&lt;/p&gt;</description><guid>http://mardy.it/it/blog/2011/08/meego-accounts-single-sign-on-project.html</guid><pubDate>Sun, 14 Aug 2011 17:20:00 GMT</pubDate></item><item><title>...e Neverputt!</title><link>http://mardy.it/it/blog/2011/07/e-neverputt.html</link><dc:creator>Alberto Mardegan</dc:creator><description>&lt;p&gt;&lt;i&gt;To celebrate the &lt;a href="http://www.interlingua.com/novas/2011-01-31-conferentia"&gt;interlingua conference&lt;/a&gt;, which is going to take place in about one week, I write this post in &lt;a href="http://www.interlingua.com"&gt;interlingua&lt;/a&gt;. I'm sure you'll be able to understand it, just with a little of extra effort — if not, just enjoy the video :-)&lt;/i&gt;&lt;/p&gt;&lt;br&gt;
&lt;p&gt;In le mesme repositorio de &lt;a href="http://neverball.org/"&gt;Neverball&lt;/a&gt;, del qual io parlava &lt;a href="http://blog.mardy.it/2011/07/neverball.html"&gt;in le post precedente&lt;/a&gt;, il ha un altere joco, &lt;em&gt;Neverputt&lt;/em&gt;, que es equalmente amusante. Illo es un joco de mini-golf, que es jocabile de uno a quatro jocatores (in turnos). Il ha multe cursos differente, de varie nivellos de habilitate e complexitate, pro tote le gustos.&lt;/p&gt;&lt;p&gt;Post que le codice del programma es largemente in commun con Neverball, le porting al &lt;a href="http://en.wikipedia.org/wiki/Nokia_N900"&gt;N900&lt;/a&gt; esseva multo facile. Io debeva solmente implementar un differente methodo de controlo, assi que on pote jocar con le touchscreen. Un demonstration es in iste video:&lt;br&gt;
&lt;/p&gt;&lt;center&gt;&lt;br&gt;
&lt;iframe width="425" height="349" src="http://www.youtube.com/embed/8QeaUwwSNVs?hl=en&amp;amp;fs=1" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br&gt;
&lt;/center&gt;&lt;br&gt;
&lt;br&gt;
&lt;p&gt;&lt;em&gt;Neverball&lt;/em&gt; e &lt;em&gt;Neverputt&lt;/em&gt; es in le repositorio &lt;i&gt;&lt;a href="http://wiki.maemo.org/Extras-testing"&gt;extras-testing&lt;/a&gt;&lt;/i&gt;. Illos non es ancora perfecte, in particular le menus debe esser ameliorate pro esser plus usabile con le touchscreen, ma io crede que illos es jam jocabile. Vole ben installar los e testar los!&lt;br&gt;
&lt;br&gt;
Nota importante: &lt;b&gt;&lt;em&gt;Neverball&lt;/em&gt; e &lt;em&gt;Neverputt&lt;/em&gt; usa 100% del CPU, anque quando in pausa!&lt;/b&gt;&lt;/p&gt;&lt;br&gt;
&lt;p&gt;In altere novas, io hodie ha recipite mi Nokia N950, le kit de developpamento pro le &lt;a href="http://swipe.nokia.com"&gt;N9&lt;/a&gt;; isto es un bon nova pro tote illes qui vole jocar con Neverball e Neverputt in lor N9 — e certemente, anque pro le fans de &lt;a href="http://www.mardy.it/mappero"&gt;Mappero&lt;/a&gt;! :-)&lt;/p&gt;</description><guid>http://mardy.it/it/blog/2011/07/e-neverputt.html</guid><pubDate>Wed, 13 Jul 2011 08:08:00 GMT</pubDate></item><item><title>Neverball</title><link>http://mardy.it/it/blog/2011/07/neverball.html</link><dc:creator>Alberto Mardegan</dc:creator><description>&lt;p&gt;&lt;i&gt;To celebrate the &lt;a href="http://www.interlingua.com/novas/2011-01-31-conferentia"&gt;interlingua conference&lt;/a&gt;, which is going to take place in a couple of weeks, I write this post in &lt;a href="http://www.interlingua.com"&gt;interlingua&lt;/a&gt;. I'm sure you'll be able to understand it, just with a little of extra effort&lt;/i&gt;&lt;/p&gt;&lt;br&gt;
&lt;p&gt;&lt;a href="http://neverball.org/"&gt;Neverball&lt;/a&gt; es un joco de habilitate, in le qual on controla un balla per mover le pavimento. Neverball es un projecto que existe desde multe annos, e es disponibile per plure systemas operative; totevia, io ignorava su existentia usque duo septimanas retro. Alora, quando io lo discoperiva, immediatemente io considerava le idea de portar lo al &lt;i&gt;smartphones&lt;/i&gt; Nokia &lt;a href="http://en.wikipedia.org/wiki/Nokia_N900"&gt;N900&lt;/a&gt; e al futur &lt;a href="http://swipe.nokia.com"&gt;N9&lt;/a&gt; (ambes es basate super le systema operative &lt;em&gt;&lt;a href="http://maemo.org"&gt;maemo&lt;/a&gt;&lt;/em&gt;). Le compatibilitate con OpenGL ES 1.1 e un stylo de programmation sufficientemente clar rende iste operation relativemente facile.&lt;/p&gt;&lt;p&gt;In alicun dies, io jam habeva un version de Neverball functionante in mi N900, benque con plure problemas. Iste septimana io addeva le supporto al accelerometro, assi que ora il es possibile controlar le pavimento per mover le telephono.&lt;br&gt;&lt;br&gt;
Multe modificationes es ancora necessari, perque le balla es terribilemente difficile a controlar con le accelerometro (supertoto perque le camera se move continuemente), ma io vole monstrar vos un &lt;i&gt;preview&lt;/i&gt;, pro stimular vostre expectationes:&lt;/p&gt;&lt;center&gt;&lt;br&gt;
&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/IIRx1bELrWY" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br&gt;
&lt;/center&gt;&lt;br&gt;
&lt;br&gt;
&lt;p&gt;Pro le programmatores curiose, le codice fonte con mi modificationes es &lt;a href="https://garage.maemo.org/plugins/ggit/browse.php/?p=neverball;a=shortlog;h=refs/heads/fremantle"&gt;hic&lt;/a&gt;.&lt;/p&gt;</description><guid>http://mardy.it/it/blog/2011/07/neverball.html</guid><pubDate>Thu, 07 Jul 2011 14:19:00 GMT</pubDate></item><item><title>An always new wallpaper for your N900</title><link>http://mardy.it/it/blog/2011/06/always-new-wallpaper-for-your-n900.html</link><dc:creator>Alberto Mardegan</dc:creator><description>&lt;p&gt;With the 0.9 version of &lt;a href="http://www.mardy.it/oculo"&gt;oculo&lt;/a&gt;, your N900 homescreen gets one level up: beautiful wallpapers that will never be the same. Well, whether they are beautiful really depends on you: you decide what tiny part of the World Wide Web should be rendered in there!&lt;/p&gt;&lt;br&gt;
&lt;center&gt;&lt;br&gt;
&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/XeZhF00P1hs?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br&gt;
&lt;/center&gt;&lt;br&gt;
&lt;p&gt;Of course you are not forced to have Oculo manage your wallpapers. :-) Oculo can still render the web content into a homescreen widget, and you can run multiple instances of it, in different modes. Also, you can have Oculo render only some of your homescreen views, while keeping the rest static.&lt;/p&gt;&lt;br&gt;
&lt;p&gt;Version 0.9 of Oculo is in the &lt;tt&gt;extras-testing&lt;/tt&gt; repository, and you can directly &lt;a href="http://repository.maemo.org/extras-devel/pool/fremantle/non-free/o/oculo/oculo_0.9_armel.deb"&gt;download it from here&lt;/a&gt;. Be warned that I just tested the widget for a couple of minutes, so anything bad can happen. :-)&lt;/p&gt;</description><guid>http://mardy.it/it/blog/2011/06/always-new-wallpaper-for-your-n900.html</guid><pubDate>Sat, 25 Jun 2011 12:12:00 GMT</pubDate></item><item><title>Oculo is now available in the Extras repository!</title><link>http://mardy.it/it/blog/2011/05/oculo-is-now-available-in-extras.html</link><dc:creator>Alberto Mardegan</dc:creator><description>&lt;p&gt;Just a quick note: &lt;a href="http://www.mardy.it/oculo"&gt;Oculo&lt;/a&gt; 0.8 is now in the &lt;a href="http://wiki.maemo.org/Extras"&gt;Maemo Extras repository&lt;/a&gt;. Known issues with the CSSU have now been resolved, and the update interval is now configurable.&lt;/p&gt;</description><guid>http://mardy.it/it/blog/2011/05/oculo-is-now-available-in-extras.html</guid><pubDate>Sun, 15 May 2011 04:05:00 GMT</pubDate></item></channel></rss>