@@ -63,7 +63,7 include_directories( | |||
|
63 | 63 | ${PYSIDE_INCLUDE_DIR}/QtGui |
|
64 | 64 | ${PYSIDE_INCLUDE_DIR}/QtWidgets) |
|
65 | 65 | |
|
66 | add_library(SciQLopBindings MODULE ${BINDINGS_SOURCE} numpy_wrappers.h) | |
|
66 | add_library(SciQLopBindings MODULE ${BINDINGS_SOURCE} numpy_wrappers.h PyDataProvider.h) | |
|
67 | 67 | set_target_properties( |
|
68 | 68 | SciQLopBindings |
|
69 | 69 | PROPERTIES |
@@ -1,16 +1,89 | |||
|
1 | 1 | #pragma once |
|
2 | #include <Data/DataProviderParameters.h> | |
|
2 | 3 | #include <Data/IDataProvider.h> |
|
4 | #include <DataSource/DataSourceController.h> | |
|
5 | #include <DataSource/DataSourceItem.h> | |
|
6 | #include <DataSource/DataSourceItemAction.h> | |
|
7 | #include <QPair> | |
|
8 | #include <SqpApplication.h> | |
|
9 | // must be included last because of Python/Qt definition of slots | |
|
10 | #include "numpy_wrappers.h" | |
|
11 | ||
|
12 | struct Product | |
|
13 | { | |
|
14 | QString path; | |
|
15 | std::vector<std::string> components; | |
|
16 | QMap<QString, QString> metadata; | |
|
17 | Product() = default; | |
|
18 | explicit Product(const QString& path, const std::vector<std::string>& components, | |
|
19 | const QMap<QString, QString>& metadata) | |
|
20 | : path { path }, components { components }, metadata { metadata } | |
|
21 | { | |
|
22 | } | |
|
23 | virtual ~Product() = default; | |
|
24 | }; | |
|
3 | 25 | |
|
4 | 26 | class PyDataProvider : public IDataProvider |
|
5 | 27 | { |
|
6 | 28 | public: |
|
7 |
PyDataProvider() |
|
|
29 | PyDataProvider() | |
|
30 | { | |
|
31 | auto& dataSourceController = sqpApp->dataSourceController(); | |
|
32 | dataSourceController.registerProvider(this); | |
|
33 | } | |
|
34 | ||
|
35 | virtual ~PyDataProvider() {} | |
|
8 | 36 | |
|
9 | virtual TimeSeries::ITimeSerie getData(const std::string& key, double start_time, double stop_time) | |
|
10 | {} | |
|
37 | virtual QPair<NpArray, NpArray> getData( | |
|
38 | const std::string& key, double start_time, double stop_time) | |
|
39 | { | |
|
40 | (void)key, (void)start_time, (void)stop_time; | |
|
41 | return {}; | |
|
42 | } | |
|
11 | 43 | |
|
12 | virtual TimeSeries::ITimeSerie* getData(const DataProviderParameters& parameters) | |
|
44 | virtual TimeSeries::ITimeSerie* getData(const DataProviderParameters& parameters) override | |
|
13 | 45 | { |
|
46 | if (parameters.m_Data.contains("name")) | |
|
47 | { | |
|
48 | auto data = getData(parameters.m_Data["name"].toString().toStdString(), | |
|
49 | parameters.m_Range.m_TStart, parameters.m_Range.m_TEnd); | |
|
50 | // TODO add shape/type switch | |
|
51 | return new ScalarTimeSerie { data.first.to_std_vect(), data.second.to_std_vect() }; | |
|
52 | } | |
|
14 | 53 | return nullptr; |
|
15 | 54 | } |
|
55 | ||
|
56 | ||
|
57 | inline void register_products(const QVector<Product*>& products) | |
|
58 | { | |
|
59 | auto& dataSourceController = sqpApp->dataSourceController(); | |
|
60 | auto id = this->id(); | |
|
61 | auto data_source_name = this->name(); | |
|
62 | std::for_each(std::cbegin(products), std::cend(products), | |
|
63 | [&id, &dataSourceController](const Product* product) { | |
|
64 | dataSourceController.setDataSourceItem(id, product->path, product->metadata); | |
|
65 | }); | |
|
66 | } | |
|
16 | 67 | }; |
|
68 | ||
|
69 | ||
|
70 | struct Providers | |
|
71 | { | |
|
72 | Providers() = default; | |
|
73 | virtual ~Providers() = default; | |
|
74 | inline void register_provider(PyDataProvider* provider) | |
|
75 | { | |
|
76 | auto& dataSourceController = sqpApp->dataSourceController(); | |
|
77 | dataSourceController.setDataProvider( | |
|
78 | provider->id(), std::unique_ptr<IDataProvider>(provider)); | |
|
79 | } | |
|
80 | }; | |
|
81 | ||
|
82 | ||
|
83 | inline ScalarTimeSerie test_PyDataProvider(PyDataProvider& prov) | |
|
84 | { | |
|
85 | auto v = prov.getData("", 0., 0.); | |
|
86 | ScalarTimeSerie s; | |
|
87 | s.set_data(v.first.to_std_vect(), v.second.to_std_vect()); | |
|
88 | return s; | |
|
89 | } |
@@ -31,18 +31,36 | |||
|
31 | 31 | </target-to-native> |
|
32 | 32 | </conversion-rule> |
|
33 | 33 | </container-type> |
|
34 | <object-type name="PyDataProvider" /> | |
|
35 | <object-type name="Product" /> | |
|
34 | 36 | <object-type name="MainWindow" /> |
|
35 | 37 | <object-type name="SqpApplication"> |
|
36 | 38 | <modify-function signature="SqpApplication(int&,char**)" access="private"/> |
|
37 | 39 | </object-type> |
|
38 |
<object-type name="P |
|
|
39 | <function signature="SqpApplication_ctor()"/> | |
|
40 | <object-type name="Providers"> | |
|
41 | <modify-function signature="register_provider(PyDataProvider*)"> | |
|
42 | <modify-argument index="1"> | |
|
43 | <define-ownership owner="c++" /> | |
|
44 | </modify-argument> | |
|
45 | </modify-function> | |
|
46 | </object-type> | |
|
47 | <function signature="SqpApplication_ctor()" return-type="SqpApplication*"/> | |
|
48 | <add-function signature="SqpApplication_ctor(PySequence)" return-type="SqpApplication*"> | |
|
49 | <inject-code class="target"> | |
|
50 | static int argc; | |
|
51 | static char **argv; | |
|
52 | Shiboken::listToArgcArgv(%1, &argc, &argv, "PySideApp"); | |
|
53 | auto retval = new SqpApplication(argc,argv); | |
|
54 | %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](retval); | |
|
55 | </inject-code> | |
|
56 | </add-function> | |
|
40 | 57 | <function signature="init_resources()"/> |
|
41 | 58 | <primitive-type name="NpArray" target-lang-api-name="PyObject"> |
|
42 | 59 | <include file-name="numpy_wrappers.h" location="local"/> |
|
43 | 60 | <conversion-rule> |
|
44 | 61 | <native-to-target> |
|
45 |
|
|
|
62 | auto result = %in.py_object(); | |
|
63 | return result; | |
|
46 | 64 | </native-to-target> |
|
47 | 65 | <target-to-native> |
|
48 | 66 | <add-conversion type="PyObject" check="NpArray::isNpArray(%in)"> |
@@ -68,5 +86,6 | |||
|
68 | 86 | </inject-code> |
|
69 | 87 | </add-function> |
|
70 | 88 | </object-type> |
|
89 | <function signature="test_PyDataProvider(PyDataProvider&)"/> | |
|
71 | 90 | <function signature="test_np_array(NpArray&)"/> |
|
72 | 91 | </typesystem> |
@@ -4,6 +4,17 | |||
|
4 | 4 | #define Py_DEBUG |
|
5 | 5 | #include <Python.h> |
|
6 | 6 | |
|
7 | wchar_t** decode_argv(int argc, char** argv) | |
|
8 | { | |
|
9 | wchar_t** _argv = static_cast<wchar_t**>(PyMem_Malloc(sizeof(wchar_t*) * argc)); | |
|
10 | for (int i = 0; i < argc; i++) | |
|
11 | { | |
|
12 | wchar_t* arg = Py_DecodeLocale(argv[i], NULL); | |
|
13 | _argv[i] = arg; | |
|
14 | } | |
|
15 | return _argv; | |
|
16 | } | |
|
17 | ||
|
7 | 18 | int main(int argc, char** argv) |
|
8 | 19 | { |
|
9 | 20 | wchar_t* program = Py_DecodeLocale(argv[0], NULL); |
@@ -12,8 +23,10 int main(int argc, char** argv) | |||
|
12 | 23 | fprintf(stderr, "Fatal error: cannot decode argv[0]\n"); |
|
13 | 24 | exit(1); |
|
14 | 25 | } |
|
26 | ||
|
15 | 27 | Py_SetProgramName(program); /* optional but recommended */ |
|
16 | 28 | Py_Initialize(); |
|
29 | PySys_SetArgv(argc, decode_argv(argc, argv)); | |
|
17 | 30 | std::ifstream t(argv[1]); |
|
18 | 31 | std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>()); |
|
19 | 32 | PyRun_SimpleString(str.data()); |
@@ -6,6 +6,7 from PySide2.QtWidgets import QApplication, QMainWindow, QDockWidget | |||
|
6 | 6 | from PySide2.QtCore import QSize, Qt |
|
7 | 7 | from PySide2 import QtGui |
|
8 | 8 | import os |
|
9 | sys.path.append(os.getcwd()) | |
|
9 | 10 | from SciQLopBindings import SqpApplication, MainWindow, init_resources, load_plugins, SqpApplication_ctor |
|
10 | 11 | from qtconsole.rich_ipython_widget import RichJupyterWidget |
|
11 | 12 | from qtconsole.inprocess import QtInProcessKernelManager |
@@ -91,7 +92,7 def print_process_id(): | |||
|
91 | 92 | |
|
92 | 93 | if __name__ == "__main__": |
|
93 | 94 | init_resources() |
|
94 | app = SqpApplication_ctor() | |
|
95 | app = SqpApplication_ctor(sys.argv) | |
|
95 | 96 | QtGui.qApp = app |
|
96 | 97 | load_plugins(app) |
|
97 | 98 | main_window = MainWindow() |
@@ -29,6 +29,8 extern "C" | |||
|
29 | 29 | #endif |
|
30 | 30 | #include <assert.h> |
|
31 | 31 | |
|
32 | #include <map> | |
|
33 | ||
|
32 | 34 | inline int init_numpy() |
|
33 | 35 | { |
|
34 | 36 | import_array(); // PyError if not successful |
@@ -39,32 +41,31 template <typename dest_type = PyObject> | |||
|
39 | 41 | struct PyObjectWrapper |
|
40 | 42 | { |
|
41 | 43 | private: |
|
42 | PyObject* _py_obj; | |
|
43 | ||
|
44 | PyObject* _py_obj = nullptr; | |
|
44 | 45 | void inc_refcount() |
|
45 | 46 | { |
|
46 |
|
|
|
47 | Py_IncRef(_py_obj); | |
|
47 | Py_XINCREF(_py_obj); | |
|
48 | 48 | } |
|
49 | 49 | void dec_refcount() |
|
50 | 50 | { |
|
51 |
|
|
|
52 | Py_DecRef(_py_obj); | |
|
51 | Py_XDECREF(_py_obj); | |
|
52 | _py_obj = nullptr; | |
|
53 | 53 | } |
|
54 | 54 | |
|
55 | 55 | public: |
|
56 | 56 | PyObjectWrapper() : _py_obj { nullptr } {} |
|
57 |
PyObjectWrapper(const PyObjectWrapper& other) : _py_obj { other._py_obj } { inc_refcount(); } |
|
|
58 | PyObjectWrapper(PyObjectWrapper&& other) : _py_obj { other._py_obj } | |
|
57 | PyObjectWrapper(const PyObjectWrapper& other) : _py_obj { other._py_obj } { inc_refcount(); } | |
|
58 | PyObjectWrapper(PyObjectWrapper&& other) : _py_obj { other._py_obj } { inc_refcount(); } | |
|
59 | explicit PyObjectWrapper(PyObject* obj) : _py_obj { obj } | |
|
59 | 60 | { |
|
60 | other._py_obj = nullptr; | |
|
61 | inc_refcount(); | |
|
61 | 62 | } |
|
62 | PyObjectWrapper(PyObject* obj) : _py_obj { obj } { inc_refcount(); } | |
|
63 | 63 | ~PyObjectWrapper() { dec_refcount(); } |
|
64 | 64 | PyObjectWrapper& operator=(PyObjectWrapper&& other) |
|
65 | 65 | { |
|
66 | dec_refcount(); | |
|
66 | 67 | this->_py_obj = other._py_obj; |
|
67 | other._py_obj = nullptr; | |
|
68 | inc_refcount(); | |
|
68 | 69 | return *this; |
|
69 | 70 | } |
|
70 | 71 | PyObjectWrapper& operator=(const PyObjectWrapper& other) |
@@ -91,14 +92,14 private: | |||
|
91 | 92 | public: |
|
92 | 93 | static bool isNpArray(PyObject* obj) |
|
93 | 94 | { |
|
94 |
|
|
|
95 | && PyArray_IS_C_CONTIGUOUS(reinterpret_cast<PyArrayObject*>(obj)); | |
|
95 | auto arr = reinterpret_cast<PyArrayObject*>(obj); | |
|
96 | auto is_c_aray = obj && PyArray_Check(arr) && PyArray_ISCARRAY(arr); | |
|
97 | return is_c_aray; | |
|
96 | 98 | } |
|
97 | 99 | NpArray() : _py_obj { nullptr } {} |
|
98 |
NpArray(NpArray&& other) : _py_obj { |
|
|
100 | NpArray(NpArray&& other) : _py_obj { other._py_obj } {} | |
|
99 | 101 | explicit NpArray(PyObject* obj) : _py_obj { obj } |
|
100 | 102 | { |
|
101 | std::cout << "NpArray ctor" << std::endl; | |
|
102 | 103 | assert(isNpArray(obj)); |
|
103 | 104 | assert(PyArray_ISFLOAT(_py_obj.get())); |
|
104 | 105 | } |
@@ -111,7 +112,7 public: | |||
|
111 | 112 | |
|
112 | 113 | NpArray& operator=(NpArray&& other) |
|
113 | 114 | { |
|
114 |
this->_py_obj = |
|
|
115 | this->_py_obj = other._py_obj; | |
|
115 | 116 | return *this; |
|
116 | 117 | } |
|
117 | 118 |
@@ -9,7 +9,7 | |||
|
9 | 9 | #include <QWidget> |
|
10 | 10 | #include <TimeWidget/TimeWidget.h> |
|
11 | 11 | |
|
12 |
// |
|
|
12 | // TODO remove this, shouldn't need to include SqpApplication to get PlotsInteractionMode | |
|
13 | 13 | #include <SqpApplication.h> |
|
14 | 14 | |
|
15 | 15 | class ToolBar : public QToolBar |
@@ -25,6 +25,7 | |||
|
25 | 25 | #include <Catalogue/CatalogueController.h> |
|
26 | 26 | #include <Catalogue2/browser.h> |
|
27 | 27 | #include <DataSource/DataSourceController.h> |
|
28 | #include <DataSource/DataSourceItem.h> | |
|
28 | 29 | #include <DataSource/DataSourceWidget.h> |
|
29 | 30 | #include <Settings/SqpSettingsDialog.h> |
|
30 | 31 | #include <Settings/SqpSettingsGeneralWidget.h> |
@@ -48,29 +49,16 | |||
|
48 | 49 | |
|
49 | 50 | Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow") |
|
50 | 51 | |
|
51 | namespace | |
|
52 | { | |
|
53 | const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0; | |
|
54 | const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1; | |
|
55 | const auto VIEWPLITTERINDEX = 2; | |
|
56 | const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3; | |
|
57 | const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4; | |
|
58 | } | |
|
59 | ||
|
60 | 52 | class MainWindow::MainWindowPrivate |
|
61 | 53 | { |
|
62 | 54 | public: |
|
63 | 55 | explicit MainWindowPrivate(MainWindow* mainWindow) |
|
64 | : m_LastOpenLeftInspectorSize {} | |
|
65 | , m_LastOpenRightInspectorSize {} | |
|
66 | , m_GeneralSettingsWidget { new SqpSettingsGeneralWidget { mainWindow } } | |
|
56 | : m_GeneralSettingsWidget { new SqpSettingsGeneralWidget { mainWindow } } | |
|
67 | 57 | , m_SettingsDialog { new SqpSettingsDialog { mainWindow } } |
|
68 | 58 | , m_CatalogExplorer { new CataloguesBrowser { mainWindow } } |
|
69 | 59 | { |
|
70 | 60 | } |
|
71 | 61 | |
|
72 | QSize m_LastOpenLeftInspectorSize; | |
|
73 | QSize m_LastOpenRightInspectorSize; | |
|
74 | 62 | /// General settings widget. MainWindow has the ownership |
|
75 | 63 | SqpSettingsGeneralWidget* m_GeneralSettingsWidget; |
|
76 | 64 | /// Settings dialog. MainWindow has the ownership |
@@ -89,67 +77,6 MainWindow::MainWindow(QWidget* parent) | |||
|
89 | 77 | m_Ui->setupUi(this); |
|
90 | 78 | setWindowTitle(QString("SciQLop v%1").arg(SCIQLOP_VERSION)); |
|
91 | 79 | |
|
92 | m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false); | |
|
93 | m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false); | |
|
94 | ||
|
95 | // impl->m_CatalogExplorer->setVisualizationWidget(m_Ui->view); | |
|
96 | ||
|
97 | ||
|
98 | auto spacerLeftTop = new QWidget {}; | |
|
99 | spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | |
|
100 | ||
|
101 | auto spacerLeftBottom = new QWidget {}; | |
|
102 | spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | |
|
103 | ||
|
104 | ||
|
105 | auto spacerRightTop = new QWidget {}; | |
|
106 | spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | |
|
107 | ||
|
108 | auto spacerRightBottom = new QWidget {}; | |
|
109 | spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | |
|
110 | ||
|
111 | ||
|
112 | auto openInspector = [this](bool checked, bool right, auto action) { | |
|
113 | action->setIcon( | |
|
114 | QIcon { (checked ^ right) ? ":/icones/next.png" : ":/icones/previous.png" }); | |
|
115 | ||
|
116 | auto& lastInspectorSize | |
|
117 | = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize; | |
|
118 | ||
|
119 | auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size() | |
|
120 | : m_Ui->leftMainInspectorWidget->size(); | |
|
121 | ||
|
122 | // Update of the last opened geometry | |
|
123 | if (checked) | |
|
124 | { | |
|
125 | lastInspectorSize = nextInspectorSize; | |
|
126 | } | |
|
127 | ||
|
128 | auto startSize = lastInspectorSize; | |
|
129 | auto endSize = startSize; | |
|
130 | endSize.setWidth(0); | |
|
131 | ||
|
132 | auto splitterInspectorIndex | |
|
133 | = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX; | |
|
134 | ||
|
135 | auto currentSizes = m_Ui->splitter->sizes(); | |
|
136 | if (checked) | |
|
137 | { | |
|
138 | // adjust sizes individually here, e.g. | |
|
139 | currentSizes[splitterInspectorIndex] -= lastInspectorSize.width(); | |
|
140 | currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width(); | |
|
141 | m_Ui->splitter->setSizes(currentSizes); | |
|
142 | } | |
|
143 | else | |
|
144 | { | |
|
145 | // adjust sizes individually here, e.g. | |
|
146 | currentSizes[splitterInspectorIndex] += lastInspectorSize.width(); | |
|
147 | currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width(); | |
|
148 | m_Ui->splitter->setSizes(currentSizes); | |
|
149 | } | |
|
150 | }; | |
|
151 | ||
|
152 | ||
|
153 | 80 | // //////////////// // |
|
154 | 81 | // Menu and Toolbar // |
|
155 | 82 | // //////////////// // |
@@ -188,8 +115,8 MainWindow::MainWindow(QWidget* parent) | |||
|
188 | 115 | // Widgets / controllers connections |
|
189 | 116 | |
|
190 | 117 | // DataSource |
|
191 |
connect(&sqpApp->dataSourceController(), |
|
|
192 |
m_Ui->dataSourceWidget, |
|
|
118 | connect(&sqpApp->dataSourceController(), &DataSourceController::dataSourceItemSet, | |
|
119 | m_Ui->dataSourceWidget, &DataSourceWidget::addDataSource); | |
|
193 | 120 | |
|
194 | 121 | // Time |
|
195 | 122 | // connect(timeWidget, SIGNAL(timeUpdated(DateTimeRange)), &sqpApp->timeController(), |
@@ -16,7 +16,7 | |||
|
16 | 16 | <property name="dockNestingEnabled"> |
|
17 | 17 | <bool>true</bool> |
|
18 | 18 | </property> |
|
19 |
<widget class=" |
|
|
19 | <widget class="VisualizationWidget" name="view"> | |
|
20 | 20 | <property name="enabled"> |
|
21 | 21 | <bool>true</bool> |
|
22 | 22 | </property> |
@@ -32,97 +32,6 | |||
|
32 | 32 | <height>16777215</height> |
|
33 | 33 | </size> |
|
34 | 34 | </property> |
|
35 | <layout class="QHBoxLayout" name="horizontalLayout"> | |
|
36 | <property name="spacing"> | |
|
37 | <number>0</number> | |
|
38 | </property> | |
|
39 | <property name="leftMargin"> | |
|
40 | <number>0</number> | |
|
41 | </property> | |
|
42 | <property name="topMargin"> | |
|
43 | <number>0</number> | |
|
44 | </property> | |
|
45 | <property name="rightMargin"> | |
|
46 | <number>0</number> | |
|
47 | </property> | |
|
48 | <property name="bottomMargin"> | |
|
49 | <number>0</number> | |
|
50 | </property> | |
|
51 | <item> | |
|
52 | <widget class="QSplitter" name="splitter"> | |
|
53 | <property name="orientation"> | |
|
54 | <enum>Qt::Horizontal</enum> | |
|
55 | </property> | |
|
56 | <widget class="QWidget" name="leftMainInspectorWidget" native="true"> | |
|
57 | <layout class="QVBoxLayout" name="verticalLayout"> | |
|
58 | <property name="spacing"> | |
|
59 | <number>0</number> | |
|
60 | </property> | |
|
61 | <property name="leftMargin"> | |
|
62 | <number>0</number> | |
|
63 | </property> | |
|
64 | <property name="topMargin"> | |
|
65 | <number>0</number> | |
|
66 | </property> | |
|
67 | <property name="rightMargin"> | |
|
68 | <number>0</number> | |
|
69 | </property> | |
|
70 | <property name="bottomMargin"> | |
|
71 | <number>0</number> | |
|
72 | </property> | |
|
73 | <item> | |
|
74 | <widget class="DataSourceWidget" name="dataSourceWidget" native="true"/> | |
|
75 | </item> | |
|
76 | <item> | |
|
77 | <widget class="QWidget" name="dateTimeWidget" native="true"/> | |
|
78 | </item> | |
|
79 | <item> | |
|
80 | <widget class="VariableInspectorWidget" name="variableInspectorWidget" native="true"/> | |
|
81 | </item> | |
|
82 | </layout> | |
|
83 | </widget> | |
|
84 | <widget class="VisualizationWidget" name="view" native="true"> | |
|
85 | <property name="sizePolicy"> | |
|
86 | <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> | |
|
87 | <horstretch>0</horstretch> | |
|
88 | <verstretch>0</verstretch> | |
|
89 | </sizepolicy> | |
|
90 | </property> | |
|
91 | </widget> | |
|
92 | <widget class="QWidget" name="rightMainInspectorWidget" native="true"> | |
|
93 | <layout class="QVBoxLayout" name="verticalLayout_3"> | |
|
94 | <property name="spacing"> | |
|
95 | <number>0</number> | |
|
96 | </property> | |
|
97 | <property name="leftMargin"> | |
|
98 | <number>0</number> | |
|
99 | </property> | |
|
100 | <property name="topMargin"> | |
|
101 | <number>0</number> | |
|
102 | </property> | |
|
103 | <property name="rightMargin"> | |
|
104 | <number>0</number> | |
|
105 | </property> | |
|
106 | <property name="bottomMargin"> | |
|
107 | <number>0</number> | |
|
108 | </property> | |
|
109 | <item> | |
|
110 | <widget class="QWidget" name="commonPropertyInspectorWidget" native="true"/> | |
|
111 | </item> | |
|
112 | <item> | |
|
113 | <widget class="QTreeWidget" name="catalogWidget"> | |
|
114 | <column> | |
|
115 | <property name="text"> | |
|
116 | <string notr="true">Name</string> | |
|
117 | </property> | |
|
118 | </column> | |
|
119 | </widget> | |
|
120 | </item> | |
|
121 | </layout> | |
|
122 | </widget> | |
|
123 | </widget> | |
|
124 | </item> | |
|
125 | </layout> | |
|
126 | 35 | </widget> |
|
127 | 36 | <widget class="QMenuBar" name="menuBar"> |
|
128 | 37 | <property name="geometry"> |
@@ -130,7 +39,7 | |||
|
130 | 39 | <x>0</x> |
|
131 | 40 | <y>0</y> |
|
132 | 41 | <width>800</width> |
|
133 |
<height>2 |
|
|
42 | <height>24</height> | |
|
134 | 43 | </rect> |
|
135 | 44 | </property> |
|
136 | 45 | <property name="sizePolicy"> |
@@ -150,6 +59,30 | |||
|
150 | 59 | </property> |
|
151 | 60 | </widget> |
|
152 | 61 | <widget class="QStatusBar" name="statusBar"/> |
|
62 | <widget class="QDockWidget" name="dockWidget"> | |
|
63 | <property name="features"> | |
|
64 | <set>QDockWidget::DockWidgetMovable</set> | |
|
65 | </property> | |
|
66 | <property name="windowTitle"> | |
|
67 | <string>Products</string> | |
|
68 | </property> | |
|
69 | <attribute name="dockWidgetArea"> | |
|
70 | <number>1</number> | |
|
71 | </attribute> | |
|
72 | <widget class="DataSourceWidget" name="dataSourceWidget"/> | |
|
73 | </widget> | |
|
74 | <widget class="QDockWidget" name="dockWidget_2"> | |
|
75 | <property name="features"> | |
|
76 | <set>QDockWidget::DockWidgetMovable</set> | |
|
77 | </property> | |
|
78 | <property name="windowTitle"> | |
|
79 | <string>Variables</string> | |
|
80 | </property> | |
|
81 | <attribute name="dockWidgetArea"> | |
|
82 | <number>1</number> | |
|
83 | </attribute> | |
|
84 | <widget class="VariableInspectorWidget" name="variableInspectorWidget"/> | |
|
85 | </widget> | |
|
153 | 86 | </widget> |
|
154 | 87 | <layoutdefault spacing="6" margin="11"/> |
|
155 | 88 | <customwidgets> |
@@ -1,1 +1,1 | |||
|
1 | Subproject commit c4e273750e74336d1d125c02989c922f2032e489 | |
|
1 | Subproject commit 9ff5f48e3d71ce2d3a8b2156f778f3f9be3ea389 |
@@ -138,7 +138,7 struct DataSourceTreeWidgetItem::DataSourceTreeWidgetItemPrivate { | |||
|
138 | 138 | QString m_Name; |
|
139 | 139 | /// Actions associated to the item. The parent of the item (QTreeWidget) takes the ownership of |
|
140 | 140 | /// the actions |
|
141 | QList<QAction *> m_Actions; | |
|
141 | QList<QAction *> m_Actions; //TODO check if no memory leak here | |
|
142 | 142 | }; |
|
143 | 143 | |
|
144 | 144 | DataSourceTreeWidgetItem::DataSourceTreeWidgetItem(const DataSourceItem *data, int type) |
@@ -8,39 +8,39 | |||
|
8 | 8 | |
|
9 | 9 | #include <QMenu> |
|
10 | 10 | |
|
11 |
namespace |
|
|
11 | namespace | |
|
12 | { | |
|
12 | 13 | |
|
13 | 14 | /// Number of columns displayed in the tree |
|
14 | 15 | const auto TREE_NB_COLUMNS = 1; |
|
15 | 16 | |
|
16 | 17 | /// Header labels for the tree |
|
17 | const auto TREE_HEADER_LABELS = QStringList{QObject::tr("Name")}; | |
|
18 | const auto TREE_HEADER_LABELS = QStringList { QObject::tr("Name") }; | |
|
18 | 19 | |
|
19 | 20 | /** |
|
20 | 21 | * Creates the item associated to a data source |
|
21 | 22 | * @param dataSource the data source for which to create the item |
|
22 | 23 | * @return the new item |
|
23 | 24 | */ |
|
24 |
DataSourceTreeWidgetItem |
|
|
25 | DataSourceTreeWidgetItem* createTreeWidgetItem(DataSourceItem* dataSource) | |
|
25 | 26 | { |
|
26 | 27 | // Creates item for the data source |
|
27 | auto item = new DataSourceTreeWidgetItem{dataSource}; | |
|
28 | ||
|
28 | auto item = new DataSourceTreeWidgetItem { dataSource }; | |
|
29 | 29 | // Generates items for the children of the data source |
|
30 | for (auto i = 0; i < dataSource->childCount(); ++i) { | |
|
31 | item->addChild(createTreeWidgetItem(dataSource->child(i))); | |
|
32 | } | |
|
33 | ||
|
30 | std::for_each(dataSource->cbegin(), dataSource->cend(), | |
|
31 | [&item](const std::unique_ptr<DataSourceItem>& child) { | |
|
32 | item->addChild(createTreeWidgetItem(child.get())); | |
|
33 | }); | |
|
34 | 34 | return item; |
|
35 | 35 | } |
|
36 | 36 | |
|
37 | 37 | } // namespace |
|
38 | 38 | |
|
39 |
DataSourceWidget::DataSourceWidget(QWidget |
|
|
40 |
: QWidget{parent} |
|
|
41 |
|
|
|
42 | m_Root{ | |
|
43 |
|
|
|
39 | DataSourceWidget::DataSourceWidget(QWidget* parent) | |
|
40 | : QWidget { parent } | |
|
41 | , ui { new Ui::DataSourceWidget } | |
|
42 | , m_Root { std::make_unique<DataSourceItem>( | |
|
43 | DataSourceItemType::NODE, QStringLiteral("Sources")) } | |
|
44 | 44 | { |
|
45 | 45 | ui->setupUi(this); |
|
46 | 46 | |
@@ -51,7 +51,7 DataSourceWidget::DataSourceWidget(QWidget *parent) | |||
|
51 | 51 | |
|
52 | 52 | // Connection to show a menu when right clicking on the tree |
|
53 | 53 | connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this, |
|
54 |
|
|
|
54 | &DataSourceWidget::onTreeMenuRequested); | |
|
55 | 55 | |
|
56 | 56 | // Connection to filter tree |
|
57 | 57 | connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &DataSourceWidget::filterChanged); |
@@ -65,14 +65,13 DataSourceWidget::~DataSourceWidget() noexcept | |||
|
65 | 65 | delete ui; |
|
66 | 66 | } |
|
67 | 67 | |
|
68 |
void DataSourceWidget::addDataSource(DataSourceItem |
|
|
68 | void DataSourceWidget::addDataSource(DataSourceItem* dataSource) noexcept | |
|
69 | 69 | { |
|
70 | 70 | // Merges the data source (without taking its root) |
|
71 |
if (dataSource) |
|
|
72 | for (auto i = 0, count = dataSource->childCount(); i < count; ++i) { | |
|
73 | m_Root->merge(*dataSource->child(i)); | |
|
74 | } | |
|
75 | ||
|
71 | if (dataSource) | |
|
72 | { | |
|
73 | std::for_each(std::cbegin(*dataSource), std::cend(*dataSource), | |
|
74 | [this](const auto& child) { this->m_Root->merge(*child.get()); }); | |
|
76 | 75 | updateTreeWidget(); |
|
77 | 76 | } |
|
78 | 77 | } |
@@ -90,33 +89,35 void DataSourceWidget::updateTreeWidget() noexcept | |||
|
90 | 89 | ui->treeWidget->sortByColumn(0, Qt::AscendingOrder); |
|
91 | 90 | } |
|
92 | 91 | |
|
93 |
void DataSourceWidget::filterChanged(const QString |
|
|
92 | void DataSourceWidget::filterChanged(const QString& text) noexcept | |
|
94 | 93 | { |
|
95 |
auto validateItem = [&text](const DataSourceTreeWidgetItem |
|
|
96 | auto regExp = QRegExp{text, Qt::CaseInsensitive, QRegExp::Wildcard}; | |
|
94 | auto validateItem = [&text](const DataSourceTreeWidgetItem& item) { | |
|
95 | auto regExp = QRegExp { text, Qt::CaseInsensitive, QRegExp::Wildcard }; | |
|
97 | 96 | |
|
98 | 97 | // An item is valid if any of its metadata validates the text filter |
|
99 | 98 | auto itemMetadata = item.data()->data(); |
|
100 | 99 | auto itemMetadataEnd = itemMetadata.cend(); |
|
101 | 100 | auto acceptFilter |
|
102 |
= [®Exp](const auto |
|
|
101 | = [®Exp](const auto& variant) { return variant.toString().contains(regExp); }; | |
|
103 | 102 | |
|
104 | 103 | return std::find_if(itemMetadata.cbegin(), itemMetadataEnd, acceptFilter) |
|
105 |
|
|
|
104 | != itemMetadataEnd; | |
|
106 | 105 | }; |
|
107 | 106 | |
|
108 | 107 | // Applies filter on tree widget |
|
109 | 108 | DataSourceTreeWidgetHelper::filter(*ui->treeWidget, validateItem); |
|
110 | 109 | } |
|
111 | 110 | |
|
112 |
void DataSourceWidget::onTreeMenuRequested(const QPoint |
|
|
111 | void DataSourceWidget::onTreeMenuRequested(const QPoint& pos) noexcept | |
|
113 | 112 | { |
|
114 | 113 | // Retrieves the selected item in the tree, and build the menu from its actions |
|
115 |
if (auto selectedItem = dynamic_cast<DataSourceTreeWidgetItem |
|
|
116 | QMenu treeMenu{}; | |
|
114 | if (auto selectedItem = dynamic_cast<DataSourceTreeWidgetItem*>(ui->treeWidget->itemAt(pos))) | |
|
115 | { | |
|
116 | QMenu treeMenu {}; | |
|
117 | 117 | treeMenu.addActions(selectedItem->actions()); |
|
118 | 118 | |
|
119 |
if (!treeMenu.isEmpty()) |
|
|
119 | if (!treeMenu.isEmpty()) | |
|
120 | { | |
|
120 | 121 | treeMenu.exec(QCursor::pos()); |
|
121 | 122 | } |
|
122 | 123 | } |
@@ -219,7 +219,7 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate | |||
|
219 | 219 | { |
|
220 | 220 | /* |
|
221 | 221 | * I give up on this for now |
|
222 |
* |
|
|
222 | * TODO implement this, the difficulty is that selection zones have their own | |
|
223 | 223 | * event handling code which seems to rely on QCP GUI event handling propagation |
|
224 | 224 | * which was a realy bad design choice. |
|
225 | 225 | */ |
@@ -506,7 +506,7 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable2> variable, | |||
|
506 | 506 | delete context; |
|
507 | 507 | }); |
|
508 | 508 | } |
|
509 |
// |
|
|
509 | //TODO this is bad! when variable is moved to another graph it still fires | |
|
510 | 510 | // even if this has been deleted |
|
511 | 511 | connect(variable.get(), &Variable2::updated, this, &VisualizationGraphWidget::variableUpdated); |
|
512 | 512 | this->onUpdateVarDisplaying(variable, range); // My bullshit |
General Comments 0
You need to be logged in to leave comments.
Login now