tags:

views:

435

answers:

4

Qt is a nice framework and great UI toolkit and it has many useful features and concepts. Most of us probably agree that Trolltech, lately Nokia, have done pretty nice job developing it. One of the latest advances in Qt is QML, which I find fascinating advancement.

However, I find some of the concepts badly designed or badly implemented, such as Model/View (the concept is fine, but implementation is not) and same goes for Phonon media framework. Some people say its the meta-object concept that drives them crazy.

All of this are obviously more or less subjective, but what features or concepts do you find annoying or burdensome to use in Qt and how do you circumvent around them?

+7  A: 

This is an odd SO question.

But I will offer my feeling that qmake is long in the tooth (and I'm not the only one to say so):

http://labs.trolltech.com/blogs/2009/10/14/to-make-or-not-to-make-qmake-and-beyond-redux/

The meta-object preprocessing build step for signals/slots/etc. is a huge buy-in. And many who'd be willing to accept the added level of abstraction are the sorts of people who'd be attracted to other environments (Java, C#, whatever-the-hey). On the other side of the fence are the hardcore C++ programmers who would rather work with boost::thread instead of QThread. (If a C++ program is more server-oriented and has no GUI, people seem to avoid Qt, and I see their point.)

The model/view is neither here nor there, but it's kind of trivial. I've criticized issues of thread affinity:

http://lists.trolltech.com/pipermail/qt-interest/2009-August/011043.html

Also, I've cross-compiled apps to Mac and Windows and Linux, and found Qt doesn't protect me from platform issues as much I might've wished. What do you expect with per-platform source forks like this:

http://qt.gitorious.org/+qt-developers/qt/releases/blobs/4.7.0/src/gui/kernel/qdnd_x11.cpp

http://qt.gitorious.org/+qt-developers/qt/releases/blobs/4.7.0/src/gui/kernel/qdnd_win.cpp

http://qt.gitorious.org/+qt-developers/qt/releases/blobs/4.7.0/src/gui/kernel/qdnd_mac.mm

Is there any hope that you'll actually write one body of code and have it act the same on all these platforms? Nope.

But all criticisms aside, I do like Qt's design, documentation, community support, and general aesthetic. You could do a lot worse! (I'm looking at you, wxWidgets and GTK.)

Hostile Fork
You sometimes find valuable information this way: people hate/are annoyed by something and they circumvent it by doing the same thing in another, possibly better possibly worse, way. I also like Qt, so this isn't bashy question :)
Tuminoid
+1  A: 

The problem I tried to solve is general for Qt, wxWidgets and possibly other UI frameworks:

void MainDialog::OnCppException()
{
    throw std::runtime_error("test unhandled exception");
}

Such unhandled C++ exception is caught by Qt framework, preventing immediate exception debugging or generating informative crash dump. In the place where Qt allows to handle this situation, original exception information and stack trace are lost. I tried to fight with this problem in both frameworks, and didn't find acceptable solution. The advice from Qt professionals "Just don't do this" is all I have, this actually means: don't make bugs, and everything will be OK. This was my greatest disappointment from Qt and wxWidjets.

Alex Farber
A: 

I'm working mostly on Qt for S60 environment, so some of the issues are specific for that platform.

Plugin system + QObjects

You cannot declare plugin interface with signals, because the plugin implementations are supposed to derive from QObject and multiple interfaces, so the interface shouldn't be QObject itself (required if you want some signals in your interface). The workaround I found on Qt-interest mailing list is adding a MyQObject* getter to your plugin interface and adding all signals to concrete MyQObject class. It works, but it's counterintuitive and ugly.

QSet and other Qt containers are less versatile than stl or boost containers

For example you can't define less function that should be used when inserting elements into QSet. Other stuff I miss is remove_if and find_if.

QServiceFramework in QtMobility package

Ridiculous library I was recently forced to use. To use a "service" installed in QServiceFramework you either have to link to dll which contains that service (which is quite pointless, considering that one of the QSf goals is to hide dependencies) or use QMetaObject::invokeMethod that doesn't provide compile-time checking of methods, argument types, etc. and reduces code readability:

// using QMetaObject::invokeMethod
QVariantHash data;
bool ok = QMetaObject::invokeMethod(myObject, "getStuff", 
    Q_RETURN_ARG(QVariantHash, data)
    Q_ARG(QString, QString("blah")));
Q_ASSERT(ok);

// using normal syntax
QVariantHash data(myObject->getStuff("blah"));

To make things worse, it uses file system quite a lot (iterating dirs looking for plugins, communication with SQLite database), which is a slow operation on S60.

QPixmap requires QApplication...

...and only QPixmap have methods for conversion between native S60 images (CFbsBitmap class) and Qt data. So you either have to make your app an QApplication (which increases startup times and memory consumption) or you have to store the data in native S60 structures (which makes the whole code Symbian specific)

chalup
Most Qt containers are compatible with the STL algorithms, so you can always call remove_if and find_if on them.
Etienne de Martel
Interesting, I didn't know about that. Thanks!
chalup
You can declare pure virtual signals in the plugin interface.
andref
+8  A: 

Most of my gripes with Qt come from the fact that the API does not fully embrace the dynamism provided by QObject. If you dared to create a meta-object compiler to add dynamic behavior to C++, why be shy about it, then?

All the stuff I list below are things my team needed at some point and we had to code it ourselves. It was a lot of fun and we learned a lot about the Qt internals, but I wouldn't mind if it was already done and ready to use.

No Distributed QObject

You know, like in Cocoa. They went half way with QtDBus -- the only thing left to do is the networking. We had to implement our own solution for this, and since we live outside the Qt code, we cannot change internals to implement all nice features.

No API for data storage

And of course everyone writes their own incomplete QObject-to-SQLite library. QDataStream is a very good beginning, though.

No Data Binding

Well, Qt Quick has data binding, but data binding should live in QtCore. With decent data binding, writing QAbstractItemModels that represent collections of QObjects should be a thing of the past: QObjectListModel should be all you need.

(Yeah, QDataWidgetMapper is a joke.)

No Automatic Undo Management for QObjects

Our model classes are usually QObjects and Q_PROPERTY has an optional NOTIFY signal that is exactly what is needed to implement automatic undo. It's so easy to do it should already be part of Qt. (It requires a few kludges, however.)

No Collection Properties

Not all properties are born equal. Some of them are collections. Being able to deal with those in an abstract way would be definitely a good thing.

Half-baked QMetaStuff API

And I only hate this API because I love it. For instance, one cannot:

  1. build QMetaObjects dynamically and replace them;
  2. call a meta-method using a QVariants as arguments;
  3. query methods by return type, name, or argument types;
  4. connect signals and slots using the respective QMetaMethods (at least not until 4.8);
  5. intercept property set/get in the same way you can intercept events, for instance.

Almost all of those can be worked around easily. A solution for #2:

QVariant call(QObject* object, QMetaMethod metaMethod, QVariantList args)
{
    QList<QGenericArgument> arguments;

    for (int i = 0; i < argumentList.size(); i++) {

        // Notice that we have to take a reference to the argument. A 
        // const_cast is needed because calling data() would detach 
        // the QVariant.

        QVariant& argument = args[i];

        QGenericArgument genericArgument(
            QMetaType::typeName(argument.userType()),
            const_cast<void*>(argument.constData())
        );

        arguments << genericArgument;
    }

    QVariant returnValue(QMetaType::type(metaMethod.typeName()), 
        static_cast<void*>(NULL));

    QGenericReturnArgument returnArgument(
        metaMethod.typeName(),
        const_cast<void*>(returnValue.constData())
    );

    // Perform the call

    bool ok = metaMethod.invoke(
        object,
        Qt::AutoConnection, // In case the object is in another thread.
        returnArgument,
        arguments.value(0),
        arguments.value(1),
        arguments.value(2),
        arguments.value(3),
        arguments.value(4),
        arguments.value(5),
        arguments.value(6),
        arguments.value(7),
        arguments.value(8),
        arguments.value(9)
    );

    if (!ok) {
        // Handle the error...
    } else {
        return returnValue;
    }
}

Useful features will probably be removed

There is talk in qt-interest that the DOM, style sheets, and custom file engines will be removed in a future version of Qt.

Phonon has no cross-platform back-end

Besides not really working all the time, Phonon has no stable back-end that works on the three most common platforms: Windows, Linux and Mac OS X. There is a VLC back-end, but it's definitely not stable, its licensing is unclear and, moreover, VLC support for Mac is "resting on shaky ground". The blame is entirely on Linux, of course. Multimedia support has never been one of its strengths. It lacks something like Quicktime or the DirectStuff.

No Crypto Classes

There is QCryptographicHash and QSSLSocket (and its funny error modes), and that's it. Fortunately, there are two good libraries to fill this gap: Botan and QCA. QCA is based on Qt, but copies its API from the Java crypto classes so, not very good. Botan has a nifty interface and (but?) is "pure" C++. A Qt-style crypto library is still lacking.

andref
+1: this is exactly what I'm looking for, great answer.
Tuminoid
+1: Thorough answer that reveals your deep knowledge of Qt.
Wolfgang Plaschg