diff -r 0f9f7d6564cd -r 23354fc917f4 src/relpipe-out-gui.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/relpipe-out-gui.cpp Sat Dec 01 23:22:41 2018 +0100 @@ -0,0 +1,111 @@ +/** + * Relational pipes + * Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info) + * + * This program 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, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "RelpipeChartMainWindow.h" +#include "QtRelationalReaderStringHadler.h" + +using namespace relpipe::cli; +using namespace relpipe::reader; + +// signal/slot parameters must be declared here and registered with qRegisterMetaType() + +Q_DECLARE_METATYPE(string_t) +Q_DECLARE_METATYPE(std::vector) + +class RelationalReaderThread : public QThread { +private: + std::shared_ptr reader; +public: + + // TODO: better background thread; lambda? + + RelationalReaderThread(std::shared_ptr reader) : + reader(reader) { + setTerminationEnabled(true); + } + + void run() { + try { + reader->process(); + } catch (RelpipeReaderException& e) { + // TODO: handle exception, show error dialog + std::wcerr << L"RelpipeReaderException: " << e.getMessge() << std::endl; + } + } +}; + +int main(int argc, char**argv) { + CLI cli(argc, argv); + // TODO: argument name collisions? Filter arguments? Use prefix for Qt? Qt: -title, -style, -geometry + QApplication app(argc, argv); + + std::shared_ptr reader(Factory::create(std::cin)); + int resultCode = CLI::EXIT_CODE_UNEXPECTED_ERROR; + + RelpipeChartMainWindow window; + window.show(); + + RelationalReaderThread t(reader); + + // Proxy that passes calls from the background thread to the GUI thread using signal-slot mechanism: + QtRelationalReaderStringHadler handler(&t); // &t instead of handler.moveToThread(&t); // QObject::moveToThread: Cannot move objects with a parent + + // see Q_DECLARE_METATYPE above + qRegisterMetaType(); + qRegisterMetaType> (); + + QObject::connect(&handler, &QtRelationalReaderStringHadler::startRelationReceived, &window, &RelpipeChartMainWindow::startRelation, Qt::ConnectionType::QueuedConnection); + QObject::connect(&handler, &QtRelationalReaderStringHadler::attributeReceived, &window, &RelpipeChartMainWindow::attribute, Qt::ConnectionType::QueuedConnection); + QObject::connect(&handler, &QtRelationalReaderStringHadler::endOfPipeReceived, &window, &RelpipeChartMainWindow::endOfPipe, Qt::ConnectionType::QueuedConnection); + + reader->addHandler(&handler); + + // Start background thread + t.start(); + + int qtResultCode = app.exec(); + + if (qtResultCode == 0) { + resultCode = CLI::EXIT_CODE_SUCCESS; + } else { + // TODO: report and log Qt errors if any + } + + if (t.isRunning()) { + std::wcerr << L"Background RelationalReader thread is still running → terminate()" << std::endl; + t.terminate(); + std::wcerr << L"Background RelationalReader thread was terminated → wait()" << std::endl; + t.wait(); + std::wcerr << L"Background RelationalReader thread wait() finished" << std::endl; + } + + return resultCode; +}