Archive for the ‘Uncategorized’ Category

The Ada Initiative

17th February 2011

LWN has an interesting article on a new startup: The Ada Initiative (“Supporting women in open technology and culture”), and about how it is taking a different approach to similar initiatives.

The link above is to an article on the LWN that is subscriber-only for the next week.  Being a subscriber, I can provide a link that you can use – if you are interested in what’s happening in Linux, and FOSS in general, I highly recommend subscribing.

There is also other press coverage.

Also, I would suggest that the founders do Ada Lovelace a disservice in calling her “the world’s first woman open source programmer” – she is arguably the world’s first programmer, full stop.

The Magic of QtDBus, and the PropertyChanged signal

7th September 2010

I’ve had reason recently to delve into the inner workings of QtDBus.  It does more for programmers than I (and probably many of you) realised.

For example, when you tell qdbusxml2cpp to generate a proxy for you, it creates a subclass of QDBusAbstractInterface, and populates it with properties, signals and slots that correspond to the D-Bus properties, methods and slots.  But there’s more going on under the hood than it seems.  In particular, all those annotations for input and output types are used for more than just simple casting of QVariants.

Consider, for example, what happens when you fetch the value of a property of D-Bus type a{sv}.  This is a map from strings to variants.  The natural representation in Qt is a QVariantMap, but it could just as easily be in a QHash<QString, QVariant>, or even something based on std::map.  Qt doesn’t know.  So you can put an annotation in your D-Bus interface specifications, indicating what type it should be represented as:

<annotation name="com.trolltech.QtDBus.QtTypeName" value="QVariantMap"/>

OK, so what does qdbusxml2cpp do with this information?  Well, in this case, we’re annotating a property.  qdbusxml2cpp will produce the following code in the proxy class:

Q_PROPERTY(QVariantMap Foo READ foo)
inline QVariantMap foo() const
{ return qvariant_cast< QVariantMap >(property("Foo")); }

As you can see, it casts a property (which is a QVariant) to a QVariantMap.  But that surely demands that the QVariant already contains a QVariantMap and not, say, a QHash<QString,QVariant>?  Well, there’s some magic in QDBusAbstractInterface to deal with this for you.

Basically, when you request a property (QObject::property()), QDBusAbstractInterface requests it over D-Bus.  If it’s something simple, like a string (D-Bus type s), it gets demarshalled automagically in the internals of QtDBus, giving you a QString in this example.  But if it’s something more complex, like the above a{sv} type, QDBusAbstractInterface looks up the type information in Qt’s meta-object system, and uses that to demarshall it into the correct type – if the property type is QVariantMap, it will be demarshalled into a QVariantMap.

A similar trick is done for signals (note that if you get the signal signature wrong, you will simply never receive the signal).  Sidenote: if you add a QDBusMessage parameter as the last parameter of the slot you connect to a D-Bus signal, you’ll get a copy of the signal message.  You can even just have the QDBusMessage parameter, although you’ll be creating more work for yourself.

So, this is all very nice, but why am I telling you about stuff that “just works”?  Well, you have to watch out for the times when it doesn’t “just work”.  I’ll illustrate just such a case with an implementation of the PropertyChanged signal.

The PropertiesChanged signal is a recent addition to the org.freedesktop.DBus.Properties interface in the D-Bus specification that allows you to receive notifications when a property value changes.  It’s rather new and hasn’t even made it into the released version of the spec yet.  However, it will be supported by the next version of GIO.  Hopefully, it will be supported in a not-too-distant release of Qt (4.8?), but in the meantime you can quite easily add support yourself.

The signal looks like

org.freedesktop.DBus.Properties.PropertiesChanged (
    STRING interface_name,
    DICT<STRING,VARIANT> changed_properties,
    ARRAY<STRING> invalidated_properties);

where changed_properties is a dictionary containing the changed properties with the new values and invalidated_properties is an array of properties that changed but the value is not conveyed.

Now, on the server side, you can’t support it “properly”, because the introspection for the org.freedesktop.DBus.Properties interface is fixed by QtDBus, but you can emit the signal yourself anyway:

QDBusMessage signal = QDBusMessage::createSignal(
 "/object/path",
 "org.freedesktop.DBus.Properties",
 "PropertiesChanged");
signal << "org.foo.MyInterface";

QVariantMap changedProps;
changedProps.insert("somestringprop", "newstringvalue");
changedProps.insert("someintprop", 4);
changedProps.insert("somemapprop", newmapvalue);
signal << changedProps;

QStringList invalidatedProps;
invalidatedProps << "invprop1" << "invprop2";
signal << invalidatedProps;

QDBusConnection::sessionBus().send(signal);

Easy as pie, right?  You can even have a helper method that does this:

void notifyPropertyChanged( const QString& interface,
                            const QString& propertyName )
{
    QDBusMessage signal = QDBusMessage::createSignal(
        "/object/path",
        "org.freedesktop.DBus.Properties",
        "PropertiesChanged");
    signal << interface;
    QVariantMap changedProps;
    changedProps.insert(propertyName, property(propertyName));
    signal << changedProps;
    signal << QStringList();
    QDBusConnection::sessionBus().send(signal);
}

On the client side, things are slightly more complex.  My approach is to insert a class into the proxy code heirachy.  While qdbusxml2cpp produces subclasses of QDBusAbstractInterface, I modify these to inherit a class of my own (DBusAbstractInterface) that in turn inherits QDBusAbstractInterface.  This class has all the magic needed to deal with the PropertiesChanged signal.

Essentially, it connects to the PropertiesChanged signal using QDBusConnection::connect(), and forwards this to any listeners.  So far, so simple.  But what happens if we have a property with D-Bus type a{si} (a map from strings to integers)?  Then the changed_properties map will contain an entry mapping the property name to an a{si} value.  How does QtDBus know how to demarshall this?

Well, the fact is, it doesn’t.  QtDBus will demarshall the changed_properties map into a QVariantMap (or whatever appropriate type the second argument of the slot has), but it can’t demarshall any complex types that are values in that map.  Do you want your a{si} map as a QMap or a QHash?  QtDBus doesn’t know, and so puts off the demarshalling by inserting a QDBusArgument value into the map.

If you know what structure you’re expecting here, you can just demarshall it with something like

QMap<QString,int> map;
changed_properties.value("foo").value<QDBusArgument>() >> map;

My helper class does something roughly similar to what QtDBus does internally, and uses the meta type system to figure out how it should demarshall the values in changed_properties.  But just remember that if you have a complex structure passed over D-Bus as a variant (D-Bus type v) and received in your code as a QVariant, the chances are it’ll be in the form of a QDBusArgument, and you’ll have to demarshall it yourself.

The Party of Gno

18th June 2010

I came across an interesting blog post about the FSF’s strategy on LWN, and thought it was worth sharing.

The essential argument is that the FSF does too much preaching about what people shouldn’t do, without offering constructive alternatives.

Fancier-than-fancy

16th March 2009

I discovered a new option in KMail for displaying email headers today.  I’m not sure how long it’s been there, but you can now select “Enterprise Headers” for your emails:

KMail with Enterprise Headers

KMail with Enterprise Headers

I quite like it, apart from the fact that you can’t have variable-width text in the header and fixed-width text in the body of the email.

Spamalot

13th March 2008

I went to see Spamalot last night in London.  It was an amazing show, happily sending up everything, especially itself.  I would happily go and see it again.  And again.  And again.

Nina Söderquist made a fantastic Lady of the Lake, the petulant diva of the show (well, along with Lancelot…).  Steven Kynman (Historian, Not Dead Fred, lead Minstrel and Prince Herbert) was also excellent, as was Andrew Spillett, who played Patsy (King Arthur’s “horse”).  Alan Dale, who played King Arthur, was a little wooden.  He was fine, but didn’t blow me away.

A special mention has to go to Ian Waller (“Swing”, which I think means dancers), who was the only person to write his biography in the spirit of the show (it starts “Ian started dancing at 7 but by 8.45 was back in bed thinking up a new career”).  Everyone else is far to serious.

The programme also contains a joke based on the subtitles of the original film.  Buy it and find out…

You Won’t Succeed In Broadway (If You Haven’t Any Jews)  was, I’m sure, a hilarious statement about musical theatre in New York.  However, it doesn’t translate very well to the West End of London.  It’s still a good song, but the joke isn’t that funny.

That said, I had an excellent time (right in front of the stage, on row A in the stalls!).  Go and see it!


Follow

Get every new post delivered to your Inbox.