Saturday, February 16, 2013

qt-signal-tools - Pre-packaged slot calls and connecting signals to arbitrary functions in Qt 4

A useful new feature in Qt 5 is the ability to connect signals to arbitrary functions instead of just Qt signals/slots/properties, including C++11 lambdas.  As this page on the Qt Project wiki explains, this is especially useful when writing code to perform async operations where you often want to pass additional context to the slot.

I've written a small library for Qt 4 which provides similar functionality. The library includes:
  • QtCallback - A pre-canned QObject method call. QtCallback stores an object, a slot to call and optionally a list of pre-bound arguments to pass to the slot. This is useful if you need to pass additional context to the slot, other than the values provided by the signal.
  • QtSignalForwarder::connect() - Connects signals from QObjects to arbitrary functions or methods or QtCallbacks. You can use this together with bind() and function<> to pass additional arguments to the method other than those provided by the signal or re-arrange arguments. You can think of this as a more flexible alternative to the QSignalMapper class that Qt 4 provides. There are also a couple of utility features:
    • QtSignalForwarder::delayedCall() - A more flexible alternative to QTimer::singleShot() which can be used to invoke an arbitrary function after a set delay.
    • Event connections - Invoke an arbitrary function or QtCallback when an object receives a particular type of event. This is useful when the object does not have a built-in signal that is emitted in response to that event and requires less boilerplate than using QObject::installEventFilter()
  • safe_bind() - A downside of connecting a signal to a function object is that the signal does not automatically disconnect if the receiver is destroyed. safe_bind() creates a wrapper around a (QObject*, function) pair which when called, invokes the function if the object still exists or does nothing and returns a default value if the object has been destroyed. You can use this together with QtSignalForwarder to connect a signal to an arbitrary method on a QObject which effectively 'disconnects' when the receiver is destroyed.
For example usage, please see the README, the examples and the tests. The code is available from github.com/robertknight/qt-signal-tools.  The requirements are:
  • Qt 4.8
  • A compiler with the TR1 standard library extensions (most C++ compilers from the past few years - including MSVC >= 2008 and GCC 4.x. I have tested with MSVC 2010 and recent GCC/Clang versions) or one which supports equivalent features from the C++11 standard library.
Compared to the implementation in Qt 5, there are a few disadvantages:
  • Argument type checking happens at runtime when QtSignalForwarder::connect() is called, similar to standard QObject signal-slot connections. QObject::connect() in Qt 5 can do type checking at compile time.
  • In order to do the runtime type checking, the types of arguments passed from the signal to the function or method must be registered using Q_DECLARE_METATYPE() or qRegisterMetaType()
  • Using QtSignalForwarder does have additional overhead since a hidden proxy object is created to route the signal and arguments to the target function. I investigated using a single proxy object for all forwarded signals or a pool of proxies. Unfortunately it turns out that the QObject::sender() and QObject::senderSignalIndex() functions which are used internally have a cost that is linear in the number of connections.
Please let me know if you find this useful. If there is any other related functionality which you'd like to see, please let me know in the comments.

Monday, August 27, 2012

qt-mustache Templating Library

I had a need for a templating library for use with several Qt projects.  I was looking preferably for something simple that is easy to drop into a project and has a familiar syntax.  Existing libraries that I found included Grantlee (a featureful library using Django template syntax), Qustache and QCTemplate (a thin wrapper around Google's CTemplate library for logic-free templates which inspired Mustache).  None of these were quite what I was looking for, so I wrote a small library which uses the popular Mustache template syntax.

Example Usage:
#include "mustache.h"

QVariantHash contact;
contact["name"] = "John Smith";
contact["email"] = "john.smith@gmail.com";

QString contactTemplate = "<b>{{name}}</b> <a href=\"mailto:{{email}}\">{{email}}</a>";

Mustache::Renderer renderer;
Mustache::QtVariantContext context(contact);

QTextStream output(stdout);
output << renderer.render(contactTemplate, &context);
Outputs:
 <b>John Smith</b> <a href="mailto:john.smith@gmail.com">john.smith@gmail.com</a>
The main feature, like Mustache itself, is that it doesn't have that many features.  The lack of logic constructs in templates prevents application logic from ending up in the templates themselves. Other 'features' are:

  • Lightweight.  Two source files.  The only dependency is QtCore.
  • Efficient.
  • Complete 'mustache' syntax support (values, sections, inverted sections, partials, lambdas, escaping). I may look at incorporating one or two facilities from Handlebars in future.
  • The standard data source is a QVariantMap or QVariantHash.  There is an interface if you wish to provide your own - eg. if you wanted to use a QAbstractItemModel as the data structure to fill in a template.
  • Partial templates can be specified as an in-memory map or .mustache files in a directory.  You can also provide your own loader if you want to be able to fetch partial templates from a different source.

The code is available from github (BSD license): https://github.com/robertknight/qt-mustache

Thursday, July 21, 2011

Qt Inspector

Whilst debugging a widget layout problem a few days ago, I was looking around for a tool to view the structure of a Qt application without having to recompile it, or in other words, Firebug / Web Inspector for Qt widgets.  I found the KSpy tool in the KDE repositories which is in need of some love and there are a variety of tools to aid in runtime debugging and modification of QML but not much in the way of tools for QWidget-based interfaces.  Please let me know in the comments if I missed any.

I have put together a simple tool called Qt Inspector.

Qt Inspector starts a specified application or connects to an existing Qt application and once connected can:
  • Browse the object tree of Qt applications.
  • View properties of objects
  • Edit properties of objects
  • Locate a widget in the object tree by clicking on it in the application
  • Copy a reference to an object for use in a debugger (eg. to manipulate it by calling methods on it, examine member fields, setup conditional breakpoints)
Here is a screenshot of Qt Inspector connected to Dolphin showing the widget tree for the settings dialog. Like the Web Inspector or Firebug, this can be used to tweak styling settings, layouts and other properties without a recompile.



Usage:

Qt Inspector can either attach to an existing application or launch
a specified application and then attach to it.

From a terminal, this can be done with:

qtinspector [process ID]
qtinspector [program name] [args]

Design:

Qt Inspector operates by injecting a helper library into the target process using gdb.  This helper library sets up a local socket and listens for requests from the inspector process. The inspector and target process communicate via protocol buffer messages over this socket.

The inspector uses Qt's meta-object system to fetch the properties of an object and read/write their values, so properties need to be declared with Q_PROPERTY for them to be visible to the inspector.

Source:

The code is up on GitHub.  Please download it and give it a whirl.  Happy forking :) 

Update:  Eva Brucherseifer let me know about the Basyskom Inspector tool in Gitorious.  In addition to being able to select and inspect widgets it can also view signals and slots, application resources and take screenshots. 

Monday, April 12, 2010

We're hiring Qt developers

I'm currently working for Mendeley, a startup based in London. We're building software for organising, reading, annotating and collaborating on research papers (mostly in PDF format) which integrates with an online network for researchers. We're currently looking for developers to join the team working on our Qt-based desktop application for Windows, Mac and Linux.

Essential skills are:


  • Knowledge of C++ and experience debugging, testing and profiling C++ applications.

  • Experience with Qt. If you're the kind of person who likes delving into the internals of Qt that's even better.

  • Solid computer science basics.

Knowledge of any of the following would be particularly useful:


  • Model/view frameworks (especially Qt's implementation). An interest in or experience with some of the upcoming Qt technologies (eg. Qt Quick) would also be a plus.

  • Databases (in particular, SQLite)

  • Search/indexing frameworks (eg. Lucene)

  • Scripting languages (eg. Python, Ruby)

  • Version control (SVN, git).

  • Automated testing tools (eg. QtTest).

  • Knowledge of platform-specific APIs such as Cocoa on Mac*.

Involvement with open source projects is a big plus. Dog fooding your own software is always helpful, so if you have a background in research or even just like reading papers to find out how things work, that would also be useful.

If you're interested, please get in touch.


* Though Qt abstracts away most platform details, there are times when using native APIs is necessary.

Friday, May 8, 2009

Konsole under Jaunty

As noted in several places, some applications feel somewhat sluggish in Ubuntu Jaunty compared with Intrepid if your system has an Intel graphics card.

There isn't a great solution for X in general yet - some options involving X.org tweaks and replacement X packages are discussed here

Applications which render a lot of text seem to be affected quite a bit. For Qt applications there is a simple workaround, in Konsole the workaround makes tab-switching much more snappy. Start Konsole with the raster graphics mode:

konsole -graphicssystem raster

This also works wonders on the Mendeley Desktop research management software which I work on.

Sunday, August 17, 2008

Konsole scrolling weirdness

Some users are experiencing weird visual glitches when scrolling in Konsole. The problem isn't trivial to debug but until it gets fixed there are a couple of workarounds:
  • Un-hide the menu bar if it is hidden
  • Set the QT_USE_NATIVE_WINDOWS environment variable to '1' before starting Konsole (export QT_USE_NATIVE_WINDOWS=1)

Saturday, June 7, 2008

Slow on NVidia?

If you have an NVidia graphics card and Konsole in trunk seems very slow in a composited desktop (eg. KWin 'desktop effects' or compiz are enabled) then start Konsole with the --notransparency option. Intel/ATI are not affected.

I do not know the cause of the problem, I'll post an update when I find out.