I won't argue that Qt is a fine toolkit in its own right, it's easy to use and can deliver high quality user interfaces. However, there are a few bits of misinformation on this thread I feel compelled to correct.
>"C++ has RTTI built in, GObject/GType does the same thing but is really ugly"
C++'s built-in RTTI is next to useless for the purposes of a GUI toolkit -- all it can really do is tell you if two objects are of the same (run time) type. It can't even return you the class name of an object in a platform-consistent way! Something like GtkInspector would be impossible without extra information which C++ can't natively provide. That's why Qt uses the whole metaobject system, which isn't really all that different to what GType does behind the scenes.
As it is, Qt adds some new keywords to C++ (`slot` and `signal` for example), which get replaced by macros by moc, which in turn get replaced by function calls by the preprocessor. GType instead gives you the macros directly. If you want something which hides away all this horrible code like moc does, then there is a very versatile GObject compiler by the name of Vala...
>"GObject signals are inefficient and not typesafe [compared with a template-based compile-time system like Boost.Signal]"
This is true as far as it goes. But until Qt5 added template-based connections as an option, Qt's signals were also entirely handled at run-time, and for a long time there was a page on the Qt website arguing why this was a superior approach.
As to type safety, it's true that in C it's basically up to the programmer to get this right. But for my money
g_signal_connnect(object, "signal", G_CALLBACK(callback), closure);
is a lot easier to get right first time than
signal.connect(sigc::bind(sigc::mem_fun(object, &Klass:func), closure));
and $DEITY help you with the error messages if you get that wrong. (Picking on sigc++ because I know it better than Boost.Signals, but the point stands. Yes, C++11 lambdas and variadic templates make this nicer, but support for C++11 isn't universal yet.)
FWIW, in Cocoa you get no help from the compiler if you send the wrong message to `id`, either...
>"GObjects are hard to subclass [in C]"
Yup. Doing so requires lots of boilerplate, and it's really pretty ugly. However, this is only true for C; with any language binding, subclassing a GObject is the same as subclassing a native object. Part of the reason for the complexity of the multi-stage GObject construction/destruction sequence is to support this (though I won't argue it could be simplified).
This also ignores the fact that in many cases subclassing isn't needed as often with GTK as it is with other toolkits. For example, one approach to drawing custom content would have been to make GtkDrawingArea an abstract base class and require you to implement the `draw` virtual function. You can still do this if you want, but an easier way to do the same thing in GTK is to just create a DrawingArea and then connect to the "draw" signal.
>"Implementing signals in GTK requires you to use horrible Makefile magic to generate the marshallers"
Until a couple of years ago this was true, but GObject can now (optionally) use libffi to do marshalling at run-time. Use g_cclosure_marshal_generic in your signal definition and it Just Works.
All of this discussion also ignores what is, for my money, the biggest strength of GTK nowadays -- that it is, for better or worse, the "Gnome Toolkit". The latest developments like GtkHeaderBar and GtkListBox (and indeed GtkInspector) have been directly driven by the needs of the Gnome designers. You might well disagree with the designers' tastes, but this strong coupling between the graphical environment and the toolkit used to implement it is a good thing, in my opinion -- and in fact, is exactly the approach used by Android, iOS, Mac OS, Windows, etc etc...
Copyright © 2018, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds