background thread for STDIN reading + proxy with signals/slots for passing data to the GUI thread v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sat, 29 Sep 2018 00:43:16 +0200
branchv_0
changeset 13 c84042d014c9
parent 12 a45d1cac365e
child 14 0a6a88e4e48f
background thread for STDIN reading + proxy with signals/slots for passing data to the GUI thread
nbproject/configurations.xml
src/CMakeLists.txt
src/QtRelationalReaderStringHadler.h
src/RelpipeChartMainWindow.cpp
src/RelpipeChartMainWindow.h
src/relpipe-out-chart.cpp
--- a/nbproject/configurations.xml	Fri Sep 28 13:23:21 2018 +0200
+++ b/nbproject/configurations.xml	Sat Sep 29 00:43:16 2018 +0200
@@ -60,6 +60,7 @@
                    projectFiles="true"
                    root="build/Debug/src/relpipe-out-chart_autogen">
       <logicalFolder name="EWIEGA46WW" displayName="EWIEGA46WW" projectFiles="true">
+        <itemPath>build/Debug/src/relpipe-out-chart_autogen/EWIEGA46WW/moc_QtRelationalReaderStringHadler.cpp</itemPath>
         <itemPath>build/Debug/src/relpipe-out-chart_autogen/EWIEGA46WW/moc_RelpipeChartMainWindow.cpp</itemPath>
       </logicalFolder>
       <logicalFolder name="include" displayName="include" projectFiles="true">
@@ -90,9 +91,6 @@
       </toolsSet>
       <flagsDictionary>
         <element flagsID="0" commonFlags="-fsanitize=address -fPIC -std=gnu++11"/>
-        <element flagsID="1"
-                 commonFlags="-mtune=generic -march=x86-64 -std=gnu++11 -fsanitize=address -fPIC -fstack-protector-strong"/>
-        <element flagsID="2" commonFlags="-std=c++14"/>
       </flagsDictionary>
       <codeAssistance>
       </codeAssistance>
@@ -102,6 +100,27 @@
           <buildCommand>${MAKE} -f Makefile</buildCommand>
           <cleanCommand>${MAKE} -f Makefile clean</cleanCommand>
           <executablePath>build/Debug/src/relpipe-out-chart</executablePath>
+          <ccTool>
+            <incDir>
+              <pElem>build/Debug/src</pElem>
+              <pElem>src</pElem>
+              <pElem>build/Debug/src/relpipe-out-chart_autogen/include</pElem>
+              <pElem>../relpipe-lib-reader.cpp/include</pElem>
+              <pElem>../relpipe-lib-cli.cpp/include</pElem>
+              <pElem>/usr/include/x86_64-linux-gnu/qt5</pElem>
+              <pElem>/usr/include/x86_64-linux-gnu/qt5/QtWidgets</pElem>
+              <pElem>/usr/include/x86_64-linux-gnu/qt5/QtGui</pElem>
+              <pElem>/usr/include/x86_64-linux-gnu/qt5/QtCore</pElem>
+              <pElem>/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++</pElem>
+              <pElem>/usr/include/x86_64-linux-gnu/qt5/QtCharts</pElem>
+            </incDir>
+            <preprocessorList>
+              <Elem>QT_CHARTS_LIB</Elem>
+              <Elem>QT_CORE_LIB</Elem>
+              <Elem>QT_GUI_LIB</Elem>
+              <Elem>QT_WIDGETS_LIB</Elem>
+            </preprocessorList>
+          </ccTool>
         </makeTool>
         <preBuild>
           <preBuildCommandWorkingDir>build/Debug</preBuildCommandWorkingDir>
@@ -113,8 +132,11 @@
             ex="false"
             tool="1"
             flavor2="11">
-        <ccTool flags="2">
-        </ccTool>
+      </item>
+      <item path="build/Debug/src/relpipe-out-chart_autogen/EWIEGA46WW/moc_QtRelationalReaderStringHadler.cpp"
+            ex="true"
+            tool="3"
+            flavor2="0">
       </item>
       <item path="build/Debug/src/relpipe-out-chart_autogen/EWIEGA46WW/moc_RelpipeChartMainWindow.cpp"
             ex="true"
@@ -125,87 +147,22 @@
             ex="false"
             tool="1"
             flavor2="8">
-        <ccTool flags="1">
+        <ccTool flags="0">
         </ccTool>
       </item>
       <folder path="Modules">
         <ccTool>
           <incDir>
-            <pElem>build/Debug/src</pElem>
-            <pElem>src</pElem>
-            <pElem>build/Debug/src/relpipe-out-chart_autogen/include</pElem>
-            <pElem>../relpipe-lib-reader.cpp/include</pElem>
-            <pElem>../relpipe-lib-cli.cpp/include</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtWidgets</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtGui</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtCore</pElem>
-            <pElem>/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtCharts</pElem>
             <pElem>/usr/include</pElem>
           </incDir>
-          <preprocessorList>
-            <Elem>QT_CHARTS_LIB</Elem>
-            <Elem>QT_CORE_LIB</Elem>
-            <Elem>QT_GUI_LIB</Elem>
-            <Elem>QT_WIDGETS_LIB</Elem>
-          </preprocessorList>
-        </ccTool>
-      </folder>
-      <folder path="relpipe-out-chart_autogen">
-        <ccTool>
-          <incDir>
-            <pElem>build/Debug/src/relpipe-out-chart_autogen/EWIEGA46WW</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtCore</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtGui</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtWidgets</pElem>
-            <pElem>build/Debug/src/relpipe-out-chart_autogen/include</pElem>
-            <pElem>src</pElem>
-            <pElem>build/Debug/src/relpipe-out-chart_autogen</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5</pElem>
-            <pElem>build/Debug/src</pElem>
-          </incDir>
         </ccTool>
       </folder>
       <item path="src/RelpipeChartMainWindow.cpp" ex="false" tool="1" flavor2="8">
         <ccTool flags="0">
-          <incDir>
-            <pElem>build/Debug/src</pElem>
-            <pElem>src</pElem>
-            <pElem>build/Debug/src/relpipe-out-chart_autogen/include</pElem>
-            <pElem>../relpipe-lib-reader.cpp/include</pElem>
-            <pElem>../relpipe-lib-cli.cpp/include</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtWidgets</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtGui</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtCore</pElem>
-            <pElem>/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtCharts</pElem>
-          </incDir>
-          <preprocessorList>
-            <Elem>QT_CHARTS_LIB</Elem>
-            <Elem>QT_CORE_LIB</Elem>
-            <Elem>QT_GUI_LIB</Elem>
-            <Elem>QT_WIDGETS_LIB</Elem>
-          </preprocessorList>
         </ccTool>
       </item>
       <item path="src/relpipe-out-chart.cpp" ex="false" tool="1" flavor2="8">
-        <ccTool flags="1">
-          <incDir>
-            <pElem>../relpipe-lib-cli.cpp/include/relpipe/cli</pElem>
-            <pElem>src</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtCore</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtGui</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5/QtWidgets</pElem>
-            <pElem>../relpipe-lib-reader.cpp/include/relpipe/reader</pElem>
-            <pElem>../relpipe-lib-reader.cpp/include/relpipe/reader/handlers</pElem>
-            <pElem>build/Debug/src/relpipe-out-chart_autogen/include</pElem>
-            <pElem>../relpipe-lib-cli.cpp/include</pElem>
-            <pElem>../relpipe-lib-reader.cpp/include</pElem>
-            <pElem>/usr/include/x86_64-linux-gnu/qt5</pElem>
-            <pElem>build/Debug/src</pElem>
-          </incDir>
+        <ccTool flags="0">
         </ccTool>
       </item>
     </conf>
--- a/src/CMakeLists.txt	Fri Sep 28 13:23:21 2018 +0200
+++ b/src/CMakeLists.txt	Sat Sep 29 00:43:16 2018 +0200
@@ -21,6 +21,7 @@
 # Executable output:
 add_executable(
 	${EXECUTABLE_FILE}
+	QtRelationalReaderStringHadler.h # QObjects must be listed here (including them from other files is not enough)
 	RelpipeChartMainWindow.ui
 	RelpipeChartMainWindow.cpp
 	relpipe-out-chart.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/QtRelationalReaderStringHadler.h	Sat Sep 29 00:43:16 2018 +0200
@@ -0,0 +1,70 @@
+#pragma once
+
+#include <QObject>
+
+#include <relpipe/reader/typedefs.h>
+#include <relpipe/reader/TypeId.h>
+#include <relpipe/reader/handlers/RelationalReaderStringHandler.h>
+#include <relpipe/reader/handlers/AttributeMetadata.h>
+
+using namespace relpipe::reader;
+using namespace relpipe::reader::handlers;
+
+// signal/slot parameters must be declared here and registered with qRegisterMetaType()
+
+Q_DECLARE_METATYPE(string_t)
+Q_DECLARE_METATYPE(std::vector<AttributeMetadata>)
+
+class QtRelationalReaderStringHadler : public QObject, public RelationalReaderStringHadler {
+	Q_OBJECT
+private:
+	RelationalReaderStringHadler* target;
+public:
+
+	QtRelationalReaderStringHadler(QObject* parent, RelationalReaderStringHadler* target) :
+	QObject(parent), target(target) {
+
+		// see Q_DECLARE_METATYPE above
+		qRegisterMetaType<string_t>();
+		qRegisterMetaType<std::vector < AttributeMetadata >> ();
+
+		QObject::connect(this, &QtRelationalReaderStringHadler::signal_startRelation, this, &QtRelationalReaderStringHadler::slot_startRelation);
+		QObject::connect(this, &QtRelationalReaderStringHadler::signal_attribute, this, &QtRelationalReaderStringHadler::slot_attribute);
+		QObject::connect(this, &QtRelationalReaderStringHadler::signal_endOfPipe, this, &QtRelationalReaderStringHadler::slot_endOfPipe);
+	}
+
+	virtual ~QtRelationalReaderStringHadler() {
+
+	}
+
+	virtual void startRelation(string_t name, std::vector<AttributeMetadata> attributes) override {
+		emit signal_startRelation(name, attributes);
+	}
+
+	virtual void attribute(const string_t& value) override {
+		emit signal_attribute(value);
+	};
+
+	virtual void endOfPipe() override {
+		emit signal_endOfPipe();
+	};
+
+signals:
+	void signal_startRelation(string_t name, std::vector<AttributeMetadata> attributes);
+	void signal_attribute(const string_t& value);
+	void signal_endOfPipe();
+
+private slots:
+
+	void slot_startRelation(string_t name, std::vector<AttributeMetadata> attributes) {
+		target->startRelation(name, attributes);
+	};
+
+	void slot_attribute(const string_t& value) {
+		target->attribute(value);
+	};
+
+	void slot_endOfPipe() {
+		target->endOfPipe();
+	};
+};
--- a/src/RelpipeChartMainWindow.cpp	Fri Sep 28 13:23:21 2018 +0200
+++ b/src/RelpipeChartMainWindow.cpp	Sat Sep 29 00:43:16 2018 +0200
@@ -6,20 +6,25 @@
 
 #include "RelpipeChartMainWindow.h"
 
+using namespace relpipe::reader;
+using namespace relpipe::reader::handlers;
+
 RelpipeChartMainWindow::RelpipeChartMainWindow() {
 	widget.setupUi(this);
 
-	QTabWidget* tabs = new QTabWidget(this);
+	tabs->addTab(new QPushButton("here will be options", tabs), "Options");
+
+	statusBar()->addWidget(new QLabel("Loading relations...", widget.statusbar));
+
 
-	for (int i = 0; i < 5; i++) {
-		QSplitter* splitter = new QSplitter(Qt::Orientation::Vertical, tabs);
-		splitter->addWidget(new QPushButton("here will be the chart", splitter));
-		splitter->addWidget(new QPushButton("here will be the table", splitter));
-		tabs->addTab(splitter, "relation_name");
-	}
-
-	//statusBar()->addWidget(new QPushButton("xxx", widget.statusbar));
-	statusBar()->addWidget(new QLabel("Loading relations...", widget.statusbar));
+	// TODO: remove; just demo
+	QPushButton* emitButton = new QPushButton("emit", widget.statusbar);
+	statusBar()->addWidget(emitButton);
+	QObject::connect(
+			emitButton, &QPushButton::pressed,
+			this, &RelpipeChartMainWindow::slot123
+			);
+	// ---
 
 	setCentralWidget(tabs);
 
@@ -27,3 +32,25 @@
 
 RelpipeChartMainWindow::~RelpipeChartMainWindow() {
 }
+
+void RelpipeChartMainWindow::slot123() {
+	// TODO: remove; just demo
+	statusBar()->addWidget(new QPushButton("slot123", widget.statusbar));
+}
+
+void RelpipeChartMainWindow::startRelation(string_t name, std::vector<AttributeMetadata> attributes) {
+	// TODO: chart and table
+	QSplitter* splitter = new QSplitter(Qt::Orientation::Vertical, tabs);
+	splitter->addWidget(new QPushButton("here will be the chart", splitter));
+	splitter->addWidget(new QPushButton("here will be the table", splitter));
+	tabs->addTab(splitter, QString::fromWCharArray(name.c_str()));
+}
+
+void RelpipeChartMainWindow::attribute(const string_t& value) {
+	// TODO: fill table and draw chart
+}
+
+void RelpipeChartMainWindow::endOfPipe() {
+	// TODO: just display a message
+	statusBar()->addWidget(new QPushButton("endOfPipe", widget.statusbar));
+}
--- a/src/RelpipeChartMainWindow.h	Fri Sep 28 13:23:21 2018 +0200
+++ b/src/RelpipeChartMainWindow.h	Sat Sep 29 00:43:16 2018 +0200
@@ -2,11 +2,27 @@
 
 #include "ui_RelpipeChartMainWindow.h"
 
-class RelpipeChartMainWindow : public QMainWindow {
+#include <relpipe/reader/typedefs.h>
+#include <relpipe/reader/TypeId.h>
+#include <relpipe/reader/handlers/RelationalReaderStringHandler.h>
+#include <relpipe/reader/handlers/AttributeMetadata.h>
+
+using namespace relpipe::reader;
+using namespace relpipe::reader::handlers;
+
+class RelpipeChartMainWindow : public QMainWindow, public RelationalReaderStringHadler {
 	Q_OBJECT
 public:
 	RelpipeChartMainWindow();
 	virtual ~RelpipeChartMainWindow();
+	virtual void startRelation(string_t name, std::vector<AttributeMetadata> attributes) override;
+	virtual void attribute(const string_t& value) override;
+	virtual void endOfPipe() override;
 private:
 	Ui::RelpipeChartMainWindow widget;
+	QTabWidget* tabs = new QTabWidget(this);
+public slots:
+	void slot123();
+signals:
+	void signal123();
 };
--- a/src/relpipe-out-chart.cpp	Fri Sep 28 13:23:21 2018 +0200
+++ b/src/relpipe-out-chart.cpp	Sat Sep 29 00:43:16 2018 +0200
@@ -1,6 +1,7 @@
 #include <iostream>
 
 #include <QApplication>
+#include <QThread>
 
 #include <relpipe/cli/CLI.h>
 #include <relpipe/cli/RelpipeCLIException.h>
@@ -9,24 +10,60 @@
 #include <relpipe/reader/RelpipeReaderException.h>
 
 #include "RelpipeChartMainWindow.h"
+#include "QtRelationalReaderStringHadler.h"
 
 using namespace relpipe::cli;
 using namespace relpipe::reader;
 
+class WorkerThread : public QThread {
+private:
+	std::shared_ptr<RelationalReader> reader;
+public:
+
+	// TODO: better background thread; lambda?
+
+	WorkerThread(std::shared_ptr<RelationalReader> reader) :
+	reader(reader) {
+	}
+
+	void run() {
+		try {
+			reader->process();
+		} catch (RelpipeReaderException& e) {
+			// TODO: handle exception, show error dialog
+		}
+	}
+};
+
 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::cout << "TODO: relpipe-out-chart..." << std::endl;
-	
+
 	std::shared_ptr<RelationalReader> reader(Factory::create(std::cin));
 
+
 	int resultCode = CLI::EXIT_CODE_UNEXPECTED_ERROR;
-	
+
 	RelpipeChartMainWindow window;
+
+	// TODO: remove; just demo
+	QObject::connect(&window, &RelpipeChartMainWindow::signal123, &window, &RelpipeChartMainWindow::slot123);
+
 	window.show();
-	
+
+	QtRelationalReaderStringHadler handler(&app, &window);
+	reader->addHandler(&handler);
+
+	// Start background thread
+	WorkerThread t(reader);
+	t.start();
+	// ---
+
+	// window.signal123();
+
 	app.exec();
 	//return app.exec();