Using c++-gtk-utils with Qt

As mentioned under GTK versions, this library can be compiled without GTK, so that the only dependency is glib. This might be useful if this library is only intended to be used by programs employing some other toolkit (or not using a GUI at all).

From version 4.2, Qt by default uses glib to provide its main loop event dispatching. That means that if Qt has been compiled with this default option, the functions and objects in this library interfacing with the glib main loop (Cgu::Callback::post(), Cgu::Notifier, Cgu::Thread::Future::when(), Cgu::Thread::TaskManager::make_task_when(), Cgu::Thread::TaskManager::make_task_when_full(), Cgu::Thread::TaskManager::make_task_compose(), Cgu::start_timeout(), Cgu::start_timeout_seconds() and Cgu::start_iowatch()) can be called in Qt programs so as to execute their callbacks in the Qt main loop.

Qt is a nice library but has a number of warts. One of those is its use of unprefixed lower-case macros, and in particular its macro definition of 'emit'. This will cause programs which directly or indirectly use this library's emitter classes to fail to compile.

To avoid this, the symbol QT_NO_EMIT can be defined before including any Qt header files in a source file that uses c++-gtk-utils (or it can be passed using the -D compiler flag). This has the effect of suppressing the 'emit' macro. Qt never requires the 'emit' macro to be used anyway when invoking a Qt signal (its macro defines to nothing), and it is there only for documentation purposes. If such documentation is seen as useful, the Q_EMIT macro can be used instead of emit.

Alternatively, the line:

CONFIG += no_keywords

can be added to the program's project (.pro) file. However this causes more far-reaching macro suppressions (required by, for example, boost). If that option is taken, as well as not using 'emit' (or using Q_EMIT instead), programs must use the macros Q_SIGNALS (or Q_SIGNAL) and Q_SLOTS (or Q_SLOT) instead of the 'signals' and 'slots' macros.

Here is a compilable example which uses Qt and c++-gtk-utils to find the meaning of life, the universe and everything:

#include <iostream>
#include <ostream>
#include <string>
#include <time.h>
#define QT_NO_EMIT
#include <QApplication>
#include <glib.h>
#include <c++-gtk-utils/task_manager.h>
#include <c++-gtk-utils/callback.h>
using namespace Cgu;
int main(int argc, char *argv[]) {
g_thread_init(0); // if glib < 2.32 is used
QApplication app{argc, argv};
Thread::TaskManager tm{2};
// execute a callback in the Qt main loop
Callback::post([]() {std::cout << "Finding the answer to the Ultimate Question of "
"Life, the Universe, and Everything\n";});
// execute a task and report the result in the Qt main loop
tm.make_task_when(
[&app] (const std::string& res) {
std::cout << res << std::endl;
app.exit();
},
0, // Qt main loop
[] () -> std::string {
// pretend this is compute intensive!
timespec ts = {0, 100000000};
nanosleep(&ts, 0);
return "The answer is 42";
}
);
app.exec();
}
Cgu
Definition: application.h:44
callback.h
This file provides classes for type erasure.
task_manager.h
Cgu::Callback::post
void post(const Callback *cb, gint priority=G_PRIORITY_DEFAULT_IDLE, GMainContext *context=0)
Cgu::Thread::TaskManager
A thread-pool class for managing tasks in multi-threaded programs.
Definition: task_manager.h:502