QxtSignalWaiter

From qtnode

Jump to: navigation, search


Please note that this is outdated and not maintained. For a maintained version, please see [1]

In many cases, writing code that assumes certain actions are synchronous is considerably simpler than breaking your function into multiple blocks and using signals and slots to connect them all. Using this class, QxtSignalWaiter::wait will block until a certain signal is emitted and then return. The return value is true if the signal was caught, or false if a user-specified timeout elapses before catching the signal.

Contents

Header File qxtsignalwaiter.h

#ifndef QXTSIGNALWAITER_H
#define QXTSIGNALWAITER_H

#include <QObject>
class QTimerEvent;

class QxtSignalWaiter : public QObject {
Q_OBJECT
public:
    QxtSignalWaiter(const QObject* sender, const char* signal);
    static bool wait(const QObject* sender, const char* signal, int msec = -1);
    bool wait(int msec = -1);
protected:
    void timerEvent(QTimerEvent* event);
private slots:
    void signalCaught();
private:
    bool ready, timeout;
    int timerID;
};

#endif

Source File qxtsignalwaiter.cpp

#include "qxtsignalwaiter.h"
#include <QCoreApplication>
#include <QTimerEvent>

QxtSignalWaiter::QxtSignalWaiter(const QObject* sender, const char* signal) : QObject(0) {
    Q_ASSERT(sender && signal);
    connect(sender, signal, this, SLOT(signalCaught()));
}   
    
// Returns true if the signal was caught, returns false if the wait timed out
bool QxtSignalWaiter::wait(const QObject* sender, const char* signal, int msec) {
    QxtSignalWaiter w(sender, signal);
    return w.wait(msec);
}

// Returns true if the signal was caught, returns false if the wait timed out
bool QxtSignalWaiter::wait(int msec) {
    // Check input parameters
    if(msec < -1) return false;
    
    // activate the timeout
    if(msec != -1) timerID = startTimer(msec);
 
    // Begin waiting   
    ready = timeout = false;
    while(!ready && !timeout)
        QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
 
    // Clean up and return status
    killTimer(timerID);
    return ready || !timeout;
}

void QxtSignalWaiter::signalCaught() {
    ready = true;
}

void QxtSignalWaiter::timerEvent(QTimerEvent* event) {
    killTimer(timerID);
    timeout = true;
}

Documentation

QxtSignalWaiter(const QObject* sender, const char* signal)

Creates a QxtSignalWaiter that will wait for the specified signal from the specified sender.

bool wait(int msec = -1)

Waits for the signal sender::signal to be emitted. If msec is not -1, wait() will return after msec milliseconds.

If a signal is not specified, the default signal specified in the constructor is used instead. If no default signal was specified in the constructor, wait() will block until the timeout has elapsed. If no timeout was specified, wait() will return immediately.

Returns true if the signal was caught, false if it timed out.

This function is not reentrant.

static bool wait(const QObject* sender, const char* signal, int msec = -1)

This is an overloaded member function, provided for convenience.

Waits for the specified signal from the specified sender to be emitted. If msec is not -1, wait() will return after msec milliseconds.

This function is equivalent to creating a QxtSignalWaiter object for the specified sender and signal and calling wait(msec) on it.

Example Usage

void MyObject::myFunction() {
    QxtSignalWaiter waiter(myOtherObject, SIGNAL(longProcessFinished()));
    myOtherObject->longProcess();
    if(waiter.wait(5000))
        doSomething(myOtherObject->information());
    else
        QMessageBox::information(0, "MyObject", "Timed out while waiting on longProcessFinished()", QMessageBox::Ok);
}

Caveat

QxtSignalWaiter is, sadly, not reentrant. In particular, only one QxtSignalWaiter object can be safely waiting at a time. If a second QxtSignalWaiter is used while the first is waiting, the first will not return until the second has timed out or successfully caught its signal. A later revision of the class may be able to solve this problem. Until then, be careful not to rely on two QxtSignalWaiter objects at the same time.

Licensing

QxtSignalWaiter is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2 or greater, or under the terms of the GNU Lesser General Public License, version 2.1 or greater, or under the terms of the Q Public License as published by Trolltech.

This disjunctive license follows the license of the linked Qt toolkit. Specifically, if you use Qt under the GPL, QxtSignalWaiter is licensed to you under the GPL. If you use Qt under the QPL, this is licensed to you under the QPL. If you use Qt with a commercial license purchased from Trolltech, this is licensed to you under the LGPL.

QxtSignalWaiter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the appropriate license agreement for more details.

Personal tools