--- /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 <http://www.gnu.org/licenses/>.
+ */
+#include <sys/prctl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <iostream>
+
+#include <QApplication>
+#include <QThread>
+
+#include <relpipe/cli/CLI.h>
+#include <relpipe/cli/RelpipeCLIException.h>
+#include <relpipe/reader/Factory.h>
+#include <relpipe/reader/RelationalReader.h>
+#include <relpipe/reader/RelpipeReaderException.h>
+
+#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<AttributeMetadata>)
+
+class RelationalReaderThread : public QThread {
+private:
+ std::shared_ptr<RelationalReader> reader;
+public:
+
+ // TODO: better background thread; lambda?
+
+ RelationalReaderThread(std::shared_ptr<RelationalReader> 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<RelationalReader> 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<string_t>();
+ qRegisterMetaType<std::vector < AttributeMetadata >> ();
+
+ 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;
+}