<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>El Tramo | Qt</title>
  <subtitle>Remko Tronçon's Homepage</subtitle>
  <link href="http://el-tramo.be/blog/tag/qt/feed/" rel="self" type="application/rss+xml"/>
  <link href="http://el-tramo.be/"/>
  <updated>2011-12-30T17:00:29+01:00</updated>
  <id>http://el-tramo.be/</id>
  <author>
    <name>Remko Tronçon</name>
    <uri>http://el-tramo.be/about/</uri>
  </author>
  
  <entry>
    <title>TwitCoop: A Desktop Cage for Twitter Mobile Web</title>
    <author>
      <name>Remko Tronçon</name>
      <uri>http://el-tramo.be/about/</uri>
    </author>
    <link href="http://el-tramo.be/blog/twitcoop"/>
    <updated>2011-05-25T00:00:00+02:00</updated>
    <id>http://el-tramo.be/blog/twitcoop</id>
    <content type="html">The official &lt;a href=&quot;http://itunes.apple.com/us/app/twitter/id409789998?mt=12&quot;&gt;Twitter for Mac&lt;/a&gt; app gives a great interface for &lt;a href=&quot;http://twitter.com&quot;&gt;Twitter&lt;/a&gt;: lightweight, compact, no bloat, and it looks great. Unfortunately, amongst the hundreds of Twitter clients already existing, I couldn't find anything similar for Linux or Windows. Instead of creating yet another client (which &lt;a href=&quot;http://arstechnica.com/software/news/2011/03/twitter-tells-third-party-devs-to-stop-making-twitter-client-apps.ars&quot;&gt;Twitter doesn't like&lt;/a&gt; anyway), I did a bit of &lt;a href=&quot;http://qt.nokia.com&quot;&gt;Qt&lt;/a&gt; WebKit coding, and created a small desktop client around the (current) Twitter Mobile Web interface.

&lt;em&gt;
Update: The mobile Twitter website was updated, and doesn't work as well anymore with TwitCoop. I will try to upgrade TwitCoop to work with the new interface, but it is currently not clear whether this is at all possible.
&lt;/em&gt;

&lt;!--more--&gt;
First, some screenshots:
&lt;p style='text-align: center'&gt;
&lt;a href=&quot;http://el-tramo.be/wordpress/wp-content/uploads/2011/05/twitcoop.png&quot;&gt;&lt;img src=&quot;http://el-tramo.be/wordpress/wp-content/uploads/2011/05/twitcoop.png&quot; alt=&quot;&quot; title=&quot;TwitCoop&quot; width=&quot;202&quot; height=&quot;492&quot; class=&quot;wp-image-1134&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://el-tramo.be/wordpress/wp-content/uploads/2011/05/twitcoop-menu.png&quot;&gt;&lt;img src=&quot;http://el-tramo.be/wordpress/wp-content/uploads/2011/05/twitcoop-menu.png&quot; alt=&quot;&quot; title=&quot;TwitCoop (Menu)&quot; width=&quot;202&quot; height=&quot;495&quot; class=&quot;wp-image-1135&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://el-tramo.be/wordpress/wp-content/uploads/2011/05/twitcoop-compact.png&quot;&gt;&lt;img src=&quot;http://el-tramo.be/wordpress/wp-content/uploads/2011/05/twitcoop-compact.png&quot; alt=&quot;&quot; title=&quot;TwitCoop (Compact)&quot; width=&quot;202&quot; height=&quot;494&quot; class=&quot;wp-image-1136&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;
Features of this desktop interface include: 

- Compact
- Provides an &quot;official&quot;, consistent Twitter interface
- Automatically refreshes when new tweets are available (with a higher refresh rate than the default mobile web interface)
- Opens external (i.e. non-Twitter) links in your preferred web browser
- Allows you to hide the Tweet box, when screen real estate is a problem (e.g. on netbooks)	
- Allows you to customize the zoom level
- Automatically logs you into your previous Twitter session on startup
- Supports &quot;kinetic scrolling&quot;
- Works on Windows and Linux

Note that some of these features may become obsolete once the &lt;a href=&quot;http://blog.twitter.com/2011/05/better-app-for-your-mobile-browser.html&quot;&gt;new mobile interface&lt;/a&gt; becomes available to everyone, and maybe some stuff will break, so I will need to update this then. The mobile web application isn't as responsive as a real native client, but this may change with the new mobile interface as well.

You can try it out for yourself by &lt;a href='/files/twitcoop/TwitCoop-win32.zip'&gt;downloading the Windows version&lt;/a&gt; (requires the &lt;a href=&quot;http://www.microsoft.com/downloads/en/details.aspx?familyid=9b2da534-3e03-4391-8a4d-074b9f2bc1bf&quot;&gt;Microsoft Visual C++ 2008 Redistributable&lt;/a&gt;, which may already be installed on your system), or by building it yourself from &lt;a href=&quot;/git/twitcoop&quot;&gt;the development repository&lt;/a&gt;.
</content>
  </entry>
  
  <entry>
    <title>Improving QtTest usability with QtTestUtil</title>
    <author>
      <name>Remko Tronçon</name>
      <uri>http://el-tramo.be/about/</uri>
    </author>
    <link href="http://el-tramo.be/blog/qttestutil"/>
    <updated>2008-11-06T00:00:00+01:00</updated>
    <id>http://el-tramo.be/blog/qttestutil</id>
    <content type="html">As much as I like &lt;a href=&quot;http://cppunit.sourceforge.net&quot;&gt;CppUnit&lt;/a&gt; for writing C++ unit tests, I still prefer using Qt's built-in &lt;a href=&quot;http://doc.trolltech.com/4.4/qttest.html&quot;&gt;QtTest&lt;/a&gt; module for Qt-based projects. This avoids a dependency on an external library, lowering the threshold for running and writing unit tests. Unfortunately, QtTest is very basic, and lacks some useful features such as automatic test registration and running multiple test suites in one test binary. In order to improve QtTest's usability, I started creating some macros and classes that fill in some of the gaps, and bundled them into &lt;a href=&quot;/git/qttestutil/snapshot/qttestutil-master.zip&quot;&gt;QtTestUtil&lt;/a&gt;.

&lt;!--more--&gt;
QtTest's recommended way to write unit tests is to compile and link one test suite per class separately, and using the &lt;code&gt;QTEST_MAIN&lt;/code&gt; macro to generate a &lt;code&gt;main()&lt;/code&gt; that runs this particular test suite. However, this introduces quite a bit of overhead in writing (creating a project file for every test/class), building (linking a binary for every test/class), and running (running a separate binary for every test/class, usually using a custom script) all unit tests. This overhead is especially painful in a project with many classes. All this conflicts with the general rule that both creating and running unit tests should be very efficient, and makes QtTest not well suited for unit testing as it is.

A first attempt at solving this problem is by manually creating a &lt;code&gt;main()&lt;/code&gt; function that runs all tests. For example:
&lt;blockquote&gt;
&lt;pre&gt;#include &quot;MyFirstTest.h&quot;
#include &quot;MySecondTest.h&quot;

int main(int argc, char* argv) {
  int result = 0;
  MyFirstTest test1;
  result |= QTest::qExec(&amp;amp;test1, argc, argv);
  MySecondTest test2;
  result |= QTest::qExec(&amp;amp;test2, argc, argv);
  return result;
}&lt;/pre&gt;
&lt;/blockquote&gt;
The resulting binary runs all listed test suites. The downside of this approach is that you have to write quite a bit of boilerplate code: every test binary needs to have its own &lt;code&gt;main()&lt;/code&gt; function that explicitly runs all the tests in that test suite, and which needs to be put in a file that has to include all the tests separately. In order remedy this, I took the idea from CppUnit to provide a macro which auto-registers a test suite, and makes it easy to run all registered test suites at once. Creating a test suite is now as simple as creating a &lt;code&gt;.cpp&lt;/code&gt; file for every unit test, adding a call to
&lt;code&gt;QTTESTUTIL_REGISTER_TEST&lt;/code&gt; to that file, and compiling that together with a shared &lt;code&gt;main()&lt;/code&gt; that does nothing but call &lt;code&gt;runTests()&lt;/code&gt; on the test registry. Since this &lt;code&gt;main()&lt;/code&gt; does not explicitly depend on any test, QtTestUtil comes with a &lt;a href=&quot;/git/qttestutil/tree/QtTestUtil/SimpleChecker.cpp&quot;&gt;&lt;code&gt;SimpleChecker.cpp&lt;/code&gt;&lt;/a&gt; containing this call, and which can be used by all unit test modules. As a result, no module needs to provide its own &lt;code&gt;main()&lt;/code&gt; anymore.

An example of a unit test module using the macro and the shared checker described above can be found in the &lt;a href=&quot;/git/qttestutil/tree/Example&quot;&gt;Example&lt;/a&gt; subdir of the &lt;a href=&quot;/git/qttestutil&quot;&gt;QtTestUtil repository&lt;/a&gt;. It is worth noticing that these QtTest-based unit tests are more compact than the same unit test written in CppUnit (because the latter requires you to call a macro for every test in a fixture).

This is just a first set of utilities that QtTestUtil provides on top of QtTest. More utility classes and macros will be added as they are needed.
</content>
  </entry>
  
  <entry>
    <title>Mixing Cocoa and Qt</title>
    <author>
      <name>Remko Tronçon</name>
      <uri>http://el-tramo.be/about/</uri>
    </author>
    <link href="http://el-tramo.be/blog/mixing-cocoa-and-qt"/>
    <updated>2008-08-16T00:00:00+02:00</updated>
    <id>http://el-tramo.be/blog/mixing-cocoa-and-qt</id>
    <content type="html">&lt;a href=&quot;http://trolltech.com/products/qt/index&quot;&gt;Qt&lt;/a&gt; does a great job at abstracting out platform-specific features into platform-independent C++ APIs. However, sometimes you still need to write platform-specific code for features that are not in Qt (e.g. to access the platform's address book),  or to access platform-specific applications (e.g. iTunes) or libraries (e.g. &lt;a href=&quot;http://sparkle.andymatuschak.org/&quot;&gt;Sparkle&lt;/a&gt;). On Mac OS X, almost all interfaces are offered through the &lt;a href=&quot;http://developer.apple.com/cocoa/&quot;&gt;Cocoa&lt;/a&gt; Objective-C interface, and the interfaces that are written in C++ have been deprecated and will disappear soon in favor of Cocoa. Although the language of Cocoa is different from Qt's, Qt and &lt;a href=&quot;http://gcc.gnu.org&quot;&gt;GCC&lt;/a&gt; make it very easy to call these interfaces from within your application. In this post, I will show how this can be done by making an auto-updating application using Sparkle.

&lt;!--more--&gt;

To create our auto-updating application, we first lay down the auto-updater interface in a (pure) virtual class:
&lt;blockquote&gt;
&lt;pre&gt;class AutoUpdater {
  public:
    virtual void checkForUpdates() = 0;
};&lt;/pre&gt;
&lt;/blockquote&gt;
The Sparkle implementation of this interface has the following C++ header:
&lt;blockquote&gt;
&lt;pre&gt;class SparkleAutoUpdater : public AutoUpdater {
  public:
    SparkleAutoUpdater(const QString&amp;amp; url);
    ~SparkleAutoUpdater();
    virtual void checkForUpdates();
  private:
    class Private;
    Private* d;
};&lt;/pre&gt;
&lt;/blockquote&gt;
Note that I am using the &lt;a href=&quot;http://c2.com/cgi/wiki?PimplIdiom&quot;&gt;Pimpl&lt;/a&gt; idiom to hide Cocoa-specific internals from the API into a private internal class.

The actual impementation of the &lt;code&gt;SparkleUpdater&lt;/code&gt; needs to call Sparkle's Objective-C API. However, we cannot write the implementation in Objective-C, since the header for our updater (which will be included from within our application) is written in C++. Luckily, GCC's Objective-C++ extension allows you to mix Objective-C with C++ without any problem. So, we create an Objective-C++ implementation of our updater, and put it in a &lt;code&gt;.mm&lt;/code&gt; file:
&lt;blockquote&gt;
&lt;pre&gt;class SparkleAutoUpdater::Private {
  public:
    SUUpdater* updater;
};

SparkleAutoUpdater::SparkleAutoUpdater(const QString&amp;amp; aUrl) {
  d = new Private;
  d-&amp;gt;updater = [[SUUpdater sharedUpdater] retain];
  NSURL* url = [NSURL URLWithString:
      [NSString stringWithUTF8String: aUrl.toUtf8().data()]];
  [d-&amp;gt;updater setFeedURL: url];
}

SparkleAutoUpdater::~SparkleAutoUpdater() {
  [d-&amp;gt;updater release];
  delete d;
}

void SparkleAutoUpdater::checkForUpdates() {
  [d-&amp;gt;updater checkForUpdatesInBackground];
}&lt;/pre&gt;
&lt;/blockquote&gt;
All we do here is create an &lt;code&gt;SUUpdater&lt;/code&gt; (Sparkle's updater class), set it up, and activate it in our &lt;code&gt;checkForUpdates()&lt;/code&gt; method.

To integrate Objective-C++ classes into a Qt project, &lt;code&gt;qmake&lt;/code&gt; provides the &lt;code&gt;OBJECTIVE_SOURCES&lt;/code&gt; variable. Knowing this, we add our new classes to our &lt;code&gt;qmake&lt;/code&gt; project file:
&lt;blockquote&gt;
&lt;pre&gt;HEADERS += AutoUpdater.h
SOURCES += AutoUpdater.cpp
mac {
  HEADERS += SparkleAutoUpdater.h
  OBJECTIVE_SOURCES += SparkleAutoUpdater.mm
  LIBS += -framework Sparkle
}&lt;/pre&gt;
&lt;/blockquote&gt;
Before we integrate the updater into our application, there is still one detail we have to take care of: if you write Objective-C code that creates objects, you need to instantiate an &lt;code&gt;NSAutoReleasePool&lt;/code&gt; to enable Cocoa's memory management. Although we could do this in &lt;code&gt;SparkleAutoUpdater&lt;/code&gt;, we're going to put this in a separate initializer class, so we can share this with other Objective-C++ implementations in our application. The body of this class looks as follows:
&lt;blockquote&gt;
&lt;pre&gt;class CocoaInitializer::Private {
  public:
    NSAutoreleasePool* autoReleasePool;
};

CocoaInitializer::CocoaInitializer() {
  d = new CocoaInitializer::Private();
  NSApplicationLoad();
  d-&amp;gt;autoReleasePool = [[NSAutoreleasePool alloc] init];
}

CocoaInitializer::~CocoaInitializer() {
  [d-&amp;gt;autoReleasePool release];
  delete d;
}&lt;/pre&gt;
&lt;/blockquote&gt;
Now all that's left to do is integrate all this into our application:
&lt;blockquote&gt;&lt;code&gt; &lt;/code&gt;
&lt;pre&gt;int main(int argc, char* argv[]) {
  ...
  AutoUpdater* updater = 0;
#ifdef Q_WS_MAC
  CocoaInitializer cocoaInitiarizer;
  updater = new SparkleUpdater(&quot;http://el-tramo.be/myapp/appcast.xml&quot;);
#endif
  ...
  if (updater) {
    updater-&amp;gt;checkForUpdates();
  }
  ...
}&lt;/pre&gt;
&lt;/blockquote&gt;
That's it! If you want to try this out yourself, just download the &lt;a href=&quot;http://el-tramo.be/files/blog/mixing-cocoa-and-qt/mixing-cocoa-and-qt.zip&quot;&gt;sources&lt;/a&gt; of this mini-project, build them, and off you go. Don't forget to remove &lt;code&gt;~/Library/Preferences/be.el-tramo.mixing-cocoa-and-qt.plist&lt;/code&gt; to clear Sparkle's state cache.
</content>
  </entry>
  
</feed>

