MeJ
MeJ

Reputation: 1108

Qt (4.8.2) GUI - Own main loop instead of QApplication::exec()

I would like to ask, if it is possible to use a custom main loop instead of running a.exec():

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Window r;
    r.showFullScreen();
    return a.exec(); 
}

something like:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Window r;
    r.showFullScreen();

    while(a.processOneEvent()) {
        read_event_from_legacy_system
    }

    return 0; 
}

In GTK I could use gtk_main_iteration_do() so I thought there is maybe something similar in Qt?

Or is there any other correct way to read custom events from a specific legacy system?

EDIT: The events which a read from the FIFOs are not system events (such as X11) they are just a struct which is sent via a FIFO to realize ipc.

Upvotes: 3

Views: 2198

Answers (3)

So you want to react on a FIFO -or pipe- file descriptor (on Linux) using Qt

With Qt5 you would probably use QAbstractSocket or QIoDevice and its readyRead signal

With Qt4 you should use QSocketNotifier and its activated signal (so call your read_event_from_legacy_system from a Qt slot connected to that signal). It can poll any file descriptor, including a fifo(7)

There is no need to change the application's event loop (even if in theory you might subclass QApplication but I don't recommend doing that). Once you set up correctly your thing, Qt event loop will poll the additional file descriptor, and your code should read it.

Upvotes: 4

MeJ
MeJ

Reputation: 1108

I have come up with following solution:

PipeReader.hpp

#ifndef PIPEREADER_HPP
#define PIPEREADER_HPP

#include <QObject>
#include <QSocketNotifier>

class PipeReader : public QObject
{
    Q_OBJECT
public:
    PipeReader(int fd, QObject *parent = 0);
    ~PipeReader();
private:
    QSocketNotifier *notifier;
    int m_fd;
signals:
    void dataReceived();
private slots:
    void readFromFd();
};

#endif  /* PIPEREADER_HPP */

PipeReader.cpp

#include <PipeReader.hpp>
#include <QObject>

PipeReader::PipeReader(int fd, QObject *parent)
: QObject(parent), notifier(NULL), m_fd(fd)
{
    notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
    QObject::connect(notifier, SIGNAL(activated(int)), this, SLOT(readFromFd()));
}

PipeReader::~PipeReader()
{

}

void PipeReader::readFromFd()
{
    qDebug("readFromFd");
    int ret_val = read(m_fd, &event, sizeof(Event), 10);

    emit dataReceived();
}

main.cpp

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

    if ((fd = open(SPECIAL_FD, O_RDONLY | O_SYNC)) < 0) {
        exit(0);
    }

    PipeReader reader(fd);

    w.showFullScreen();
    return a.exec();
}

I get all events read from a specific file descriptor. If you want to use the events in MyWindow just connect the signal dataReceived() with a public slot of MyWindow.

Upvotes: 1

nh_
nh_

Reputation: 2241

Although this might not be the best solution for your problem, you can write your own main loop like this:

QApplication app(argc, argv);
QMainWindow wnd;

wnd.show();

while(wnd.isVisible())
{
    app.processEvents();

    // perform your own actions here
}

Instead of wnd.isVisible() you can of course use your own breaking condition.

Upvotes: 1

Related Questions