Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

emit SIGNAL when GUI Thread is idle in Qt?

Tags:

c++

qt

I have GUI Thread which creates & manages the GUI content. Now when the application is idle i.e. all threads are idle (or even if only the GUI thread is idle) then I want my QMainWindow inherited class's object to emit a SIGNAL. So that whenever the Application is idle I will silently create the Widgets required for the next stage. So I would like to know how do I make that object to emit a SIGNAL whenever the GUI Thread is idle? My Application is multi-threaded & has multiple classes, so it is not necessary that the SIGNAL is emitted in the GUI class only. Also the SIGNAL should not be emitted as soon as the thread becomes idle. I want that the thread should be idle for a sufficient amount of time so that I am sure that the user is actually idling. Thank You!

like image 828
Cool_Coder Avatar asked Feb 15 '13 10:02

Cool_Coder


1 Answers

QAbstractEventDispatcher allows one to plug their own events into Qt's event loop. Also it allows to monitor event loop's workload.

Here is an example. The widget is listening for QAbstractEventDispatcher::awake() and QAbstractEventDispatcher::aboutToBlock() signals to know when event loop is busy.

#include <QtGui>

class IdleAwareWidget : public QWidget
{
    Q_OBJECT

public:
    IdleAwareWidget(QWidget *parent = 0) : QWidget(parent) {
        dispatcher = QAbstractEventDispatcher::instance();
        connect(dispatcher, SIGNAL(awake()), SLOT(awake()));
        connect(dispatcher, SIGNAL(aboutToBlock()), SLOT(aboutToBlock()));
    }

private slots:
    void awake() {
        lastAwake = QTime::currentTime();
        qDebug() << "Slept for " << lastBlock.msecsTo(lastAwake) << " msec";
    }

    void aboutToBlock() {
        lastBlock = QTime::currentTime();
        qDebug() << "Worked for " << lastAwake.msecsTo(lastBlock) << " msec";
    }

private:
    QAbstractEventDispatcher *dispatcher;
    QTime lastAwake;
    QTime lastBlock;
};

main.cpp:

#include <QtGui>

#include "idle_widget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    IdleWidget widget;
    widget.show();

    return a.exec();
}

If the question is just about idle processing, then QTimer with 0 interval is an option:

QTimer::singleShot(0, this, SLOT(doWorkInIdle()));

This will schedule call to doWorkInIdle() slot as soon as the event loop goes to idle state. Splitting work to small chucks won't block the loop and application will remain responsive.

like image 181
divanov Avatar answered Oct 10 '22 17:10

divanov