0

Just a quick question. I'm developing a QT Console application. Now, I'd like to run it until the user presses any key (or, if it is easier, until the enter key is pressed).

The application has a running event queue (or better two, one for the "main", the other for the data parser).

Here is a mock up of the relevant part of the code:

main.cpp

#include <QCoreApplication>
#include <QTimer>
#include "mainprogram.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QCoreApplication::setApplicationVersion("1.0");

    MainProgram mainProg(&a);
    QTimer::singleShot(0, &mainProg, SLOT(executeMain()));

    return a.exec();
}

mainprogram.h

#ifndef MAINPROGRAM_H
#define MAINPROGRAM_H

#include <QObject>
#include <QThread>
#include "datasourceparser.h"

class MainProgram : public QObject
{
    Q_OBJECT
public:
    explicit MainProgram(QObject *parent = 0);
    ~MainProgram();

public slots:
    void executeMain();
    void terminateProgram(int resultCode);

private:
    DataSourceParser *dataParser;
    QThread dataParserThread;
};

#endif // MAINPROGRAM_H

mainprogram.cpp

#include "mainprogram.h"
#include <QCoreApplication>

MainProgram::MainProgram(QObject *parent) : QObject(parent)
{

}

MainProgram::~MainProgram() {
    dataParserThread.quit();
    dataParserThread.wait();
}

void MainProgram::executeMain()
{
    dataParser = new DataSourceParser();
    dataParser->moveToThread(&dataParserThread);

    QObject::connect(&dataParserThread, SIGNAL(started()), dataParser, SLOT(execute()));
    QObject::connect(&dataParserThread, SIGNAL(finished()), dataParser, SLOT(deleteLater()));

    dataParserThread.start();

}

void MainProgram::terminateProgram(int resultCode)
{
    QCoreApplication::exit(resultCode);
}

Now, the DataSourceParser does all the elaboration. If something fails, it clls the MainProgram::terminateProgram slot to properly exit, and everything works.

Now, I need something which calls that slot when the user presses a key (or just enter, if easier).

This solution should be cross platform (or, at least, Windows and Linux x86/x64)

And, most important, it should NOT block the main thread events queue (so a readline inside the executeMain() function is not feasible).

Thank you

EDIT:

As Karsten Koop, I tried to add the QSocketNotifier implementation found here: I copied the header and source file content (just replaced the #pragma once with the usual #ifndef CONSOLEREADER_H etc). Then, before the call to dataParser->moveToThread(&dataParserThread);, I added

ConsoleReader *cr = new ConsoleReader(this);
QSignalMapper *signalMapper = new QSignalMapper(this);
QObject::connect(cr, SIGNAL(textReceived(QString)), signalMapper, SLOT(map()));
signalMapper->setMapping(cr, 1);
this->connect(signalMapper, SIGNAL(mapped(int)), SLOT(terminateProgram(int)));

However the text slot is never called..

Community
  • 1
  • 1
frarugi87
  • 2,826
  • 1
  • 20
  • 41
  • This is a drive by kudos on both correctly using `QThread` and on the single shot timer idea to push a slot into the event queue at startup. The `QTimer` solution is something I will mercilessly take and use in my own code. Thanks. – jonspaceharper Jun 17 '16 at 11:56
  • 1
    @JonHarper Thank you ;) In fact, that is a solution I found on the internet quite a while ago, at the beginning of my "Qt era"... So it's just something I've been using for quite a lot of time, not my own idea :P – frarugi87 Jun 17 '16 at 12:04
  • 1
    @JonHarper You don't really need a `QTimer::singleShot` for that. You can use [`QMetaObject::invokeMethod`](http://doc.qt.io/qt-5/qmetaobject.html#invokeMethod) with a queued connection. That is what happens [internally](https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qtimer.cpp.html#_ZN6QTimer10singleShotEiN2Qt9TimerTypeEPK7QObjectPKc). – thuga Jun 17 '16 at 12:11
  • 1
    [Here](http://stackoverflow.com/questions/6878507/using-qsocketnotifier-to-select-on-a-char-device/7389622#7389622) someone says you can use `QSocketNotifier` with stdin, but this might only work on Linux – Karsten Koop Jun 17 '16 at 12:20
  • @KarstenKoop Thank you for your help. Unluckily I tried to implement it, as written in the edit, but I didn't succeed. Did I do something wrong? – frarugi87 Jun 17 '16 at 13:01
  • 1
    There is no cross-platform solution. On Unices, you'd use a `QSocketNotifier`, on Windows you need a `QWinEventNotifier` - the console handle gets signaled when there's data available to read. – Kuba hasn't forgotten Monica Jun 17 '16 at 16:41

0 Answers0