Auto status change to "Under Review"
Closed
Pull request !148
Created on
Wed, 14 Jun 2017 14:47:53,
- add {} missing
- Add const and override
- Add the visualization gui classes
- Add const and override
- Add the visualization gui classes
Pull request versions not available.
ver | Time | Author | Commit | Description | |
---|---|---|---|---|---|
latest
|
r113:c1f92d4a498b
|
|
|||
latest
|
r112:ab875bffb49d
|
|
|||
latest
|
r111:58d173e4af62
|
|
@@ -0,0 +1,1 | |||||
|
1 | TODO |
@@ -1,31 +1,1 | |||||
1 | ![](gui/resources/icones/sciqlop2PNG_1024.png){:.some-css-class style="width: 20%"} |
|
1 | TODO No newline at end of file | |
2 |
|
||||
3 |
|
||||
4 | # Overview |
|
|||
5 |
|
||||
6 | ** SciQLOP ** (**SCI**entific **Q**t application for **L**earning from **O**bservations of **P**lasmas) aims to be an ergonomic |
|
|||
7 | and powerful tool enabling visualization and analysis of in-situ space plasma data. This goal rises some |
|
|||
8 | challenges either technical and in the conception and the design. |
|
|||
9 | The time resolution allowed by nowadays measurements imply the ability to plot millions of points just for |
|
|||
10 | one sensor with no compromise on interactivity. Plots may stay responsive even with millions of points. |
|
|||
11 | Being able to scroll, zoom, move and export the plots with the mouse are the minimal interactions expected by the user. |
|
|||
12 | SciQLOP may also abstract the manipulation of physic data while providing contextual features such as |
|
|||
13 | coordinate transform, physical quantity extraction from data. |
|
|||
14 | That said increasing graphical features usually lead to slower software and more complex GUI. Keeping |
|
|||
15 | SciQLOP lightweight and intuitive is one of the priorities to make it usable and competitive. |
|
|||
16 |
|
||||
17 |
|
||||
18 | ## How to build |
|
|||
19 |
|
||||
20 | ``` |
|
|||
21 | git clone https://hephaistos.lpp.polytechnique.fr/rhodecode/HG_REPOSITORIES/LPP/SciQLOP_Repos/SciQLop |
|
|||
22 | cd SciQLop |
|
|||
23 | mkdir build && cd build |
|
|||
24 | cmake ../ |
|
|||
25 | make |
|
|||
26 |
|
||||
27 | ``` |
|
|||
28 |
|
||||
29 | ## How to contribute |
|
|||
30 |
|
||||
31 | Contact sciqlop@lpp.polytechnique.fr |
|
@@ -66,12 +66,7 set_property(TARGET ${EXECUTABLE_NAME} PROPERTY CXX_STANDARD 14) | |||||
66 | set_property(TARGET ${EXECUTABLE_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) |
|
66 | set_property(TARGET ${EXECUTABLE_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) | |
67 | target_link_libraries(${EXECUTABLE_NAME} |
|
67 | target_link_libraries(${EXECUTABLE_NAME} | |
68 | ${LIBRARIES}) |
|
68 | ${LIBRARIES}) | |
69 |
|
69 | |||
70 | INSTALL(TARGETS ${EXECUTABLE_NAME} |
|
|||
71 | RUNTIME DESTINATION ${INSTALL_BINARY_DIR} |
|
|||
72 | LIBRARY DESTINATION ${INSTALL_BINARY_DIR} |
|
|||
73 | ARCHIVE DESTINATION ${INSTALL_BINARY_DIR} |
|
|||
74 | ) |
|
|||
75 | # Link with Qt5 modules |
|
70 | # Link with Qt5 modules | |
76 | qt5_use_modules(${EXECUTABLE_NAME} Core Widgets) |
|
71 | qt5_use_modules(${EXECUTABLE_NAME} Core Widgets) | |
77 |
|
72 |
@@ -28,15 +28,11 | |||||
28 | #include <Plugin/PluginManager.h> |
|
28 | #include <Plugin/PluginManager.h> | |
29 | #include <QDir> |
|
29 | #include <QDir> | |
30 |
|
30 | |||
31 | #include <QLoggingCategory> |
|
|||
32 |
|
||||
33 | Q_LOGGING_CATEGORY(LOG_Main, "Main") |
|
|||
34 |
|
||||
35 | namespace { |
|
31 | namespace { | |
36 |
|
32 | |||
|
33 | /// Name of the directory containing the plugins | |||
37 | const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins"); |
|
34 | const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins"); | |
38 |
|
35 | |||
39 |
|
||||
40 | } // namespace |
|
36 | } // namespace | |
41 |
|
37 | |||
42 | int main(int argc, char *argv[]) |
|
38 | int main(int argc, char *argv[]) | |
@@ -49,32 +45,15 int main(int argc, char *argv[]) | |||||
49 | w.show(); |
|
45 | w.show(); | |
50 |
|
46 | |||
51 | // Loads plugins |
|
47 | // Loads plugins | |
52 |
auto pluginDir = QDir{ |
|
48 | auto pluginDir = QDir{sqpApp->applicationDirPath()}; | |
53 | auto pluginLookupPath = { |
|
|||
54 | a.applicationDirPath(), |
|
|||
55 | a.applicationDirPath() + "/" + PLUGIN_DIRECTORY_NAME, |
|
|||
56 | a.applicationDirPath() + "/../lib64/SciQlop", |
|
|||
57 | a.applicationDirPath() + "/../lib64/sciqlop", |
|
|||
58 | a.applicationDirPath() + "/../lib/SciQlop", |
|
|||
59 | a.applicationDirPath() + "/../lib/sciqlop", |
|
|||
60 | a.applicationDirPath() + "/../plugins", |
|
|||
61 | }; |
|
|||
62 |
|
||||
63 | #if _WIN32 || _WIN64 |
|
|||
64 | pluginDir.mkdir(PLUGIN_DIRECTORY_NAME); |
|
49 | pluginDir.mkdir(PLUGIN_DIRECTORY_NAME); | |
65 | pluginDir.cd(PLUGIN_DIRECTORY_NAME); |
|
50 | pluginDir.cd(PLUGIN_DIRECTORY_NAME); | |
66 | #endif |
|
|||
67 |
|
51 | |||
68 | PluginManager pluginManager{}; |
|
52 | qCDebug(LOG_PluginManager()) | |
|
53 | << QObject::tr("Plugin directory: %1").arg(pluginDir.absolutePath()); | |||
69 |
|
54 | |||
70 | for (auto &&path : pluginLookupPath) { |
|
55 | PluginManager pluginManager{}; | |
71 | QDir directory{path}; |
|
56 | pluginManager.loadPlugins(pluginDir); | |
72 | if (directory.exists()) { |
|
|||
73 | qCDebug(LOG_Main()) |
|
|||
74 | << QObject::tr("Plugin directory: %1").arg(directory.absolutePath()); |
|
|||
75 | pluginManager.loadPlugins(directory); |
|
|||
76 | } |
|
|||
77 | } |
|
|||
78 |
|
57 | |||
79 | return a.exec(); |
|
58 | return a.exec(); | |
80 | } |
|
59 | } |
@@ -24,24 +24,29 | |||||
24 |
|
24 | |||
25 | #include <DataSource/DataSourceController.h> |
|
25 | #include <DataSource/DataSourceController.h> | |
26 | #include <DataSource/DataSourceWidget.h> |
|
26 | #include <DataSource/DataSourceWidget.h> | |
27 | #include <Settings/SqpSettingsDialog.h> |
|
|||
28 | #include <Settings/SqpSettingsGeneralWidget.h> |
|
|||
29 | #include <SidePane/SqpSidePane.h> |
|
27 | #include <SidePane/SqpSidePane.h> | |
30 | #include <SqpApplication.h> |
|
28 | #include <SqpApplication.h> | |
31 | #include <Time/TimeController.h> |
|
|||
32 | #include <TimeWidget/TimeWidget.h> |
|
|||
33 | #include <Variable/Variable.h> |
|
|||
34 | #include <Variable/VariableController.h> |
|
|||
35 | #include <Visualization/VisualizationController.h> |
|
|||
36 |
|
29 | |||
37 | #include <QAction> |
|
30 | #include <QAction> | |
38 | #include <QDate> |
|
31 | #include <QDate> | |
|
32 | #include <QDateTime> | |||
39 | #include <QDir> |
|
33 | #include <QDir> | |
40 | #include <QFileDialog> |
|
34 | #include <QFileDialog> | |
41 | #include <QToolBar> |
|
35 | #include <QToolBar> | |
42 | #include <QToolButton> |
|
|||
43 | #include <memory.h> |
|
36 | #include <memory.h> | |
44 |
|
37 | |||
|
38 | //#include <omp.h> | |||
|
39 | //#include <network/filedownloader.h> | |||
|
40 | //#include <qlopdatabase.h> | |||
|
41 | //#include <qlopsettings.h> | |||
|
42 | //#include <qlopgui.h> | |||
|
43 | //#include <spacedata.h> | |||
|
44 | //#include "qlopcore.h" | |||
|
45 | //#include "qlopcodecmanager.h" | |||
|
46 | //#include "cdfcodec.h" | |||
|
47 | //#include "amdatxtcodec.h" | |||
|
48 | //#include <qlopplotmanager.h> | |||
|
49 | ||||
45 | #include "iostream" |
|
50 | #include "iostream" | |
46 |
|
51 | |||
47 | Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow") |
|
52 | Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow") | |
@@ -56,191 +61,156 const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4; | |||||
56 |
|
61 | |||
57 | class MainWindow::MainWindowPrivate { |
|
62 | class MainWindow::MainWindowPrivate { | |
58 | public: |
|
63 | public: | |
59 | explicit MainWindowPrivate(MainWindow *mainWindow) |
|
|||
60 | : m_LastOpenLeftInspectorSize{}, |
|
|||
61 | m_LastOpenRightInspectorSize{}, |
|
|||
62 | m_GeneralSettingsWidget{new SqpSettingsGeneralWidget{mainWindow}}, |
|
|||
63 | m_SettingsDialog{new SqpSettingsDialog{mainWindow}} |
|
|||
64 | { |
|
|||
65 | } |
|
|||
66 |
|
||||
67 | QSize m_LastOpenLeftInspectorSize; |
|
64 | QSize m_LastOpenLeftInspectorSize; | |
68 | QSize m_LastOpenRightInspectorSize; |
|
65 | QSize m_LastOpenRightInspectorSize; | |
69 | /// General settings widget. MainWindow has the ownership |
|
|||
70 | SqpSettingsGeneralWidget *m_GeneralSettingsWidget; |
|
|||
71 | /// Settings dialog. MainWindow has the ownership |
|
|||
72 | SqpSettingsDialog *m_SettingsDialog; |
|
|||
73 | }; |
|
66 | }; | |
74 |
|
67 | |||
75 | MainWindow::MainWindow(QWidget *parent) |
|
68 | MainWindow::MainWindow(QWidget *parent) | |
76 | : QMainWindow{parent}, |
|
69 | : QMainWindow{parent}, | |
77 | m_Ui{new Ui::MainWindow}, |
|
70 | m_Ui{new Ui::MainWindow}, | |
78 |
impl{spimpl::make_unique_impl<MainWindowPrivate>( |
|
71 | impl{spimpl::make_unique_impl<MainWindowPrivate>()} | |
79 | { |
|
72 | { | |
80 | m_Ui->setupUi(this); |
|
73 | m_Ui->setupUi(this); | |
81 |
|
74 | |||
82 | m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false); |
|
75 | m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false); | |
83 | m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false); |
|
76 | m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false); | |
84 |
|
77 | |||
85 |
|
78 | // NOTE: These lambda could be factorized. Be careful of theirs parameters | ||
86 | auto leftSidePane = m_Ui->leftInspectorSidePane->sidePane(); |
|
79 | // Lambda that defines what's happened when clicking on the leftSidePaneInspector open button | |
87 |
auto openLeftInspector |
|
80 | auto openLeftInspector = [this](bool checked) { | |
88 | ":/icones/previous.png", |
|
|||
89 | }, |
|
|||
90 | tr("Show/hide the left inspector"), this}; |
|
|||
91 |
|
||||
92 |
|
||||
93 | auto spacerLeftTop = new QWidget{}; |
|
|||
94 | spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
|
|||
95 |
|
||||
96 | auto spacerLeftBottom = new QWidget{}; |
|
|||
97 | spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
|
|||
98 |
|
||||
99 | leftSidePane->addWidget(spacerLeftTop); |
|
|||
100 | leftSidePane->addAction(openLeftInspectorAction); |
|
|||
101 | leftSidePane->addWidget(spacerLeftBottom); |
|
|||
102 |
|
||||
103 |
|
||||
104 | auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane(); |
|
|||
105 | auto openRightInspectorAction = new QAction{QIcon{ |
|
|||
106 | ":/icones/next.png", |
|
|||
107 | }, |
|
|||
108 | tr("Show/hide the right inspector"), this}; |
|
|||
109 |
|
||||
110 | auto spacerRightTop = new QWidget{}; |
|
|||
111 | spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
|
|||
112 |
|
||||
113 | auto spacerRightBottom = new QWidget{}; |
|
|||
114 | spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
|
|||
115 |
|
||||
116 | rightSidePane->addWidget(spacerRightTop); |
|
|||
117 | rightSidePane->addAction(openRightInspectorAction); |
|
|||
118 | rightSidePane->addWidget(spacerRightBottom); |
|
|||
119 |
|
||||
120 | openLeftInspectorAction->setCheckable(true); |
|
|||
121 | openRightInspectorAction->setCheckable(true); |
|
|||
122 |
|
||||
123 | auto openInspector = [this](bool checked, bool right, auto action) { |
|
|||
124 |
|
||||
125 | action->setIcon(QIcon{(checked xor right) ? ":/icones/next.png" : ":/icones/previous.png"}); |
|
|||
126 |
|
||||
127 | auto &lastInspectorSize |
|
|||
128 | = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize; |
|
|||
129 |
|
||||
130 | auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size() |
|
|||
131 | : m_Ui->leftMainInspectorWidget->size(); |
|
|||
132 |
|
81 | |||
133 | // Update of the last opened geometry |
|
82 | // Update of the last opened geometry | |
134 | if (checked) { |
|
83 | if (checked) { | |
135 |
lastInspectorSize = |
|
84 | impl->m_LastOpenLeftInspectorSize = m_Ui->leftMainInspectorWidget->size(); | |
136 | } |
|
85 | } | |
137 |
|
86 | |||
138 | auto startSize = lastInspectorSize; |
|
87 | auto startSize = impl->m_LastOpenLeftInspectorSize; | |
139 | auto endSize = startSize; |
|
88 | auto endSize = startSize; | |
140 | endSize.setWidth(0); |
|
89 | endSize.setWidth(0); | |
141 |
|
90 | |||
142 | auto splitterInspectorIndex |
|
|||
143 | = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX; |
|
|||
144 |
|
||||
145 | auto currentSizes = m_Ui->splitter->sizes(); |
|
91 | auto currentSizes = m_Ui->splitter->sizes(); | |
146 | if (checked) { |
|
92 | if (checked) { | |
147 | // adjust sizes individually here, e.g. |
|
93 | // adjust sizes individually here, e.g. | |
148 | currentSizes[splitterInspectorIndex] -= lastInspectorSize.width(); |
|
94 | currentSizes[LEFTMAININSPECTORWIDGETSPLITTERINDEX] | |
149 | currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width(); |
|
95 | -= impl->m_LastOpenLeftInspectorSize.width(); | |
|
96 | currentSizes[VIEWPLITTERINDEX] += impl->m_LastOpenLeftInspectorSize.width(); | |||
150 | m_Ui->splitter->setSizes(currentSizes); |
|
97 | m_Ui->splitter->setSizes(currentSizes); | |
151 | } |
|
98 | } | |
152 | else { |
|
99 | else { | |
153 | // adjust sizes individually here, e.g. |
|
100 | // adjust sizes individually here, e.g. | |
154 | currentSizes[splitterInspectorIndex] += lastInspectorSize.width(); |
|
101 | currentSizes[LEFTMAININSPECTORWIDGETSPLITTERINDEX] | |
155 | currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width(); |
|
102 | += impl->m_LastOpenLeftInspectorSize.width(); | |
|
103 | currentSizes[VIEWPLITTERINDEX] -= impl->m_LastOpenLeftInspectorSize.width(); | |||
156 | m_Ui->splitter->setSizes(currentSizes); |
|
104 | m_Ui->splitter->setSizes(currentSizes); | |
157 | } |
|
105 | } | |
158 |
|
106 | |||
159 | }; |
|
107 | }; | |
160 |
|
108 | |||
|
109 | // Lambda that defines what's happened when clicking on the SidePaneInspector open button | |||
|
110 | auto openRightInspector = [this](bool checked) { | |||
161 |
|
111 | |||
162 | connect(openLeftInspectorAction, &QAction::triggered, |
|
112 | // Update of the last opened geometry | |
163 | [openInspector, openLeftInspectorAction](bool checked) { |
|
113 | if (checked) { | |
164 | openInspector(checked, false, openLeftInspectorAction); |
|
114 | impl->m_LastOpenRightInspectorSize = m_Ui->rightMainInspectorWidget->size(); | |
165 |
|
|
115 | } | |
166 | connect(openRightInspectorAction, &QAction::triggered, |
|
|||
167 | [openInspector, openRightInspectorAction](bool checked) { |
|
|||
168 | openInspector(checked, true, openRightInspectorAction); |
|
|||
169 | }); |
|
|||
170 |
|
116 | |||
171 | // //// // |
|
117 | auto startSize = impl->m_LastOpenRightInspectorSize; | |
172 | // Menu // |
|
118 | auto endSize = startSize; | |
173 | // //// // |
|
119 | endSize.setWidth(0); | |
174 | this->menuBar()->addAction(tr("File")); |
|
120 | ||
175 | auto toolsMenu = this->menuBar()->addMenu(tr("Tools")); |
|
121 | auto currentSizes = m_Ui->splitter->sizes(); | |
176 | toolsMenu->addAction(tr("Settings..."), [this]() { |
|
122 | if (checked) { | |
177 | // Loads settings |
|
123 | // adjust sizes individually here, e.g. | |
178 | impl->m_SettingsDialog->loadSettings(); |
|
124 | currentSizes[RIGHTMAININSPECTORWIDGETSPLITTERINDEX] | |
179 |
|
125 | -= impl->m_LastOpenRightInspectorSize.width(); | ||
180 | // Open settings dialog and save settings if the dialog is accepted |
|
126 | currentSizes[VIEWPLITTERINDEX] += impl->m_LastOpenRightInspectorSize.width(); | |
181 | if (impl->m_SettingsDialog->exec() == QDialog::Accepted) { |
|
127 | m_Ui->splitter->setSizes(currentSizes); | |
182 | impl->m_SettingsDialog->saveSettings(); |
|
128 | } | |
|
129 | else { | |||
|
130 | // adjust sizes individually here, e.g. | |||
|
131 | currentSizes[RIGHTMAININSPECTORWIDGETSPLITTERINDEX] | |||
|
132 | += impl->m_LastOpenRightInspectorSize.width(); | |||
|
133 | currentSizes[VIEWPLITTERINDEX] -= impl->m_LastOpenRightInspectorSize.width(); | |||
|
134 | m_Ui->splitter->setSizes(currentSizes); | |||
183 | } |
|
135 | } | |
184 |
|
136 | |||
185 |
} |
|
137 | }; | |
186 |
|
138 | |||
187 | auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar")); |
|
|||
188 |
|
139 | |||
189 | auto timeWidget = new TimeWidget{}; |
|
140 | QToolBar *leftSidePane = m_Ui->leftInspectorSidePane->sidePane(); | |
190 | mainToolBar->addWidget(timeWidget); |
|
141 | auto openLeftInspectorAction = leftSidePane->addAction( | |
|
142 | QIcon{ | |||
|
143 | ":/icones/openInspector.png", | |||
|
144 | }, | |||
|
145 | tr("Show/hide the left inspector"), openLeftInspector); | |||
191 |
|
146 | |||
192 | // //////// // |
|
147 | openLeftInspectorAction->setCheckable(true); | |
193 | // Settings // |
|
|||
194 | // //////// // |
|
|||
195 |
|
148 | |||
196 | // Registers "general settings" widget to the settings dialog |
|
149 | auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane(); | |
197 | impl->m_SettingsDialog->registerWidget(QStringLiteral("General"), |
|
150 | auto openRightInspectorAction = rightSidePane->addAction( | |
198 | impl->m_GeneralSettingsWidget); |
|
151 | QIcon{ | |
|
152 | ":/icones/openInspector.png", | |||
|
153 | }, | |||
|
154 | tr("Show/hide the right inspector"), openRightInspector); | |||
199 |
|
155 | |||
200 | // /////////// // |
|
156 | openRightInspectorAction->setCheckable(true); | |
201 | // Connections // |
|
|||
202 | // /////////// // |
|
|||
203 |
|
157 | |||
204 | // Controllers / controllers connections |
|
158 | this->menuBar()->addAction(tr("File")); | |
205 | connect(&sqpApp->timeController(), SIGNAL(timeUpdated(SqpRange)), &sqpApp->variableController(), |
|
159 | auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar")); | |
206 | SLOT(onDateTimeOnSelection(SqpRange))); |
|
160 | mainToolBar->addAction(QStringLiteral("A1")); | |
207 |
|
161 | |||
208 | // Widgets / controllers connections |
|
162 | // Widgets / controllers connections | |
209 |
|
||||
210 | // DataSource |
|
|||
211 | connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)), |
|
163 | connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)), | |
212 | m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem *))); |
|
164 | m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem *))); | |
213 |
|
165 | |||
214 | // Time |
|
166 | /* QLopGUI::registerMenuBar(menuBar()); | |
215 | connect(timeWidget, SIGNAL(timeUpdated(SqpRange)), &sqpApp->timeController(), |
|
167 | this->setWindowIcon(QIcon(":/sciqlopLOGO.svg")); | |
216 | SLOT(onTimeToUpdate(SqpRange))); |
|
168 | this->m_progressWidget = new QWidget(); | |
217 |
|
169 | this->m_progressLayout = new QVBoxLayout(this->m_progressWidget); | ||
218 | // Visualization |
|
170 | this->m_progressWidget->setLayout(this->m_progressLayout); | |
219 | connect(&sqpApp->visualizationController(), |
|
171 | this->m_progressWidget->setWindowModality(Qt::WindowModal); | |
220 | SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), m_Ui->view, |
|
172 | m_progressThreadIds = (int*) malloc(OMP_THREADS*sizeof(int)); | |
221 | SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable>))); |
|
173 | for(int i=0;i<OMP_THREADS;i++) | |
222 |
|
174 | { | ||
223 | connect(&sqpApp->visualizationController(), |
|
175 | this->m_progress.append(new QProgressBar(this->m_progressWidget)); | |
224 | SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)), m_Ui->view, |
|
176 | this->m_progress.last()->setMinimum(0); | |
225 | SLOT(onRangeChanged(std::shared_ptr<Variable>, const SqpRange &))); |
|
177 | this->m_progress.last()->setMaximum(100); | |
226 |
|
178 | this->m_progressLayout->addWidget(this->m_progress.last()); | ||
227 | // Widgets / widgets connections |
|
179 | this->m_progressWidget->hide(); | |
228 |
|
180 | this->m_progressThreadIds[i] = -1; | ||
229 | // For the following connections, we use DirectConnection to allow each widget that can |
|
181 | } | |
230 | // potentially attach a menu to the variable's menu to do so before this menu is displayed. |
|
182 | this->m_progressWidget->setWindowTitle("Loading File"); | |
231 | // The order of connections is also important, since it determines the order in which each |
|
183 | const QList<QLopService*>ServicesToLoad=QList<QLopService*>() | |
232 | // widget will attach its menu |
|
184 | << QLopCore::self() | |
233 | connect( |
|
185 | << QLopPlotManager::self() | |
234 | m_Ui->variableInspectorWidget, |
|
186 | << QLopCodecManager::self() | |
235 | SIGNAL(tableMenuAboutToBeDisplayed(QMenu *, const QVector<std::shared_ptr<Variable> > &)), |
|
187 | << FileDownloader::self() | |
236 | m_Ui->view, SLOT(attachVariableMenu(QMenu *, const QVector<std::shared_ptr<Variable> > &)), |
|
188 | << QLopDataBase::self() | |
237 | Qt::DirectConnection); |
|
189 | << SpaceData::self(); | |
|
190 | ||||
|
191 | CDFCodec::registerToManager(); | |||
|
192 | AMDATXTCodec::registerToManager(); | |||
|
193 | ||||
|
194 | ||||
|
195 | for(int i=0;i<ServicesToLoad.count();i++) | |||
|
196 | { | |||
|
197 | qDebug()<<ServicesToLoad.at(i)->serviceName(); | |||
|
198 | ServicesToLoad.at(i)->initialize(); //must be called before getGUI | |||
|
199 | QDockWidget* wdgt=ServicesToLoad.at(i)->getGUI(); | |||
|
200 | if(wdgt) | |||
|
201 | { | |||
|
202 | wdgt->setAllowedAreas(Qt::AllDockWidgetAreas); | |||
|
203 | this->addDockWidget(Qt::TopDockWidgetArea,wdgt); | |||
|
204 | } | |||
|
205 | PythonQt::self()->getMainModule().addObject(ServicesToLoad.at(i)->serviceName(),(QObject*)ServicesToLoad.at(i)); | |||
|
206 | }*/ | |||
238 | } |
|
207 | } | |
239 |
|
208 | |||
240 | MainWindow::~MainWindow() |
|
209 | MainWindow::~MainWindow() | |
241 | { |
|
210 | { | |
242 | } |
|
211 | } | |
243 |
|
212 | |||
|
213 | ||||
244 | void MainWindow::changeEvent(QEvent *e) |
|
214 | void MainWindow::changeEvent(QEvent *e) | |
245 | { |
|
215 | { | |
246 | QMainWindow::changeEvent(e); |
|
216 | QMainWindow::changeEvent(e); |
@@ -11,7 +11,7 | |||||
11 | </rect> |
|
11 | </rect> | |
12 | </property> |
|
12 | </property> | |
13 | <property name="windowTitle"> |
|
13 | <property name="windowTitle"> | |
14 |
<string> |
|
14 | <string>QLop</string> | |
15 | </property> |
|
15 | </property> | |
16 | <property name="dockNestingEnabled"> |
|
16 | <property name="dockNestingEnabled"> | |
17 | <bool>true</bool> |
|
17 | <bool>true</bool> | |
@@ -126,7 +126,7 | |||||
126 | <x>0</x> |
|
126 | <x>0</x> | |
127 | <y>0</y> |
|
127 | <y>0</y> | |
128 | <width>800</width> |
|
128 | <width>800</width> | |
129 |
<height>2 |
|
129 | <height>26</height> | |
130 | </rect> |
|
130 | </rect> | |
131 | </property> |
|
131 | </property> | |
132 | </widget> |
|
132 | </widget> |
@@ -1,5 +1,3 | |||||
1 | # Ignore false positive relative to App macro |
|
1 | # Ignore false positive relative to App macro | |
2 | \.h:\d+:.IPSIS_S04.*found: Ui |
|
2 | \.h:\d+:.IPSIS_S04.*found: Ui | |
3 |
|
3 | |||
4 | # Ignore false positive relative to macros |
|
|||
5 | Main\.cpp:\d+:.*IPSIS_S04_VARIABLE.*found: (__ppc64__) No newline at end of file |
|
@@ -21,7 +21,7 INCLUDE("cmake/sciqlop_params.cmake") | |||||
21 | # |
|
21 | # | |
22 | # Configure the compiler |
|
22 | # Configure the compiler | |
23 | # |
|
23 | # | |
24 |
|
|
24 | INCLUDE("cmake/compiler/compiler.cmake") | |
25 |
|
25 | |||
26 | # |
|
26 | # | |
27 | # Find all necessary dependencies |
|
27 | # Find all necessary dependencies |
@@ -1,3 +1,17 | |||||
|
1 | # | |||
|
2 | # Sciqlop_modules.cmake | |||
|
3 | # | |||
|
4 | # Set ouptut directories | |||
|
5 | # | |||
|
6 | SET (EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/dist) | |||
|
7 | SET (LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/dist) | |||
|
8 | IF (UNIX) | |||
|
9 | SET (CONFIG_OUTPUT_PATH $ENV{HOME}/.config/QtProject) | |||
|
10 | ELSEIF(WIN32) | |||
|
11 | SET (CONFIG_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/dist/app/QtProject) | |||
|
12 | ELSE() | |||
|
13 | SET (CONFIG_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/dist) | |||
|
14 | ENDIF() | |||
1 |
|
15 | |||
2 | if(BUILD_TESTS) |
|
16 | if(BUILD_TESTS) | |
3 | INCLUDE ("cmake/sciqlop_code_coverage.cmake") |
|
17 | INCLUDE ("cmake/sciqlop_code_coverage.cmake") | |
@@ -26,18 +40,6 IF(BUILD_PLUGINS) | |||||
26 | set(sciqlop-mockplugin_DIR "${CMAKE_SOURCE_DIR}/plugins/mockplugin/cmake") |
|
40 | set(sciqlop-mockplugin_DIR "${CMAKE_SOURCE_DIR}/plugins/mockplugin/cmake") | |
27 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-mockplugin_DIR}") |
|
41 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-mockplugin_DIR}") | |
28 | ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugins/mockplugin") |
|
42 | ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugins/mockplugin") | |
29 |
|
||||
30 | set(sciqlop-amda_DIR "${CMAKE_SOURCE_DIR}/plugins/amda/cmake") |
|
|||
31 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-amda_DIR}") |
|
|||
32 | ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugins/amda") |
|
|||
33 |
|
||||
34 | # Temporary target to copy to plugins dir |
|
|||
35 | find_package(sciqlop-mockplugin) |
|
|||
36 | find_package(sciqlop-amda) |
|
|||
37 | ADD_CUSTOM_TARGET(plugins |
|
|||
38 | COMMAND ${CMAKE_COMMAND} -E copy ${SCIQLOP-MOCKPLUGIN_LIBRARIES} "${LIBRARY_OUTPUT_PATH}/plugins/${SCIQLOP-MOCKPLUGIN_LIBRARIES_NAME}" |
|
|||
39 | COMMAND ${CMAKE_COMMAND} -E copy ${SCIQLOP-AMDA_LIBRARIES} "${LIBRARY_OUTPUT_PATH}/plugins/${SCIQLOP-AMDA_LIBRARIES_NAME}" |
|
|||
40 | ) |
|
|||
41 | ENDIF(BUILD_PLUGINS) |
|
43 | ENDIF(BUILD_PLUGINS) | |
42 |
|
44 | |||
43 | # LOGGER |
|
45 | # LOGGER |
@@ -26,11 +26,11 SET (CPACK_PACKAGE_VERSION_MAJOR "${SCIQLOP_VERSION_MAJOR}") | |||||
26 | SET (CPACK_PACKAGE_VERSION_MINOR "${SCIQLOP_VERSION_MINOR}") |
|
26 | SET (CPACK_PACKAGE_VERSION_MINOR "${SCIQLOP_VERSION_MINOR}") | |
27 | SET (CPACK_PACKAGE_VERSION_PATCH "${SCIQLOP_VERSION_PATCH}${SCIQLOP_VERSION_SUFFIX}") |
|
27 | SET (CPACK_PACKAGE_VERSION_PATCH "${SCIQLOP_VERSION_PATCH}${SCIQLOP_VERSION_SUFFIX}") | |
28 | SET (CPACK_PACKAGE_VERSION "${SCIQLOP_VERSION}") |
|
28 | SET (CPACK_PACKAGE_VERSION "${SCIQLOP_VERSION}") | |
29 |
SET (CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/ |
|
29 | SET (CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE) | |
30 | SET (CPACK_PACKAGE_CONTACT "nicolas.aunai@lpp.polytechnique.fr") |
|
30 | SET (CPACK_PACKAGE_CONTACT "nicolas.aunai@lpp.polytechnique.fr") | |
31 | SET(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/README.md) |
|
31 | SET(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/README.md) | |
32 | # SET(CPACK_RESOURCE_FILE_WELCOME ${CMAKE_CURRENT_SOURCE_DIR}/WARN.txt) |
|
32 | # SET(CPACK_RESOURCE_FILE_WELCOME ${CMAKE_CURRENT_SOURCE_DIR}/WARN.txt) | |
33 |
SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/ |
|
33 | SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE) | |
34 | # SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME}-${PROJECT_VERSION}) |
|
34 | # SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME}-${PROJECT_VERSION}) | |
35 | SET(FULLBUILD ON) |
|
35 | SET(FULLBUILD ON) | |
36 |
|
36 |
@@ -7,7 +7,7 SET(WINDEPLOYQT_ARGS --${CMAKE_BUILD_TYPE_TO_LOWER} --list mapping --no-system-d | |||||
7 | #ENDFOREACH() |
|
7 | #ENDFOREACH() | |
8 |
|
8 | |||
9 | EXECUTE_PROCESS( |
|
9 | EXECUTE_PROCESS( | |
10 |
COMMAND windeployqt ${WINDEPLOYQT_ARGS} |
|
10 | COMMAND windeployqt ${WINDEPLOYQT_ARGS} ${SCIQLOP_EXE_LOCATION} | |
11 | OUTPUT_VARIABLE QT_FILES |
|
11 | OUTPUT_VARIABLE QT_FILES | |
12 | ) |
|
12 | ) | |
13 |
|
13 |
@@ -44,30 +44,6 else() | |||||
44 | set(libRootDirForceValue) |
|
44 | set(libRootDirForceValue) | |
45 | endif() |
|
45 | endif() | |
46 |
|
46 | |||
47 | # |
|
|||
48 | # Sciqlop_modules.cmake |
|
|||
49 | # |
|
|||
50 | # Set ouptut directories |
|
|||
51 | # |
|
|||
52 | IF (UNIX) |
|
|||
53 | # 32 or 64 bits compiler |
|
|||
54 | IF( CMAKE_SIZEOF_VOID_P EQUAL 8 ) |
|
|||
55 | SET(defaultLib "lib64/sciqlop") |
|
|||
56 | ELSE() |
|
|||
57 | SET(defaultLib "lib/sciqlop") |
|
|||
58 | ENDIF() |
|
|||
59 | SET (EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/bin) |
|
|||
60 | SET (CONFIG_OUTPUT_PATH $ENV{HOME}/.config/QtProject) |
|
|||
61 | SET (LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${defaultLib}) |
|
|||
62 | ELSEIF(WIN32) |
|
|||
63 | SET (EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/dist) |
|
|||
64 | SET (LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/dist) |
|
|||
65 | SET (CONFIG_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/dist/app/QtProject) |
|
|||
66 | ELSE() |
|
|||
67 | SET (EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/dist) |
|
|||
68 | SET (CONFIG_OUTPUT_PATH $ENV{HOME}/.config/QtProject) |
|
|||
69 | SET (LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/dist) |
|
|||
70 | ENDIF() |
|
|||
71 |
|
47 | |||
72 |
|
48 | |||
73 | # |
|
49 | # | |
@@ -78,51 +54,33 OPTION (BUILD_SHARED_LIBS "Build the shared libraries" ON) | |||||
78 | # Generate position independant code (-fPIC) |
|
54 | # Generate position independant code (-fPIC) | |
79 | SET(CMAKE_POSITION_INDEPENDENT_CODE TRUE) |
|
55 | SET(CMAKE_POSITION_INDEPENDENT_CODE TRUE) | |
80 |
|
56 | |||
81 |
|
57 | # | ||
82 |
|
58 | # Configure installation directories | ||
83 | # Configuration for make install |
|
59 | # | |
84 |
|
||||
85 | set(PROJECT_PLUGIN_PREFIX "SciQlop") |
|
|||
86 |
|
||||
87 | IF (UNIX) |
|
60 | IF (UNIX) | |
88 | SET(CMAKE_INSTALL_PREFIX "/usr/local/${PROJECT_PLUGIN_PREFIX}") |
|
|||
89 | SET(defaultBin "bin") |
|
61 | SET(defaultBin "bin") | |
90 | SET(defaultInc "include/sciqlop") |
|
62 | SET(defaultInc "include/sciqlop") | |
91 |
|
63 | |||
92 | # 32 or 64 bits compiler |
|
64 | # 32 or 64 bits compiler | |
93 | IF( CMAKE_SIZEOF_VOID_P EQUAL 8 ) |
|
65 | IF( CMAKE_SIZEOF_VOID_P EQUAL 8 ) | |
94 | SET(defaultLib "lib64") |
|
66 | SET(defaultLib "lib64/sciqlop") | |
95 | SET(defaultPluginsLib "lib64/${PROJECT_PLUGIN_PREFIX}") |
|
|||
96 | ELSE() |
|
67 | ELSE() | |
97 | SET(defaultLib "lib/") |
|
68 | SET(defaultLib "lib/sciqlop") | |
98 | SET(defaultPluginsLib "lib/${PROJECT_PLUGIN_PREFIX}") |
|
|||
99 | ENDIF() |
|
69 | ENDIF() | |
100 |
|
70 | |||
101 |
SET(defaultDoc "share/docs/ |
|
71 | SET(defaultDoc "share/docs/sciqlop") | |
102 | ELSE() |
|
72 | ELSE() | |
103 | SET(defaultBin "bin") |
|
73 | SET(defaultBin "bin") | |
104 |
SET(defaultInc "include/ |
|
74 | SET(defaultInc "include/sciqlop") | |
105 | SET(defaultLib "lib") |
|
75 | SET(defaultLib "lib/sciqlop") | |
106 | SET(defaultPluginsLib "lib/${PROJECT_PLUGIN_PREFIX}") |
|
76 | SET(defaultDoc "docs/sciqlop") | |
107 | SET(defaultDoc "docs/${PROJECT_PLUGIN_PREFIX}") |
|
|||
108 | ENDIF() |
|
77 | ENDIF() | |
109 |
|
78 | |||
110 | SET(INSTALL_BINARY_DIR "${defaultBin}" CACHE STRING |
|
79 | SET(INSTALL_BINARY_DIR "${defaultBin}" CACHE STRING | |
111 | "Installation directory for binaries") |
|
80 | "Installation directory for binaries") | |
112 | SET(INSTALL_LIBRARY_DIR "${defaultLib}" CACHE STRING |
|
81 | SET(INSTALL_LIBRARY_DIR "${defaultLib}" CACHE STRING | |
113 | "Installation directory for libraries") |
|
82 | "Installation directory for libraries") | |
114 | SET(INSTALL_PLUGINS_LIBRARY_DIR "${defaultPluginsLib}" CACHE STRING |
|
|||
115 | "Installation directory for libraries") |
|
|||
116 | SET(INSTALL_INCLUDE_DIR "${defaultInc}" CACHE STRING |
|
83 | SET(INSTALL_INCLUDE_DIR "${defaultInc}" CACHE STRING | |
117 | "Installation directory for headers") |
|
84 | "Installation directory for headers") | |
118 | SET(INSTALL_DOCUMENTATION_DIR "${defaultDoc}" CACHE STRING |
|
85 | SET(INSTALL_DOCUMENTATION_DIR "${defaultDoc}" CACHE STRING | |
119 | "Installation directory for documentations") |
|
86 | "Installation directory for documentations") | |
120 |
|
||||
121 |
|
||||
122 | # Set the rpath when installing |
|
|||
123 | SET(CMAKE_SKIP_BUILD_RPATH FALSE) |
|
|||
124 | SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) |
|
|||
125 | SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBRARY_DIR}") |
|
|||
126 | SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) |
|
|||
127 |
|
||||
128 | message("Install RPATH: ${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBRARY_DIR}") |
|
@@ -24,14 +24,11 INCLUDE_DIRECTORIES(${SCIQLOP-PLUGIN_INCLUDE_DIR}) | |||||
24 | # |
|
24 | # | |
25 | # Find Qt modules |
|
25 | # Find Qt modules | |
26 | # |
|
26 | # | |
27 |
SCIQLOP_FIND_QT(Core |
|
27 | SCIQLOP_FIND_QT(Core) | |
28 |
|
28 | |||
29 | # |
|
29 | # | |
30 | # Compile the library library |
|
30 | # Compile the library library | |
31 | # |
|
31 | # | |
32 |
|
||||
33 | ADD_DEFINITIONS(-DCORE_LIB) |
|
|||
34 |
|
||||
35 | FILE (GLOB_RECURSE MODULE_SOURCES |
|
32 | FILE (GLOB_RECURSE MODULE_SOURCES | |
36 | ${INCLUDES_DIR}/*.h |
|
33 | ${INCLUDES_DIR}/*.h | |
37 | ${SOURCES_DIR}/*.c |
|
34 | ${SOURCES_DIR}/*.c | |
@@ -42,14 +39,8 ADD_LIBRARY(${SQPCORE_LIBRARY_NAME} ${MODULE_SOURCES}) | |||||
42 | set_property(TARGET ${SQPCORE_LIBRARY_NAME} PROPERTY CXX_STANDARD 14) |
|
39 | set_property(TARGET ${SQPCORE_LIBRARY_NAME} PROPERTY CXX_STANDARD 14) | |
43 | set_property(TARGET ${SQPCORE_LIBRARY_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) |
|
40 | set_property(TARGET ${SQPCORE_LIBRARY_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) | |
44 | TARGET_LINK_LIBRARIES(${SQPCORE_LIBRARY_NAME}) |
|
41 | TARGET_LINK_LIBRARIES(${SQPCORE_LIBRARY_NAME}) | |
45 |
qt5_use_modules(${SQPCORE_LIBRARY_NAME} Core |
|
42 | qt5_use_modules(${SQPCORE_LIBRARY_NAME} Core) | |
46 |
|
43 | |||
47 | INSTALL(TARGETS ${SQPCORE_LIBRARY_NAME} |
|
|||
48 | RUNTIME DESTINATION ${INSTALL_BINARY_DIR} |
|
|||
49 | LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR} |
|
|||
50 | ARCHIVE DESTINATION ${INSTALL_LIBRARY_DIR} |
|
|||
51 | ) |
|
|||
52 |
|
||||
53 | # From cmake documentation: http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html |
|
44 | # From cmake documentation: http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html | |
54 | # Entries in the COMPILE_DEFINITIONS are prefixed with -D or /D and added to the compile line in an unspecified order. |
|
45 | # Entries in the COMPILE_DEFINITIONS are prefixed with -D or /D and added to the compile line in an unspecified order. | |
55 | # The DEFINE_SYMBOL target property is also added as a compile definition as a special convenience case for SHARED and MODULE library targets |
|
46 | # The DEFINE_SYMBOL target property is also added as a compile definition as a special convenience case for SHARED and MODULE library targets |
@@ -1,8 +1,6 | |||||
1 | #ifndef SCIQLOP_DATASOURCECONTROLLER_H |
|
1 | #ifndef SCIQLOP_DATASOURCECONTROLLER_H | |
2 | #define SCIQLOP_DATASOURCECONTROLLER_H |
|
2 | #define SCIQLOP_DATASOURCECONTROLLER_H | |
3 |
|
3 | |||
4 | #include "CoreGlobal.h" |
|
|||
5 |
|
||||
6 | #include <QLoggingCategory> |
|
4 | #include <QLoggingCategory> | |
7 | #include <QObject> |
|
5 | #include <QObject> | |
8 | #include <QUuid> |
|
6 | #include <QUuid> | |
@@ -12,7 +10,6 | |||||
12 | Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController) |
|
10 | Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController) | |
13 |
|
11 | |||
14 | class DataSourceItem; |
|
12 | class DataSourceItem; | |
15 | class IDataProvider; |
|
|||
16 |
|
13 | |||
17 | /** |
|
14 | /** | |
18 | * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This |
|
15 | * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This | |
@@ -21,7 +18,7 class IDataProvider; | |||||
21 | * source) then others specifics method will be able to access it. You can load a data source driver |
|
18 | * source) then others specifics method will be able to access it. You can load a data source driver | |
22 | * plugin then create a data source. |
|
19 | * plugin then create a data source. | |
23 | */ |
|
20 | */ | |
24 |
class |
|
21 | class DataSourceController : public QObject { | |
25 | Q_OBJECT |
|
22 | Q_OBJECT | |
26 | public: |
|
23 | public: | |
27 | explicit DataSourceController(QObject *parent = 0); |
|
24 | explicit DataSourceController(QObject *parent = 0); | |
@@ -39,31 +36,12 public: | |||||
39 | * Sets the structure of a data source. The controller takes ownership of the structure. |
|
36 | * Sets the structure of a data source. The controller takes ownership of the structure. | |
40 | * @param dataSourceUid the unique id with which the data source has been registered into the |
|
37 | * @param dataSourceUid the unique id with which the data source has been registered into the | |
41 | * controller. If it is invalid, the method has no effect. |
|
38 | * controller. If it is invalid, the method has no effect. | |
42 |
* @param dataSourceItem the structure of the data source |
|
39 | * @param dataSourceItem the structure of the data source | |
43 | * @sa registerDataSource() |
|
40 | * @sa registerDataSource() | |
44 | */ |
|
41 | */ | |
45 | void setDataSourceItem(const QUuid &dataSourceUid, |
|
42 | void setDataSourceItem(const QUuid &dataSourceUid, | |
46 | std::unique_ptr<DataSourceItem> dataSourceItem) noexcept; |
|
43 | std::unique_ptr<DataSourceItem> dataSourceItem) noexcept; | |
47 |
|
44 | |||
48 | /** |
|
|||
49 | * Sets the data provider used to retrieve data from of a data source. The controller takes |
|
|||
50 | * ownership of the provider. |
|
|||
51 | * @param dataSourceUid the unique id with which the data source has been registered into the |
|
|||
52 | * controller. If it is invalid, the method has no effect. |
|
|||
53 | * @param dataProvider the provider of the data source |
|
|||
54 | * @sa registerDataSource() |
|
|||
55 | */ |
|
|||
56 | void setDataProvider(const QUuid &dataSourceUid, |
|
|||
57 | std::unique_ptr<IDataProvider> dataProvider) noexcept; |
|
|||
58 |
|
||||
59 | /** |
|
|||
60 | * Loads an item (product) as a variable in SciQlop |
|
|||
61 | * @param dataSourceUid the unique id of the data source containing the item. It is used to get |
|
|||
62 | * the data provider associated to the data source, and pass it to for the variable creation |
|
|||
63 | * @param productItem the item to load |
|
|||
64 | */ |
|
|||
65 | void loadProductItem(const QUuid &dataSourceUid, const DataSourceItem &productItem) noexcept; |
|
|||
66 |
|
||||
67 | public slots: |
|
45 | public slots: | |
68 | /// Manage init/end of the controller |
|
46 | /// Manage init/end of the controller | |
69 | void initialize(); |
|
47 | void initialize(); | |
@@ -73,17 +51,6 signals: | |||||
73 | /// Signal emitted when a structure has been set for a data source |
|
51 | /// Signal emitted when a structure has been set for a data source | |
74 | void dataSourceItemSet(DataSourceItem *dataSourceItem); |
|
52 | void dataSourceItemSet(DataSourceItem *dataSourceItem); | |
75 |
|
53 | |||
76 | /** |
|
|||
77 | * Signal emitted when a variable creation is asked for a product |
|
|||
78 | * @param variableName the name of the variable |
|
|||
79 | * @param variableMetadata the metadata of the variable |
|
|||
80 | * @param variableProvider the provider that will be used to retrieve the data of the variable |
|
|||
81 | * (can be null) |
|
|||
82 | */ |
|
|||
83 | void variableCreationRequested(const QString &variableName, |
|
|||
84 | const QVariantHash &variableMetadata, |
|
|||
85 | std::shared_ptr<IDataProvider> variableProvider); |
|
|||
86 |
|
||||
87 | private: |
|
54 | private: | |
88 | void waitForFinish(); |
|
55 | void waitForFinish(); | |
89 |
|
56 |
@@ -1,19 +1,15 | |||||
1 | #ifndef SCIQLOP_DATASOURCEITEM_H |
|
1 | #ifndef SCIQLOP_DATASOURCEITEM_H | |
2 | #define SCIQLOP_DATASOURCEITEM_H |
|
2 | #define SCIQLOP_DATASOURCEITEM_H | |
3 |
|
3 | |||
4 | #include "CoreGlobal.h" |
|
|||
5 |
|
||||
6 | #include <Common/spimpl.h> |
|
4 | #include <Common/spimpl.h> | |
7 |
|
5 | |||
8 | #include <QVariant> |
|
6 | #include <QVariant> | |
9 | #include <QVector> |
|
7 | #include <QVector> | |
10 |
|
8 | |||
11 | class DataSourceItemAction; |
|
|||
12 |
|
||||
13 | /** |
|
9 | /** | |
14 | * Possible types of an item |
|
10 | * Possible types of an item | |
15 | */ |
|
11 | */ | |
16 |
enum class DataSourceItemType { NODE, PRODUCT |
|
12 | enum class DataSourceItemType { NODE, PRODUCT }; | |
17 |
|
13 | |||
18 | /** |
|
14 | /** | |
19 | * @brief The DataSourceItem class aims to represent a structure element of a data source. |
|
15 | * @brief The DataSourceItem class aims to represent a structure element of a data source. | |
@@ -21,23 +17,9 enum class DataSourceItemType { NODE, PRODUCT, COMPONENT }; | |||||
21 | * containing other DataSourceItem objects (children). |
|
17 | * containing other DataSourceItem objects (children). | |
22 | * For each DataSourceItem can be associated a set of data representing it. |
|
18 | * For each DataSourceItem can be associated a set of data representing it. | |
23 | */ |
|
19 | */ | |
24 |
class |
|
20 | class DataSourceItem { | |
25 | public: |
|
21 | public: | |
26 | /// Key associated with the name of the item |
|
22 | explicit DataSourceItem(DataSourceItemType type, QVector<QVariant> data = {}); | |
27 | static const QString NAME_DATA_KEY; |
|
|||
28 |
|
||||
29 | explicit DataSourceItem(DataSourceItemType type, const QString &name); |
|
|||
30 | explicit DataSourceItem(DataSourceItemType type, QVariantHash data = {}); |
|
|||
31 |
|
||||
32 | /// @return the actions of the item as a vector |
|
|||
33 | QVector<DataSourceItemAction *> actions() const noexcept; |
|
|||
34 |
|
||||
35 | /** |
|
|||
36 | * Adds an action to the item. The item takes ownership of the action, and the action is |
|
|||
37 | * automatically associated to the item |
|
|||
38 | * @param action the action to add |
|
|||
39 | */ |
|
|||
40 | void addAction(std::unique_ptr<DataSourceItemAction> action) noexcept; |
|
|||
41 |
|
23 | |||
42 | /** |
|
24 | /** | |
43 | * Adds a child to the item. The item takes ownership of the child. |
|
25 | * Adds a child to the item. The item takes ownership of the child. | |
@@ -55,18 +37,11 public: | |||||
55 | int childCount() const noexcept; |
|
37 | int childCount() const noexcept; | |
56 |
|
38 | |||
57 | /** |
|
39 | /** | |
58 |
* Get the data associated to a |
|
40 | * Get the data associated to an index | |
59 |
* @param |
|
41 | * @param dataIndex the index to search | |
60 |
* @return the data found if |
|
42 | * @return the data found if index is valid, default QVariant otherwise | |
61 | */ |
|
43 | */ | |
62 |
QVariant data( |
|
44 | QVariant data(int dataIndex) const noexcept; | |
63 |
|
||||
64 | /// Gets all data |
|
|||
65 | QVariantHash data() const noexcept; |
|
|||
66 |
|
||||
67 | bool isRoot() const noexcept; |
|
|||
68 |
|
||||
69 | QString name() const noexcept; |
|
|||
70 |
|
45 | |||
71 | /** |
|
46 | /** | |
72 | * Get the item's parent |
|
47 | * Get the item's parent | |
@@ -74,26 +49,8 public: | |||||
74 | */ |
|
49 | */ | |
75 | DataSourceItem *parentItem() const noexcept; |
|
50 | DataSourceItem *parentItem() const noexcept; | |
76 |
|
51 | |||
77 | /** |
|
|||
78 | * Gets the item's root |
|
|||
79 | * @return the top parent, the item itself if it's the root item |
|
|||
80 | */ |
|
|||
81 | const DataSourceItem &rootItem() const noexcept; |
|
|||
82 |
|
||||
83 | /** |
|
|||
84 | * Sets or appends a value to a key |
|
|||
85 | * @param key the key |
|
|||
86 | * @param value the value |
|
|||
87 | * @param append if true, the value is added to the values already existing for the key, |
|
|||
88 | * otherwise it replaces the existing values |
|
|||
89 | */ |
|
|||
90 | void setData(const QString &key, const QVariant &value, bool append = false) noexcept; |
|
|||
91 |
|
||||
92 | DataSourceItemType type() const noexcept; |
|
52 | DataSourceItemType type() const noexcept; | |
93 |
|
53 | |||
94 | bool operator==(const DataSourceItem &other); |
|
|||
95 | bool operator!=(const DataSourceItem &other); |
|
|||
96 |
|
||||
97 | private: |
|
54 | private: | |
98 | class DataSourceItemPrivate; |
|
55 | class DataSourceItemPrivate; | |
99 | spimpl::unique_impl_ptr<DataSourceItemPrivate> impl; |
|
56 | spimpl::unique_impl_ptr<DataSourceItemPrivate> impl; |
@@ -1,8 +1,6 | |||||
1 | #ifndef SCIQLOP_PLUGINMANAGER_H |
|
1 | #ifndef SCIQLOP_PLUGINMANAGER_H | |
2 | #define SCIQLOP_PLUGINMANAGER_H |
|
2 | #define SCIQLOP_PLUGINMANAGER_H | |
3 |
|
3 | |||
4 | #include "CoreGlobal.h" |
|
|||
5 |
|
||||
6 | #include <Common/spimpl.h> |
|
4 | #include <Common/spimpl.h> | |
7 |
|
5 | |||
8 | #include <QLoggingCategory> |
|
6 | #include <QLoggingCategory> | |
@@ -14,7 +12,7 Q_DECLARE_LOGGING_CATEGORY(LOG_PluginManager) | |||||
14 | /** |
|
12 | /** | |
15 | * @brief The PluginManager class aims to handle the plugins loaded dynamically into SciQLop. |
|
13 | * @brief The PluginManager class aims to handle the plugins loaded dynamically into SciQLop. | |
16 | */ |
|
14 | */ | |
17 |
class |
|
15 | class PluginManager { | |
18 | public: |
|
16 | public: | |
19 | explicit PluginManager(); |
|
17 | explicit PluginManager(); | |
20 |
|
18 |
@@ -1,83 +1,20 | |||||
1 | #ifndef SCIQLOP_VARIABLE_H |
|
1 | #ifndef SCIQLOP_VARIABLE_H | |
2 | #define SCIQLOP_VARIABLE_H |
|
2 | #define SCIQLOP_VARIABLE_H | |
3 |
|
3 | |||
4 | #include "CoreGlobal.h" |
|
4 | #include <QString> | |
5 |
|
||||
6 | #include <Data/DataSeriesIterator.h> |
|
|||
7 | #include <Data/SqpRange.h> |
|
|||
8 |
|
||||
9 | #include <QLoggingCategory> |
|
|||
10 | #include <QObject> |
|
|||
11 |
|
||||
12 | #include <Common/MetaTypes.h> |
|
|||
13 | #include <Common/spimpl.h> |
|
|||
14 |
|
||||
15 | Q_DECLARE_LOGGING_CATEGORY(LOG_Variable) |
|
|||
16 |
|
||||
17 | class IDataSeries; |
|
|||
18 | class QString; |
|
|||
19 |
|
5 | |||
20 | /** |
|
6 | /** | |
21 |
* @brief The Variable |
|
7 | * @brief The Variable struct represents a variable in SciQlop. | |
22 | */ |
|
8 | */ | |
23 | class SCIQLOP_CORE_EXPORT Variable : public QObject { |
|
9 | struct Variable { | |
24 |
|
10 | explicit Variable(const QString &name, const QString &unit, const QString &mission) | ||
25 | Q_OBJECT |
|
11 | : m_Name{name}, m_Unit{unit}, m_Mission{mission} | |
26 |
|
12 | { | ||
27 | public: |
|
13 | } | |
28 | explicit Variable(const QString &name, const QVariantHash &metadata = {}); |
|
14 | ||
29 |
|
15 | QString m_Name; | ||
30 | /// Copy ctor |
|
16 | QString m_Unit; | |
31 | explicit Variable(const Variable &other); |
|
17 | QString m_Mission; | |
32 |
|
||||
33 | std::shared_ptr<Variable> clone() const; |
|
|||
34 |
|
||||
35 | QString name() const noexcept; |
|
|||
36 | void setName(const QString &name) noexcept; |
|
|||
37 | SqpRange range() const noexcept; |
|
|||
38 | void setRange(const SqpRange &range) noexcept; |
|
|||
39 | SqpRange cacheRange() const noexcept; |
|
|||
40 | void setCacheRange(const SqpRange &cacheRange) noexcept; |
|
|||
41 |
|
||||
42 | /// @return the number of points hold by the variable. The number of points is updated each time |
|
|||
43 | /// the data series changes |
|
|||
44 | int nbPoints() const noexcept; |
|
|||
45 |
|
||||
46 | /// Returns the real range of the variable, i.e. the min and max x-axis values of the data |
|
|||
47 | /// series between the range of the variable. The real range is updated each time the variable |
|
|||
48 | /// range or the data series changed |
|
|||
49 | /// @return the real range, invalid range if the data series is null or empty |
|
|||
50 | /// @sa setDataSeries() |
|
|||
51 | /// @sa setRange() |
|
|||
52 | SqpRange realRange() const noexcept; |
|
|||
53 |
|
||||
54 | /// @return the data of the variable, nullptr if there is no data |
|
|||
55 | std::shared_ptr<IDataSeries> dataSeries() const noexcept; |
|
|||
56 |
|
||||
57 | QVariantHash metadata() const noexcept; |
|
|||
58 |
|
||||
59 | bool contains(const SqpRange &range) const noexcept; |
|
|||
60 | bool intersect(const SqpRange &range) const noexcept; |
|
|||
61 | bool isInside(const SqpRange &range) const noexcept; |
|
|||
62 |
|
||||
63 | bool cacheContains(const SqpRange &range) const noexcept; |
|
|||
64 | bool cacheIntersect(const SqpRange &range) const noexcept; |
|
|||
65 | bool cacheIsInside(const SqpRange &range) const noexcept; |
|
|||
66 |
|
||||
67 | QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept; |
|
|||
68 | QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept; |
|
|||
69 | void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept; |
|
|||
70 |
|
||||
71 | signals: |
|
|||
72 | void updated(); |
|
|||
73 |
|
||||
74 | private: |
|
|||
75 | class VariablePrivate; |
|
|||
76 | spimpl::unique_impl_ptr<VariablePrivate> impl; |
|
|||
77 | }; |
|
18 | }; | |
78 |
|
19 | |||
79 | // Required for using shared_ptr in signals/slots |
|
|||
80 | SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>) |
|
|||
81 | SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >) |
|
|||
82 |
|
||||
83 | #endif // SCIQLOP_VARIABLE_H |
|
20 | #endif // SCIQLOP_VARIABLE_H |
@@ -1,122 +1,31 | |||||
1 | #ifndef SCIQLOP_VARIABLECONTROLLER_H |
|
1 | #ifndef SCIQLOP_VARIABLECONTROLLER_H | |
2 | #define SCIQLOP_VARIABLECONTROLLER_H |
|
2 | #define SCIQLOP_VARIABLECONTROLLER_H | |
3 |
|
3 | |||
4 | #include "CoreGlobal.h" |
|
|||
5 |
|
||||
6 | #include <Data/AcquisitionDataPacket.h> |
|
|||
7 | #include <Data/SqpRange.h> |
|
|||
8 |
|
||||
9 | #include <QLoggingCategory> |
|
4 | #include <QLoggingCategory> | |
10 | #include <QObject> |
|
5 | #include <QObject> | |
11 | #include <QUuid> |
|
|||
12 |
|
6 | |||
13 | #include <Common/spimpl.h> |
|
7 | #include <Common/spimpl.h> | |
14 |
|
8 | |||
15 | class IDataProvider; |
|
|||
16 | class QItemSelectionModel; |
|
|||
17 | class TimeController; |
|
|||
18 | class Variable; |
|
9 | class Variable; | |
19 | class VariableModel; |
|
|||
20 |
|
||||
21 | Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController) |
|
10 | Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController) | |
22 |
|
11 | |||
23 |
|
||||
24 | /** |
|
|||
25 | * Possible types of zoom operation |
|
|||
26 | */ |
|
|||
27 | enum class AcquisitionZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown }; |
|
|||
28 |
|
||||
29 |
|
||||
30 | /** |
|
12 | /** | |
31 | * @brief The VariableController class aims to handle the variables in SciQlop. |
|
13 | * @brief The VariableController class aims to handle the variables in SciQlop. | |
32 | */ |
|
14 | */ | |
33 |
class |
|
15 | class VariableController : public QObject { | |
34 | Q_OBJECT |
|
16 | Q_OBJECT | |
35 | public: |
|
17 | public: | |
36 | explicit VariableController(QObject *parent = 0); |
|
18 | explicit VariableController(QObject *parent = 0); | |
37 | virtual ~VariableController(); |
|
19 | virtual ~VariableController(); | |
38 |
|
20 | |||
39 | VariableModel *variableModel() noexcept; |
|
|||
40 | QItemSelectionModel *variableSelectionModel() noexcept; |
|
|||
41 |
|
||||
42 | void setTimeController(TimeController *timeController) noexcept; |
|
|||
43 |
|
||||
44 | /** |
|
|||
45 | * Clones the variable passed in parameter and adds the duplicate to the controller |
|
|||
46 | * @param variable the variable to duplicate |
|
|||
47 | * @return the duplicate created, nullptr if the variable couldn't be created |
|
|||
48 | */ |
|
|||
49 | std::shared_ptr<Variable> cloneVariable(std::shared_ptr<Variable> variable) noexcept; |
|
|||
50 |
|
||||
51 | /** |
|
|||
52 | * Deletes from the controller the variable passed in parameter. |
|
|||
53 | * |
|
|||
54 | * Delete a variable includes: |
|
|||
55 | * - the deletion of the various references to the variable in SciQlop |
|
|||
56 | * - the deletion of the model variable |
|
|||
57 | * - the deletion of the provider associated with the variable |
|
|||
58 | * - removing the cache associated with the variable |
|
|||
59 | * |
|
|||
60 | * @param variable the variable to delete from the controller. |
|
|||
61 | */ |
|
|||
62 | void deleteVariable(std::shared_ptr<Variable> variable) noexcept; |
|
|||
63 |
|
||||
64 | /** |
|
21 | /** | |
65 | * Deletes from the controller the variables passed in parameter. |
|
22 | * Creates a new variable | |
66 | * @param variables the variables to delete from the controller. |
|
|||
67 | * @sa deleteVariable() |
|
|||
68 | */ |
|
|||
69 | void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept; |
|
|||
70 |
|
||||
71 |
|
||||
72 | static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange); |
|
|||
73 | signals: |
|
|||
74 | /// Signal emitted when a variable is about to be deleted from the controller |
|
|||
75 | void variableAboutToBeDeleted(std::shared_ptr<Variable> variable); |
|
|||
76 |
|
||||
77 | /// Signal emitted when a data acquisition is requested on a range for a variable |
|
|||
78 | void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range); |
|
|||
79 |
|
||||
80 | /// Signal emitted when a sub range of the cacheRange of the variable can be displayed |
|
|||
81 | void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range); |
|
|||
82 |
|
||||
83 | public slots: |
|
|||
84 | /// Request the data loading of the variable whithin range |
|
|||
85 | void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range, |
|
|||
86 | const SqpRange &oldRange, bool synchronise); |
|
|||
87 | /** |
|
|||
88 | * Creates a new variable and adds it to the model |
|
|||
89 | * @param name the name of the new variable |
|
23 | * @param name the name of the new variable | |
90 | * @param metadata the metadata of the new variable |
|
24 | * @return the variable if it was created successfully, nullptr otherwise | |
91 | * @param provider the data provider for the new variable |
|
|||
92 | * @return the pointer to the new variable or nullptr if the creation failed |
|
|||
93 | */ |
|
25 | */ | |
94 |
|
|
26 | Variable *createVariable(const QString &name) noexcept; | |
95 | std::shared_ptr<IDataProvider> provider) noexcept; |
|
|||
96 |
|
||||
97 | /// Update the temporal parameters of every selected variable to dateTime |
|
|||
98 | void onDateTimeOnSelection(const SqpRange &dateTime); |
|
|||
99 |
|
||||
100 |
|
||||
101 | void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested, |
|
|||
102 | const SqpRange &cacheRangeRequested, |
|
|||
103 | QVector<AcquisitionDataPacket> dataAcquired); |
|
|||
104 |
|
||||
105 | void onVariableRetrieveDataInProgress(QUuid identifier, double progress); |
|
|||
106 |
|
||||
107 | /// Cancel the current request for the variable |
|
|||
108 | void onAbortProgressRequested(std::shared_ptr<Variable> variable); |
|
|||
109 | void onAbortAcquisitionRequested(QUuid vIdentifier); |
|
|||
110 |
|
||||
111 | // synchronization group methods |
|
|||
112 | void onAddSynchronizationGroupId(QUuid synchronizationGroupId); |
|
|||
113 | void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId); |
|
|||
114 | void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId); |
|
|||
115 |
|
||||
116 | /// Desynchronizes the variable of the group whose identifier is passed in parameter |
|
|||
117 | /// @remarks the method does nothing if the variable is not part of the group |
|
|||
118 | void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId); |
|
|||
119 |
|
27 | |||
|
28 | public slots: | |||
120 | void initialize(); |
|
29 | void initialize(); | |
121 | void finalize(); |
|
30 | void finalize(); | |
122 |
|
31 |
@@ -1,95 +1,31 | |||||
1 | #ifndef SCIQLOP_VARIABLEMODEL_H |
|
1 | #ifndef SCIQLOP_VARIABLEMODEL_H | |
2 | #define SCIQLOP_VARIABLEMODEL_H |
|
2 | #define SCIQLOP_VARIABLEMODEL_H | |
3 |
|
3 | |||
4 |
#include |
|
4 | #include <Common/spimpl.h> | |
5 |
|
||||
6 | #include <Data/SqpRange.h> |
|
|||
7 |
|
5 | |||
8 | #include <QAbstractTableModel> |
|
|||
9 | #include <QLoggingCategory> |
|
6 | #include <QLoggingCategory> | |
10 |
|
7 | |||
11 | #include <Common/MetaTypes.h> |
|
|||
12 | #include <Common/spimpl.h> |
|
|||
13 |
|
||||
14 | Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel) |
|
8 | Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel) | |
15 |
|
9 | |||
16 | enum VariableRoles { ProgressRole = Qt::UserRole }; |
|
|||
17 |
|
||||
18 |
|
||||
19 | class IDataSeries; |
|
|||
20 | class Variable; |
|
10 | class Variable; | |
21 |
|
11 | |||
22 | /** |
|
12 | /** | |
23 | * @brief The VariableModel class aims to hold the variables that have been created in SciQlop |
|
13 | * @brief The VariableModel class aims to hold the variables that have been created in SciQlop | |
24 | */ |
|
14 | */ | |
25 | class SCIQLOP_CORE_EXPORT VariableModel : public QAbstractTableModel { |
|
15 | class VariableModel { | |
26 | Q_OBJECT |
|
|||
27 | public: |
|
16 | public: | |
28 |
explicit VariableModel( |
|
17 | explicit VariableModel(); | |
29 |
|
||||
30 | /** |
|
|||
31 | * Adds an existing variable in the model. |
|
|||
32 | * @param variable the variable to add. |
|
|||
33 | * @remarks the variable's name is modified to avoid name duplicates |
|
|||
34 | * @remarks this method does nothing if the variable already exists in the model |
|
|||
35 | */ |
|
|||
36 | void addVariable(std::shared_ptr<Variable> variable) noexcept; |
|
|||
37 |
|
||||
38 | /** |
|
|||
39 | * Checks that a variable is contained in the model |
|
|||
40 | * @param variable the variable to check |
|
|||
41 | * @return true if the variable is in the model, false otherwise |
|
|||
42 | */ |
|
|||
43 | bool containsVariable(std::shared_ptr<Variable> variable) const noexcept; |
|
|||
44 |
|
18 | |||
45 | /** |
|
19 | /** | |
46 | * Creates a new variable in the model |
|
20 | * Creates a new variable in the model | |
47 | * @param name the name of the new variable |
|
21 | * @param name the name of the new variable | |
48 | * @param metadata the metadata associated to the new variable |
|
22 | * @return the variable if it was created successfully, nullptr otherwise | |
49 | * @return the pointer to the new variable |
|
|||
50 | */ |
|
|||
51 | std::shared_ptr<Variable> createVariable(const QString &name, |
|
|||
52 | const QVariantHash &metadata) noexcept; |
|
|||
53 |
|
||||
54 | /** |
|
|||
55 | * Deletes a variable from the model, if it exists |
|
|||
56 | * @param variable the variable to delete |
|
|||
57 | */ |
|
23 | */ | |
58 | void deleteVariable(std::shared_ptr<Variable> variable) noexcept; |
|
24 | Variable *createVariable(const QString &name) noexcept; | |
59 |
|
||||
60 |
|
||||
61 | std::shared_ptr<Variable> variable(int index) const; |
|
|||
62 | std::vector<std::shared_ptr<Variable> > variables() const; |
|
|||
63 |
|
||||
64 | void setDataProgress(std::shared_ptr<Variable> variable, double progress); |
|
|||
65 |
|
||||
66 |
|
||||
67 | // /////////////////////////// // |
|
|||
68 | // QAbstractTableModel methods // |
|
|||
69 | // /////////////////////////// // |
|
|||
70 |
|
||||
71 | virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override; |
|
|||
72 | virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override; |
|
|||
73 | virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; |
|
|||
74 | virtual QVariant headerData(int section, Qt::Orientation orientation, |
|
|||
75 | int role = Qt::DisplayRole) const override; |
|
|||
76 |
|
||||
77 |
|
||||
78 | void abortProgress(const QModelIndex &index); |
|
|||
79 |
|
||||
80 | signals: |
|
|||
81 | void abortProgessRequested(std::shared_ptr<Variable> variable); |
|
|||
82 |
|
25 | |||
83 | private: |
|
26 | private: | |
84 | class VariableModelPrivate; |
|
27 | class VariableModelPrivate; | |
85 | spimpl::unique_impl_ptr<VariableModelPrivate> impl; |
|
28 | spimpl::unique_impl_ptr<VariableModelPrivate> impl; | |
86 |
|
||||
87 | private slots: |
|
|||
88 | /// Slot called when data of a variable has been updated |
|
|||
89 | void onVariableUpdated() noexcept; |
|
|||
90 | }; |
|
29 | }; | |
91 |
|
30 | |||
92 | // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal |
|
|||
93 | SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>) |
|
|||
94 |
|
||||
95 | #endif // SCIQLOP_VARIABLEMODEL_H |
|
31 | #endif // SCIQLOP_VARIABLEMODEL_H |
@@ -1,10 +1,6 | |||||
1 | #ifndef SCIQLOP_VISUALIZATIONCONTROLLER_H |
|
1 | #ifndef SCIQLOP_VISUALIZATIONCONTROLLER_H | |
2 | #define SCIQLOP_VISUALIZATIONCONTROLLER_H |
|
2 | #define SCIQLOP_VISUALIZATIONCONTROLLER_H | |
3 |
|
3 | |||
4 | #include "CoreGlobal.h" |
|
|||
5 |
|
||||
6 | #include <Data/SqpRange.h> |
|
|||
7 |
|
||||
8 | #include <QLoggingCategory> |
|
4 | #include <QLoggingCategory> | |
9 | #include <QObject> |
|
5 | #include <QObject> | |
10 | #include <QUuid> |
|
6 | #include <QUuid> | |
@@ -14,7 +10,6 | |||||
14 | Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationController) |
|
10 | Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationController) | |
15 |
|
11 | |||
16 | class DataSourceItem; |
|
12 | class DataSourceItem; | |
17 | class Variable; |
|
|||
18 |
|
13 | |||
19 | /** |
|
14 | /** | |
20 | * @brief The VisualizationController class aims to make the link between SciQlop and its plugins. |
|
15 | * @brief The VisualizationController class aims to make the link between SciQlop and its plugins. | |
@@ -23,19 +18,12 class Variable; | |||||
23 | * plugin source) then others specifics method will be able to access it. You can load a data source |
|
18 | * plugin source) then others specifics method will be able to access it. You can load a data source | |
24 | * driver plugin then create a data source. |
|
19 | * driver plugin then create a data source. | |
25 | */ |
|
20 | */ | |
26 |
class |
|
21 | class VisualizationController : public QObject { | |
27 | Q_OBJECT |
|
22 | Q_OBJECT | |
28 | public: |
|
23 | public: | |
29 | explicit VisualizationController(QObject *parent = 0); |
|
24 | explicit VisualizationController(QObject *parent = 0); | |
30 | virtual ~VisualizationController(); |
|
25 | virtual ~VisualizationController(); | |
31 |
|
26 | |||
32 | signals: |
|
|||
33 | /// Signal emitted when a variable is about to be deleted from SciQlop |
|
|||
34 | void variableAboutToBeDeleted(std::shared_ptr<Variable> variable); |
|
|||
35 |
|
||||
36 | /// Signal emitted when a data acquisition is requested on a range for a variable |
|
|||
37 | void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range); |
|
|||
38 |
|
||||
39 | public slots: |
|
27 | public slots: | |
40 | /// Manage init/end of the controller |
|
28 | /// Manage init/end of the controller | |
41 | void initialize(); |
|
29 | void initialize(); |
@@ -1,7 +1,5 | |||||
1 |
#include |
|
1 | #include <DataSource/DataSourceController.h> | |
2 |
#include |
|
2 | #include <DataSource/DataSourceItem.h> | |
3 |
|
||||
4 | #include <Data/IDataProvider.h> |
|
|||
5 |
|
3 | |||
6 | #include <QMutex> |
|
4 | #include <QMutex> | |
7 | #include <QThread> |
|
5 | #include <QThread> | |
@@ -11,28 +9,6 | |||||
11 |
|
9 | |||
12 | Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController") |
|
10 | Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController") | |
13 |
|
11 | |||
14 | namespace { |
|
|||
15 |
|
||||
16 | /** |
|
|||
17 | * Builds the metadata of the variable that will be generated from the loading of an item |
|
|||
18 | * @param dataSourceItem the data source item from which to generate the metadata |
|
|||
19 | * @return the metadata of the variable |
|
|||
20 | */ |
|
|||
21 | QVariantHash variableMetadata(const DataSourceItem &dataSourceItem) |
|
|||
22 | { |
|
|||
23 | // Variable metadata contains... |
|
|||
24 |
|
||||
25 | // ... all metadata of the item |
|
|||
26 | auto result = dataSourceItem.data(); |
|
|||
27 |
|
||||
28 | // ... and the name of the plugin, recovered from root item |
|
|||
29 | result.insert(QStringLiteral("plugin"), dataSourceItem.rootItem().name()); |
|
|||
30 |
|
||||
31 | return result; |
|
|||
32 | } |
|
|||
33 |
|
||||
34 | } // namespace |
|
|||
35 |
|
||||
36 | class DataSourceController::DataSourceControllerPrivate { |
|
12 | class DataSourceController::DataSourceControllerPrivate { | |
37 | public: |
|
13 | public: | |
38 | QMutex m_WorkingMutex; |
|
14 | QMutex m_WorkingMutex; | |
@@ -40,10 +16,6 public: | |||||
40 | QHash<QUuid, QString> m_DataSources; |
|
16 | QHash<QUuid, QString> m_DataSources; | |
41 | /// Data sources structures |
|
17 | /// Data sources structures | |
42 | std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems; |
|
18 | std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems; | |
43 | /// Data providers registered |
|
|||
44 | /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and |
|
|||
45 | /// continue to live without necessarily the data source controller |
|
|||
46 | std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders; |
|
|||
47 | }; |
|
19 | }; | |
48 |
|
20 | |||
49 | DataSourceController::DataSourceController(QObject *parent) |
|
21 | DataSourceController::DataSourceController(QObject *parent) | |
@@ -71,14 +43,7 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) no | |||||
71 | void DataSourceController::setDataSourceItem( |
|
43 | void DataSourceController::setDataSourceItem( | |
72 | const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept |
|
44 | const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept | |
73 | { |
|
45 | { | |
74 | if (!dataSourceItem) { |
|
|||
75 | qCWarning(LOG_DataSourceController()) |
|
|||
76 | << tr("Data source item can't be registered (null item)"); |
|
|||
77 | return; |
|
|||
78 | } |
|
|||
79 |
|
||||
80 | if (impl->m_DataSources.contains(dataSourceUid)) { |
|
46 | if (impl->m_DataSources.contains(dataSourceUid)) { | |
81 | // The data provider is implicitly converted to a shared_ptr |
|
|||
82 | impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem))); |
|
47 | impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem))); | |
83 |
|
48 | |||
84 | // Retrieves the data source item to emit the signal with it |
|
49 | // Retrieves the data source item to emit the signal with it | |
@@ -94,36 +59,6 void DataSourceController::setDataSourceItem( | |||||
94 | } |
|
59 | } | |
95 | } |
|
60 | } | |
96 |
|
61 | |||
97 | void DataSourceController::setDataProvider(const QUuid &dataSourceUid, |
|
|||
98 | std::unique_ptr<IDataProvider> dataProvider) noexcept |
|
|||
99 | { |
|
|||
100 | if (impl->m_DataSources.contains(dataSourceUid)) { |
|
|||
101 | impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider))); |
|
|||
102 | } |
|
|||
103 | else { |
|
|||
104 | qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data " |
|
|||
105 | "source has been registered with the uid") |
|
|||
106 | .arg(dataSourceUid.toString()); |
|
|||
107 | } |
|
|||
108 | } |
|
|||
109 |
|
||||
110 | void DataSourceController::loadProductItem(const QUuid &dataSourceUid, |
|
|||
111 | const DataSourceItem &productItem) noexcept |
|
|||
112 | { |
|
|||
113 | if (productItem.type() == DataSourceItemType::PRODUCT |
|
|||
114 | || productItem.type() == DataSourceItemType::COMPONENT) { |
|
|||
115 | /// Retrieves the data provider of the data source (if any) |
|
|||
116 | auto it = impl->m_DataProviders.find(dataSourceUid); |
|
|||
117 | auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr; |
|
|||
118 |
|
||||
119 | emit variableCreationRequested(productItem.name(), variableMetadata(productItem), |
|
|||
120 | dataProvider); |
|
|||
121 | } |
|
|||
122 | else { |
|
|||
123 | qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product"); |
|
|||
124 | } |
|
|||
125 | } |
|
|||
126 |
|
||||
127 | void DataSourceController::initialize() |
|
62 | void DataSourceController::initialize() | |
128 | { |
|
63 | { | |
129 | qCDebug(LOG_DataSourceController()) << tr("DataSourceController init") |
|
64 | qCDebug(LOG_DataSourceController()) << tr("DataSourceController init") |
@@ -1,49 +1,24 | |||||
1 | #include <DataSource/DataSourceItem.h> |
|
1 | #include <DataSource/DataSourceItem.h> | |
2 | #include <DataSource/DataSourceItemAction.h> |
|
|||
3 |
|
2 | |||
4 | #include <QVector> |
|
3 | #include <QVector> | |
5 |
|
4 | |||
6 | const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name"); |
|
|||
7 |
|
||||
8 | struct DataSourceItem::DataSourceItemPrivate { |
|
5 | struct DataSourceItem::DataSourceItemPrivate { | |
9 |
explicit DataSourceItemPrivate(DataSourceItemType type, QVariant |
|
6 | explicit DataSourceItemPrivate(DataSourceItemType type, QVector<QVariant> data) | |
10 |
: m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)} |
|
7 | : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)} | |
11 | { |
|
8 | { | |
12 | } |
|
9 | } | |
13 |
|
10 | |||
14 | DataSourceItem *m_Parent; |
|
11 | DataSourceItem *m_Parent; | |
15 | std::vector<std::unique_ptr<DataSourceItem> > m_Children; |
|
12 | std::vector<std::unique_ptr<DataSourceItem> > m_Children; | |
16 | DataSourceItemType m_Type; |
|
13 | DataSourceItemType m_Type; | |
17 |
QVariant |
|
14 | QVector<QVariant> m_Data; | |
18 | std::vector<std::unique_ptr<DataSourceItemAction> > m_Actions; |
|
|||
19 | }; |
|
15 | }; | |
20 |
|
16 | |||
21 |
DataSourceItem::DataSourceItem(DataSourceItemType type, con |
|
17 | DataSourceItem::DataSourceItem(DataSourceItemType type, QVector<QVariant> data) | |
22 | : DataSourceItem{type, QVariantHash{{NAME_DATA_KEY, name}}} |
|
|||
23 | { |
|
|||
24 | } |
|
|||
25 |
|
||||
26 | DataSourceItem::DataSourceItem(DataSourceItemType type, QVariantHash data) |
|
|||
27 | : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))} |
|
18 | : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))} | |
28 | { |
|
19 | { | |
29 | } |
|
20 | } | |
30 |
|
21 | |||
31 | QVector<DataSourceItemAction *> DataSourceItem::actions() const noexcept |
|
|||
32 | { |
|
|||
33 | auto result = QVector<DataSourceItemAction *>{}; |
|
|||
34 |
|
||||
35 | std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions), |
|
|||
36 | std::back_inserter(result), [](const auto &action) { return action.get(); }); |
|
|||
37 |
|
||||
38 | return result; |
|
|||
39 | } |
|
|||
40 |
|
||||
41 | void DataSourceItem::addAction(std::unique_ptr<DataSourceItemAction> action) noexcept |
|
|||
42 | { |
|
|||
43 | action->setDataSourceItem(this); |
|
|||
44 | impl->m_Actions.push_back(std::move(action)); |
|
|||
45 | } |
|
|||
46 |
|
||||
47 | void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept |
|
22 | void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept | |
48 | { |
|
23 | { | |
49 | child->impl->m_Parent = this; |
|
24 | child->impl->m_Parent = this; | |
@@ -65,24 +40,9 int DataSourceItem::childCount() const noexcept | |||||
65 | return impl->m_Children.size(); |
|
40 | return impl->m_Children.size(); | |
66 | } |
|
41 | } | |
67 |
|
42 | |||
68 |
QVariant DataSourceItem::data( |
|
43 | QVariant DataSourceItem::data(int dataIndex) const noexcept | |
69 | { |
|
|||
70 | return impl->m_Data.value(key); |
|
|||
71 | } |
|
|||
72 |
|
||||
73 | QVariantHash DataSourceItem::data() const noexcept |
|
|||
74 | { |
|
|||
75 | return impl->m_Data; |
|
|||
76 | } |
|
|||
77 |
|
||||
78 | bool DataSourceItem::isRoot() const noexcept |
|
|||
79 | { |
|
|||
80 | return impl->m_Parent == nullptr; |
|
|||
81 | } |
|
|||
82 |
|
||||
83 | QString DataSourceItem::name() const noexcept |
|
|||
84 | { |
|
44 | { | |
85 | return data(NAME_DATA_KEY).toString(); |
|
45 | return impl->m_Data.value(dataIndex); | |
86 | } |
|
46 | } | |
87 |
|
47 | |||
88 | DataSourceItem *DataSourceItem::parentItem() const noexcept |
|
48 | DataSourceItem *DataSourceItem::parentItem() const noexcept | |
@@ -90,56 +50,7 DataSourceItem *DataSourceItem::parentItem() const noexcept | |||||
90 | return impl->m_Parent; |
|
50 | return impl->m_Parent; | |
91 | } |
|
51 | } | |
92 |
|
52 | |||
93 | const DataSourceItem &DataSourceItem::rootItem() const noexcept |
|
|||
94 | { |
|
|||
95 | return isRoot() ? *this : parentItem()->rootItem(); |
|
|||
96 | } |
|
|||
97 |
|
||||
98 | void DataSourceItem::setData(const QString &key, const QVariant &value, bool append) noexcept |
|
|||
99 | { |
|
|||
100 | auto it = impl->m_Data.constFind(key); |
|
|||
101 | if (append && it != impl->m_Data.constEnd()) { |
|
|||
102 | // Case of an existing value to which we want to add to the new value |
|
|||
103 | if (it->canConvert<QVariantList>()) { |
|
|||
104 | auto variantList = it->value<QVariantList>(); |
|
|||
105 | variantList.append(value); |
|
|||
106 |
|
||||
107 | impl->m_Data.insert(key, variantList); |
|
|||
108 | } |
|
|||
109 | else { |
|
|||
110 | impl->m_Data.insert(key, QVariantList{*it, value}); |
|
|||
111 | } |
|
|||
112 | } |
|
|||
113 | else { |
|
|||
114 | // Other cases : |
|
|||
115 | // - new value in map OR |
|
|||
116 | // - replacement of an existing value (not appending) |
|
|||
117 | impl->m_Data.insert(key, value); |
|
|||
118 | } |
|
|||
119 | } |
|
|||
120 |
|
||||
121 | DataSourceItemType DataSourceItem::type() const noexcept |
|
53 | DataSourceItemType DataSourceItem::type() const noexcept | |
122 | { |
|
54 | { | |
123 | return impl->m_Type; |
|
55 | return impl->m_Type; | |
124 | } |
|
56 | } | |
125 |
|
||||
126 | bool DataSourceItem::operator==(const DataSourceItem &other) |
|
|||
127 | { |
|
|||
128 | // Compares items' attributes |
|
|||
129 | if (std::tie(impl->m_Type, impl->m_Data) == std::tie(other.impl->m_Type, other.impl->m_Data)) { |
|
|||
130 | // Compares contents of items' children |
|
|||
131 | return std::equal(std::cbegin(impl->m_Children), std::cend(impl->m_Children), |
|
|||
132 | std::cbegin(other.impl->m_Children), |
|
|||
133 | [](const auto &itemChild, const auto &otherChild) { |
|
|||
134 | return *itemChild == *otherChild; |
|
|||
135 | }); |
|
|||
136 | } |
|
|||
137 | else { |
|
|||
138 | return false; |
|
|||
139 | } |
|
|||
140 | } |
|
|||
141 |
|
||||
142 | bool DataSourceItem::operator!=(const DataSourceItem &other) |
|
|||
143 | { |
|
|||
144 | return !(*this == other); |
|
|||
145 | } |
|
@@ -106,15 +106,9 PluginManager::PluginManager() : impl{spimpl::make_unique_impl<PluginManagerPriv | |||||
106 | void PluginManager::loadPlugins(const QDir &pluginDir) |
|
106 | void PluginManager::loadPlugins(const QDir &pluginDir) | |
107 | { |
|
107 | { | |
108 | // Load plugins |
|
108 | // Load plugins | |
109 | auto pluginInfoList |
|
109 | auto pluginInfoList = pluginDir.entryInfoList(QDir::Files, QDir::Name); | |
110 | = pluginDir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); |
|
110 | for (auto pluginInfo : qAsConst(pluginInfoList)) { | |
111 | for (auto entryInfo : qAsConst(pluginInfoList)) { |
|
111 | impl->loadPlugin(pluginInfo.absoluteFilePath()); | |
112 | if (entryInfo.isDir()) { |
|
|||
113 | this->loadPlugins(QDir{entryInfo.absoluteFilePath()}); |
|
|||
114 | } |
|
|||
115 | else if (QLibrary::isLibrary(entryInfo.absoluteFilePath())) { |
|
|||
116 | impl->loadPlugin(entryInfo.absoluteFilePath()); |
|
|||
117 | } |
|
|||
118 | } |
|
112 | } | |
119 | } |
|
113 | } | |
120 |
|
114 |
This diff has been collapsed as it changes many lines, (809 lines changed) Show them Hide them | |||||
@@ -1,532 +1,40 | |||||
1 | #include <Variable/Variable.h> |
|
|||
2 | #include <Variable/VariableAcquisitionWorker.h> |
|
|||
3 | #include <Variable/VariableCacheStrategy.h> |
|
|||
4 | #include <Variable/VariableCacheStrategyFactory.h> |
|
|||
5 |
|
|
1 | #include <Variable/VariableController.h> | |
6 | #include <Variable/VariableModel.h> |
|
2 | #include <Variable/VariableModel.h> | |
7 | #include <Variable/VariableSynchronizationGroup.h> |
|
|||
8 |
|
||||
9 | #include <Data/DataProviderParameters.h> |
|
|||
10 | #include <Data/IDataProvider.h> |
|
|||
11 | #include <Data/IDataSeries.h> |
|
|||
12 | #include <Data/VariableRequest.h> |
|
|||
13 | #include <Time/TimeController.h> |
|
|||
14 |
|
3 | |||
15 | #include <QMutex> |
|
4 | #include <QMutex> | |
16 | #include <QThread> |
|
5 | #include <QThread> | |
17 | #include <QUuid> |
|
|||
18 | #include <QtCore/QItemSelectionModel> |
|
|||
19 |
|
||||
20 | #include <deque> |
|
|||
21 | #include <set> |
|
|||
22 | #include <unordered_map> |
|
|||
23 |
|
6 | |||
24 | Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController") |
|
7 | Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController") | |
25 |
|
8 | |||
26 | namespace { |
|
|||
27 |
|
||||
28 | SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange, |
|
|||
29 | const SqpRange &oldGraphRange) |
|
|||
30 | { |
|
|||
31 | auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange); |
|
|||
32 |
|
||||
33 | auto varRangeRequested = varRange; |
|
|||
34 | switch (zoomType) { |
|
|||
35 | case AcquisitionZoomType::ZoomIn: { |
|
|||
36 | auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart; |
|
|||
37 | auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd; |
|
|||
38 | varRangeRequested.m_TStart += deltaLeft; |
|
|||
39 | varRangeRequested.m_TEnd -= deltaRight; |
|
|||
40 | break; |
|
|||
41 | } |
|
|||
42 |
|
||||
43 | case AcquisitionZoomType::ZoomOut: { |
|
|||
44 | auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart; |
|
|||
45 | auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd; |
|
|||
46 | varRangeRequested.m_TStart -= deltaLeft; |
|
|||
47 | varRangeRequested.m_TEnd += deltaRight; |
|
|||
48 | break; |
|
|||
49 | } |
|
|||
50 | case AcquisitionZoomType::PanRight: { |
|
|||
51 | auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd; |
|
|||
52 | varRangeRequested.m_TStart += deltaRight; |
|
|||
53 | varRangeRequested.m_TEnd += deltaRight; |
|
|||
54 | break; |
|
|||
55 | } |
|
|||
56 | case AcquisitionZoomType::PanLeft: { |
|
|||
57 | auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart; |
|
|||
58 | varRangeRequested.m_TStart -= deltaLeft; |
|
|||
59 | varRangeRequested.m_TEnd -= deltaLeft; |
|
|||
60 | break; |
|
|||
61 | } |
|
|||
62 | case AcquisitionZoomType::Unknown: { |
|
|||
63 | qCCritical(LOG_VariableController()) |
|
|||
64 | << VariableController::tr("Impossible to synchronize: zoom type unknown"); |
|
|||
65 | break; |
|
|||
66 | } |
|
|||
67 | default: |
|
|||
68 | qCCritical(LOG_VariableController()) << VariableController::tr( |
|
|||
69 | "Impossible to synchronize: zoom type not take into account"); |
|
|||
70 | // No action |
|
|||
71 | break; |
|
|||
72 | } |
|
|||
73 |
|
||||
74 | return varRangeRequested; |
|
|||
75 | } |
|
|||
76 | } |
|
|||
77 |
|
||||
78 | struct VariableController::VariableControllerPrivate { |
|
9 | struct VariableController::VariableControllerPrivate { | |
79 |
explicit VariableControllerPrivate( |
|
10 | explicit VariableControllerPrivate() | |
80 | : m_WorkingMutex{}, |
|
11 | : m_WorkingMutex{}, m_VariableModel{std::make_unique<VariableModel>()} | |
81 | m_VariableModel{new VariableModel{parent}}, |
|
|||
82 | m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}}, |
|
|||
83 | // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()}, |
|
|||
84 | m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy( |
|
|||
85 | CacheStrategy::SingleThreshold)}, |
|
|||
86 | m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()}, |
|
|||
87 | q{parent} |
|
|||
88 | { |
|
12 | { | |
89 |
|
||||
90 | m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread); |
|
|||
91 | m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread"); |
|
|||
92 | } |
|
13 | } | |
93 |
|
14 | |||
94 |
|
||||
95 | virtual ~VariableControllerPrivate() |
|
|||
96 | { |
|
|||
97 | qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction"); |
|
|||
98 | m_VariableAcquisitionWorkerThread.quit(); |
|
|||
99 | m_VariableAcquisitionWorkerThread.wait(); |
|
|||
100 | } |
|
|||
101 |
|
||||
102 |
|
||||
103 | void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested, |
|
|||
104 | QUuid varRequestId); |
|
|||
105 |
|
||||
106 | QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable, |
|
|||
107 | const SqpRange &dateTime); |
|
|||
108 |
|
||||
109 | std::shared_ptr<Variable> findVariable(QUuid vIdentifier); |
|
|||
110 | std::shared_ptr<IDataSeries> |
|
|||
111 | retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector); |
|
|||
112 |
|
||||
113 | void registerProvider(std::shared_ptr<IDataProvider> provider); |
|
|||
114 |
|
||||
115 | void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest); |
|
|||
116 | QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries); |
|
|||
117 | void updateVariableRequest(QUuid varRequestId); |
|
|||
118 | void cancelVariableRequest(QUuid varRequestId); |
|
|||
119 |
|
||||
120 | QMutex m_WorkingMutex; |
|
15 | QMutex m_WorkingMutex; | |
121 | /// Variable model. The VariableController has the ownership |
|
16 | std::unique_ptr<VariableModel> m_VariableModel; | |
122 | VariableModel *m_VariableModel; |
|
|||
123 | QItemSelectionModel *m_VariableSelectionModel; |
|
|||
124 |
|
||||
125 |
|
||||
126 | TimeController *m_TimeController{nullptr}; |
|
|||
127 | std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy; |
|
|||
128 | std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker; |
|
|||
129 | QThread m_VariableAcquisitionWorkerThread; |
|
|||
130 |
|
||||
131 | std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> > |
|
|||
132 | m_VariableToProviderMap; |
|
|||
133 | std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap; |
|
|||
134 | std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> > |
|
|||
135 | m_GroupIdToVariableSynchronizationGroupMap; |
|
|||
136 | std::map<QUuid, QUuid> m_VariableIdGroupIdMap; |
|
|||
137 | std::set<std::shared_ptr<IDataProvider> > m_ProviderSet; |
|
|||
138 |
|
||||
139 | std::map<QUuid, std::map<QUuid, VariableRequest> > m_VarRequestIdToVarIdVarRequestMap; |
|
|||
140 |
|
||||
141 | std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap; |
|
|||
142 |
|
||||
143 |
|
||||
144 | VariableController *q; |
|
|||
145 | }; |
|
17 | }; | |
146 |
|
18 | |||
147 |
|
||||
148 | VariableController::VariableController(QObject *parent) |
|
19 | VariableController::VariableController(QObject *parent) | |
149 |
: QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>( |
|
20 | : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>()} | |
150 | { |
|
|||
151 | qCDebug(LOG_VariableController()) << tr("VariableController construction") |
|
|||
152 | << QThread::currentThread(); |
|
|||
153 |
|
||||
154 | connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this, |
|
|||
155 | &VariableController::onAbortProgressRequested); |
|
|||
156 |
|
||||
157 | connect(impl->m_VariableAcquisitionWorker.get(), |
|
|||
158 | &VariableAcquisitionWorker::variableCanceledRequested, this, |
|
|||
159 | &VariableController::onAbortAcquisitionRequested); |
|
|||
160 |
|
||||
161 | connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this, |
|
|||
162 | &VariableController::onDataProvided); |
|
|||
163 | connect(impl->m_VariableAcquisitionWorker.get(), |
|
|||
164 | &VariableAcquisitionWorker::variableRequestInProgress, this, |
|
|||
165 | &VariableController::onVariableRetrieveDataInProgress); |
|
|||
166 |
|
||||
167 |
|
||||
168 | connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started, |
|
|||
169 | impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize); |
|
|||
170 | connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished, |
|
|||
171 | impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize); |
|
|||
172 |
|
||||
173 |
|
||||
174 | impl->m_VariableAcquisitionWorkerThread.start(); |
|
|||
175 | } |
|
|||
176 |
|
||||
177 | VariableController::~VariableController() |
|
|||
178 | { |
|
|||
179 | qCDebug(LOG_VariableController()) << tr("VariableController destruction") |
|
|||
180 | << QThread::currentThread(); |
|
|||
181 | this->waitForFinish(); |
|
|||
182 | } |
|
|||
183 |
|
||||
184 | VariableModel *VariableController::variableModel() noexcept |
|
|||
185 | { |
|
|||
186 | return impl->m_VariableModel; |
|
|||
187 | } |
|
|||
188 |
|
||||
189 | QItemSelectionModel *VariableController::variableSelectionModel() noexcept |
|
|||
190 | { |
|
|||
191 | return impl->m_VariableSelectionModel; |
|
|||
192 | } |
|
|||
193 |
|
||||
194 | void VariableController::setTimeController(TimeController *timeController) noexcept |
|
|||
195 | { |
|
|||
196 | impl->m_TimeController = timeController; |
|
|||
197 | } |
|
|||
198 |
|
||||
199 | std::shared_ptr<Variable> |
|
|||
200 | VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept |
|
|||
201 | { |
|
|||
202 | if (impl->m_VariableModel->containsVariable(variable)) { |
|
|||
203 | // Clones variable |
|
|||
204 | auto duplicate = variable->clone(); |
|
|||
205 |
|
||||
206 | // Adds clone to model |
|
|||
207 | impl->m_VariableModel->addVariable(duplicate); |
|
|||
208 |
|
||||
209 | // Generates clone identifier |
|
|||
210 | impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid(); |
|
|||
211 |
|
||||
212 | // Registers provider |
|
|||
213 | auto variableProvider = impl->m_VariableToProviderMap.at(variable); |
|
|||
214 | auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr; |
|
|||
215 |
|
||||
216 | impl->m_VariableToProviderMap[duplicate] = duplicateProvider; |
|
|||
217 | if (duplicateProvider) { |
|
|||
218 | impl->registerProvider(duplicateProvider); |
|
|||
219 | } |
|
|||
220 |
|
||||
221 | return duplicate; |
|
|||
222 | } |
|
|||
223 | else { |
|
|||
224 | qCCritical(LOG_VariableController()) |
|
|||
225 | << tr("Can't create duplicate of variable %1: variable not registered in the model") |
|
|||
226 | .arg(variable->name()); |
|
|||
227 | return nullptr; |
|
|||
228 | } |
|
|||
229 | } |
|
|||
230 |
|
||||
231 | void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept |
|
|||
232 | { |
|
21 | { | |
233 | if (!variable) { |
|
|||
234 | qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null"; |
|
|||
235 | return; |
|
|||
236 | } |
|
|||
237 |
|
||||
238 | // Spreads in SciQlop that the variable will be deleted, so that potential receivers can |
|
|||
239 | // make some treatments before the deletion |
|
|||
240 | emit variableAboutToBeDeleted(variable); |
|
|||
241 |
|
||||
242 | // Deletes identifier |
|
|||
243 | impl->m_VariableToIdentifierMap.erase(variable); |
|
|||
244 |
|
||||
245 | // Deletes provider |
|
|||
246 | auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable); |
|
|||
247 | qCDebug(LOG_VariableController()) |
|
22 | qCDebug(LOG_VariableController()) | |
248 | << tr("Number of providers deleted for variable %1: %2") |
|
23 | << tr("VariableController construction") << QThread::currentThread(); | |
249 | .arg(variable->name(), QString::number(nbProvidersDeleted)); |
|
|||
250 |
|
||||
251 |
|
||||
252 | // Deletes from model |
|
|||
253 | impl->m_VariableModel->deleteVariable(variable); |
|
|||
254 | } |
|
|||
255 |
|
||||
256 | void VariableController::deleteVariables( |
|
|||
257 | const QVector<std::shared_ptr<Variable> > &variables) noexcept |
|
|||
258 | { |
|
|||
259 | for (auto variable : qAsConst(variables)) { |
|
|||
260 | deleteVariable(variable); |
|
|||
261 | } |
|
|||
262 | } |
|
24 | } | |
263 |
|
25 | |||
264 | std::shared_ptr<Variable> |
|
26 | VariableController::~VariableController() | |
265 | VariableController::createVariable(const QString &name, const QVariantHash &metadata, |
|
|||
266 | std::shared_ptr<IDataProvider> provider) noexcept |
|
|||
267 | { |
|
|||
268 | if (!impl->m_TimeController) { |
|
|||
269 | qCCritical(LOG_VariableController()) |
|
|||
270 | << tr("Impossible to create variable: The time controller is null"); |
|
|||
271 | return nullptr; |
|
|||
272 | } |
|
|||
273 |
|
||||
274 | auto range = impl->m_TimeController->dateTime(); |
|
|||
275 |
|
||||
276 | if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) { |
|
|||
277 | auto identifier = QUuid::createUuid(); |
|
|||
278 |
|
||||
279 | // store the provider |
|
|||
280 | impl->registerProvider(provider); |
|
|||
281 |
|
||||
282 | // Associate the provider |
|
|||
283 | impl->m_VariableToProviderMap[newVariable] = provider; |
|
|||
284 | qCInfo(LOG_VariableController()) << "createVariable: " << identifier; |
|
|||
285 | impl->m_VariableToIdentifierMap[newVariable] = identifier; |
|
|||
286 |
|
||||
287 |
|
||||
288 | auto varRequestId = QUuid::createUuid(); |
|
|||
289 | impl->processRequest(newVariable, range, varRequestId); |
|
|||
290 | impl->updateVariableRequest(varRequestId); |
|
|||
291 |
|
||||
292 | return newVariable; |
|
|||
293 | } |
|
|||
294 | } |
|
|||
295 |
|
||||
296 | void VariableController::onDateTimeOnSelection(const SqpRange &dateTime) |
|
|||
297 | { |
|
|||
298 | // TODO check synchronisation and Rescale |
|
|||
299 | qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection" |
|
|||
300 | << QThread::currentThread()->objectName(); |
|
|||
301 | auto selectedRows = impl->m_VariableSelectionModel->selectedRows(); |
|
|||
302 | auto varRequestId = QUuid::createUuid(); |
|
|||
303 |
|
||||
304 | for (const auto &selectedRow : qAsConst(selectedRows)) { |
|
|||
305 | if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) { |
|
|||
306 | selectedVariable->setRange(dateTime); |
|
|||
307 | impl->processRequest(selectedVariable, dateTime, varRequestId); |
|
|||
308 |
|
||||
309 | // notify that rescale operation has to be done |
|
|||
310 | emit rangeChanged(selectedVariable, dateTime); |
|
|||
311 | } |
|
|||
312 | } |
|
|||
313 | impl->updateVariableRequest(varRequestId); |
|
|||
314 | } |
|
|||
315 |
|
||||
316 | void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested, |
|
|||
317 | const SqpRange &cacheRangeRequested, |
|
|||
318 | QVector<AcquisitionDataPacket> dataAcquired) |
|
|||
319 | { |
|
|||
320 | auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired); |
|
|||
321 | auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries); |
|
|||
322 | if (!varRequestId.isNull()) { |
|
|||
323 | impl->updateVariableRequest(varRequestId); |
|
|||
324 | } |
|
|||
325 | } |
|
|||
326 |
|
||||
327 | void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress) |
|
|||
328 | { |
|
27 | { | |
329 | qCDebug(LOG_VariableController()) |
|
28 | qCDebug(LOG_VariableController()) | |
330 | << "TORM: variableController::onVariableRetrieveDataInProgress" |
|
29 | << tr("VariableController destruction") << QThread::currentThread(); | |
331 | << QThread::currentThread()->objectName() << progress; |
|
30 | this->waitForFinish(); | |
332 | if (auto var = impl->findVariable(identifier)) { |
|
|||
333 | impl->m_VariableModel->setDataProgress(var, progress); |
|
|||
334 | } |
|
|||
335 | else { |
|
|||
336 | qCCritical(LOG_VariableController()) |
|
|||
337 | << tr("Impossible to notify progression of a null variable"); |
|
|||
338 | } |
|
|||
339 | } |
|
|||
340 |
|
||||
341 | void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable) |
|
|||
342 | { |
|
|||
343 | auto it = impl->m_VariableToIdentifierMap.find(variable); |
|
|||
344 | if (it != impl->m_VariableToIdentifierMap.cend()) { |
|
|||
345 | impl->m_VariableAcquisitionWorker->abortProgressRequested(it->second); |
|
|||
346 |
|
||||
347 | QUuid varRequestId; |
|
|||
348 | auto varIdToVarRequestIdQueueMapIt = impl->m_VarIdToVarRequestIdQueueMap.find(it->second); |
|
|||
349 | if (varIdToVarRequestIdQueueMapIt != impl->m_VarIdToVarRequestIdQueueMap.cend()) { |
|
|||
350 | auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second; |
|
|||
351 | varRequestId = varRequestIdQueue.front(); |
|
|||
352 | impl->cancelVariableRequest(varRequestId); |
|
|||
353 |
|
||||
354 | // Finish the progression for the request |
|
|||
355 | impl->m_VariableModel->setDataProgress(variable, 0.0); |
|
|||
356 | } |
|
|||
357 | else { |
|
|||
358 | qCWarning(LOG_VariableController()) |
|
|||
359 | << tr("Aborting progression of inexistant variable request detected !!!") |
|
|||
360 | << QThread::currentThread()->objectName(); |
|
|||
361 | } |
|
|||
362 | } |
|
|||
363 | else { |
|
|||
364 | qCWarning(LOG_VariableController()) |
|
|||
365 | << tr("Aborting progression of inexistant variable detected !!!") |
|
|||
366 | << QThread::currentThread()->objectName(); |
|
|||
367 | } |
|
|||
368 | } |
|
|||
369 |
|
||||
370 | void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier) |
|
|||
371 | { |
|
|||
372 | qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested" |
|
|||
373 | << QThread::currentThread()->objectName() << vIdentifier; |
|
|||
374 |
|
||||
375 | if (auto var = impl->findVariable(vIdentifier)) { |
|
|||
376 | this->onAbortProgressRequested(var); |
|
|||
377 | } |
|
|||
378 | else { |
|
|||
379 | qCCritical(LOG_VariableController()) |
|
|||
380 | << tr("Impossible to abort Acquisition Requestof a null variable"); |
|
|||
381 | } |
|
|||
382 | } |
|
|||
383 |
|
||||
384 | void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId) |
|
|||
385 | { |
|
|||
386 | qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId" |
|
|||
387 | << QThread::currentThread()->objectName() |
|
|||
388 | << synchronizationGroupId; |
|
|||
389 | auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>(); |
|
|||
390 | impl->m_GroupIdToVariableSynchronizationGroupMap.insert( |
|
|||
391 | std::make_pair(synchronizationGroupId, vSynchroGroup)); |
|
|||
392 | } |
|
|||
393 |
|
||||
394 | void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId) |
|
|||
395 | { |
|
|||
396 | impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId); |
|
|||
397 | } |
|
|||
398 |
|
||||
399 | void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable, |
|
|||
400 | QUuid synchronizationGroupId) |
|
|||
401 |
|
||||
402 | { |
|
|||
403 | qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized" |
|
|||
404 | << synchronizationGroupId; |
|
|||
405 | auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable); |
|
|||
406 | if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) { |
|
|||
407 | auto groupIdToVSGIt |
|
|||
408 | = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId); |
|
|||
409 | if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) { |
|
|||
410 | impl->m_VariableIdGroupIdMap.insert( |
|
|||
411 | std::make_pair(varToVarIdIt->second, synchronizationGroupId)); |
|
|||
412 | groupIdToVSGIt->second->addVariableId(varToVarIdIt->second); |
|
|||
413 | } |
|
|||
414 | else { |
|
|||
415 | qCCritical(LOG_VariableController()) |
|
|||
416 | << tr("Impossible to synchronize a variable with an unknown sycnhronization group") |
|
|||
417 | << variable->name(); |
|
|||
418 | } |
|
|||
419 | } |
|
|||
420 | else { |
|
|||
421 | qCCritical(LOG_VariableController()) |
|
|||
422 | << tr("Impossible to synchronize a variable with no identifier") << variable->name(); |
|
|||
423 | } |
|
|||
424 | } |
|
|||
425 |
|
||||
426 | void VariableController::desynchronize(std::shared_ptr<Variable> variable, |
|
|||
427 | QUuid synchronizationGroupId) |
|
|||
428 | { |
|
|||
429 | // Gets variable id |
|
|||
430 | auto variableIt = impl->m_VariableToIdentifierMap.find(variable); |
|
|||
431 | if (variableIt == impl->m_VariableToIdentifierMap.cend()) { |
|
|||
432 | qCCritical(LOG_VariableController()) |
|
|||
433 | << tr("Can't desynchronize variable %1: variable identifier not found") |
|
|||
434 | .arg(variable->name()); |
|
|||
435 | return; |
|
|||
436 | } |
|
|||
437 |
|
||||
438 | // Gets synchronization group |
|
|||
439 | auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId); |
|
|||
440 | if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) { |
|
|||
441 | qCCritical(LOG_VariableController()) |
|
|||
442 | << tr("Can't desynchronize variable %1: unknown synchronization group") |
|
|||
443 | .arg(variable->name()); |
|
|||
444 | return; |
|
|||
445 | } |
|
|||
446 |
|
||||
447 | auto variableId = variableIt->second; |
|
|||
448 |
|
||||
449 | // Removes variable from synchronization group |
|
|||
450 | auto synchronizationGroup = groupIt->second; |
|
|||
451 | synchronizationGroup->removeVariableId(variableId); |
|
|||
452 |
|
||||
453 | // Removes link between variable and synchronization group |
|
|||
454 | impl->m_VariableIdGroupIdMap.erase(variableId); |
|
|||
455 | } |
|
31 | } | |
456 |
|
32 | |||
457 | void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, |
|
33 | Variable *VariableController::createVariable(const QString &name) noexcept | |
458 | const SqpRange &range, const SqpRange &oldRange, |
|
|||
459 | bool synchronise) |
|
|||
460 | { |
|
34 | { | |
461 | // NOTE: oldRange isn't really necessary since oldRange == variable->range(). |
|
35 | return impl->m_VariableModel->createVariable(name); | |
462 |
|
||||
463 | // we want to load data of the variable for the dateTime. |
|
|||
464 | // First we check if the cache contains some of them. |
|
|||
465 | // For the other, we ask the provider to give them. |
|
|||
466 |
|
||||
467 | auto varRequestId = QUuid::createUuid(); |
|
|||
468 | qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading" |
|
|||
469 | << QThread::currentThread()->objectName() << varRequestId; |
|
|||
470 |
|
||||
471 | for (const auto &var : variables) { |
|
|||
472 | qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId; |
|
|||
473 | impl->processRequest(var, range, varRequestId); |
|
|||
474 | } |
|
|||
475 |
|
||||
476 | if (synchronise) { |
|
|||
477 | // Get the group ids |
|
|||
478 | qCDebug(LOG_VariableController()) |
|
|||
479 | << "TORM VariableController::onRequestDataLoading for synchro var ENABLE"; |
|
|||
480 | auto groupIds = std::set<QUuid>{}; |
|
|||
481 | auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{}; |
|
|||
482 | for (const auto &var : variables) { |
|
|||
483 | auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var); |
|
|||
484 | if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) { |
|
|||
485 | auto vId = varToVarIdIt->second; |
|
|||
486 | auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId); |
|
|||
487 | if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) { |
|
|||
488 | auto gId = varIdToGroupIdIt->second; |
|
|||
489 | groupIdToOldRangeMap.insert(std::make_pair(gId, var->range())); |
|
|||
490 | if (groupIds.find(gId) == groupIds.cend()) { |
|
|||
491 | qCDebug(LOG_VariableController()) << "Synchro detect group " << gId; |
|
|||
492 | groupIds.insert(gId); |
|
|||
493 | } |
|
|||
494 | } |
|
|||
495 | } |
|
|||
496 | } |
|
|||
497 |
|
||||
498 | // We assume here all group ids exist |
|
|||
499 | for (const auto &gId : groupIds) { |
|
|||
500 | auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId); |
|
|||
501 | auto vSyncIds = vSynchronizationGroup->getIds(); |
|
|||
502 | qCDebug(LOG_VariableController()) << "Var in synchro group "; |
|
|||
503 | for (auto vId : vSyncIds) { |
|
|||
504 | auto var = impl->findVariable(vId); |
|
|||
505 |
|
||||
506 | // Don't process already processed var |
|
|||
507 | if (!variables.contains(var)) { |
|
|||
508 | if (var != nullptr) { |
|
|||
509 | qCDebug(LOG_VariableController()) << "processRequest synchro for" |
|
|||
510 | << var->name(); |
|
|||
511 | auto vSyncRangeRequested = computeSynchroRangeRequested( |
|
|||
512 | var->range(), range, groupIdToOldRangeMap.at(gId)); |
|
|||
513 | qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested; |
|
|||
514 | impl->processRequest(var, vSyncRangeRequested, varRequestId); |
|
|||
515 | } |
|
|||
516 | else { |
|
|||
517 | qCCritical(LOG_VariableController()) |
|
|||
518 |
|
||||
519 | << tr("Impossible to synchronize a null variable"); |
|
|||
520 | } |
|
|||
521 | } |
|
|||
522 | } |
|
|||
523 | } |
|
|||
524 | } |
|
|||
525 |
|
||||
526 | impl->updateVariableRequest(varRequestId); |
|
|||
527 | } |
|
36 | } | |
528 |
|
37 | |||
529 |
|
||||
530 | void VariableController::initialize() |
|
38 | void VariableController::initialize() | |
531 | { |
|
39 | { | |
532 | qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread(); |
|
40 | qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread(); | |
@@ -543,300 +51,3 void VariableController::waitForFinish() | |||||
543 | { |
|
51 | { | |
544 | QMutexLocker locker{&impl->m_WorkingMutex}; |
|
52 | QMutexLocker locker{&impl->m_WorkingMutex}; | |
545 | } |
|
53 | } | |
546 |
|
||||
547 | AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange) |
|
|||
548 | { |
|
|||
549 | // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd |
|
|||
550 | auto zoomType = AcquisitionZoomType::Unknown; |
|
|||
551 | if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) { |
|
|||
552 | zoomType = AcquisitionZoomType::ZoomOut; |
|
|||
553 | } |
|
|||
554 | else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) { |
|
|||
555 | zoomType = AcquisitionZoomType::PanRight; |
|
|||
556 | } |
|
|||
557 | else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) { |
|
|||
558 | zoomType = AcquisitionZoomType::PanLeft; |
|
|||
559 | } |
|
|||
560 | else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) { |
|
|||
561 | zoomType = AcquisitionZoomType::ZoomIn; |
|
|||
562 | } |
|
|||
563 | else { |
|
|||
564 | qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected"; |
|
|||
565 | } |
|
|||
566 | return zoomType; |
|
|||
567 | } |
|
|||
568 |
|
||||
569 | void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var, |
|
|||
570 | const SqpRange &rangeRequested, |
|
|||
571 | QUuid varRequestId) |
|
|||
572 | { |
|
|||
573 |
|
||||
574 | // TODO: protect at |
|
|||
575 | auto varRequest = VariableRequest{}; |
|
|||
576 | auto varId = m_VariableToIdentifierMap.at(var); |
|
|||
577 |
|
||||
578 | auto varStrategyRangesRequested |
|
|||
579 | = m_VariableCacheStrategy->computeRange(var->range(), rangeRequested); |
|
|||
580 |
|
||||
581 | auto notInCacheRangeList = QVector<SqpRange>{varStrategyRangesRequested.second}; |
|
|||
582 | auto inCacheRangeList = QVector<SqpRange>{}; |
|
|||
583 | if (m_VarIdToVarRequestIdQueueMap.find(varId) == m_VarIdToVarRequestIdQueueMap.cend()) { |
|
|||
584 | notInCacheRangeList = var->provideNotInCacheRangeList(varStrategyRangesRequested.second); |
|
|||
585 | inCacheRangeList = var->provideInCacheRangeList(varStrategyRangesRequested.second); |
|
|||
586 | } |
|
|||
587 |
|
||||
588 | if (!notInCacheRangeList.empty()) { |
|
|||
589 | varRequest.m_RangeRequested = varStrategyRangesRequested.first; |
|
|||
590 | varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second; |
|
|||
591 |
|
||||
592 | // store VarRequest |
|
|||
593 | storeVariableRequest(varId, varRequestId, varRequest); |
|
|||
594 |
|
||||
595 | auto varProvider = m_VariableToProviderMap.at(var); |
|
|||
596 | if (varProvider != nullptr) { |
|
|||
597 | auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest( |
|
|||
598 | varRequestId, varId, varStrategyRangesRequested.first, |
|
|||
599 | varStrategyRangesRequested.second, |
|
|||
600 | DataProviderParameters{std::move(notInCacheRangeList), var->metadata()}, |
|
|||
601 | varProvider); |
|
|||
602 |
|
||||
603 | if (!varRequestIdCanceled.isNull()) { |
|
|||
604 | qCDebug(LOG_VariableAcquisitionWorker()) << tr("vsarRequestIdCanceled: ") |
|
|||
605 | << varRequestIdCanceled; |
|
|||
606 | cancelVariableRequest(varRequestIdCanceled); |
|
|||
607 | } |
|
|||
608 | } |
|
|||
609 | else { |
|
|||
610 | qCCritical(LOG_VariableController()) |
|
|||
611 | << "Impossible to provide data with a null provider"; |
|
|||
612 | } |
|
|||
613 |
|
||||
614 | if (!inCacheRangeList.empty()) { |
|
|||
615 | emit q->updateVarDisplaying(var, inCacheRangeList.first()); |
|
|||
616 | } |
|
|||
617 | } |
|
|||
618 | else { |
|
|||
619 | varRequest.m_RangeRequested = varStrategyRangesRequested.first; |
|
|||
620 | varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second; |
|
|||
621 | // store VarRequest |
|
|||
622 | storeVariableRequest(varId, varRequestId, varRequest); |
|
|||
623 | acceptVariableRequest(varId, |
|
|||
624 | var->dataSeries()->subDataSeries(varStrategyRangesRequested.second)); |
|
|||
625 | } |
|
|||
626 | } |
|
|||
627 |
|
||||
628 | std::shared_ptr<Variable> |
|
|||
629 | VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier) |
|
|||
630 | { |
|
|||
631 | std::shared_ptr<Variable> var; |
|
|||
632 | auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; }; |
|
|||
633 |
|
||||
634 | auto end = m_VariableToIdentifierMap.cend(); |
|
|||
635 | auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply); |
|
|||
636 | if (it != end) { |
|
|||
637 | var = it->first; |
|
|||
638 | } |
|
|||
639 | else { |
|
|||
640 | qCCritical(LOG_VariableController()) |
|
|||
641 | << tr("Impossible to find the variable with the identifier: ") << vIdentifier; |
|
|||
642 | } |
|
|||
643 |
|
||||
644 | return var; |
|
|||
645 | } |
|
|||
646 |
|
||||
647 | std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries( |
|
|||
648 | const QVector<AcquisitionDataPacket> acqDataPacketVector) |
|
|||
649 | { |
|
|||
650 | qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size") |
|
|||
651 | << acqDataPacketVector.size(); |
|
|||
652 | std::shared_ptr<IDataSeries> dataSeries; |
|
|||
653 | if (!acqDataPacketVector.isEmpty()) { |
|
|||
654 | dataSeries = acqDataPacketVector[0].m_DateSeries; |
|
|||
655 | for (int i = 1; i < acqDataPacketVector.size(); ++i) { |
|
|||
656 | dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get()); |
|
|||
657 | } |
|
|||
658 | } |
|
|||
659 | qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END") |
|
|||
660 | << acqDataPacketVector.size(); |
|
|||
661 | return dataSeries; |
|
|||
662 | } |
|
|||
663 |
|
||||
664 | void VariableController::VariableControllerPrivate::registerProvider( |
|
|||
665 | std::shared_ptr<IDataProvider> provider) |
|
|||
666 | { |
|
|||
667 | if (m_ProviderSet.find(provider) == m_ProviderSet.end()) { |
|
|||
668 | qCDebug(LOG_VariableController()) << tr("Registering of a new provider") |
|
|||
669 | << provider->objectName(); |
|
|||
670 | m_ProviderSet.insert(provider); |
|
|||
671 | connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(), |
|
|||
672 | &VariableAcquisitionWorker::onVariableDataAcquired); |
|
|||
673 | connect(provider.get(), &IDataProvider::dataProvidedProgress, |
|
|||
674 | m_VariableAcquisitionWorker.get(), |
|
|||
675 | &VariableAcquisitionWorker::onVariableRetrieveDataInProgress); |
|
|||
676 | connect(provider.get(), &IDataProvider::dataProvidedFailed, |
|
|||
677 | m_VariableAcquisitionWorker.get(), |
|
|||
678 | &VariableAcquisitionWorker::onVariableAcquisitionFailed); |
|
|||
679 | } |
|
|||
680 | else { |
|
|||
681 | qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists "); |
|
|||
682 | } |
|
|||
683 | } |
|
|||
684 |
|
||||
685 | void VariableController::VariableControllerPrivate::storeVariableRequest( |
|
|||
686 | QUuid varId, QUuid varRequestId, const VariableRequest &varRequest) |
|
|||
687 | { |
|
|||
688 | // First request for the variable. we can create an entry for it |
|
|||
689 | auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId); |
|
|||
690 | if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) { |
|
|||
691 | auto varRequestIdQueue = std::deque<QUuid>{}; |
|
|||
692 | qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE"); |
|
|||
693 | varRequestIdQueue.push_back(varRequestId); |
|
|||
694 | m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue))); |
|
|||
695 | } |
|
|||
696 | else { |
|
|||
697 | qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE"); |
|
|||
698 | auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second; |
|
|||
699 | varRequestIdQueue.push_back(varRequestId); |
|
|||
700 | } |
|
|||
701 |
|
||||
702 | auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId); |
|
|||
703 | if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) { |
|
|||
704 | auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{}; |
|
|||
705 | varIdToVarRequestMap.insert(std::make_pair(varId, varRequest)); |
|
|||
706 | qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP"); |
|
|||
707 | m_VarRequestIdToVarIdVarRequestMap.insert( |
|
|||
708 | std::make_pair(varRequestId, std::move(varIdToVarRequestMap))); |
|
|||
709 | } |
|
|||
710 | else { |
|
|||
711 | auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second; |
|
|||
712 | qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP"); |
|
|||
713 | varIdToVarRequestMap.insert(std::make_pair(varId, varRequest)); |
|
|||
714 | } |
|
|||
715 | } |
|
|||
716 |
|
||||
717 | QUuid VariableController::VariableControllerPrivate::acceptVariableRequest( |
|
|||
718 | QUuid varId, std::shared_ptr<IDataSeries> dataSeries) |
|
|||
719 | { |
|
|||
720 | QUuid varRequestId; |
|
|||
721 | auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId); |
|
|||
722 | if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) { |
|
|||
723 | auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second; |
|
|||
724 | varRequestId = varRequestIdQueue.front(); |
|
|||
725 | auto varRequestIdToVarIdVarRequestMapIt |
|
|||
726 | = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId); |
|
|||
727 | if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) { |
|
|||
728 | auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second; |
|
|||
729 | auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId); |
|
|||
730 | if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) { |
|
|||
731 | qCDebug(LOG_VariableController()) << tr("acceptVariableRequest"); |
|
|||
732 | auto &varRequest = varIdToVarRequestMapIt->second; |
|
|||
733 | varRequest.m_DataSeries = dataSeries; |
|
|||
734 | varRequest.m_CanUpdate = true; |
|
|||
735 | } |
|
|||
736 | else { |
|
|||
737 | qCDebug(LOG_VariableController()) |
|
|||
738 | << tr("Impossible to acceptVariableRequest of a unknown variable id attached " |
|
|||
739 | "to a variableRequestId") |
|
|||
740 | << varRequestId << varId; |
|
|||
741 | } |
|
|||
742 | } |
|
|||
743 | else { |
|
|||
744 | qCCritical(LOG_VariableController()) |
|
|||
745 | << tr("Impossible to acceptVariableRequest of a unknown variableRequestId") |
|
|||
746 | << varRequestId; |
|
|||
747 | } |
|
|||
748 |
|
||||
749 | varRequestIdQueue.pop_front(); |
|
|||
750 | if (varRequestIdQueue.empty()) { |
|
|||
751 | qCDebug(LOG_VariableController()) |
|
|||
752 | << tr("TORM Erase REQUEST because it has been accepted") << varId; |
|
|||
753 | m_VarIdToVarRequestIdQueueMap.erase(varId); |
|
|||
754 | } |
|
|||
755 | } |
|
|||
756 | else { |
|
|||
757 | qCCritical(LOG_VariableController()) |
|
|||
758 | << tr("Impossible to acceptVariableRequest of a unknown variable id") << varId; |
|
|||
759 | } |
|
|||
760 |
|
||||
761 | return varRequestId; |
|
|||
762 | } |
|
|||
763 |
|
||||
764 | void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId) |
|
|||
765 | { |
|
|||
766 |
|
||||
767 | auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId); |
|
|||
768 | if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) { |
|
|||
769 | bool processVariableUpdate = true; |
|
|||
770 | auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second; |
|
|||
771 | for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin(); |
|
|||
772 | (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) && processVariableUpdate; |
|
|||
773 | ++varIdToVarRequestMapIt) { |
|
|||
774 | processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate; |
|
|||
775 | qCDebug(LOG_VariableController()) << tr("updateVariableRequest") |
|
|||
776 | << processVariableUpdate; |
|
|||
777 | } |
|
|||
778 |
|
||||
779 | if (processVariableUpdate) { |
|
|||
780 | for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin(); |
|
|||
781 | varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) { |
|
|||
782 | if (auto var = findVariable(varIdToVarRequestMapIt->first)) { |
|
|||
783 | auto &varRequest = varIdToVarRequestMapIt->second; |
|
|||
784 | var->setRange(varRequest.m_RangeRequested); |
|
|||
785 | var->setCacheRange(varRequest.m_CacheRangeRequested); |
|
|||
786 | qCDebug(LOG_VariableController()) << tr("1: onDataProvided") |
|
|||
787 | << varRequest.m_RangeRequested; |
|
|||
788 | qCDebug(LOG_VariableController()) << tr("2: onDataProvided") |
|
|||
789 | << varRequest.m_CacheRangeRequested; |
|
|||
790 | var->mergeDataSeries(varRequest.m_DataSeries); |
|
|||
791 | qCDebug(LOG_VariableController()) << tr("3: onDataProvided") |
|
|||
792 | << varRequest.m_DataSeries->range(); |
|
|||
793 | qCDebug(LOG_VariableController()) << tr("4: onDataProvided"); |
|
|||
794 |
|
||||
795 | /// @todo MPL: confirm |
|
|||
796 | // Variable update is notified only if there is no pending request for it |
|
|||
797 | // if |
|
|||
798 | // (m_VarIdToVarRequestIdQueueMap.count(varIdToVarRequestMapIt->first) |
|
|||
799 | // == 0) { |
|
|||
800 | emit var->updated(); |
|
|||
801 | // } |
|
|||
802 | } |
|
|||
803 | else { |
|
|||
804 | qCCritical(LOG_VariableController()) |
|
|||
805 | << tr("Impossible to update data to a null variable"); |
|
|||
806 | } |
|
|||
807 | } |
|
|||
808 |
|
||||
809 | // cleaning varRequestId |
|
|||
810 | qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?") |
|
|||
811 | << m_VarRequestIdToVarIdVarRequestMap.size(); |
|
|||
812 | m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId); |
|
|||
813 | qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?") |
|
|||
814 | << m_VarRequestIdToVarIdVarRequestMap.size(); |
|
|||
815 | } |
|
|||
816 | } |
|
|||
817 | else { |
|
|||
818 | qCCritical(LOG_VariableController()) |
|
|||
819 | << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId; |
|
|||
820 | } |
|
|||
821 | } |
|
|||
822 |
|
||||
823 | void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId) |
|
|||
824 | { |
|
|||
825 | // cleaning varRequestId |
|
|||
826 | m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId); |
|
|||
827 |
|
||||
828 | for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin(); |
|
|||
829 | varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.end();) { |
|
|||
830 | auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second; |
|
|||
831 | varRequestIdQueue.erase( |
|
|||
832 | std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId), |
|
|||
833 | varRequestIdQueue.end()); |
|
|||
834 | if (varRequestIdQueue.empty()) { |
|
|||
835 | varIdToVarRequestIdQueueMapIt |
|
|||
836 | = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt); |
|
|||
837 | } |
|
|||
838 | else { |
|
|||
839 | ++varIdToVarRequestIdQueueMapIt; |
|
|||
840 | } |
|
|||
841 | } |
|
|||
842 | } |
|
@@ -1,293 +1,24 | |||||
1 | #include <Variable/Variable.h> |
|
|||
2 |
|
|
1 | #include <Variable/VariableModel.h> | |
3 |
|
2 | |||
4 | #include <Common/DateUtils.h> |
|
3 | #include <Variable/Variable.h> | |
5 | #include <Common/StringUtils.h> |
|
|||
6 |
|
||||
7 | #include <Data/IDataSeries.h> |
|
|||
8 |
|
||||
9 | #include <QSize> |
|
|||
10 | #include <unordered_map> |
|
|||
11 |
|
4 | |||
12 | Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel") |
|
5 | Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel") | |
13 |
|
6 | |||
14 | namespace { |
|
|||
15 |
|
||||
16 | // Column indexes |
|
|||
17 | const auto NAME_COLUMN = 0; |
|
|||
18 | const auto TSTART_COLUMN = 1; |
|
|||
19 | const auto TEND_COLUMN = 2; |
|
|||
20 | const auto NBPOINTS_COLUMN = 3; |
|
|||
21 | const auto UNIT_COLUMN = 4; |
|
|||
22 | const auto MISSION_COLUMN = 5; |
|
|||
23 | const auto PLUGIN_COLUMN = 6; |
|
|||
24 | const auto NB_COLUMNS = 7; |
|
|||
25 |
|
||||
26 | // Column properties |
|
|||
27 | const auto DEFAULT_HEIGHT = 25; |
|
|||
28 | const auto DEFAULT_WIDTH = 100; |
|
|||
29 |
|
||||
30 | struct ColumnProperties { |
|
|||
31 | ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH, |
|
|||
32 | int height = DEFAULT_HEIGHT) |
|
|||
33 | : m_Name{name}, m_Width{width}, m_Height{height} |
|
|||
34 | { |
|
|||
35 | } |
|
|||
36 |
|
||||
37 | QString m_Name; |
|
|||
38 | int m_Width; |
|
|||
39 | int m_Height; |
|
|||
40 | }; |
|
|||
41 |
|
||||
42 | const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{ |
|
|||
43 | {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}}, |
|
|||
44 | {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}}, |
|
|||
45 | {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}}, |
|
|||
46 | {PLUGIN_COLUMN, {QObject::tr("Plugin")}}}; |
|
|||
47 |
|
||||
48 | /// Format for datetimes |
|
|||
49 | const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz"); |
|
|||
50 |
|
||||
51 | QString uniqueName(const QString &defaultName, |
|
|||
52 | const std::vector<std::shared_ptr<Variable> > &variables) |
|
|||
53 | { |
|
|||
54 | auto forbiddenNames = std::vector<QString>(variables.size()); |
|
|||
55 | std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(), |
|
|||
56 | [](const auto &variable) { return variable->name(); }); |
|
|||
57 | auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames); |
|
|||
58 | Q_ASSERT(!uniqueName.isEmpty()); |
|
|||
59 |
|
||||
60 | return uniqueName; |
|
|||
61 | } |
|
|||
62 |
|
||||
63 | } // namespace |
|
|||
64 |
|
||||
65 | struct VariableModel::VariableModelPrivate { |
|
7 | struct VariableModel::VariableModelPrivate { | |
66 | /// Variables created in SciQlop |
|
8 | /// Variables created in SciQlop | |
67 |
std::vector<std:: |
|
9 | std::vector<std::unique_ptr<Variable> > m_Variables; | |
68 | std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress; |
|
|||
69 |
|
||||
70 | /// Return the row index of the variable. -1 if it's not found |
|
|||
71 | int indexOfVariable(Variable *variable) const noexcept; |
|
|||
72 | }; |
|
10 | }; | |
73 |
|
11 | |||
74 | VariableModel::VariableModel(QObject *parent) |
|
12 | VariableModel::VariableModel() : impl{spimpl::make_unique_impl<VariableModelPrivate>()} | |
75 | : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()} |
|
|||
76 | { |
|
|||
77 | } |
|
|||
78 |
|
||||
79 | void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept |
|
|||
80 | { |
|
|||
81 | auto insertIndex = rowCount(); |
|
|||
82 | beginInsertRows({}, insertIndex, insertIndex); |
|
|||
83 |
|
||||
84 | // Generates unique name for the variable |
|
|||
85 | variable->setName(uniqueName(variable->name(), impl->m_Variables)); |
|
|||
86 |
|
||||
87 | impl->m_Variables.push_back(variable); |
|
|||
88 | connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated); |
|
|||
89 |
|
||||
90 | endInsertRows(); |
|
|||
91 | } |
|
|||
92 |
|
||||
93 | bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept |
|
|||
94 | { |
|
|||
95 | auto end = impl->m_Variables.cend(); |
|
|||
96 | return std::find(impl->m_Variables.cbegin(), end, variable) != end; |
|
|||
97 | } |
|
|||
98 |
|
||||
99 | std::shared_ptr<Variable> VariableModel::createVariable(const QString &name, |
|
|||
100 | const QVariantHash &metadata) noexcept |
|
|||
101 | { |
|
|||
102 | auto variable = std::make_shared<Variable>(name, metadata); |
|
|||
103 | addVariable(variable); |
|
|||
104 |
|
||||
105 | return variable; |
|
|||
106 | } |
|
|||
107 |
|
||||
108 | void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept |
|
|||
109 | { |
|
|||
110 | if (!variable) { |
|
|||
111 | qCCritical(LOG_Variable()) << "Can't delete a null variable from the model"; |
|
|||
112 | return; |
|
|||
113 | } |
|
|||
114 |
|
||||
115 | // Finds variable in the model |
|
|||
116 | auto begin = impl->m_Variables.cbegin(); |
|
|||
117 | auto end = impl->m_Variables.cend(); |
|
|||
118 | auto it = std::find(begin, end, variable); |
|
|||
119 | if (it != end) { |
|
|||
120 | auto removeIndex = std::distance(begin, it); |
|
|||
121 |
|
||||
122 | // Deletes variable |
|
|||
123 | beginRemoveRows({}, removeIndex, removeIndex); |
|
|||
124 | impl->m_Variables.erase(it); |
|
|||
125 | endRemoveRows(); |
|
|||
126 | } |
|
|||
127 | else { |
|
|||
128 | qCritical(LOG_VariableModel()) |
|
|||
129 | << tr("Can't delete variable %1 from the model: the variable is not in the model") |
|
|||
130 | .arg(variable->name()); |
|
|||
131 | } |
|
|||
132 |
|
||||
133 | // Removes variable from progress map |
|
|||
134 | impl->m_VariableToProgress.erase(variable); |
|
|||
135 | } |
|
|||
136 |
|
||||
137 |
|
||||
138 | std::shared_ptr<Variable> VariableModel::variable(int index) const |
|
|||
139 | { |
|
|||
140 | return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr; |
|
|||
141 | } |
|
|||
142 |
|
||||
143 | std::vector<std::shared_ptr<Variable> > VariableModel::variables() const |
|
|||
144 | { |
|
|||
145 | return impl->m_Variables; |
|
|||
146 | } |
|
|||
147 |
|
||||
148 | void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress) |
|
|||
149 | { |
|
|||
150 | if (progress > 0.0) { |
|
|||
151 | impl->m_VariableToProgress[variable] = progress; |
|
|||
152 | } |
|
|||
153 | else { |
|
|||
154 | impl->m_VariableToProgress.erase(variable); |
|
|||
155 | } |
|
|||
156 | auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN); |
|
|||
157 |
|
||||
158 | emit dataChanged(modelIndex, modelIndex); |
|
|||
159 | } |
|
|||
160 |
|
||||
161 | int VariableModel::columnCount(const QModelIndex &parent) const |
|
|||
162 | { |
|
|||
163 | Q_UNUSED(parent); |
|
|||
164 |
|
||||
165 | return NB_COLUMNS; |
|
|||
166 | } |
|
|||
167 |
|
||||
168 | int VariableModel::rowCount(const QModelIndex &parent) const |
|
|||
169 | { |
|
|||
170 | Q_UNUSED(parent); |
|
|||
171 |
|
||||
172 | return impl->m_Variables.size(); |
|
|||
173 | } |
|
|||
174 |
|
||||
175 | QVariant VariableModel::data(const QModelIndex &index, int role) const |
|
|||
176 | { |
|
|||
177 | if (!index.isValid()) { |
|
|||
178 | return QVariant{}; |
|
|||
179 | } |
|
|||
180 |
|
||||
181 | if (index.row() < 0 || index.row() >= rowCount()) { |
|
|||
182 | return QVariant{}; |
|
|||
183 | } |
|
|||
184 |
|
||||
185 | if (role == Qt::DisplayRole) { |
|
|||
186 | if (auto variable = impl->m_Variables.at(index.row()).get()) { |
|
|||
187 | switch (index.column()) { |
|
|||
188 | case NAME_COLUMN: |
|
|||
189 | return variable->name(); |
|
|||
190 | case TSTART_COLUMN: { |
|
|||
191 | auto range = variable->realRange(); |
|
|||
192 | return range != INVALID_RANGE |
|
|||
193 | ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT) |
|
|||
194 | : QVariant{}; |
|
|||
195 | } |
|
|||
196 | case TEND_COLUMN: { |
|
|||
197 | auto range = variable->realRange(); |
|
|||
198 | return range != INVALID_RANGE |
|
|||
199 | ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT) |
|
|||
200 | : QVariant{}; |
|
|||
201 | } |
|
|||
202 | case NBPOINTS_COLUMN: |
|
|||
203 | return variable->nbPoints(); |
|
|||
204 | case UNIT_COLUMN: |
|
|||
205 | return variable->metadata().value(QStringLiteral("units")); |
|
|||
206 | case MISSION_COLUMN: |
|
|||
207 | return variable->metadata().value(QStringLiteral("mission")); |
|
|||
208 | case PLUGIN_COLUMN: |
|
|||
209 | return variable->metadata().value(QStringLiteral("plugin")); |
|
|||
210 | default: |
|
|||
211 | // No action |
|
|||
212 | break; |
|
|||
213 | } |
|
|||
214 |
|
||||
215 | qWarning(LOG_VariableModel()) |
|
|||
216 | << tr("Can't get data (unknown column %1)").arg(index.column()); |
|
|||
217 | } |
|
|||
218 | else { |
|
|||
219 | qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)"); |
|
|||
220 | } |
|
|||
221 | } |
|
|||
222 | else if (role == VariableRoles::ProgressRole) { |
|
|||
223 | if (auto variable = impl->m_Variables.at(index.row())) { |
|
|||
224 |
|
||||
225 | auto it = impl->m_VariableToProgress.find(variable); |
|
|||
226 | if (it != impl->m_VariableToProgress.cend()) { |
|
|||
227 | return it->second; |
|
|||
228 | } |
|
|||
229 | } |
|
|||
230 | } |
|
|||
231 |
|
||||
232 | return QVariant{}; |
|
|||
233 | } |
|
|||
234 |
|
||||
235 | QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const |
|
|||
236 | { |
|
13 | { | |
237 | if (role != Qt::DisplayRole && role != Qt::SizeHintRole) { |
|
|||
238 | return QVariant{}; |
|
|||
239 | } |
|
|||
240 |
|
||||
241 | if (orientation == Qt::Horizontal) { |
|
|||
242 | auto propertiesIt = COLUMN_PROPERTIES.find(section); |
|
|||
243 | if (propertiesIt != COLUMN_PROPERTIES.cend()) { |
|
|||
244 | // Role is either DisplayRole or SizeHintRole |
|
|||
245 | return (role == Qt::DisplayRole) |
|
|||
246 | ? QVariant{propertiesIt->m_Name} |
|
|||
247 | : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}}; |
|
|||
248 | } |
|
|||
249 | else { |
|
|||
250 | qWarning(LOG_VariableModel()) |
|
|||
251 | << tr("Can't get header data (unknown column %1)").arg(section); |
|
|||
252 | } |
|
|||
253 | } |
|
|||
254 |
|
||||
255 | return QVariant{}; |
|
|||
256 | } |
|
|||
257 |
|
||||
258 | void VariableModel::abortProgress(const QModelIndex &index) |
|
|||
259 | { |
|
|||
260 | if (auto variable = impl->m_Variables.at(index.row())) { |
|
|||
261 | emit abortProgessRequested(variable); |
|
|||
262 | } |
|
|||
263 | } |
|
|||
264 |
|
||||
265 | void VariableModel::onVariableUpdated() noexcept |
|
|||
266 | { |
|
|||
267 | // Finds variable that has been updated in the model |
|
|||
268 | if (auto updatedVariable = dynamic_cast<Variable *>(sender())) { |
|
|||
269 | auto updatedVariableIndex = impl->indexOfVariable(updatedVariable); |
|
|||
270 |
|
||||
271 | if (updatedVariableIndex > -1) { |
|
|||
272 | emit dataChanged(createIndex(updatedVariableIndex, 0), |
|
|||
273 | createIndex(updatedVariableIndex, columnCount() - 1)); |
|
|||
274 | } |
|
|||
275 | } |
|
|||
276 | } |
|
14 | } | |
277 |
|
15 | |||
278 | int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept |
|
16 | Variable *VariableModel::createVariable(const QString &name) noexcept | |
279 | { |
|
17 | { | |
280 | auto begin = std::cbegin(m_Variables); |
|
18 | /// @todo For the moment, the other data of the variable is initialized with default values | |
281 | auto end = std::cend(m_Variables); |
|
19 | auto variable | |
282 | auto it |
|
20 | = std::make_unique<Variable>(name, QStringLiteral("unit"), QStringLiteral("mission")); | |
283 | = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; }); |
|
21 | impl->m_Variables.push_back(std::move(variable)); | |
284 |
|
22 | |||
285 | if (it != end) { |
|
23 | return impl->m_Variables.back().get(); | |
286 | // Gets the index of the variable in the model: we assume here that views have the same |
|
|||
287 | // order as the model |
|
|||
288 | return std::distance(begin, it); |
|
|||
289 | } |
|
|||
290 | else { |
|
|||
291 | return -1; |
|
|||
292 | } |
|
|||
293 | } |
|
24 | } |
@@ -1,7 +1,5 | |||||
1 | #include <Visualization/VisualizationController.h> |
|
1 | #include <Visualization/VisualizationController.h> | |
2 |
|
2 | |||
3 | #include <Variable/Variable.h> |
|
|||
4 |
|
||||
5 | #include <QMutex> |
|
3 | #include <QMutex> | |
6 | #include <QThread> |
|
4 | #include <QThread> | |
7 |
|
5 |
@@ -30,7 +30,9 void TestDataSourceController::testSetDataSourceItem() | |||||
30 |
|
30 | |||
31 | // Create a data source item |
|
31 | // Create a data source item | |
32 | auto source1Name = QStringLiteral("Source1"); |
|
32 | auto source1Name = QStringLiteral("Source1"); | |
33 | auto source1Item = std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, source1Name); |
|
33 | auto source1Values = QVector<QVariant>{source1Name}; | |
|
34 | auto source1Item | |||
|
35 | = std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, std::move(source1Values)); | |||
34 |
|
36 | |||
35 | // Add data source item to the controller and check that a signal has been emitted after setting |
|
37 | // Add data source item to the controller and check that a signal has been emitted after setting | |
36 | // data source item in the controller |
|
38 | // data source item in the controller |
@@ -2,51 +2,5 | |||||
2 | Common/spimpl\.h:\d+:.* |
|
2 | Common/spimpl\.h:\d+:.* | |
3 |
|
3 | |||
4 | # Ignore false positive relative to two class definitions in a same file |
|
4 | # Ignore false positive relative to two class definitions in a same file | |
5 | ArrayData\.h:\d+:.*IPSIS_S01.* |
|
|||
6 | ArrayDataIterator\.h:\d+:.*IPSIS_S01.* |
|
|||
7 | DataSourceItem\.h:\d+:.*IPSIS_S01.* |
|
5 | DataSourceItem\.h:\d+:.*IPSIS_S01.* | |
8 | DataSeries\.h:\d+:.*IPSIS_S01.* |
|
|||
9 | DataSeriesIterator\.h:\d+:.*IPSIS_S01.* |
|
|||
10 | DataSeriesMergeHelper\.h:\d+:.*IPSIS_S01.* |
|
|||
11 |
|
6 | |||
12 | # Ignore false positive relative to a template class |
|
|||
13 | ArrayData\.h:\d+:.*IPSIS_S04_METHOD.*found: push_back |
|
|||
14 | ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (const_iterator) |
|
|||
15 | ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (D) |
|
|||
16 | ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (IC) |
|
|||
17 | ArrayData\.h:\d+:.*IPSIS_S04_NAMESPACE.*found: (arraydata_detail) |
|
|||
18 | ArrayData\.h:\d+:.*IPSIS_S06.*found: (D) |
|
|||
19 | ArrayData\.h:\d+:.*IPSIS_S06.*found: (Dim) |
|
|||
20 | ArrayData\.h:\d+:.*IPSIS_S06.*found: (IC) |
|
|||
21 | ArrayData\.h:\d+:.*IPSIS_S06.*found: (IsConst) |
|
|||
22 | DataSeries\.h:\d+:.*IPSIS_S04_METHOD.*found: LOG_DataSeries |
|
|||
23 | DataSeries\.h:\d+:.*IPSIS_S04_METHOD.*found: push_back |
|
|||
24 | DataSeries\.h:\d+:.*IPSIS_S04_VARIABLE.* |
|
|||
25 | DataSeries\.h:\d+:.*IPSIS_S04_NAMESPACE.*found: (dataseries_detail) |
|
|||
26 | DataSeries\.h:\d+:.*IPSIS_S05.* |
|
|||
27 | DataSeries\.h:\d+:.*IPSIS_S06.*found: (value_type) |
|
|||
28 | DataSeries\.h:\d+:.*IPSIS_S06.*found: (DataSeriesIteratorValue) |
|
|||
29 | DataSeries\.h:\d+:.*IPSIS_S06.*found: (Dim) |
|
|||
30 | DataSeries\.h:\d+:.*IPSIS_S06.*found: (IC) |
|
|||
31 | DataSeries\.h:\d+:.*IPSIS_S06.*found: (IsConst) |
|
|||
32 |
|
||||
33 | # Ignore false positive relative to iterators |
|
|||
34 | SqpIterator\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (random_access_iterator_tag) |
|
|||
35 | SqpIterator\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (T) |
|
|||
36 | SqpIterator\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (ptrdiff_t) |
|
|||
37 | SqpIterator\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (value_type) |
|
|||
38 | SqpIterator\.h:\d+:.*IPSIS_S06.*found: (iterator_category) |
|
|||
39 | SqpIterator\.h:\d+:.*IPSIS_S06.*found: (random_access_iterator_tag) |
|
|||
40 | SqpIterator\.h:\d+:.*IPSIS_S06.*found: (value_type) |
|
|||
41 | SqpIterator\.h:\d+:.*IPSIS_S06.*found: (T) |
|
|||
42 | SqpIterator\.h:\d+:.*IPSIS_S06.*found: (difference_type) |
|
|||
43 | SqpIterator\.h:\d+:.*IPSIS_S06.*found: (ptrdiff_t) |
|
|||
44 | SqpIterator\.h:\d+:.*IPSIS_S06.*found: (pointer) |
|
|||
45 | SqpIterator\.h:\d+:.*IPSIS_S06.*found: (reference) |
|
|||
46 | SqpIterator\.h:\d+:.*IPSIS_S06.*found: (value_type) |
|
|||
47 |
|
||||
48 | # Ignore false positive relative to an alias |
|
|||
49 | DataSourceItemAction\.h:\d+:.*IPSIS_S06.*found: (ExecuteFunction) |
|
|||
50 |
|
||||
51 | # Ignore false positive relative to unnamed namespace |
|
|||
52 | VariableController\.cpp:\d+:.*IPSIS_F13.* |
|
@@ -63,7 +63,6 FUNCTION(ADD_CLANGFORMAT_TARGETS) | |||||
63 | clangformat_incr(i) |
|
63 | clangformat_incr(i) | |
64 | ENDWHILE() |
|
64 | ENDWHILE() | |
65 |
|
65 | |||
66 |
|
||||
67 | # Retrieve source files to format |
|
66 | # Retrieve source files to format | |
68 | IF(recurse) |
|
67 | IF(recurse) | |
69 | FILE(GLOB_RECURSE srcs ${globs}) |
|
68 | FILE(GLOB_RECURSE srcs ${globs}) | |
@@ -82,15 +81,6 FUNCTION(ADD_CLANGFORMAT_TARGETS) | |||||
82 | # Create the directory where the touched files will be saved |
|
81 | # Create the directory where the touched files will be saved | |
83 | SET(formatDirectory "${CMAKE_CURRENT_BINARY_DIR}/format") |
|
82 | SET(formatDirectory "${CMAKE_CURRENT_BINARY_DIR}/format") | |
84 | FILE(MAKE_DIRECTORY ${formatDirectory}) |
|
83 | FILE(MAKE_DIRECTORY ${formatDirectory}) | |
85 | # STRING(REPLACE "*.ui" "" srcs ${srcs}) |
|
|||
86 | FOREACH(item ${globs}) |
|
|||
87 | STRING(REGEX MATCH ".*\.ui$" item ${item}) |
|
|||
88 | IF(item) |
|
|||
89 | LIST(APPEND UIS ${item}) |
|
|||
90 | ENDIF(item) |
|
|||
91 | ENDFOREACH(item ${globs}) |
|
|||
92 |
|
||||
93 | LIST(REMOVE_ITEM srcs ${UIS}) |
|
|||
94 | FOREACH (s ${srcs}) |
|
84 | FOREACH (s ${srcs}) | |
95 | SET(touchedFile ${formatDirectory}/format_touchedfile_${reportNb}) |
|
85 | SET(touchedFile ${formatDirectory}/format_touchedfile_${reportNb}) | |
96 | IF(addToAll) |
|
86 | IF(addToAll) |
@@ -10,10 +10,3 | |||||
10 | # Ignore false positive relative to 'override' keyword |
|
10 | # Ignore false positive relative to 'override' keyword | |
11 | .*IPSIS_S04_VARIABLE.*found: override |
|
11 | .*IPSIS_S04_VARIABLE.*found: override | |
12 | .*IPSIS_S06.*found: override |
|
12 | .*IPSIS_S06.*found: override | |
13 |
|
||||
14 | # Ignore false positive relative to 'final' keyword |
|
|||
15 | .*IPSIS_S04_VARIABLE.*found: final |
|
|||
16 | .*IPSIS_S06.*found: final |
|
|||
17 |
|
||||
18 | # Ignore false positive relative to unnamed namespace |
|
|||
19 | .*IPSIS_F13.* |
|
@@ -67,12 +67,6 set_property(TARGET ${SQPGUI_LIBRARY_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) | |||||
67 | TARGET_LINK_LIBRARIES(${SQPGUI_LIBRARY_NAME} ${LIBRARIES}) |
|
67 | TARGET_LINK_LIBRARIES(${SQPGUI_LIBRARY_NAME} ${LIBRARIES}) | |
68 | qt5_use_modules(${SQPGUI_LIBRARY_NAME} Core Widgets PrintSupport) |
|
68 | qt5_use_modules(${SQPGUI_LIBRARY_NAME} Core Widgets PrintSupport) | |
69 |
|
69 | |||
70 |
|
||||
71 | INSTALL(TARGETS ${SQPGUI_LIBRARY_NAME} |
|
|||
72 | RUNTIME DESTINATION ${INSTALL_BINARY_DIR} |
|
|||
73 | LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR} |
|
|||
74 | ARCHIVE DESTINATION ${INSTALL_LIBRARY_DIR} |
|
|||
75 | ) |
|
|||
76 | add_dependencies(${SQPGUI_LIBRARY_NAME} ${SQPCORE_LIBRARY_NAME}) |
|
70 | add_dependencies(${SQPGUI_LIBRARY_NAME} ${SQPCORE_LIBRARY_NAME}) | |
77 |
|
71 | |||
78 |
|
72 |
@@ -21,14 +21,9 public: | |||||
21 | explicit DataSourceTreeWidgetItem(QTreeWidget *parent, const DataSourceItem *data, |
|
21 | explicit DataSourceTreeWidgetItem(QTreeWidget *parent, const DataSourceItem *data, | |
22 | int type = Type); |
|
22 | int type = Type); | |
23 |
|
23 | |||
24 | const DataSourceItem *data() const; |
|
|||
25 |
|
||||
26 | virtual QVariant data(int column, int role) const override; |
|
24 | virtual QVariant data(int column, int role) const override; | |
27 | virtual void setData(int column, int role, const QVariant &value) override; |
|
25 | virtual void setData(int column, int role, const QVariant &value) override; | |
28 |
|
26 | |||
29 | /// @return the actions associated to the item |
|
|||
30 | QList<QAction *> actions() const noexcept; |
|
|||
31 |
|
||||
32 | private: |
|
27 | private: | |
33 | class DataSourceTreeWidgetItemPrivate; |
|
28 | class DataSourceTreeWidgetItemPrivate; | |
34 | spimpl::unique_impl_ptr<DataSourceTreeWidgetItemPrivate> impl; |
|
29 | spimpl::unique_impl_ptr<DataSourceTreeWidgetItemPrivate> impl; |
@@ -18,7 +18,6 class DataSourceWidget : public QWidget { | |||||
18 |
|
18 | |||
19 | public: |
|
19 | public: | |
20 | explicit DataSourceWidget(QWidget *parent = 0); |
|
20 | explicit DataSourceWidget(QWidget *parent = 0); | |
21 | virtual ~DataSourceWidget() noexcept; |
|
|||
22 |
|
21 | |||
23 | public slots: |
|
22 | public slots: | |
24 | /** |
|
23 | /** | |
@@ -30,13 +29,6 public slots: | |||||
30 |
|
29 | |||
31 | private: |
|
30 | private: | |
32 | Ui::DataSourceWidget *ui; |
|
31 | Ui::DataSourceWidget *ui; | |
33 |
|
||||
34 | private slots: |
|
|||
35 | /// Slot called when the filtering text has changed |
|
|||
36 | void filterChanged(const QString &text) noexcept; |
|
|||
37 |
|
||||
38 | /// Slot called when right clicking on an item in the tree (displays a menu) |
|
|||
39 | void onTreeMenuRequested(const QPoint &pos) noexcept; |
|
|||
40 | }; |
|
32 | }; | |
41 |
|
33 | |||
42 | #endif // SCIQLOP_DATASOURCEWIDGET_H |
|
34 | #endif // SCIQLOP_DATASOURCEWIDGET_H |
@@ -16,8 +16,6 Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication) | |||||
16 | #define sqpApp (static_cast<SqpApplication *>(QCoreApplication::instance())) |
|
16 | #define sqpApp (static_cast<SqpApplication *>(QCoreApplication::instance())) | |
17 |
|
17 | |||
18 | class DataSourceController; |
|
18 | class DataSourceController; | |
19 | class NetworkController; |
|
|||
20 | class TimeController; |
|
|||
21 | class VariableController; |
|
19 | class VariableController; | |
22 | class VisualizationController; |
|
20 | class VisualizationController; | |
23 |
|
21 | |||
@@ -39,8 +37,6 public: | |||||
39 |
|
37 | |||
40 | /// Accessors for the differents sciqlop controllers |
|
38 | /// Accessors for the differents sciqlop controllers | |
41 | DataSourceController &dataSourceController() noexcept; |
|
39 | DataSourceController &dataSourceController() noexcept; | |
42 | NetworkController &networkController() noexcept; |
|
|||
43 | TimeController &timeController() noexcept; |
|
|||
44 | VariableController &variableController() noexcept; |
|
40 | VariableController &variableController() noexcept; | |
45 | VisualizationController &visualizationController() noexcept; |
|
41 | VisualizationController &visualizationController() noexcept; | |
46 |
|
42 |
@@ -1,18 +1,8 | |||||
1 | #ifndef SCIQLOP_VARIABLEINSPECTORWIDGET_H |
|
1 | #ifndef SCIQLOP_VARIABLEINSPECTORWIDGET_H | |
2 | #define SCIQLOP_VARIABLEINSPECTORWIDGET_H |
|
2 | #define SCIQLOP_VARIABLEINSPECTORWIDGET_H | |
3 |
|
3 | |||
4 | #include <QLoggingCategory> |
|
|||
5 | #include <QMenu> |
|
|||
6 | #include <QWidget> |
|
4 | #include <QWidget> | |
7 |
|
5 | |||
8 | #include <memory> |
|
|||
9 |
|
||||
10 | Q_DECLARE_LOGGING_CATEGORY(LOG_VariableInspectorWidget) |
|
|||
11 |
|
||||
12 | class Variable; |
|
|||
13 |
|
||||
14 | class QProgressBarItemDelegate; |
|
|||
15 |
|
||||
16 | namespace Ui { |
|
6 | namespace Ui { | |
17 | class VariableInspectorWidget; |
|
7 | class VariableInspectorWidget; | |
18 | } // Ui |
|
8 | } // Ui | |
@@ -29,28 +19,8 public: | |||||
29 | explicit VariableInspectorWidget(QWidget *parent = 0); |
|
19 | explicit VariableInspectorWidget(QWidget *parent = 0); | |
30 | virtual ~VariableInspectorWidget(); |
|
20 | virtual ~VariableInspectorWidget(); | |
31 |
|
21 | |||
32 | signals: |
|
|||
33 | /** |
|
|||
34 | * Signal emitted before a menu concerning variables is displayed. It is used for other widgets |
|
|||
35 | * to complete the menu. |
|
|||
36 | * @param tableMenu the menu to be completed |
|
|||
37 | * @param variables the variables concerned by the menu |
|
|||
38 | * @remarks To make the dynamic addition of menus work, the connections to this signal must be |
|
|||
39 | * in Qt :: DirectConnection |
|
|||
40 | */ |
|
|||
41 | void tableMenuAboutToBeDisplayed(QMenu *tableMenu, |
|
|||
42 | const QVector<std::shared_ptr<Variable> > &variables); |
|
|||
43 |
|
||||
44 | private: |
|
22 | private: | |
45 | Ui::VariableInspectorWidget *ui; |
|
23 | Ui::VariableInspectorWidget *ui; | |
46 |
|
||||
47 | QProgressBarItemDelegate *m_ProgressBarItemDelegate; |
|
|||
48 |
|
||||
49 | private slots: |
|
|||
50 | /// Slot called when right clicking on an variable in the table (displays a menu) |
|
|||
51 | void onTableMenuRequested(const QPoint &pos) noexcept; |
|
|||
52 | /// Refreshes instantly the variable view |
|
|||
53 | void refresh() noexcept; |
|
|||
54 | }; |
|
24 | }; | |
55 |
|
25 | |||
56 | #endif // SCIQLOP_VARIABLEINSPECTORWIDGET_H |
|
26 | #endif // SCIQLOP_VARIABLEINSPECTORWIDGET_H |
@@ -1,23 +1,22 | |||||
1 | #ifndef SCIQLOP_IVISUALIZATIONWIDGET_H |
|
1 | #ifndef SCIQLOP_IVISUALIZATIONWIDGET_H | |
2 | #define SCIQLOP_IVISUALIZATIONWIDGET_H |
|
2 | #define SCIQLOP_IVISUALIZATIONWIDGET_H | |
3 |
|
3 | |||
4 |
#include "Visualization/IV |
|
4 | #include "Visualization/IVisualizationWidgetVisitor.h" | |
5 |
|
5 | |||
6 | #include <QString> |
|
6 | #include <QString> | |
7 | #include <memory> |
|
7 | #include <memory> | |
8 |
|
8 | |||
9 | class IVisualizationWidgetVisitor; |
|
|||
10 |
|
||||
11 | /** |
|
9 | /** | |
12 | * @brief The IVisualizationWidget handles the visualization widget. |
|
10 | * @brief The IVisualizationWidget handles the visualization widget. | |
13 | */ |
|
11 | */ | |
14 |
class IVisualizationWidget |
|
12 | class IVisualizationWidget { | |
15 |
|
13 | |||
16 | public: |
|
14 | public: | |
17 | virtual ~IVisualizationWidget() = default; |
|
15 | virtual ~IVisualizationWidget() = default; | |
18 |
|
16 | |||
19 | /// Initializes the plugin |
|
17 | /// Initializes the plugin | |
20 |
virtual void accept(IVisualizationWidget |
|
18 | virtual void accept(IVisualizationWidget *visitor) = 0; | |
|
19 | virtual void close() = 0; | |||
21 | virtual QString name() const = 0; |
|
20 | virtual QString name() const = 0; | |
22 | }; |
|
21 | }; | |
23 |
|
22 |
@@ -15,12 +15,9 class IVisualizationWidgetVisitor { | |||||
15 | public: |
|
15 | public: | |
16 | virtual ~IVisualizationWidgetVisitor() = default; |
|
16 | virtual ~IVisualizationWidgetVisitor() = default; | |
17 |
|
17 | |||
18 |
virtual void visit |
|
18 | virtual void visit(VisualizationWidget *widget) = 0; | |
19 |
virtual void visit |
|
19 | virtual void visit(VisualizationTabWidget *tabWidget) = 0; | |
20 |
virtual void visit |
|
20 | virtual void visit(VisualizationZoneWidget *zoneWidget) = 0; | |
21 | virtual void visitLeave(VisualizationTabWidget *tabWidget) = 0; |
|
|||
22 | virtual void visitEnter(VisualizationZoneWidget *zoneWidget) = 0; |
|
|||
23 | virtual void visitLeave(VisualizationZoneWidget *zoneWidget) = 0; |
|
|||
24 | virtual void visit(VisualizationGraphWidget *graphWidget) = 0; |
|
21 | virtual void visit(VisualizationGraphWidget *graphWidget) = 0; | |
25 | }; |
|
22 | }; | |
26 |
|
23 |
@@ -3,18 +3,12 | |||||
3 |
|
3 | |||
4 | #include "Visualization/IVisualizationWidget.h" |
|
4 | #include "Visualization/IVisualizationWidget.h" | |
5 |
|
5 | |||
6 | #include <QLoggingCategory> |
|
|||
7 | #include <QWidget> |
|
6 | #include <QWidget> | |
8 |
|
7 | |||
9 | #include <memory> |
|
8 | #include <memory> | |
10 |
|
9 | |||
11 | #include <Common/spimpl.h> |
|
10 | #include <Common/spimpl.h> | |
12 |
|
11 | |||
13 | Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget) |
|
|||
14 |
|
||||
15 | class QCPRange; |
|
|||
16 | class QCustomPlot; |
|
|||
17 | class SqpRange; |
|
|||
18 | class Variable; |
|
12 | class Variable; | |
19 |
|
13 | |||
20 | namespace Ui { |
|
14 | namespace Ui { | |
@@ -24,75 +18,22 class VisualizationGraphWidget; | |||||
24 | class VisualizationGraphWidget : public QWidget, public IVisualizationWidget { |
|
18 | class VisualizationGraphWidget : public QWidget, public IVisualizationWidget { | |
25 | Q_OBJECT |
|
19 | Q_OBJECT | |
26 |
|
20 | |||
27 | friend class QCustomPlotSynchronizer; |
|
|||
28 | friend class VisualizationGraphRenderingDelegate; |
|
|||
29 |
|
||||
30 | public: |
|
21 | public: | |
31 |
explicit VisualizationGraphWidget( |
|
22 | explicit VisualizationGraphWidget(QWidget *parent = 0); | |
32 | virtual ~VisualizationGraphWidget(); |
|
23 | virtual ~VisualizationGraphWidget(); | |
33 |
|
24 | |||
34 | /// If acquisition isn't enable, requestDataLoading signal cannot be emit |
|
25 | void addVariable(std::shared_ptr<Variable> variable); | |
35 | void enableAcquisition(bool enable); |
|
|||
36 |
|
||||
37 | void addVariable(std::shared_ptr<Variable> variable, SqpRange range); |
|
|||
38 |
|
||||
39 | /// Removes a variable from the graph |
|
|||
40 | void removeVariable(std::shared_ptr<Variable> variable) noexcept; |
|
|||
41 |
|
||||
42 | void setRange(std::shared_ptr<Variable> variable, const SqpRange &range); |
|
|||
43 | void setYRange(const SqpRange &range); |
|
|||
44 | SqpRange graphRange() const noexcept; |
|
|||
45 | void setGraphRange(const SqpRange &range); |
|
|||
46 |
|
26 | |||
47 | // IVisualizationWidget interface |
|
27 | // IVisualizationWidget interface | |
48 |
void accept(IVisualizationWidget |
|
28 | void accept(IVisualizationWidget *visitor) override; | |
49 | bool canDrop(const Variable &variable) const override; |
|
29 | void close() override; | |
50 | bool contains(const Variable &variable) const override; |
|
30 | QString name() const; | |
51 | QString name() const override; |
|
|||
52 |
|
||||
53 |
|
||||
54 | signals: |
|
|||
55 | void synchronize(const SqpRange &range, const SqpRange &oldRange); |
|
|||
56 | void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range, |
|
|||
57 | const SqpRange &oldRange, bool synchronise); |
|
|||
58 |
|
||||
59 | /// Signal emitted when the variable is about to be removed from the graph |
|
|||
60 | void variableAboutToBeRemoved(std::shared_ptr<Variable> var); |
|
|||
61 | /// Signal emitted when the variable has been added to the graph |
|
|||
62 | void variableAdded(std::shared_ptr<Variable> var); |
|
|||
63 |
|
||||
64 | protected: |
|
|||
65 | void closeEvent(QCloseEvent *event) override; |
|
|||
66 | void enterEvent(QEvent *event) override; |
|
|||
67 | void leaveEvent(QEvent *event) override; |
|
|||
68 |
|
||||
69 | QCustomPlot &plot() noexcept; |
|
|||
70 |
|
31 | |||
71 | private: |
|
32 | private: | |
72 | Ui::VisualizationGraphWidget *ui; |
|
33 | Ui::VisualizationGraphWidget *ui; | |
73 |
|
34 | |||
74 | class VisualizationGraphWidgetPrivate; |
|
35 | class VisualizationGraphWidgetPrivate; | |
75 | spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl; |
|
36 | spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl; | |
76 |
|
||||
77 | private slots: |
|
|||
78 | /// Slot called when right clicking on the graph (displays a menu) |
|
|||
79 | void onGraphMenuRequested(const QPoint &pos) noexcept; |
|
|||
80 |
|
||||
81 | /// Rescale the X axe to range parameter |
|
|||
82 | void onRangeChanged(const QCPRange &t1, const QCPRange &t2); |
|
|||
83 |
|
||||
84 | /// Slot called when a mouse move was made |
|
|||
85 | void onMouseMove(QMouseEvent *event) noexcept; |
|
|||
86 | /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done |
|
|||
87 | void onMouseWheel(QWheelEvent *event) noexcept; |
|
|||
88 | /// Slot called when a mouse press was made, to activate the calibration of a graph |
|
|||
89 | void onMousePress(QMouseEvent *event) noexcept; |
|
|||
90 | /// Slot called when a mouse release was made, to deactivate the calibration of a graph |
|
|||
91 | void onMouseRelease(QMouseEvent *event) noexcept; |
|
|||
92 |
|
||||
93 | void onDataCacheVariableUpdated(); |
|
|||
94 |
|
||||
95 | void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range); |
|
|||
96 | }; |
|
37 | }; | |
97 |
|
38 | |||
98 | #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H |
|
39 | #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H |
@@ -3,14 +3,8 | |||||
3 |
|
3 | |||
4 | #include "Visualization/IVisualizationWidget.h" |
|
4 | #include "Visualization/IVisualizationWidget.h" | |
5 |
|
5 | |||
6 | #include <Common/spimpl.h> |
|
|||
7 |
|
||||
8 | #include <QLoggingCategory> |
|
|||
9 | #include <QWidget> |
|
6 | #include <QWidget> | |
10 |
|
7 | |||
11 | Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget) |
|
|||
12 |
|
||||
13 | class Variable; |
|
|||
14 | class VisualizationZoneWidget; |
|
8 | class VisualizationZoneWidget; | |
15 |
|
9 | |||
16 | namespace Ui { |
|
10 | namespace Ui { | |
@@ -21,37 +15,25 class VisualizationTabWidget : public QWidget, public IVisualizationWidget { | |||||
21 | Q_OBJECT |
|
15 | Q_OBJECT | |
22 |
|
16 | |||
23 | public: |
|
17 | public: | |
24 |
explicit VisualizationTabWidget( |
|
18 | explicit VisualizationTabWidget(QWidget *parent = 0); | |
25 | virtual ~VisualizationTabWidget(); |
|
19 | virtual ~VisualizationTabWidget(); | |
26 |
|
20 | |||
27 | /// Add a zone widget |
|
21 | /// Add a zone widget | |
28 | void addZone(VisualizationZoneWidget *zoneWidget); |
|
22 | void addZone(VisualizationZoneWidget *zoneWidget); | |
29 |
|
23 | |||
30 | /** |
|
24 | /// Create a zone using a Variable | |
31 | * Creates a zone using a variable. The variable will be displayed in a new graph of the new |
|
25 | VisualizationZoneWidget *createZone(); | |
32 | * zone. |
|
26 | ||
33 | * @param variable the variable for which to create the zone |
|
27 | /// Remove a zone | |
34 | * @return the pointer to the created zone |
|
28 | void removeZone(VisualizationZoneWidget *zone); | |
35 | */ |
|
|||
36 | VisualizationZoneWidget *createZone(std::shared_ptr<Variable> variable); |
|
|||
37 |
|
29 | |||
38 | // IVisualizationWidget interface |
|
30 | // IVisualizationWidget interface | |
39 |
void accept(IVisualizationWidget |
|
31 | void accept(IVisualizationWidget *visitor) override; | |
40 | bool canDrop(const Variable &variable) const override; |
|
32 | void close() override; | |
41 | bool contains(const Variable &variable) const override; |
|
|||
42 | QString name() const override; |
|
33 | QString name() const override; | |
43 |
|
34 | |||
44 | protected: |
|
|||
45 | void closeEvent(QCloseEvent *event) override; |
|
|||
46 |
|
||||
47 | private: |
|
35 | private: | |
48 | /// @return the layout of tab in which zones are added |
|
|||
49 | QLayout &tabLayout() const noexcept; |
|
|||
50 |
|
||||
51 | Ui::VisualizationTabWidget *ui; |
|
36 | Ui::VisualizationTabWidget *ui; | |
52 |
|
||||
53 | class VisualizationTabWidgetPrivate; |
|
|||
54 | spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl; |
|
|||
55 | }; |
|
37 | }; | |
56 |
|
38 | |||
57 | #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H |
|
39 | #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H |
@@ -2,17 +2,14 | |||||
2 | #define SCIQLOP_VISUALIZATIONWIDGET_H |
|
2 | #define SCIQLOP_VISUALIZATIONWIDGET_H | |
3 |
|
3 | |||
4 | #include "Visualization/IVisualizationWidget.h" |
|
4 | #include "Visualization/IVisualizationWidget.h" | |
5 | #include <Data/SqpRange.h> |
|
|||
6 |
|
5 | |||
7 | #include <QLoggingCategory> |
|
6 | #include <QLoggingCategory> | |
8 | #include <QWidget> |
|
7 | #include <QWidget> | |
9 |
|
8 | |||
10 | Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationWidget) |
|
|||
11 |
|
||||
12 | class QMenu; |
|
|||
13 | class Variable; |
|
|||
14 | class VisualizationTabWidget; |
|
9 | class VisualizationTabWidget; | |
15 |
|
10 | |||
|
11 | Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationWidget) | |||
|
12 | ||||
16 | namespace Ui { |
|
13 | namespace Ui { | |
17 | class VisualizationWidget; |
|
14 | class VisualizationWidget; | |
18 | } // namespace Ui |
|
15 | } // namespace Ui | |
@@ -24,28 +21,19 public: | |||||
24 | explicit VisualizationWidget(QWidget *parent = 0); |
|
21 | explicit VisualizationWidget(QWidget *parent = 0); | |
25 | virtual ~VisualizationWidget(); |
|
22 | virtual ~VisualizationWidget(); | |
26 |
|
23 | |||
|
24 | /// Add a zone widget | |||
|
25 | virtual void addTab(VisualizationTabWidget *tabWidget); | |||
|
26 | ||||
|
27 | /// Create a tab using a Variable | |||
|
28 | VisualizationTabWidget *createTab(); | |||
|
29 | ||||
|
30 | /// Remove a tab | |||
|
31 | void removeTab(VisualizationTabWidget *tab); | |||
|
32 | ||||
27 | // IVisualizationWidget interface |
|
33 | // IVisualizationWidget interface | |
28 |
void accept(IVisualizationWidget |
|
34 | void accept(IVisualizationWidget *visitor) override; | |
29 | bool canDrop(const Variable &variable) const override; |
|
35 | void close() override; | |
30 | bool contains(const Variable &variable) const override; |
|
36 | QString name() const; | |
31 | QString name() const override; |
|
|||
32 |
|
||||
33 | public slots: |
|
|||
34 | /** |
|
|||
35 | * Attaches to a menu the menu relative to the visualization of variables |
|
|||
36 | * @param menu the parent menu of the generated menu |
|
|||
37 | * @param variables the variables for which to generate the menu |
|
|||
38 | */ |
|
|||
39 | void attachVariableMenu(QMenu *menu, |
|
|||
40 | const QVector<std::shared_ptr<Variable> > &variables) noexcept; |
|
|||
41 |
|
||||
42 | /// Slot called when a variable is about to be deleted from SciQlop |
|
|||
43 | void onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept; |
|
|||
44 |
|
||||
45 | void onRangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range) noexcept; |
|
|||
46 |
|
||||
47 | protected: |
|
|||
48 | void closeEvent(QCloseEvent *event) override; |
|
|||
49 |
|
37 | |||
50 | private: |
|
38 | private: | |
51 | Ui::VisualizationWidget *ui; |
|
39 | Ui::VisualizationWidget *ui; |
@@ -3,58 +3,37 | |||||
3 |
|
3 | |||
4 | #include "Visualization/IVisualizationWidget.h" |
|
4 | #include "Visualization/IVisualizationWidget.h" | |
5 |
|
5 | |||
6 | #include <QLoggingCategory> |
|
6 | class VisualizationGraphWidget; | |
7 | #include <QWidget> |
|
|||
8 |
|
||||
9 | #include <memory> |
|
|||
10 |
|
||||
11 | #include <Common/spimpl.h> |
|
|||
12 |
|
7 | |||
13 | Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget) |
|
8 | #include <QWidget> | |
14 |
|
9 | |||
15 | namespace Ui { |
|
10 | namespace Ui { | |
16 | class VisualizationZoneWidget; |
|
11 | class VisualizationZoneWidget; | |
17 | } // Ui |
|
12 | } // Ui | |
18 |
|
13 | |||
19 | class Variable; |
|
|||
20 | class VisualizationGraphWidget; |
|
|||
21 |
|
||||
22 | class VisualizationZoneWidget : public QWidget, public IVisualizationWidget { |
|
14 | class VisualizationZoneWidget : public QWidget, public IVisualizationWidget { | |
23 | Q_OBJECT |
|
15 | Q_OBJECT | |
24 |
|
16 | |||
25 | public: |
|
17 | public: | |
26 |
explicit VisualizationZoneWidget( |
|
18 | explicit VisualizationZoneWidget(QWidget *parent = 0); | |
27 | virtual ~VisualizationZoneWidget(); |
|
19 | virtual ~VisualizationZoneWidget(); | |
28 |
|
20 | |||
29 | /// Add a graph widget |
|
21 | /// Add a graph widget | |
30 | void addGraph(VisualizationGraphWidget *graphWidget); |
|
22 | void addGraph(VisualizationGraphWidget *graphWidget); | |
31 |
|
23 | |||
32 | /** |
|
24 | /// Create a graph using a Variable | |
33 | * Creates a graph using a variable. The variable will be displayed in the new graph. |
|
25 | VisualizationGraphWidget *createGraph(); | |
34 | * @param variable the variable for which to create the graph |
|
26 | ||
35 | * @return the pointer to the created graph |
|
27 | /// Remove a graph | |
36 | */ |
|
28 | void removeGraph(VisualizationGraphWidget *graph); | |
37 | VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable); |
|
|||
38 |
|
29 | |||
39 | // IVisualizationWidget interface |
|
30 | // IVisualizationWidget interface | |
40 |
void accept(IVisualizationWidget |
|
31 | void accept(IVisualizationWidget *visitor) override; | |
41 | bool canDrop(const Variable &variable) const override; |
|
32 | void close() override; | |
42 | bool contains(const Variable &variable) const override; |
|
|||
43 | QString name() const override; |
|
33 | QString name() const override; | |
44 |
|
34 | |||
45 | protected: |
|
|||
46 | void closeEvent(QCloseEvent *event) override; |
|
|||
47 |
|
||||
48 | private: |
|
35 | private: | |
49 | Ui::VisualizationZoneWidget *ui; |
|
36 | Ui::VisualizationZoneWidget *ui; | |
50 |
|
||||
51 | class VisualizationZoneWidgetPrivate; |
|
|||
52 | spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl; |
|
|||
53 |
|
||||
54 | private slots: |
|
|||
55 | void onVariableAdded(std::shared_ptr<Variable> variable); |
|
|||
56 | /// Slot called when a variable is about to be removed from a graph contained in the zone |
|
|||
57 | void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable); |
|
|||
58 | }; |
|
37 | }; | |
59 |
|
38 | |||
60 | #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H |
|
39 | #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H |
@@ -42,9 +42,6 | |||||
42 |
|
42 | |||
43 | #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) |
|
43 | #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) | |
44 | #define QCP_DEVICEPIXELRATIO_SUPPORTED |
|
44 | #define QCP_DEVICEPIXELRATIO_SUPPORTED | |
45 | #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) |
|
|||
46 | #define QCP_DEVICEPIXELRATIO_FLOAT |
|
|||
47 | #endif |
|
|||
48 | #endif |
|
45 | #endif | |
49 |
|
46 | |||
50 | #include <QtCore/QCache> |
|
47 | #include <QtCore/QCache> | |
@@ -112,8 +109,8 class QCPColorMap; | |||||
112 | class QCPColorScale; |
|
109 | class QCPColorScale; | |
113 | class QCPBars; |
|
110 | class QCPBars; | |
114 |
|
111 | |||
115 |
/* including file 'src/global.h', size 16 |
|
112 | /* including file 'src/global.h', size 16131 */ | |
116 | /* commit e7c6a5540d344a96d107dce53f9d4414a09a7320 2017-07-25 00:52:29 +0200 */ |
|
113 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
117 |
|
114 | |||
118 | // decl definitions for shared library compilation/usage: |
|
115 | // decl definitions for shared library compilation/usage: | |
119 | #if defined(QCUSTOMPLOT_COMPILE_LIBRARY) |
|
116 | #if defined(QCUSTOMPLOT_COMPILE_LIBRARY) | |
@@ -1797,8 +1794,8 protected: | |||||
1797 | /* end of 'src/axis/axistickerdatetime.h' */ |
|
1794 | /* end of 'src/axis/axistickerdatetime.h' */ | |
1798 |
|
1795 | |||
1799 |
|
1796 | |||
1800 |
/* including file 'src/axis/axistickertime.h', size 3 |
|
1797 | /* including file 'src/axis/axistickertime.h', size 3288 */ | |
1801 | /* commit c38adb94d83c6a752597a5d43d45c0561fbe1d4d 2017-08-13 17:37:53 +0200 */ |
|
1798 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
1802 |
|
1799 | |||
1803 | class QCP_LIB_DECL QCPAxisTickerTime : public QCPAxisTicker { |
|
1800 | class QCP_LIB_DECL QCPAxisTickerTime : public QCPAxisTicker { | |
1804 | Q_GADGET |
|
1801 | Q_GADGET | |
@@ -1808,17 +1805,7 public: | |||||
1808 |
|
1805 | |||
1809 | \see setFieldWidth, setTimeFormat |
|
1806 | \see setFieldWidth, setTimeFormat | |
1810 | */ |
|
1807 | */ | |
1811 | enum TimeUnit { |
|
1808 | enum TimeUnit { tuMilliseconds, tuSeconds, tuMinutes, tuHours, tuDays }; | |
1812 | tuMilliseconds ///< Milliseconds, one thousandth of a second (%%z in \ref setTimeFormat) |
|
|||
1813 | , |
|
|||
1814 | tuSeconds ///< Seconds (%%s in \ref setTimeFormat) |
|
|||
1815 | , |
|
|||
1816 | tuMinutes ///< Minutes (%%m in \ref setTimeFormat) |
|
|||
1817 | , |
|
|||
1818 | tuHours ///< Hours (%%h in \ref setTimeFormat) |
|
|||
1819 | , |
|
|||
1820 | tuDays ///< Days (%%d in \ref setTimeFormat) |
|
|||
1821 | }; |
|
|||
1822 | Q_ENUMS(TimeUnit) |
|
1809 | Q_ENUMS(TimeUnit) | |
1823 |
|
1810 | |||
1824 | QCPAxisTickerTime(); |
|
1811 | QCPAxisTickerTime(); | |
@@ -2039,8 +2026,8 protected: | |||||
2039 | /* end of 'src/axis/axistickerlog.h' */ |
|
2026 | /* end of 'src/axis/axistickerlog.h' */ | |
2040 |
|
2027 | |||
2041 |
|
2028 | |||
2042 |
/* including file 'src/axis/axis.h', size 20 |
|
2029 | /* including file 'src/axis/axis.h', size 20230 */ | |
2043 | /* commit 0cc4d9f61f7bf45321a88fec89d909b020ffa26f 2017-08-14 00:43:29 +0200 */ |
|
2030 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
2044 |
|
2031 | |||
2045 | class QCP_LIB_DECL QCPGrid : public QCPLayerable { |
|
2032 | class QCP_LIB_DECL QCPGrid : public QCPLayerable { | |
2046 | Q_OBJECT |
|
2033 | Q_OBJECT | |
@@ -2377,9 +2364,6 protected: | |||||
2377 | QVector<double> mSubTickVector; |
|
2364 | QVector<double> mSubTickVector; | |
2378 | bool mCachedMarginValid; |
|
2365 | bool mCachedMarginValid; | |
2379 | int mCachedMargin; |
|
2366 | int mCachedMargin; | |
2380 | bool mDragging; |
|
|||
2381 | QCPRange mDragStartRange; |
|
|||
2382 | QCP::AntialiasedElements mAADragBackup, mNotAADragBackup; |
|
|||
2383 |
|
2367 | |||
2384 | // introduced virtual methods: |
|
2368 | // introduced virtual methods: | |
2385 | virtual int calculateMargin(); |
|
2369 | virtual int calculateMargin(); | |
@@ -2392,11 +2376,6 protected: | |||||
2392 | virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, |
|
2376 | virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, | |
2393 | bool *selectionStateChanged) Q_DECL_OVERRIDE; |
|
2377 | bool *selectionStateChanged) Q_DECL_OVERRIDE; | |
2394 | virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE; |
|
2378 | virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE; | |
2395 | // mouse events: |
|
|||
2396 | virtual void mousePressEvent(QMouseEvent *event, const QVariant &details); |
|
|||
2397 | virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos); |
|
|||
2398 | virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos); |
|
|||
2399 | virtual void wheelEvent(QWheelEvent *event); |
|
|||
2400 |
|
2379 | |||
2401 | // non-virtual methods: |
|
2380 | // non-virtual methods: | |
2402 | void setupTickVectors(); |
|
2381 | void setupTickVectors(); | |
@@ -2633,8 +2612,8 Q_DECLARE_METATYPE(QCPScatterStyle::ScatterShape) | |||||
2633 | /* end of 'src/scatterstyle.h' */ |
|
2612 | /* end of 'src/scatterstyle.h' */ | |
2634 |
|
2613 | |||
2635 |
|
2614 | |||
2636 |
/* including file 'src/datacontainer.h', size 45 |
|
2615 | /* including file 'src/datacontainer.h', size 4535 */ | |
2637 | /* commit bee82298bd87b91a50093fb0b81cd7c734724a6f 2017-08-13 16:10:24 +0200 */ |
|
2616 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
2638 |
|
2617 | |||
2639 | /*! \relates QCPDataContainer |
|
2618 | /*! \relates QCPDataContainer | |
2640 | Returns whether the sort key of \a a is less than the sort key of \a b. |
|
2619 | Returns whether the sort key of \a a is less than the sort key of \a b. | |
@@ -2648,8 +2627,7 inline bool qcpLessThanSortKey(const DataType &a, const DataType &b) | |||||
2648 | } |
|
2627 | } | |
2649 |
|
2628 | |||
2650 | template <class DataType> |
|
2629 | template <class DataType> | |
2651 | class QCPDataContainer // no QCP_LIB_DECL, template class ends up in header (cpp included below) |
|
2630 | class QCP_LIB_DECL QCPDataContainer { | |
2652 | { |
|
|||
2653 | public: |
|
2631 | public: | |
2654 | typedef typename QVector<DataType>::const_iterator const_iterator; |
|
2632 | typedef typename QVector<DataType>::const_iterator const_iterator; | |
2655 | typedef typename QVector<DataType>::iterator iterator; |
|
2633 | typedef typename QVector<DataType>::iterator iterator; | |
@@ -2708,8 +2686,8 protected: | |||||
2708 |
|
2686 | |||
2709 | // include implementation in header since it is a class template: |
|
2687 | // include implementation in header since it is a class template: | |
2710 |
|
2688 | |||
2711 |
/* including file 'src/datacontainer.cpp', size 31 |
|
2689 | /* including file 'src/datacontainer.cpp', size 31224 */ | |
2712 | /* commit 820d2282db70144c358c13433cd74b4175f9252b 2017-07-24 00:24:17 +0200 */ |
|
2690 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
2713 |
|
2691 | |||
2714 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2692 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
2715 | //////////////////// QCPDataContainer |
|
2693 | //////////////////// QCPDataContainer | |
@@ -3425,8 +3403,7 QCPRange QCPDataContainer<DataType>::valueRange(bool &foundRange, QCP::SignDomai | |||||
3425 |
|
3403 | |||
3426 | /*! |
|
3404 | /*! | |
3427 | Makes sure \a begin and \a end mark a data range that is both within the bounds of this data |
|
3405 | Makes sure \a begin and \a end mark a data range that is both within the bounds of this data | |
3428 |
container's data, as well as within the specified \a dataRange. |
|
3406 | container's data, as well as within the specified \a dataRange. | |
3429 | the passed iterators \a begin and \a end is never expanded, only contracted if necessary. |
|
|||
3430 |
|
3407 | |||
3431 | This function doesn't require for \a dataRange to be within the bounds of this data container's |
|
3408 | This function doesn't require for \a dataRange to be within the bounds of this data container's | |
3432 | valid range. |
|
3409 | valid range. | |
@@ -3683,8 +3660,8 private: | |||||
3683 | /* end of 'src/plottable.h' */ |
|
3660 | /* end of 'src/plottable.h' */ | |
3684 |
|
3661 | |||
3685 |
|
3662 | |||
3686 |
/* including file 'src/item.h', size 938 |
|
3663 | /* including file 'src/item.h', size 9368 */ | |
3687 | /* commit 681a87c5e5365a5c7187d20b4077031003c48449 2017-07-23 23:46:48 +0200 */ |
|
3664 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
3688 |
|
3665 | |||
3689 | class QCP_LIB_DECL QCPItemAnchor { |
|
3666 | class QCP_LIB_DECL QCPItemAnchor { | |
3690 | Q_GADGET |
|
3667 | Q_GADGET | |
@@ -3773,7 +3750,7 public: | |||||
3773 | QCPAxis *keyAxis() const { return mKeyAxis.data(); } |
|
3750 | QCPAxis *keyAxis() const { return mKeyAxis.data(); } | |
3774 | QCPAxis *valueAxis() const { return mValueAxis.data(); } |
|
3751 | QCPAxis *valueAxis() const { return mValueAxis.data(); } | |
3775 | QCPAxisRect *axisRect() const; |
|
3752 | QCPAxisRect *axisRect() const; | |
3776 |
virtual QPointF pixelPosition() const |
|
3753 | virtual QPointF pixelPosition() const; | |
3777 |
|
3754 | |||
3778 | // setters: |
|
3755 | // setters: | |
3779 | void setType(PositionType type); |
|
3756 | void setType(PositionType type); | |
@@ -3880,8 +3857,8 private: | |||||
3880 | /* end of 'src/item.h' */ |
|
3857 | /* end of 'src/item.h' */ | |
3881 |
|
3858 | |||
3882 |
|
3859 | |||
3883 |
/* including file 'src/core.h', size 14 |
|
3860 | /* including file 'src/core.h', size 14797 */ | |
3884 | /* commit 29aafbce469a36d175d4fb32cbfd1f50a6072890 2016-10-12 19:21:24 +0200 */ |
|
3861 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
3885 |
|
3862 | |||
3886 | class QCP_LIB_DECL QCustomPlot : public QWidget { |
|
3863 | class QCP_LIB_DECL QCustomPlot : public QWidget { | |
3887 | Q_OBJECT |
|
3864 | Q_OBJECT | |
@@ -4114,9 +4091,7 protected: | |||||
4114 | QPoint mMousePressPos; |
|
4091 | QPoint mMousePressPos; | |
4115 | bool mMouseHasMoved; |
|
4092 | bool mMouseHasMoved; | |
4116 | QPointer<QCPLayerable> mMouseEventLayerable; |
|
4093 | QPointer<QCPLayerable> mMouseEventLayerable; | |
4117 | QPointer<QCPLayerable> mMouseSignalLayerable; |
|
|||
4118 | QVariant mMouseEventLayerableDetails; |
|
4094 | QVariant mMouseEventLayerableDetails; | |
4119 | QVariant mMouseSignalLayerableDetails; |
|
|||
4120 | bool mReplotting; |
|
4095 | bool mReplotting; | |
4121 | bool mReplotQueued; |
|
4096 | bool mReplotQueued; | |
4122 | int mOpenGlMultisamples; |
|
4097 | int mOpenGlMultisamples; | |
@@ -4178,12 +4153,11 Q_DECLARE_METATYPE(QCustomPlot::RefreshPriority) | |||||
4178 | /* end of 'src/core.h' */ |
|
4153 | /* end of 'src/core.h' */ | |
4179 |
|
4154 | |||
4180 |
|
4155 | |||
4181 |
/* including file 'src/plottable1d.h', size 4 |
|
4156 | /* including file 'src/plottable1d.h', size 4250 */ | |
4182 | /* commit bee82298bd87b91a50093fb0b81cd7c734724a6f 2017-08-13 16:10:24 +0200 */ |
|
4157 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
4183 |
|
4158 | |||
4184 | class QCPPlottableInterface1D { |
|
4159 | class QCP_LIB_DECL QCPPlottableInterface1D { | |
4185 | public: |
|
4160 | public: | |
4186 | virtual ~QCPPlottableInterface1D() {} |
|
|||
4187 | // introduced pure virtual methods: |
|
4161 | // introduced pure virtual methods: | |
4188 | virtual int dataCount() const = 0; |
|
4162 | virtual int dataCount() const = 0; | |
4189 | virtual double dataMainKey(int index) const = 0; |
|
4163 | virtual double dataMainKey(int index) const = 0; | |
@@ -4198,11 +4172,8 public: | |||||
4198 | }; |
|
4172 | }; | |
4199 |
|
4173 | |||
4200 | template <class DataType> |
|
4174 | template <class DataType> | |
4201 | class QCPAbstractPlottable1D : public QCPAbstractPlottable, |
|
4175 | class QCP_LIB_DECL QCPAbstractPlottable1D : public QCPAbstractPlottable, | |
4202 |
public QCPPlottableInterface1D |
|
4176 | public QCPPlottableInterface1D { | |
4203 | // ends up in header (cpp included |
|
|||
4204 | // below) |
|
|||
4205 | { |
|
|||
4206 | // No Q_OBJECT macro due to template class |
|
4177 | // No Q_OBJECT macro due to template class | |
4207 |
|
4178 | |||
4208 | public: |
|
4179 | public: | |
@@ -4210,22 +4181,20 public: | |||||
4210 | virtual ~QCPAbstractPlottable1D(); |
|
4181 | virtual ~QCPAbstractPlottable1D(); | |
4211 |
|
4182 | |||
4212 | // virtual methods of 1d plottable interface: |
|
4183 | // virtual methods of 1d plottable interface: | |
4213 |
virtual int dataCount() const |
|
4184 | virtual int dataCount() const; | |
4214 |
virtual double dataMainKey(int index) const |
|
4185 | virtual double dataMainKey(int index) const; | |
4215 |
virtual double dataSortKey(int index) const |
|
4186 | virtual double dataSortKey(int index) const; | |
4216 |
virtual double dataMainValue(int index) const |
|
4187 | virtual double dataMainValue(int index) const; | |
4217 |
virtual QCPRange dataValueRange(int index) const |
|
4188 | virtual QCPRange dataValueRange(int index) const; | |
4218 |
virtual QPointF dataPixelPosition(int index) const |
|
4189 | virtual QPointF dataPixelPosition(int index) const; | |
4219 |
virtual bool sortKeyIsMainKey() const |
|
4190 | virtual bool sortKeyIsMainKey() const; | |
4220 | virtual QCPDataSelection selectTestRect(const QRectF &rect, |
|
4191 | virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const; | |
4221 | bool onlySelectable) const Q_DECL_OVERRIDE; |
|
4192 | virtual int findBegin(double sortKey, bool expandedRange = true) const; | |
4222 |
virtual int find |
|
4193 | virtual int findEnd(double sortKey, bool expandedRange = true) const; | |
4223 | virtual int findEnd(double sortKey, bool expandedRange = true) const Q_DECL_OVERRIDE; |
|
|||
4224 |
|
4194 | |||
4225 |
// |
|
4195 | // virtual methods: | |
4226 | virtual double selectTest(const QPointF &pos, bool onlySelectable, |
|
4196 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details = 0) const; | |
4227 | QVariant *details = 0) const Q_DECL_OVERRIDE; |
|
4197 | virtual QCPPlottableInterface1D *interface1D() { return this; } | |
4228 | virtual QCPPlottableInterface1D *interface1D() Q_DECL_OVERRIDE { return this; } |
|
|||
4229 |
|
4198 | |||
4230 | protected: |
|
4199 | protected: | |
4231 | // property members: |
|
4200 | // property members: | |
@@ -4894,8 +4863,8 Q_DECLARE_METATYPE(QCPColorGradient::GradientPreset) | |||||
4894 | /* end of 'src/colorgradient.h' */ |
|
4863 | /* end of 'src/colorgradient.h' */ | |
4895 |
|
4864 | |||
4896 |
|
4865 | |||
4897 |
/* including file 'src/selectiondecorator-bracket.h', size 44 |
|
4866 | /* including file 'src/selectiondecorator-bracket.h', size 4426 */ | |
4898 | /* commit 681a87c5e5365a5c7187d20b4077031003c48449 2017-07-23 23:46:48 +0200 */ |
|
4867 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
4899 |
|
4868 | |||
4900 | class QCP_LIB_DECL QCPSelectionDecoratorBracket : public QCPSelectionDecorator { |
|
4869 | class QCP_LIB_DECL QCPSelectionDecoratorBracket : public QCPSelectionDecorator { | |
4901 | Q_GADGET |
|
4870 | Q_GADGET | |
@@ -4947,7 +4916,7 public: | |||||
4947 | virtual void drawBracket(QCPPainter *painter, int direction) const; |
|
4916 | virtual void drawBracket(QCPPainter *painter, int direction) const; | |
4948 |
|
4917 | |||
4949 | // virtual methods: |
|
4918 | // virtual methods: | |
4950 |
virtual void drawDecoration(QCPPainter *painter, QCPDataSelection selection) |
|
4919 | virtual void drawDecoration(QCPPainter *painter, QCPDataSelection selection); | |
4951 |
|
4920 | |||
4952 | protected: |
|
4921 | protected: | |
4953 | // property members: |
|
4922 | // property members: | |
@@ -4969,8 +4938,8 Q_DECLARE_METATYPE(QCPSelectionDecoratorBracket::BracketStyle) | |||||
4969 | /* end of 'src/selectiondecorator-bracket.h' */ |
|
4938 | /* end of 'src/selectiondecorator-bracket.h' */ | |
4970 |
|
4939 | |||
4971 |
|
4940 | |||
4972 |
/* including file 'src/layoutelements/layoutelement-axisrect.h', size 75 |
|
4941 | /* including file 'src/layoutelements/layoutelement-axisrect.h', size 7528 */ | |
4973 | /* commit 77ba168312f935543fc31d1ae9b4cdcf34aae4f9 2017-08-13 18:29:48 +0200 */ |
|
4942 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
4974 |
|
4943 | |||
4975 | class QCP_LIB_DECL QCPAxisRect : public QCPLayoutElement { |
|
4944 | class QCP_LIB_DECL QCPAxisRect : public QCPLayoutElement { | |
4976 | Q_OBJECT |
|
4945 | Q_OBJECT | |
@@ -5068,6 +5037,7 protected: | |||||
5068 | // non-property members: |
|
5037 | // non-property members: | |
5069 | QList<QCPRange> mDragStartHorzRange, mDragStartVertRange; |
|
5038 | QList<QCPRange> mDragStartHorzRange, mDragStartVertRange; | |
5070 | QCP::AntialiasedElements mAADragBackup, mNotAADragBackup; |
|
5039 | QCP::AntialiasedElements mAADragBackup, mNotAADragBackup; | |
|
5040 | QPoint mDragStart; | |||
5071 | bool mDragging; |
|
5041 | bool mDragging; | |
5072 | QHash<QCPAxis::AxisType, QList<QCPAxis *> > mAxes; |
|
5042 | QHash<QCPAxis::AxisType, QList<QCPAxis *> > mAxes; | |
5073 |
|
5043 | |||
@@ -5408,8 +5378,8 private: | |||||
5408 | /* end of 'src/layoutelements/layoutelement-textelement.h' */ |
|
5378 | /* end of 'src/layoutelements/layoutelement-textelement.h' */ | |
5409 |
|
5379 | |||
5410 |
|
5380 | |||
5411 |
/* including file 'src/layoutelements/layoutelement-colorscale.h', size 59 |
|
5381 | /* including file 'src/layoutelements/layoutelement-colorscale.h', size 5907 */ | |
5412 | /* commit 681a87c5e5365a5c7187d20b4077031003c48449 2017-07-23 23:46:48 +0200 */ |
|
5382 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
5413 |
|
5383 | |||
5414 |
|
5384 | |||
5415 | class QCPColorScaleAxisRectPrivate : public QCPAxisRect { |
|
5385 | class QCPColorScaleAxisRectPrivate : public QCPAxisRect { | |
@@ -5428,7 +5398,7 protected: | |||||
5428 | using QCPAxisRect::mouseReleaseEvent; |
|
5398 | using QCPAxisRect::mouseReleaseEvent; | |
5429 | using QCPAxisRect::wheelEvent; |
|
5399 | using QCPAxisRect::wheelEvent; | |
5430 | using QCPAxisRect::update; |
|
5400 | using QCPAxisRect::update; | |
5431 |
virtual void draw(QCPPainter *painter) |
|
5401 | virtual void draw(QCPPainter *painter); | |
5432 | void updateGradientImage(); |
|
5402 | void updateGradientImage(); | |
5433 | Q_SLOT void axisSelectionChanged(QCPAxis::SelectableParts selectedParts); |
|
5403 | Q_SLOT void axisSelectionChanged(QCPAxis::SelectableParts selectedParts); | |
5434 | Q_SLOT void axisSelectableChanged(QCPAxis::SelectableParts selectableParts); |
|
5404 | Q_SLOT void axisSelectableChanged(QCPAxis::SelectableParts selectableParts); | |
@@ -5516,8 +5486,8 private: | |||||
5516 | /* end of 'src/layoutelements/layoutelement-colorscale.h' */ |
|
5486 | /* end of 'src/layoutelements/layoutelement-colorscale.h' */ | |
5517 |
|
5487 | |||
5518 |
|
5488 | |||
5519 |
/* including file 'src/plottables/plottable-graph.h', size |
|
5489 | /* including file 'src/plottables/plottable-graph.h', size 8826 */ | |
5520 | /* commit f3881770eaf7366171012ad01cad2aaf5f61dd27 2017-06-23 02:48:21 +0200 */ |
|
5490 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
5521 |
|
5491 | |||
5522 | class QCP_LIB_DECL QCPGraphData { |
|
5492 | class QCP_LIB_DECL QCPGraphData { | |
5523 | public: |
|
5493 | public: | |
@@ -5654,20 +5624,11 protected: | |||||
5654 | QVector<QPointF> dataToStepRightLines(const QVector<QCPGraphData> &data) const; |
|
5624 | QVector<QPointF> dataToStepRightLines(const QVector<QCPGraphData> &data) const; | |
5655 | QVector<QPointF> dataToStepCenterLines(const QVector<QCPGraphData> &data) const; |
|
5625 | QVector<QPointF> dataToStepCenterLines(const QVector<QCPGraphData> &data) const; | |
5656 | QVector<QPointF> dataToImpulseLines(const QVector<QCPGraphData> &data) const; |
|
5626 | QVector<QPointF> dataToImpulseLines(const QVector<QCPGraphData> &data) const; | |
5657 | QVector<QCPDataRange> getNonNanSegments(const QVector<QPointF> *lineData, |
|
5627 | void addFillBasePoints(QVector<QPointF> *lines) const; | |
5658 | Qt::Orientation keyOrientation) const; |
|
5628 | void removeFillBasePoints(QVector<QPointF> *lines) const; | |
5659 | QVector<QPair<QCPDataRange, QCPDataRange> > |
|
5629 | QPointF lowerFillBasePoint(double lowerKey) const; | |
5660 | getOverlappingSegments(QVector<QCPDataRange> thisSegments, const QVector<QPointF> *thisData, |
|
5630 | QPointF upperFillBasePoint(double upperKey) const; | |
5661 | QVector<QCPDataRange> otherSegments, |
|
5631 | const QPolygonF getChannelFillPolygon(const QVector<QPointF> *lines) const; | |
5662 | const QVector<QPointF> *otherData) const; |
|
|||
5663 | bool segmentsIntersect(double aLower, double aUpper, double bLower, double bUpper, |
|
|||
5664 | int &bPrecedence) const; |
|
|||
5665 | QPointF getFillBasePoint(QPointF matchingDataPoint) const; |
|
|||
5666 | const QPolygonF getFillPolygon(const QVector<QPointF> *lineData, QCPDataRange segment) const; |
|
|||
5667 | const QPolygonF getChannelFillPolygon(const QVector<QPointF> *lineData, |
|
|||
5668 | QCPDataRange thisSegment, |
|
|||
5669 | const QVector<QPointF> *otherData, |
|
|||
5670 | QCPDataRange otherSegment) const; |
|
|||
5671 | int findIndexBelowX(const QVector<QPointF> *data, double x) const; |
|
5632 | int findIndexBelowX(const QVector<QPointF> *data, double x) const; | |
5672 | int findIndexAboveX(const QVector<QPointF> *data, double x) const; |
|
5633 | int findIndexAboveX(const QVector<QPointF> *data, double x) const; | |
5673 | int findIndexBelowY(const QVector<QPointF> *data, double y) const; |
|
5634 | int findIndexBelowY(const QVector<QPointF> *data, double y) const; | |
@@ -6464,8 +6425,8 Q_DECLARE_METATYPE(QCPFinancial::ChartStyle) | |||||
6464 | /* end of 'src/plottables/plottable-financial.h' */ |
|
6425 | /* end of 'src/plottables/plottable-financial.h' */ | |
6465 |
|
6426 | |||
6466 |
|
6427 | |||
6467 |
/* including file 'src/plottables/plottable-errorbar.h', size 7 |
|
6428 | /* including file 'src/plottables/plottable-errorbar.h', size 7567 */ | |
6468 | /* commit 681a87c5e5365a5c7187d20b4077031003c48449 2017-07-23 23:46:48 +0200 */ |
|
6429 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
6469 |
|
6430 | |||
6470 | class QCP_LIB_DECL QCPErrorBarsData { |
|
6431 | class QCP_LIB_DECL QCPErrorBarsData { | |
6471 | public: |
|
6432 | public: | |
@@ -6544,17 +6505,16 public: | |||||
6544 | void addData(double errorMinus, double errorPlus); |
|
6505 | void addData(double errorMinus, double errorPlus); | |
6545 |
|
6506 | |||
6546 | // virtual methods of 1d plottable interface: |
|
6507 | // virtual methods of 1d plottable interface: | |
6547 |
virtual int dataCount() const |
|
6508 | virtual int dataCount() const; | |
6548 |
virtual double dataMainKey(int index) const |
|
6509 | virtual double dataMainKey(int index) const; | |
6549 |
virtual double dataSortKey(int index) const |
|
6510 | virtual double dataSortKey(int index) const; | |
6550 |
virtual double dataMainValue(int index) const |
|
6511 | virtual double dataMainValue(int index) const; | |
6551 |
virtual QCPRange dataValueRange(int index) const |
|
6512 | virtual QCPRange dataValueRange(int index) const; | |
6552 |
virtual QPointF dataPixelPosition(int index) const |
|
6513 | virtual QPointF dataPixelPosition(int index) const; | |
6553 |
virtual bool sortKeyIsMainKey() const |
|
6514 | virtual bool sortKeyIsMainKey() const; | |
6554 | virtual QCPDataSelection selectTestRect(const QRectF &rect, |
|
6515 | virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const; | |
6555 | bool onlySelectable) const Q_DECL_OVERRIDE; |
|
6516 | virtual int findBegin(double sortKey, bool expandedRange = true) const; | |
6556 |
virtual int find |
|
6517 | virtual int findEnd(double sortKey, bool expandedRange = true) const; | |
6557 | virtual int findEnd(double sortKey, bool expandedRange = true) const Q_DECL_OVERRIDE; |
|
|||
6558 |
|
6518 | |||
6559 | // reimplemented virtual methods: |
|
6519 | // reimplemented virtual methods: | |
6560 | virtual double selectTest(const QPointF &pos, bool onlySelectable, |
|
6520 | virtual double selectTest(const QPointF &pos, bool onlySelectable, |
@@ -1,16 +1,5 | |||||
1 | <RCC> |
|
1 | <RCC> | |
2 | <qresource prefix="/"> |
|
2 | <qresource prefix="/"> | |
3 | <file>icones/dataSourceComponent.png</file> |
|
|||
4 | <file>icones/dataSourceNode.png</file> |
|
|||
5 | <file>icones/dataSourceProduct.png</file> |
|
|||
6 | <file>icones/dataSourceRoot.png</file> |
|
|||
7 | <file>icones/delete.png</file> |
|
|||
8 | <file>icones/down.png</file> |
|
|||
9 | <file>icones/openInspector.png</file> |
|
3 | <file>icones/openInspector.png</file> | |
10 | <file>icones/next.png</file> |
|
|||
11 | <file>icones/plot.png</file> |
|
|||
12 | <file>icones/previous.png</file> |
|
|||
13 | <file>icones/unplot.png</file> |
|
|||
14 | <file>icones/up.png</file> |
|
|||
15 | </qresource> |
|
4 | </qresource> | |
16 | </RCC> |
|
5 | </RCC> |
@@ -1,29 +1,21 | |||||
1 | #include <DataSource/DataSourceItem.h> |
|
1 | #include <DataSource/DataSourceItem.h> | |
2 | #include <DataSource/DataSourceItemAction.h> |
|
|||
3 | #include <DataSource/DataSourceTreeWidgetItem.h> |
|
2 | #include <DataSource/DataSourceTreeWidgetItem.h> | |
4 |
|
3 | |||
5 |
#include < |
|
4 | #include <SqpApplication.h> | |
6 |
|
5 | |||
7 | Q_LOGGING_CATEGORY(LOG_DataSourceTreeWidgetItem, "DataSourceTreeWidgetItem") |
|
6 | Q_LOGGING_CATEGORY(LOG_DataSourceTreeWidgetItem, "DataSourceTreeWidgetItem") | |
8 |
|
7 | |||
9 | namespace { |
|
8 | namespace { | |
10 |
|
9 | |||
11 | // Column indexes |
|
|||
12 | const auto NAME_COLUMN = 0; |
|
|||
13 |
|
||||
14 | QIcon itemIcon(const DataSourceItem *dataSource) |
|
10 | QIcon itemIcon(const DataSourceItem *dataSource) | |
15 | { |
|
11 | { | |
16 | if (dataSource) { |
|
12 | if (dataSource) { | |
17 | auto dataSourceType = dataSource->type(); |
|
13 | auto dataSourceType = dataSource->type(); | |
18 | switch (dataSourceType) { |
|
14 | switch (dataSourceType) { | |
19 |
case DataSourceItemType::NODE: |
|
15 | case DataSourceItemType::NODE: | |
20 | return dataSource->isRoot() ? QIcon{":/icones/dataSourceRoot.png"} |
|
16 | return sqpApp->style()->standardIcon(QStyle::SP_DirIcon); | |
21 | : QIcon{":/icones/dataSourceNode.png"}; |
|
|||
22 | } |
|
|||
23 | case DataSourceItemType::PRODUCT: |
|
17 | case DataSourceItemType::PRODUCT: | |
24 | return QIcon{":/icones/dataSourceProduct.png"}; |
|
18 | return sqpApp->style()->standardIcon(QStyle::SP_FileIcon); | |
25 | case DataSourceItemType::COMPONENT: |
|
|||
26 | return QIcon{":/icones/dataSourceComponent.png"}; |
|
|||
27 | default: |
|
19 | default: | |
28 | // No action |
|
20 | // No action | |
29 | break; |
|
21 | break; | |
@@ -33,7 +25,7 QIcon itemIcon(const DataSourceItem *dataSource) | |||||
33 | << QObject::tr("Can't set data source icon : unknown data source type"); |
|
25 | << QObject::tr("Can't set data source icon : unknown data source type"); | |
34 | } |
|
26 | } | |
35 | else { |
|
27 | else { | |
36 |
qC |
|
28 | qCWarning(LOG_DataSourceTreeWidgetItem()) | |
37 | << QObject::tr("Can't set data source icon : the data source is null"); |
|
29 | << QObject::tr("Can't set data source icon : the data source is null"); | |
38 | } |
|
30 | } | |
39 |
|
31 | |||
@@ -41,54 +33,6 QIcon itemIcon(const DataSourceItem *dataSource) | |||||
41 | return QIcon{}; |
|
33 | return QIcon{}; | |
42 | } |
|
34 | } | |
43 |
|
35 | |||
44 | /// @return the tooltip text for a variant. The text depends on whether the data is a simple variant |
|
|||
45 | /// or a list of variants |
|
|||
46 | QString tooltipValue(const QVariant &variant) noexcept |
|
|||
47 | { |
|
|||
48 | // If the variant is a list of variants, the text of the tooltip is of the form: {val1, val2, |
|
|||
49 | // ...} |
|
|||
50 | if (variant.canConvert<QVariantList>()) { |
|
|||
51 | auto valueString = QStringLiteral("{"); |
|
|||
52 |
|
||||
53 | auto variantList = variant.value<QVariantList>(); |
|
|||
54 | for (auto it = variantList.cbegin(), end = variantList.cend(); it != end; ++it) { |
|
|||
55 | valueString.append(it->toString()); |
|
|||
56 |
|
||||
57 | if (std::distance(it, end) != 1) { |
|
|||
58 | valueString.append(", "); |
|
|||
59 | } |
|
|||
60 | } |
|
|||
61 |
|
||||
62 | valueString.append(QStringLiteral("}")); |
|
|||
63 |
|
||||
64 | return valueString; |
|
|||
65 | } |
|
|||
66 | else { |
|
|||
67 | return variant.toString(); |
|
|||
68 | } |
|
|||
69 | } |
|
|||
70 |
|
||||
71 | QString itemTooltip(const DataSourceItem *dataSource) noexcept |
|
|||
72 | { |
|
|||
73 | // The tooltip displays all item's data |
|
|||
74 | if (dataSource) { |
|
|||
75 | auto result = QString{}; |
|
|||
76 |
|
||||
77 | const auto &data = dataSource->data(); |
|
|||
78 | for (auto it = data.cbegin(), end = data.cend(); it != end; ++it) { |
|
|||
79 | result.append(QString{"<b>%1:</b> %2<br/>"}.arg(it.key(), tooltipValue(it.value()))); |
|
|||
80 | } |
|
|||
81 |
|
||||
82 | return result; |
|
|||
83 | } |
|
|||
84 | else { |
|
|||
85 | qCCritical(LOG_DataSourceTreeWidgetItem()) |
|
|||
86 | << QObject::tr("Can't set data source tooltip : the data source is null"); |
|
|||
87 |
|
||||
88 | return QString{}; |
|
|||
89 | } |
|
|||
90 | } |
|
|||
91 |
|
||||
92 | } // namespace |
|
36 | } // namespace | |
93 |
|
37 | |||
94 | struct DataSourceTreeWidgetItem::DataSourceTreeWidgetItemPrivate { |
|
38 | struct DataSourceTreeWidgetItem::DataSourceTreeWidgetItemPrivate { | |
@@ -96,9 +40,6 struct DataSourceTreeWidgetItem::DataSourceTreeWidgetItemPrivate { | |||||
96 |
|
40 | |||
97 | /// Model used to retrieve data source information |
|
41 | /// Model used to retrieve data source information | |
98 | const DataSourceItem *m_Data; |
|
42 | const DataSourceItem *m_Data; | |
99 | /// Actions associated to the item. The parent of the item (QTreeWidget) takes the ownership of |
|
|||
100 | /// the actions |
|
|||
101 | QList<QAction *> m_Actions; |
|
|||
102 | }; |
|
43 | }; | |
103 |
|
44 | |||
104 | DataSourceTreeWidgetItem::DataSourceTreeWidgetItem(const DataSourceItem *data, int type) |
|
45 | DataSourceTreeWidgetItem::DataSourceTreeWidgetItem(const DataSourceItem *data, int type) | |
@@ -111,51 +52,14 DataSourceTreeWidgetItem::DataSourceTreeWidgetItem(QTreeWidget *parent, const Da | |||||
111 | : QTreeWidgetItem{parent, type}, |
|
52 | : QTreeWidgetItem{parent, type}, | |
112 | impl{spimpl::make_unique_impl<DataSourceTreeWidgetItemPrivate>(data)} |
|
53 | impl{spimpl::make_unique_impl<DataSourceTreeWidgetItemPrivate>(data)} | |
113 | { |
|
54 | { | |
114 |
// Sets the icon |
|
55 | // Sets the icon depending on the data source | |
115 | setIcon(0, itemIcon(impl->m_Data)); |
|
56 | setIcon(0, itemIcon(impl->m_Data)); | |
116 | setToolTip(0, itemTooltip(impl->m_Data)); |
|
|||
117 |
|
||||
118 | // Generates tree actions based on the item actions |
|
|||
119 | auto createTreeAction = [this, &parent](const auto &itemAction) { |
|
|||
120 | auto treeAction = new QAction{itemAction->name(), parent}; |
|
|||
121 |
|
||||
122 | // Executes item action when tree action is triggered |
|
|||
123 | QObject::connect(treeAction, &QAction::triggered, itemAction, |
|
|||
124 | &DataSourceItemAction::execute); |
|
|||
125 |
|
||||
126 | return treeAction; |
|
|||
127 | }; |
|
|||
128 |
|
||||
129 | auto itemActions = impl->m_Data->actions(); |
|
|||
130 | std::transform(std::cbegin(itemActions), std::cend(itemActions), |
|
|||
131 | std::back_inserter(impl->m_Actions), createTreeAction); |
|
|||
132 | } |
|
|||
133 |
|
||||
134 | const DataSourceItem *DataSourceTreeWidgetItem::data() const |
|
|||
135 | { |
|
|||
136 | return impl->m_Data; |
|
|||
137 | } |
|
57 | } | |
138 |
|
58 | |||
139 | QVariant DataSourceTreeWidgetItem::data(int column, int role) const |
|
59 | QVariant DataSourceTreeWidgetItem::data(int column, int role) const | |
140 | { |
|
60 | { | |
141 | if (role == Qt::DisplayRole) { |
|
61 | if (role == Qt::DisplayRole) { | |
142 | if (impl->m_Data) { |
|
62 | return (impl->m_Data) ? impl->m_Data->data(column) : QVariant{}; | |
143 | switch (column) { |
|
|||
144 | case NAME_COLUMN: |
|
|||
145 | return impl->m_Data->name(); |
|
|||
146 | default: |
|
|||
147 | // No action |
|
|||
148 | break; |
|
|||
149 | } |
|
|||
150 |
|
||||
151 | qCWarning(LOG_DataSourceTreeWidgetItem()) |
|
|||
152 | << QObject::tr("Can't get data (unknown column %1)").arg(column); |
|
|||
153 | } |
|
|||
154 | else { |
|
|||
155 | qCCritical(LOG_DataSourceTreeWidgetItem()) << QObject::tr("Can't get data (null item)"); |
|
|||
156 | } |
|
|||
157 |
|
||||
158 | return QVariant{}; |
|
|||
159 | } |
|
63 | } | |
160 | else { |
|
64 | else { | |
161 | return QTreeWidgetItem::data(column, role); |
|
65 | return QTreeWidgetItem::data(column, role); | |
@@ -169,8 +73,3 void DataSourceTreeWidgetItem::setData(int column, int role, const QVariant &val | |||||
169 | QTreeWidgetItem::setData(column, role, value); |
|
73 | QTreeWidgetItem::setData(column, role, value); | |
170 | } |
|
74 | } | |
171 | } |
|
75 | } | |
172 |
|
||||
173 | QList<QAction *> DataSourceTreeWidgetItem::actions() const noexcept |
|
|||
174 | { |
|
|||
175 | return impl->m_Actions; |
|
|||
176 | } |
|
@@ -3,11 +3,8 | |||||
3 | #include <ui_DataSourceWidget.h> |
|
3 | #include <ui_DataSourceWidget.h> | |
4 |
|
4 | |||
5 | #include <DataSource/DataSourceItem.h> |
|
5 | #include <DataSource/DataSourceItem.h> | |
6 | #include <DataSource/DataSourceTreeWidgetHelper.h> |
|
|||
7 | #include <DataSource/DataSourceTreeWidgetItem.h> |
|
6 | #include <DataSource/DataSourceTreeWidgetItem.h> | |
8 |
|
7 | |||
9 | #include <QMenu> |
|
|||
10 |
|
||||
11 | namespace { |
|
8 | namespace { | |
12 |
|
9 | |||
13 | /// Number of columns displayed in the tree |
|
10 | /// Number of columns displayed in the tree | |
@@ -43,19 +40,6 DataSourceWidget::DataSourceWidget(QWidget *parent) : QWidget{parent}, ui{new Ui | |||||
43 | // Set tree properties |
|
40 | // Set tree properties | |
44 | ui->treeWidget->setColumnCount(TREE_NB_COLUMNS); |
|
41 | ui->treeWidget->setColumnCount(TREE_NB_COLUMNS); | |
45 | ui->treeWidget->setHeaderLabels(TREE_HEADER_LABELS); |
|
42 | ui->treeWidget->setHeaderLabels(TREE_HEADER_LABELS); | |
46 | ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu); |
|
|||
47 |
|
||||
48 | // Connection to show a menu when right clicking on the tree |
|
|||
49 | connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this, |
|
|||
50 | &DataSourceWidget::onTreeMenuRequested); |
|
|||
51 |
|
||||
52 | // Connection to filter tree |
|
|||
53 | connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &DataSourceWidget::filterChanged); |
|
|||
54 | } |
|
|||
55 |
|
||||
56 | DataSourceWidget::~DataSourceWidget() noexcept |
|
|||
57 | { |
|
|||
58 | delete ui; |
|
|||
59 | } |
|
43 | } | |
60 |
|
44 | |||
61 | void DataSourceWidget::addDataSource(DataSourceItem *dataSource) noexcept |
|
45 | void DataSourceWidget::addDataSource(DataSourceItem *dataSource) noexcept | |
@@ -66,35 +50,3 void DataSourceWidget::addDataSource(DataSourceItem *dataSource) noexcept | |||||
66 | ui->treeWidget->addTopLevelItem(createTreeWidgetItem(dataSource)); |
|
50 | ui->treeWidget->addTopLevelItem(createTreeWidgetItem(dataSource)); | |
67 | } |
|
51 | } | |
68 | } |
|
52 | } | |
69 |
|
||||
70 | void DataSourceWidget::filterChanged(const QString &text) noexcept |
|
|||
71 | { |
|
|||
72 | auto validateItem = [&text](const DataSourceTreeWidgetItem &item) { |
|
|||
73 | auto regExp = QRegExp{text, Qt::CaseInsensitive, QRegExp::Wildcard}; |
|
|||
74 |
|
||||
75 | // An item is valid if any of its metadata validates the text filter |
|
|||
76 | auto itemMetadata = item.data()->data(); |
|
|||
77 | auto itemMetadataEnd = itemMetadata.cend(); |
|
|||
78 | auto acceptFilter |
|
|||
79 | = [®Exp](const auto &variant) { return variant.toString().contains(regExp); }; |
|
|||
80 |
|
||||
81 | return std::find_if(itemMetadata.cbegin(), itemMetadataEnd, acceptFilter) |
|
|||
82 | != itemMetadataEnd; |
|
|||
83 | }; |
|
|||
84 |
|
||||
85 | // Applies filter on tree widget |
|
|||
86 | DataSourceTreeWidgetHelper::filter(*ui->treeWidget, validateItem); |
|
|||
87 | } |
|
|||
88 |
|
||||
89 | void DataSourceWidget::onTreeMenuRequested(const QPoint &pos) noexcept |
|
|||
90 | { |
|
|||
91 | // Retrieves the selected item in the tree, and build the menu from its actions |
|
|||
92 | if (auto selectedItem = dynamic_cast<DataSourceTreeWidgetItem *>(ui->treeWidget->itemAt(pos))) { |
|
|||
93 | QMenu treeMenu{}; |
|
|||
94 | treeMenu.addActions(selectedItem->actions()); |
|
|||
95 |
|
||||
96 | if (!treeMenu.isEmpty()) { |
|
|||
97 | treeMenu.exec(QCursor::pos()); |
|
|||
98 | } |
|
|||
99 | } |
|
|||
100 | } |
|
@@ -34,6 +34,13 SqpSidePane::SqpSidePane(QWidget *parent) : QWidget{parent}, ui{new Ui::SqpSideP | |||||
34 | this->layout()->addWidget(m_SidePaneToolbar); |
|
34 | this->layout()->addWidget(m_SidePaneToolbar); | |
35 |
|
35 | |||
36 | m_SidePaneToolbar->setStyleSheet(SQPSIDEPANESTYLESHEET); |
|
36 | m_SidePaneToolbar->setStyleSheet(SQPSIDEPANESTYLESHEET); | |
|
37 | ||||
|
38 | this->setStyleSheet( | |||
|
39 | " QWidget {" | |||
|
40 | "background: red;" | |||
|
41 | ||||
|
42 | "border: 1px;" | |||
|
43 | " }"); | |||
37 | } |
|
44 | } | |
38 |
|
45 | |||
39 | SqpSidePane::~SqpSidePane() |
|
46 | SqpSidePane::~SqpSidePane() |
@@ -1,11 +1,7 | |||||
1 | #include "SqpApplication.h" |
|
1 | #include "SqpApplication.h" | |
2 |
|
2 | |||
3 | #include <Data/IDataProvider.h> |
|
|||
4 | #include <DataSource/DataSourceController.h> |
|
3 | #include <DataSource/DataSourceController.h> | |
5 | #include <Network/NetworkController.h> |
|
|||
6 | #include <QThread> |
|
4 | #include <QThread> | |
7 | #include <Time/TimeController.h> |
|
|||
8 | #include <Variable/Variable.h> |
|
|||
9 | #include <Variable/VariableController.h> |
|
5 | #include <Variable/VariableController.h> | |
10 | #include <Visualization/VisualizationController.h> |
|
6 | #include <Visualization/VisualizationController.h> | |
11 |
|
7 | |||
@@ -15,57 +11,20 class SqpApplication::SqpApplicationPrivate { | |||||
15 | public: |
|
11 | public: | |
16 | SqpApplicationPrivate() |
|
12 | SqpApplicationPrivate() | |
17 | : m_DataSourceController{std::make_unique<DataSourceController>()}, |
|
13 | : m_DataSourceController{std::make_unique<DataSourceController>()}, | |
18 | m_NetworkController{std::make_unique<NetworkController>()}, |
|
|||
19 | m_TimeController{std::make_unique<TimeController>()}, |
|
|||
20 | m_VariableController{std::make_unique<VariableController>()}, |
|
14 | m_VariableController{std::make_unique<VariableController>()}, | |
21 | m_VisualizationController{std::make_unique<VisualizationController>()} |
|
15 | m_VisualizationController{std::make_unique<VisualizationController>()} | |
22 | { |
|
16 | { | |
23 | // /////////////////////////////// // |
|
|||
24 | // Connections between controllers // |
|
|||
25 | // /////////////////////////////// // |
|
|||
26 |
|
||||
27 | // VariableController <-> DataSourceController |
|
|||
28 | connect(m_DataSourceController.get(), |
|
|||
29 | SIGNAL(variableCreationRequested(const QString &, const QVariantHash &, |
|
|||
30 | std::shared_ptr<IDataProvider>)), |
|
|||
31 | m_VariableController.get(), |
|
|||
32 | SLOT(createVariable(const QString &, const QVariantHash &, |
|
|||
33 | std::shared_ptr<IDataProvider>))); |
|
|||
34 |
|
||||
35 | // VariableController <-> VisualizationController |
|
|||
36 | connect(m_VariableController.get(), |
|
|||
37 | SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), |
|
|||
38 | m_VisualizationController.get(), |
|
|||
39 | SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection); |
|
|||
40 |
|
||||
41 | connect(m_VariableController.get(), |
|
|||
42 | SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)), |
|
|||
43 | m_VisualizationController.get(), |
|
|||
44 | SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &))); |
|
|||
45 |
|
||||
46 |
|
||||
47 | m_DataSourceController->moveToThread(&m_DataSourceControllerThread); |
|
17 | m_DataSourceController->moveToThread(&m_DataSourceControllerThread); | |
48 | m_DataSourceControllerThread.setObjectName("DataSourceControllerThread"); |
|
|||
49 | m_NetworkController->moveToThread(&m_NetworkControllerThread); |
|
|||
50 | m_NetworkControllerThread.setObjectName("NetworkControllerThread"); |
|
|||
51 | m_VariableController->moveToThread(&m_VariableControllerThread); |
|
18 | m_VariableController->moveToThread(&m_VariableControllerThread); | |
52 | m_VariableControllerThread.setObjectName("VariableControllerThread"); |
|
|||
53 | m_VisualizationController->moveToThread(&m_VisualizationControllerThread); |
|
19 | m_VisualizationController->moveToThread(&m_VisualizationControllerThread); | |
54 | m_VisualizationControllerThread.setObjectName("VsualizationControllerThread"); |
|
|||
55 |
|
||||
56 |
|
||||
57 | // Additionnal init |
|
|||
58 | m_VariableController->setTimeController(m_TimeController.get()); |
|
|||
59 | } |
|
20 | } | |
60 |
|
21 | |||
61 | virtual ~SqpApplicationPrivate() |
|
22 | virtual ~SqpApplicationPrivate() | |
62 | { |
|
23 | { | |
|
24 | qCInfo(LOG_SqpApplication()) << tr("SqpApplicationPrivate destruction"); | |||
63 | m_DataSourceControllerThread.quit(); |
|
25 | m_DataSourceControllerThread.quit(); | |
64 | m_DataSourceControllerThread.wait(); |
|
26 | m_DataSourceControllerThread.wait(); | |
65 |
|
27 | |||
66 | m_NetworkControllerThread.quit(); |
|
|||
67 | m_NetworkControllerThread.wait(); |
|
|||
68 |
|
||||
69 | m_VariableControllerThread.quit(); |
|
28 | m_VariableControllerThread.quit(); | |
70 | m_VariableControllerThread.wait(); |
|
29 | m_VariableControllerThread.wait(); | |
71 |
|
30 | |||
@@ -75,11 +34,8 public: | |||||
75 |
|
34 | |||
76 | std::unique_ptr<DataSourceController> m_DataSourceController; |
|
35 | std::unique_ptr<DataSourceController> m_DataSourceController; | |
77 | std::unique_ptr<VariableController> m_VariableController; |
|
36 | std::unique_ptr<VariableController> m_VariableController; | |
78 | std::unique_ptr<TimeController> m_TimeController; |
|
|||
79 | std::unique_ptr<NetworkController> m_NetworkController; |
|
|||
80 | std::unique_ptr<VisualizationController> m_VisualizationController; |
|
37 | std::unique_ptr<VisualizationController> m_VisualizationController; | |
81 | QThread m_DataSourceControllerThread; |
|
38 | QThread m_DataSourceControllerThread; | |
82 | QThread m_NetworkControllerThread; |
|
|||
83 | QThread m_VariableControllerThread; |
|
39 | QThread m_VariableControllerThread; | |
84 | QThread m_VisualizationControllerThread; |
|
40 | QThread m_VisualizationControllerThread; | |
85 | }; |
|
41 | }; | |
@@ -88,18 +44,13 public: | |||||
88 | SqpApplication::SqpApplication(int &argc, char **argv) |
|
44 | SqpApplication::SqpApplication(int &argc, char **argv) | |
89 | : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()} |
|
45 | : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()} | |
90 | { |
|
46 | { | |
91 |
qC |
|
47 | qCInfo(LOG_SqpApplication()) << tr("SqpApplication construction"); | |
92 |
|
48 | |||
93 | connect(&impl->m_DataSourceControllerThread, &QThread::started, |
|
49 | connect(&impl->m_DataSourceControllerThread, &QThread::started, | |
94 | impl->m_DataSourceController.get(), &DataSourceController::initialize); |
|
50 | impl->m_DataSourceController.get(), &DataSourceController::initialize); | |
95 | connect(&impl->m_DataSourceControllerThread, &QThread::finished, |
|
51 | connect(&impl->m_DataSourceControllerThread, &QThread::finished, | |
96 | impl->m_DataSourceController.get(), &DataSourceController::finalize); |
|
52 | impl->m_DataSourceController.get(), &DataSourceController::finalize); | |
97 |
|
53 | |||
98 | connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(), |
|
|||
99 | &NetworkController::initialize); |
|
|||
100 | connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(), |
|
|||
101 | &NetworkController::finalize); |
|
|||
102 |
|
||||
103 | connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(), |
|
54 | connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(), | |
104 | &VariableController::initialize); |
|
55 | &VariableController::initialize); | |
105 | connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(), |
|
56 | connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(), | |
@@ -110,8 +61,8 SqpApplication::SqpApplication(int &argc, char **argv) | |||||
110 | connect(&impl->m_VisualizationControllerThread, &QThread::finished, |
|
61 | connect(&impl->m_VisualizationControllerThread, &QThread::finished, | |
111 | impl->m_VisualizationController.get(), &VisualizationController::finalize); |
|
62 | impl->m_VisualizationController.get(), &VisualizationController::finalize); | |
112 |
|
63 | |||
|
64 | ||||
113 | impl->m_DataSourceControllerThread.start(); |
|
65 | impl->m_DataSourceControllerThread.start(); | |
114 | impl->m_NetworkControllerThread.start(); |
|
|||
115 | impl->m_VariableControllerThread.start(); |
|
66 | impl->m_VariableControllerThread.start(); | |
116 | impl->m_VisualizationControllerThread.start(); |
|
67 | impl->m_VisualizationControllerThread.start(); | |
117 | } |
|
68 | } | |
@@ -129,16 +80,6 DataSourceController &SqpApplication::dataSourceController() noexcept | |||||
129 | return *impl->m_DataSourceController; |
|
80 | return *impl->m_DataSourceController; | |
130 | } |
|
81 | } | |
131 |
|
82 | |||
132 | NetworkController &SqpApplication::networkController() noexcept |
|
|||
133 | { |
|
|||
134 | return *impl->m_NetworkController; |
|
|||
135 | } |
|
|||
136 |
|
||||
137 | TimeController &SqpApplication::timeController() noexcept |
|
|||
138 | { |
|
|||
139 | return *impl->m_TimeController; |
|
|||
140 | } |
|
|||
141 |
|
||||
142 | VariableController &SqpApplication::variableController() noexcept |
|
83 | VariableController &SqpApplication::variableController() noexcept | |
143 | { |
|
84 | { | |
144 | return *impl->m_VariableController; |
|
85 | return *impl->m_VariableController; |
@@ -1,239 +1,14 | |||||
1 | #include <Variable/RenameVariableDialog.h> |
|
|||
2 | #include <Variable/Variable.h> |
|
|||
3 | #include <Variable/VariableController.h> |
|
|||
4 |
|
|
1 | #include <Variable/VariableInspectorWidget.h> | |
5 | #include <Variable/VariableMenuHeaderWidget.h> |
|
|||
6 | #include <Variable/VariableModel.h> |
|
|||
7 |
|
2 | |||
8 | #include <ui_VariableInspectorWidget.h> |
|
3 | #include <ui_VariableInspectorWidget.h> | |
9 |
|
4 | |||
10 | #include <QMouseEvent> |
|
|||
11 | #include <QSortFilterProxyModel> |
|
|||
12 | #include <QStyledItemDelegate> |
|
|||
13 | #include <QWidgetAction> |
|
|||
14 |
|
||||
15 | #include <SqpApplication.h> |
|
|||
16 |
|
||||
17 | Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget") |
|
|||
18 |
|
||||
19 |
|
||||
20 | class QProgressBarItemDelegate : public QStyledItemDelegate { |
|
|||
21 |
|
||||
22 | public: |
|
|||
23 | QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {} |
|
|||
24 |
|
||||
25 | void paint(QPainter *painter, const QStyleOptionViewItem &option, |
|
|||
26 | const QModelIndex &index) const |
|
|||
27 | { |
|
|||
28 | auto data = index.data(Qt::DisplayRole); |
|
|||
29 | auto progressData = index.data(VariableRoles::ProgressRole); |
|
|||
30 | if (data.isValid() && progressData.isValid()) { |
|
|||
31 | auto name = data.value<QString>(); |
|
|||
32 | auto progress = progressData.value<double>(); |
|
|||
33 | if (progress > 0) { |
|
|||
34 | auto cancelButtonWidth = 20; |
|
|||
35 | auto progressBarOption = QStyleOptionProgressBar{}; |
|
|||
36 | auto progressRect = option.rect; |
|
|||
37 | progressRect.setWidth(progressRect.width() - cancelButtonWidth); |
|
|||
38 | progressBarOption.rect = progressRect; |
|
|||
39 | progressBarOption.minimum = 0; |
|
|||
40 | progressBarOption.maximum = 100; |
|
|||
41 | progressBarOption.progress = progress; |
|
|||
42 | progressBarOption.text |
|
|||
43 | = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%"); |
|
|||
44 | progressBarOption.textVisible = true; |
|
|||
45 | progressBarOption.textAlignment = Qt::AlignCenter; |
|
|||
46 |
|
||||
47 |
|
||||
48 | QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, |
|
|||
49 | painter); |
|
|||
50 |
|
||||
51 | // Cancel button |
|
|||
52 | auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth, |
|
|||
53 | option.rect.height()); |
|
|||
54 | auto buttonOption = QStyleOptionButton{}; |
|
|||
55 | buttonOption.rect = buttonRect; |
|
|||
56 | buttonOption.text = "X"; |
|
|||
57 |
|
||||
58 | QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter); |
|
|||
59 | } |
|
|||
60 | else { |
|
|||
61 | QStyledItemDelegate::paint(painter, option, index); |
|
|||
62 | } |
|
|||
63 | } |
|
|||
64 | else { |
|
|||
65 | QStyledItemDelegate::paint(painter, option, index); |
|
|||
66 | } |
|
|||
67 | } |
|
|||
68 |
|
||||
69 | bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, |
|
|||
70 | const QModelIndex &index) |
|
|||
71 | { |
|
|||
72 | if (event->type() == QEvent::MouseButtonRelease) { |
|
|||
73 | auto data = index.data(Qt::DisplayRole); |
|
|||
74 | auto progressData = index.data(VariableRoles::ProgressRole); |
|
|||
75 | if (data.isValid() && progressData.isValid()) { |
|
|||
76 | auto cancelButtonWidth = 20; |
|
|||
77 | auto progressRect = option.rect; |
|
|||
78 | progressRect.setWidth(progressRect.width() - cancelButtonWidth); |
|
|||
79 | // Cancel button |
|
|||
80 | auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth, |
|
|||
81 | option.rect.height()); |
|
|||
82 |
|
||||
83 | auto e = (QMouseEvent *)event; |
|
|||
84 | auto clickX = e->x(); |
|
|||
85 | auto clickY = e->y(); |
|
|||
86 |
|
||||
87 | auto x = buttonRect.left(); // the X coordinate |
|
|||
88 | auto y = buttonRect.top(); // the Y coordinate |
|
|||
89 | auto w = buttonRect.width(); // button width |
|
|||
90 | auto h = buttonRect.height(); // button height |
|
|||
91 |
|
||||
92 | if (clickX > x && clickX < x + w) { |
|
|||
93 | if (clickY > y && clickY < y + h) { |
|
|||
94 | auto variableModel = sqpApp->variableController().variableModel(); |
|
|||
95 | variableModel->abortProgress(index); |
|
|||
96 | } |
|
|||
97 | return true; |
|
|||
98 | } |
|
|||
99 | else { |
|
|||
100 | return QStyledItemDelegate::editorEvent(event, model, option, index); |
|
|||
101 | } |
|
|||
102 | } |
|
|||
103 | else { |
|
|||
104 | return QStyledItemDelegate::editorEvent(event, model, option, index); |
|
|||
105 | } |
|
|||
106 | } |
|
|||
107 | else { |
|
|||
108 | return QStyledItemDelegate::editorEvent(event, model, option, index); |
|
|||
109 | } |
|
|||
110 |
|
||||
111 |
|
||||
112 | return QStyledItemDelegate::editorEvent(event, model, option, index); |
|
|||
113 | } |
|
|||
114 | }; |
|
|||
115 |
|
||||
116 | VariableInspectorWidget::VariableInspectorWidget(QWidget *parent) |
|
5 | VariableInspectorWidget::VariableInspectorWidget(QWidget *parent) | |
117 | : QWidget{parent}, |
|
6 | : QWidget{parent}, ui{new Ui::VariableInspectorWidget} | |
118 | ui{new Ui::VariableInspectorWidget}, |
|
|||
119 | m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}} |
|
|||
120 | { |
|
7 | { | |
121 | ui->setupUi(this); |
|
8 | ui->setupUi(this); | |
122 |
|
||||
123 | // Sets model for table |
|
|||
124 | // auto sortFilterModel = new QSortFilterProxyModel{this}; |
|
|||
125 | // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel()); |
|
|||
126 |
|
||||
127 | auto variableModel = sqpApp->variableController().variableModel(); |
|
|||
128 | ui->tableView->setModel(variableModel); |
|
|||
129 |
|
||||
130 | // Adds extra signal/slot between view and model, so the view can be updated instantly when |
|
|||
131 | // there is a change of data in the model |
|
|||
132 | connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, |
|
|||
133 | SLOT(refresh())); |
|
|||
134 |
|
||||
135 | ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel()); |
|
|||
136 | ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate); |
|
|||
137 |
|
||||
138 | // Fixes column sizes |
|
|||
139 | auto model = ui->tableView->model(); |
|
|||
140 | const auto count = model->columnCount(); |
|
|||
141 | for (auto i = 0; i < count; ++i) { |
|
|||
142 | ui->tableView->setColumnWidth( |
|
|||
143 | i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width()); |
|
|||
144 | } |
|
|||
145 |
|
||||
146 | // Sets selection options |
|
|||
147 | ui->tableView->setSelectionBehavior(QTableView::SelectRows); |
|
|||
148 | ui->tableView->setSelectionMode(QTableView::ExtendedSelection); |
|
|||
149 |
|
||||
150 | // Connection to show a menu when right clicking on the tree |
|
|||
151 | ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu); |
|
|||
152 | connect(ui->tableView, &QTableView::customContextMenuRequested, this, |
|
|||
153 | &VariableInspectorWidget::onTableMenuRequested); |
|
|||
154 | } |
|
9 | } | |
155 |
|
10 | |||
156 | VariableInspectorWidget::~VariableInspectorWidget() |
|
11 | VariableInspectorWidget::~VariableInspectorWidget() | |
157 | { |
|
12 | { | |
158 | delete ui; |
|
13 | delete ui; | |
159 | } |
|
14 | } | |
160 |
|
||||
161 | void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept |
|
|||
162 | { |
|
|||
163 | auto selectedRows = ui->tableView->selectionModel()->selectedRows(); |
|
|||
164 |
|
||||
165 | // Gets the model to retrieve the underlying selected variables |
|
|||
166 | auto model = sqpApp->variableController().variableModel(); |
|
|||
167 | auto selectedVariables = QVector<std::shared_ptr<Variable> >{}; |
|
|||
168 | for (const auto &selectedRow : qAsConst(selectedRows)) { |
|
|||
169 | if (auto selectedVariable = model->variable(selectedRow.row())) { |
|
|||
170 | selectedVariables.push_back(selectedVariable); |
|
|||
171 | } |
|
|||
172 | } |
|
|||
173 |
|
||||
174 | QMenu tableMenu{}; |
|
|||
175 |
|
||||
176 | // Emits a signal so that potential receivers can populate the menu before displaying it |
|
|||
177 | emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables); |
|
|||
178 |
|
||||
179 | // Adds menu-specific actions |
|
|||
180 | if (!selectedVariables.isEmpty()) { |
|
|||
181 | tableMenu.addSeparator(); |
|
|||
182 |
|
||||
183 | // 'Rename' and 'Duplicate' actions (only if one variable selected) |
|
|||
184 | if (selectedVariables.size() == 1) { |
|
|||
185 | auto selectedVariable = selectedVariables.front(); |
|
|||
186 |
|
||||
187 | auto duplicateFun = [varW = std::weak_ptr<Variable>(selectedVariable)]() |
|
|||
188 | { |
|
|||
189 | if (auto var = varW.lock()) { |
|
|||
190 | sqpApp->variableController().cloneVariable(var); |
|
|||
191 | } |
|
|||
192 | }; |
|
|||
193 |
|
||||
194 | tableMenu.addAction(tr("Duplicate"), duplicateFun); |
|
|||
195 |
|
||||
196 | auto renameFun = [ varW = std::weak_ptr<Variable>(selectedVariable), &model, this ]() |
|
|||
197 | { |
|
|||
198 | if (auto var = varW.lock()) { |
|
|||
199 | // Generates forbidden names (names associated to existing variables) |
|
|||
200 | auto allVariables = model->variables(); |
|
|||
201 | auto forbiddenNames = QVector<QString>(allVariables.size()); |
|
|||
202 | std::transform(allVariables.cbegin(), allVariables.cend(), |
|
|||
203 | forbiddenNames.begin(), |
|
|||
204 | [](const auto &variable) { return variable->name(); }); |
|
|||
205 |
|
||||
206 | RenameVariableDialog dialog{var->name(), forbiddenNames, this}; |
|
|||
207 | if (dialog.exec() == QDialog::Accepted) { |
|
|||
208 | var->setName(dialog.name()); |
|
|||
209 | } |
|
|||
210 | } |
|
|||
211 | }; |
|
|||
212 |
|
||||
213 | tableMenu.addAction(tr("Rename..."), renameFun); |
|
|||
214 | } |
|
|||
215 |
|
||||
216 | // 'Delete' action |
|
|||
217 | auto deleteFun = [&selectedVariables]() { |
|
|||
218 | sqpApp->variableController().deleteVariables(selectedVariables); |
|
|||
219 | }; |
|
|||
220 |
|
||||
221 | tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun); |
|
|||
222 | } |
|
|||
223 |
|
||||
224 | if (!tableMenu.isEmpty()) { |
|
|||
225 | // Generates menu header (inserted before first action) |
|
|||
226 | auto firstAction = tableMenu.actions().first(); |
|
|||
227 | auto headerAction = new QWidgetAction{&tableMenu}; |
|
|||
228 | headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu}); |
|
|||
229 | tableMenu.insertAction(firstAction, headerAction); |
|
|||
230 |
|
||||
231 | // Displays menu |
|
|||
232 | tableMenu.exec(QCursor::pos()); |
|
|||
233 | } |
|
|||
234 | } |
|
|||
235 |
|
||||
236 | void VariableInspectorWidget::refresh() noexcept |
|
|||
237 | { |
|
|||
238 | ui->tableView->viewport()->update(); |
|
|||
239 | } |
|
@@ -1,356 +1,47 | |||||
1 | #include "Visualization/VisualizationGraphWidget.h" |
|
1 | #include "Visualization/VisualizationGraphWidget.h" | |
2 | #include "Visualization/IVisualizationWidgetVisitor.h" |
|
|||
3 | #include "Visualization/VisualizationDefs.h" |
|
|||
4 | #include "Visualization/VisualizationGraphHelper.h" |
|
|||
5 | #include "Visualization/VisualizationGraphRenderingDelegate.h" |
|
|||
6 | #include "ui_VisualizationGraphWidget.h" |
|
2 | #include "ui_VisualizationGraphWidget.h" | |
7 |
|
3 | |||
8 | #include <Data/ArrayData.h> |
|
|||
9 | #include <Data/IDataSeries.h> |
|
|||
10 | #include <Settings/SqpSettingsDefs.h> |
|
|||
11 | #include <SqpApplication.h> |
|
|||
12 | #include <Variable/Variable.h> |
|
4 | #include <Variable/Variable.h> | |
13 | #include <Variable/VariableController.h> |
|
|||
14 |
|
5 | |||
15 | #include <unordered_map> |
|
6 | #include <unordered_map> | |
16 |
|
7 | |||
17 | Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget") |
|
|||
18 |
|
||||
19 | namespace { |
|
|||
20 |
|
||||
21 | /// Key pressed to enable zoom on horizontal axis |
|
|||
22 | const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier; |
|
|||
23 |
|
||||
24 | /// Key pressed to enable zoom on vertical axis |
|
|||
25 | const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier; |
|
|||
26 |
|
||||
27 | } // namespace |
|
|||
28 |
|
||||
29 | struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate { |
|
8 | struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate { | |
30 |
|
9 | |||
31 | explicit VisualizationGraphWidgetPrivate(const QString &name) |
|
|||
32 | : m_Name{name}, |
|
|||
33 | m_DoAcquisition{true}, |
|
|||
34 | m_IsCalibration{false}, |
|
|||
35 | m_RenderingDelegate{nullptr} |
|
|||
36 | { |
|
|||
37 | } |
|
|||
38 |
|
||||
39 | QString m_Name; |
|
|||
40 | // 1 variable -> n qcpplot |
|
10 | // 1 variable -> n qcpplot | |
41 |
std::map<std::shared_ptr<Variable>, Plottable |
|
11 | std::unordered_map<std::shared_ptr<Variable>, std::unique_ptr<QCPAbstractPlottable> > | |
42 | bool m_DoAcquisition; |
|
12 | m_VariableToPlotMap; | |
43 | bool m_IsCalibration; |
|
|||
44 | QCPItemTracer *m_TextTracer; |
|
|||
45 | /// Delegate used to attach rendering features to the plot |
|
|||
46 | std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate; |
|
|||
47 | }; |
|
13 | }; | |
48 |
|
14 | |||
49 |
VisualizationGraphWidget::VisualizationGraphWidget( |
|
15 | VisualizationGraphWidget::VisualizationGraphWidget(QWidget *parent) | |
50 | : QWidget{parent}, |
|
16 | : QWidget{parent}, | |
51 | ui{new Ui::VisualizationGraphWidget}, |
|
17 | ui{new Ui::VisualizationGraphWidget}, | |
52 |
impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>( |
|
18 | impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()} | |
53 | { |
|
19 | { | |
54 | ui->setupUi(this); |
|
20 | ui->setupUi(this); | |
55 |
|
||||
56 | // 'Close' options : widget is deleted when closed |
|
|||
57 | setAttribute(Qt::WA_DeleteOnClose); |
|
|||
58 |
|
||||
59 | // Set qcpplot properties : |
|
|||
60 | // - Drag (on x-axis) and zoom are enabled |
|
|||
61 | // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation |
|
|||
62 | ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems); |
|
|||
63 | ui->widget->axisRect()->setRangeDrag(Qt::Horizontal); |
|
|||
64 |
|
||||
65 | // The delegate must be initialized after the ui as it uses the plot |
|
|||
66 | impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this); |
|
|||
67 |
|
||||
68 | connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress); |
|
|||
69 | connect(ui->widget, &QCustomPlot::mouseRelease, this, |
|
|||
70 | &VisualizationGraphWidget::onMouseRelease); |
|
|||
71 | connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove); |
|
|||
72 | connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel); |
|
|||
73 | connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>( |
|
|||
74 | &QCPAxis::rangeChanged), |
|
|||
75 | this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection); |
|
|||
76 |
|
||||
77 | // Activates menu when right clicking on the graph |
|
|||
78 | ui->widget->setContextMenuPolicy(Qt::CustomContextMenu); |
|
|||
79 | connect(ui->widget, &QCustomPlot::customContextMenuRequested, this, |
|
|||
80 | &VisualizationGraphWidget::onGraphMenuRequested); |
|
|||
81 |
|
||||
82 | connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(), |
|
|||
83 | &VariableController::onRequestDataLoading); |
|
|||
84 |
|
||||
85 | connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this, |
|
|||
86 | &VisualizationGraphWidget::onUpdateVarDisplaying); |
|
|||
87 | } |
|
21 | } | |
88 |
|
22 | |||
89 |
|
||||
90 | VisualizationGraphWidget::~VisualizationGraphWidget() |
|
23 | VisualizationGraphWidget::~VisualizationGraphWidget() | |
91 | { |
|
24 | { | |
92 | delete ui; |
|
25 | delete ui; | |
93 | } |
|
26 | } | |
94 |
|
27 | |||
95 |
void VisualizationGraphWidget:: |
|
28 | void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable) | |
96 | { |
|
29 | { | |
97 | impl->m_DoAcquisition = enable; |
|
30 | // todo: first check is variable contains data then check how many plot have to be created | |
98 | } |
|
31 | } | |
99 |
|
32 | |||
100 | void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range) |
|
33 | void VisualizationGraphWidget::accept(IVisualizationWidget *visitor) | |
101 | { |
|
34 | { | |
102 | // Uses delegate to create the qcpplot components according to the variable |
|
35 | // TODO: manage the visitor | |
103 | auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget); |
|
|||
104 | impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)}); |
|
|||
105 |
|
||||
106 | // Set axes properties according to the units of the data series |
|
|||
107 | /// @todo : for the moment, no control is performed on the axes: the units and the tickers |
|
|||
108 | /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph |
|
|||
109 | auto xAxisUnit = Unit{}; |
|
|||
110 | auto valuesUnit = Unit{}; |
|
|||
111 |
|
||||
112 | if (auto dataSeries = variable->dataSeries()) { |
|
|||
113 | dataSeries->lockRead(); |
|
|||
114 | xAxisUnit = dataSeries->xAxisUnit(); |
|
|||
115 | valuesUnit = dataSeries->valuesUnit(); |
|
|||
116 | dataSeries->unlock(); |
|
|||
117 | } |
|
|||
118 | impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit); |
|
|||
119 |
|
||||
120 | connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated())); |
|
|||
121 |
|
||||
122 | auto varRange = variable->range(); |
|
|||
123 |
|
||||
124 | this->enableAcquisition(false); |
|
|||
125 | this->setGraphRange(range); |
|
|||
126 | this->enableAcquisition(true); |
|
|||
127 |
|
||||
128 | emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, varRange, |
|
|||
129 | false); |
|
|||
130 |
|
||||
131 | emit variableAdded(variable); |
|
|||
132 | } |
|
36 | } | |
133 |
|
37 | |||
134 | void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept |
|
38 | void VisualizationGraphWidget::close() | |
135 | { |
|
39 | { | |
136 | // Each component associated to the variable : |
|
40 | // The main view cannot be directly closed. | |
137 | // - is removed from qcpplot (which deletes it) |
|
41 | return; | |
138 | // - is no longer referenced in the map |
|
|||
139 | auto variableIt = impl->m_VariableToPlotMultiMap.find(variable); |
|
|||
140 | if (variableIt != impl->m_VariableToPlotMultiMap.cend()) { |
|
|||
141 | emit variableAboutToBeRemoved(variable); |
|
|||
142 |
|
||||
143 | auto &plottablesMap = variableIt->second; |
|
|||
144 |
|
||||
145 | for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend(); |
|
|||
146 | plottableIt != plottableEnd;) { |
|
|||
147 | ui->widget->removePlottable(plottableIt->second); |
|
|||
148 | plottableIt = plottablesMap.erase(plottableIt); |
|
|||
149 | } |
|
|||
150 |
|
||||
151 | impl->m_VariableToPlotMultiMap.erase(variableIt); |
|
|||
152 | } |
|
|||
153 |
|
||||
154 | // Updates graph |
|
|||
155 | ui->widget->replot(); |
|
|||
156 | } |
|
|||
157 |
|
||||
158 | void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable, const SqpRange &range) |
|
|||
159 | { |
|
|||
160 | // Note: in case of different axes that depends on variable, we could start with a code like |
|
|||
161 | // that: |
|
|||
162 | // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable); |
|
|||
163 | // for (auto it = componentsIt.first; it != componentsIt.second;) { |
|
|||
164 | // } |
|
|||
165 | ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd); |
|
|||
166 | ui->widget->replot(); |
|
|||
167 | } |
|
|||
168 |
|
||||
169 | void VisualizationGraphWidget::setYRange(const SqpRange &range) |
|
|||
170 | { |
|
|||
171 | ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd); |
|
|||
172 | } |
|
|||
173 |
|
||||
174 | SqpRange VisualizationGraphWidget::graphRange() const noexcept |
|
|||
175 | { |
|
|||
176 | auto graphRange = ui->widget->xAxis->range(); |
|
|||
177 | return SqpRange{graphRange.lower, graphRange.upper}; |
|
|||
178 | } |
|
|||
179 |
|
||||
180 | void VisualizationGraphWidget::setGraphRange(const SqpRange &range) |
|
|||
181 | { |
|
|||
182 | qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START"); |
|
|||
183 | ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd); |
|
|||
184 | ui->widget->replot(); |
|
|||
185 | qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END"); |
|
|||
186 | } |
|
|||
187 |
|
||||
188 | void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor) |
|
|||
189 | { |
|
|||
190 | if (visitor) { |
|
|||
191 | visitor->visit(this); |
|
|||
192 | } |
|
|||
193 | else { |
|
|||
194 | qCCritical(LOG_VisualizationGraphWidget()) |
|
|||
195 | << tr("Can't visit widget : the visitor is null"); |
|
|||
196 | } |
|
|||
197 | } |
|
|||
198 |
|
||||
199 | bool VisualizationGraphWidget::canDrop(const Variable &variable) const |
|
|||
200 | { |
|
|||
201 | /// @todo : for the moment, a graph can always accomodate a variable |
|
|||
202 | Q_UNUSED(variable); |
|
|||
203 | return true; |
|
|||
204 | } |
|
|||
205 |
|
||||
206 | bool VisualizationGraphWidget::contains(const Variable &variable) const |
|
|||
207 | { |
|
|||
208 | // Finds the variable among the keys of the map |
|
|||
209 | auto variablePtr = &variable; |
|
|||
210 | auto findVariable |
|
|||
211 | = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); }; |
|
|||
212 |
|
||||
213 | auto end = impl->m_VariableToPlotMultiMap.cend(); |
|
|||
214 | auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable); |
|
|||
215 | return it != end; |
|
|||
216 | } |
|
42 | } | |
217 |
|
43 | |||
218 | QString VisualizationGraphWidget::name() const |
|
44 | QString VisualizationGraphWidget::name() const | |
219 | { |
|
45 | { | |
220 | return impl->m_Name; |
|
46 | return QStringLiteral("MainView"); | |
221 | } |
|
|||
222 |
|
||||
223 | void VisualizationGraphWidget::closeEvent(QCloseEvent *event) |
|
|||
224 | { |
|
|||
225 | Q_UNUSED(event); |
|
|||
226 |
|
||||
227 | // Prevents that all variables will be removed from graph when it will be closed |
|
|||
228 | for (auto &variableEntry : impl->m_VariableToPlotMultiMap) { |
|
|||
229 | emit variableAboutToBeRemoved(variableEntry.first); |
|
|||
230 | } |
|
|||
231 | } |
|
|||
232 |
|
||||
233 | void VisualizationGraphWidget::enterEvent(QEvent *event) |
|
|||
234 | { |
|
|||
235 | Q_UNUSED(event); |
|
|||
236 | impl->m_RenderingDelegate->showGraphOverlay(true); |
|
|||
237 | } |
|
|||
238 |
|
||||
239 | void VisualizationGraphWidget::leaveEvent(QEvent *event) |
|
|||
240 | { |
|
|||
241 | Q_UNUSED(event); |
|
|||
242 | impl->m_RenderingDelegate->showGraphOverlay(false); |
|
|||
243 | } |
|
|||
244 |
|
||||
245 | QCustomPlot &VisualizationGraphWidget::plot() noexcept |
|
|||
246 | { |
|
|||
247 | return *ui->widget; |
|
|||
248 | } |
|
|||
249 |
|
||||
250 | void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept |
|
|||
251 | { |
|
|||
252 | QMenu graphMenu{}; |
|
|||
253 |
|
||||
254 | // Iterates on variables (unique keys) |
|
|||
255 | for (auto it = impl->m_VariableToPlotMultiMap.cbegin(), |
|
|||
256 | end = impl->m_VariableToPlotMultiMap.cend(); |
|
|||
257 | it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) { |
|
|||
258 | // 'Remove variable' action |
|
|||
259 | graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()), |
|
|||
260 | [ this, var = it->first ]() { removeVariable(var); }); |
|
|||
261 | } |
|
|||
262 |
|
||||
263 | if (!graphMenu.isEmpty()) { |
|
|||
264 | graphMenu.exec(QCursor::pos()); |
|
|||
265 | } |
|
|||
266 | } |
|
|||
267 |
|
||||
268 | void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2) |
|
|||
269 | { |
|
|||
270 | qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged") |
|
|||
271 | << QThread::currentThread()->objectName() << "DoAcqui" |
|
|||
272 | << impl->m_DoAcquisition; |
|
|||
273 |
|
||||
274 | auto graphRange = SqpRange{t1.lower, t1.upper}; |
|
|||
275 | auto oldGraphRange = SqpRange{t2.lower, t2.upper}; |
|
|||
276 |
|
||||
277 | if (impl->m_DoAcquisition) { |
|
|||
278 | QVector<std::shared_ptr<Variable> > variableUnderGraphVector; |
|
|||
279 |
|
||||
280 | for (auto it = impl->m_VariableToPlotMultiMap.begin(), |
|
|||
281 | end = impl->m_VariableToPlotMultiMap.end(); |
|
|||
282 | it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) { |
|
|||
283 | variableUnderGraphVector.push_back(it->first); |
|
|||
284 | } |
|
|||
285 | emit requestDataLoading(std::move(variableUnderGraphVector), graphRange, oldGraphRange, |
|
|||
286 | !impl->m_IsCalibration); |
|
|||
287 |
|
||||
288 | if (!impl->m_IsCalibration) { |
|
|||
289 | qCDebug(LOG_VisualizationGraphWidget()) |
|
|||
290 | << tr("TORM: VisualizationGraphWidget::Synchronize notify !!") |
|
|||
291 | << QThread::currentThread()->objectName() << graphRange << oldGraphRange; |
|
|||
292 | emit synchronize(graphRange, oldGraphRange); |
|
|||
293 | } |
|
|||
294 | } |
|
|||
295 | } |
|
|||
296 |
|
||||
297 | void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept |
|
|||
298 | { |
|
|||
299 | // Handles plot rendering when mouse is moving |
|
|||
300 | impl->m_RenderingDelegate->onMouseMove(event); |
|
|||
301 | } |
|
|||
302 |
|
||||
303 | void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept |
|
|||
304 | { |
|
|||
305 | auto zoomOrientations = QFlags<Qt::Orientation>{}; |
|
|||
306 |
|
||||
307 | // Lambda that enables a zoom orientation if the key modifier related to this orientation |
|
|||
308 | // has |
|
|||
309 | // been pressed |
|
|||
310 | auto enableOrientation |
|
|||
311 | = [&zoomOrientations, event](const auto &orientation, const auto &modifier) { |
|
|||
312 | auto orientationEnabled = event->modifiers().testFlag(modifier); |
|
|||
313 | zoomOrientations.setFlag(orientation, orientationEnabled); |
|
|||
314 | }; |
|
|||
315 | enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER); |
|
|||
316 | enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER); |
|
|||
317 |
|
||||
318 | ui->widget->axisRect()->setRangeZoom(zoomOrientations); |
|
|||
319 | } |
|
|||
320 |
|
||||
321 | void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept |
|
|||
322 | { |
|
|||
323 | impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier); |
|
|||
324 | } |
|
|||
325 |
|
||||
326 | void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept |
|
|||
327 | { |
|
|||
328 | impl->m_IsCalibration = false; |
|
|||
329 | } |
|
|||
330 |
|
||||
331 | void VisualizationGraphWidget::onDataCacheVariableUpdated() |
|
|||
332 | { |
|
|||
333 | auto graphRange = ui->widget->xAxis->range(); |
|
|||
334 | auto dateTime = SqpRange{graphRange.lower, graphRange.upper}; |
|
|||
335 |
|
||||
336 | for (auto &variableEntry : impl->m_VariableToPlotMultiMap) { |
|
|||
337 | auto variable = variableEntry.first; |
|
|||
338 | qCDebug(LOG_VisualizationGraphWidget()) |
|
|||
339 | << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range(); |
|
|||
340 | qCDebug(LOG_VisualizationGraphWidget()) |
|
|||
341 | << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime; |
|
|||
342 | if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) { |
|
|||
343 | VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(), |
|
|||
344 | variable->range()); |
|
|||
345 | } |
|
|||
346 | } |
|
|||
347 | } |
|
|||
348 |
|
||||
349 | void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable, |
|
|||
350 | const SqpRange &range) |
|
|||
351 | { |
|
|||
352 | auto it = impl->m_VariableToPlotMultiMap.find(variable); |
|
|||
353 | if (it != impl->m_VariableToPlotMultiMap.end()) { |
|
|||
354 | VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range); |
|
|||
355 | } |
|
|||
356 | } |
|
47 | } |
@@ -1,62 +1,13 | |||||
1 | #include "Visualization/VisualizationTabWidget.h" |
|
1 | #include "Visualization/VisualizationTabWidget.h" | |
2 | #include "Visualization/IVisualizationWidgetVisitor.h" |
|
|||
3 | #include "ui_VisualizationTabWidget.h" |
|
2 | #include "ui_VisualizationTabWidget.h" | |
4 |
|
3 | |||
5 | #include "Visualization/VisualizationZoneWidget.h" |
|
4 | #include "Visualization/VisualizationZoneWidget.h" | |
6 |
|
5 | |||
7 | Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget") |
|
|||
8 |
|
6 | |||
9 | namespace { |
|
7 | VisualizationTabWidget::VisualizationTabWidget(QWidget *parent) | |
10 |
|
8 | : QWidget{parent}, ui{new Ui::VisualizationTabWidget} | ||
11 | /// Generates a default name for a new zone, according to the number of zones already displayed in |
|
|||
12 | /// the tab |
|
|||
13 | QString defaultZoneName(const QLayout &layout) |
|
|||
14 | { |
|
|||
15 | auto count = 0; |
|
|||
16 | for (auto i = 0; i < layout.count(); ++i) { |
|
|||
17 | if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) { |
|
|||
18 | count++; |
|
|||
19 | } |
|
|||
20 | } |
|
|||
21 |
|
||||
22 | return QObject::tr("Zone %1").arg(count + 1); |
|
|||
23 | } |
|
|||
24 |
|
||||
25 | /** |
|
|||
26 | * Applies a function to all zones of the tab represented by its layout |
|
|||
27 | * @param layout the layout that contains zones |
|
|||
28 | * @param fun the function to apply to each zone |
|
|||
29 | */ |
|
|||
30 | template <typename Fun> |
|
|||
31 | void processZones(QLayout &layout, Fun fun) |
|
|||
32 | { |
|
|||
33 | for (auto i = 0; i < layout.count(); ++i) { |
|
|||
34 | if (auto item = layout.itemAt(i)) { |
|
|||
35 | if (auto visualizationZoneWidget |
|
|||
36 | = dynamic_cast<VisualizationZoneWidget *>(item->widget())) { |
|
|||
37 | fun(*visualizationZoneWidget); |
|
|||
38 | } |
|
|||
39 | } |
|
|||
40 | } |
|
|||
41 | } |
|
|||
42 |
|
||||
43 | } // namespace |
|
|||
44 |
|
||||
45 | struct VisualizationTabWidget::VisualizationTabWidgetPrivate { |
|
|||
46 | explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {} |
|
|||
47 |
|
||||
48 | QString m_Name; |
|
|||
49 | }; |
|
|||
50 |
|
||||
51 | VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent) |
|
|||
52 | : QWidget{parent}, |
|
|||
53 | ui{new Ui::VisualizationTabWidget}, |
|
|||
54 | impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)} |
|
|||
55 | { |
|
9 | { | |
56 | ui->setupUi(this); |
|
10 | ui->setupUi(this); | |
57 |
|
||||
58 | // Widget is deleted when closed |
|
|||
59 | setAttribute(Qt::WA_DeleteOnClose); |
|
|||
60 | } |
|
11 | } | |
61 |
|
12 | |||
62 | VisualizationTabWidget::~VisualizationTabWidget() |
|
13 | VisualizationTabWidget::~VisualizationTabWidget() | |
@@ -66,64 +17,33 VisualizationTabWidget::~VisualizationTabWidget() | |||||
66 |
|
17 | |||
67 | void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget) |
|
18 | void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget) | |
68 | { |
|
19 | { | |
69 |
t |
|
20 | this->layout()->addWidget(zoneWidget); | |
70 | } |
|
21 | } | |
71 |
|
22 | |||
72 |
VisualizationZoneWidget *VisualizationTabWidget::createZone( |
|
23 | VisualizationZoneWidget *VisualizationTabWidget::createZone() | |
73 | { |
|
24 | { | |
74 |
auto zoneWidget = new VisualizationZoneWidget{ |
|
25 | auto zoneWidget = new VisualizationZoneWidget{this}; | |
75 | this->addZone(zoneWidget); |
|
26 | this->addZone(zoneWidget); | |
76 |
|
27 | |||
77 | // Creates a new graph into the zone |
|
|||
78 | zoneWidget->createGraph(variable); |
|
|||
79 |
|
||||
80 | return zoneWidget; |
|
28 | return zoneWidget; | |
81 | } |
|
29 | } | |
82 |
|
30 | |||
83 |
void VisualizationTabWidget:: |
|
31 | void VisualizationTabWidget::removeZone(VisualizationZoneWidget *zone) | |
84 | { |
|
32 | { | |
85 | if (visitor) { |
|
|||
86 | visitor->visitEnter(this); |
|
|||
87 |
|
||||
88 | // Apply visitor to zone children: widgets different from zones are not visited (no action) |
|
|||
89 | processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) { |
|
|||
90 | zoneWidget.accept(visitor); |
|
|||
91 | }); |
|
|||
92 |
|
||||
93 | visitor->visitLeave(this); |
|
|||
94 | } |
|
|||
95 | else { |
|
|||
96 | qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null"); |
|
|||
97 | } |
|
|||
98 | } |
|
33 | } | |
99 |
|
34 | |||
100 | bool VisualizationTabWidget::canDrop(const Variable &variable) const |
|
35 | void VisualizationTabWidget::accept(IVisualizationWidget *visitor) | |
101 | { |
|
36 | { | |
102 | // A tab can always accomodate a variable |
|
37 | // TODO: manage the visitor | |
103 | Q_UNUSED(variable); |
|
|||
104 | return true; |
|
|||
105 | } |
|
38 | } | |
106 |
|
39 | |||
107 | bool VisualizationTabWidget::contains(const Variable &variable) const |
|
40 | void VisualizationTabWidget::close() | |
108 | { |
|
41 | { | |
109 | Q_UNUSED(variable); |
|
42 | // The main view cannot be directly closed. | |
110 |
return |
|
43 | return; | |
111 | } |
|
44 | } | |
112 |
|
45 | |||
113 | QString VisualizationTabWidget::name() const |
|
46 | QString VisualizationTabWidget::name() const | |
114 | { |
|
47 | { | |
115 | return impl->m_Name; |
|
48 | return QStringLiteral("MainView"); | |
116 | } |
|
|||
117 |
|
||||
118 | void VisualizationTabWidget::closeEvent(QCloseEvent *event) |
|
|||
119 | { |
|
|||
120 | // Closes zones in the tab |
|
|||
121 | processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); }); |
|
|||
122 |
|
||||
123 | QWidget::closeEvent(event); |
|
|||
124 | } |
|
|||
125 |
|
||||
126 | QLayout &VisualizationTabWidget::tabLayout() const noexcept |
|
|||
127 | { |
|
|||
128 | return *ui->scrollAreaWidgetContents->layout(); |
|
|||
129 | } |
|
49 | } |
@@ -1,12 +1,5 | |||||
1 | #include "Visualization/VisualizationWidget.h" |
|
1 | #include "Visualization/VisualizationWidget.h" | |
2 | #include "Visualization/IVisualizationWidgetVisitor.h" |
|
|||
3 | #include "Visualization/VisualizationGraphWidget.h" |
|
|||
4 | #include "Visualization/VisualizationTabWidget.h" |
|
2 | #include "Visualization/VisualizationTabWidget.h" | |
5 | #include "Visualization/VisualizationZoneWidget.h" |
|
|||
6 | #include "Visualization/operations/FindVariableOperation.h" |
|
|||
7 | #include "Visualization/operations/GenerateVariableMenuOperation.h" |
|
|||
8 | #include "Visualization/operations/RemoveVariableOperation.h" |
|
|||
9 | #include "Visualization/operations/RescaleAxeOperation.h" |
|
|||
10 | #include "Visualization/qcustomplot.h" |
|
3 | #include "Visualization/qcustomplot.h" | |
11 |
|
4 | |||
12 | #include "ui_VisualizationWidget.h" |
|
5 | #include "ui_VisualizationWidget.h" | |
@@ -23,52 +16,24 VisualizationWidget::VisualizationWidget(QWidget *parent) | |||||
23 | auto addTabViewButton = new QToolButton{ui->tabWidget}; |
|
16 | auto addTabViewButton = new QToolButton{ui->tabWidget}; | |
24 | addTabViewButton->setText(tr("Add View")); |
|
17 | addTabViewButton->setText(tr("Add View")); | |
25 | addTabViewButton->setCursor(Qt::ArrowCursor); |
|
18 | addTabViewButton->setCursor(Qt::ArrowCursor); | |
|
19 | addTabViewButton->setAutoRaise(true); | |||
26 | ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner); |
|
20 | ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner); | |
27 |
|
21 | |||
28 | auto enableMinimumCornerWidgetSize = [this](bool enable) { |
|
22 | auto addTabView = [&]() { | |
29 |
|
23 | auto index = ui->tabWidget->addTab(new VisualizationTabWidget(ui->tabWidget), | ||
30 | auto tabViewCornerWidget = ui->tabWidget->cornerWidget(); |
|
24 | QString("View %1").arg(ui->tabWidget->count() + 1)); | |
31 | auto width = enable ? tabViewCornerWidget->width() : 0; |
|
|||
32 | auto height = enable ? tabViewCornerWidget->height() : 0; |
|
|||
33 | tabViewCornerWidget->setMinimumHeight(height); |
|
|||
34 | tabViewCornerWidget->setMinimumWidth(width); |
|
|||
35 | ui->tabWidget->setMinimumHeight(height); |
|
|||
36 | ui->tabWidget->setMinimumWidth(width); |
|
|||
37 | }; |
|
|||
38 |
|
||||
39 | auto addTabView = [this, enableMinimumCornerWidgetSize]() { |
|
|||
40 | auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1), |
|
|||
41 | ui->tabWidget}; |
|
|||
42 | auto index = ui->tabWidget->addTab(widget, widget->name()); |
|
|||
43 | if (ui->tabWidget->count() > 0) { |
|
|||
44 | enableMinimumCornerWidgetSize(false); |
|
|||
45 | } |
|
|||
46 | qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index); |
|
25 | qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index); | |
47 | }; |
|
26 | }; | |
48 |
|
27 | |||
49 |
auto removeTabView = [ |
|
28 | auto removeTabView = [&](int index) { | |
50 | if (ui->tabWidget->count() == 1) { |
|
|||
51 | enableMinimumCornerWidgetSize(true); |
|
|||
52 | } |
|
|||
53 |
|
||||
54 | // Removes widget from tab and closes it |
|
|||
55 | auto widget = ui->tabWidget->widget(index); |
|
|||
56 | ui->tabWidget->removeTab(index); |
|
29 | ui->tabWidget->removeTab(index); | |
57 | if (widget) { |
|
|||
58 | widget->close(); |
|
|||
59 | } |
|
|||
60 |
|
||||
61 | qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index); |
|
30 | qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index); | |
62 |
|
||||
63 | }; |
|
31 | }; | |
64 |
|
32 | |||
65 | ui->tabWidget->setTabsClosable(true); |
|
33 | ui->tabWidget->setTabsClosable(true); | |
66 |
|
34 | |||
67 | connect(addTabViewButton, &QToolButton::clicked, addTabView); |
|
35 | connect(addTabViewButton, &QToolButton::clicked, addTabView); | |
68 | connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView); |
|
36 | connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView); | |
69 |
|
||||
70 | // Adds default tab |
|
|||
71 | addTabView(); |
|
|||
72 | } |
|
37 | } | |
73 |
|
38 | |||
74 | VisualizationWidget::~VisualizationWidget() |
|
39 | VisualizationWidget::~VisualizationWidget() | |
@@ -76,97 +41,34 VisualizationWidget::~VisualizationWidget() | |||||
76 | delete ui; |
|
41 | delete ui; | |
77 | } |
|
42 | } | |
78 |
|
43 | |||
79 |
void VisualizationWidget::a |
|
44 | void VisualizationWidget::addTab(VisualizationTabWidget *tabWidget) | |
80 | { |
|
45 | { | |
81 | if (visitor) { |
|
46 | // NOTE: check is this method has to be deleted because of its dupplicated version visible as | |
82 | visitor->visitEnter(this); |
|
47 | // lambda function (in the constructor) | |
83 |
|
||||
84 | // Apply visitor for tab children |
|
|||
85 | for (auto i = 0; i < ui->tabWidget->count(); ++i) { |
|
|||
86 | // Widgets different from tabs are not visited (no action) |
|
|||
87 | if (auto visualizationTabWidget |
|
|||
88 | = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) { |
|
|||
89 | visualizationTabWidget->accept(visitor); |
|
|||
90 | } |
|
|||
91 | } |
|
|||
92 |
|
||||
93 | visitor->visitLeave(this); |
|
|||
94 | } |
|
|||
95 | else { |
|
|||
96 | qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null"); |
|
|||
97 | } |
|
|||
98 | } |
|
48 | } | |
99 |
|
49 | |||
100 | bool VisualizationWidget::canDrop(const Variable &variable) const |
|
50 | VisualizationTabWidget *VisualizationWidget::createTab() | |
101 | { |
|
51 | { | |
102 | // The main widget can never accomodate a variable |
|
|||
103 | Q_UNUSED(variable); |
|
|||
104 | return false; |
|
|||
105 | } |
|
52 | } | |
106 |
|
53 | |||
107 | bool VisualizationWidget::contains(const Variable &variable) const |
|
54 | void VisualizationWidget::removeTab(VisualizationTabWidget *tab) | |
108 | { |
|
55 | { | |
109 | Q_UNUSED(variable); |
|
56 | // NOTE: check is this method has to be deleted because of its dupplicated version visible as | |
110 | return false; |
|
57 | // lambda function (in the constructor) | |
111 | } |
|
58 | } | |
112 |
|
59 | |||
113 | QString VisualizationWidget::name() const |
|
60 | void VisualizationWidget::accept(IVisualizationWidget *visitor) | |
114 | { |
|
61 | { | |
115 | return QStringLiteral("MainView"); |
|
62 | // TODO: manage the visitor | |
116 | } |
|
63 | } | |
117 |
|
64 | |||
118 |
void VisualizationWidget:: |
|
65 | void VisualizationWidget::close() | |
119 | QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept |
|
|||
120 | { |
|
66 | { | |
121 | // Menu is generated only if there is a single variable |
|
67 | // The main view cannot be directly closed. | |
122 | if (variables.size() == 1) { |
|
68 | return; | |
123 | if (auto variable = variables.first()) { |
|
|||
124 | // Gets the containers of the variable |
|
|||
125 | FindVariableOperation findVariableOperation{variable}; |
|
|||
126 | accept(&findVariableOperation); |
|
|||
127 | auto variableContainers = findVariableOperation.result(); |
|
|||
128 |
|
||||
129 | // Generates the actions that make it possible to visualize the variable |
|
|||
130 | GenerateVariableMenuOperation generateVariableMenuOperation{ |
|
|||
131 | menu, variable, std::move(variableContainers)}; |
|
|||
132 | accept(&generateVariableMenuOperation); |
|
|||
133 | } |
|
|||
134 | else { |
|
|||
135 | qCCritical(LOG_VisualizationWidget()) << tr( |
|
|||
136 | "Can't generate the menu relative to the visualization: the variable is null"); |
|
|||
137 | } |
|
|||
138 | } |
|
|||
139 | else { |
|
|||
140 | qCDebug(LOG_VisualizationWidget()) |
|
|||
141 | << tr("No generation of the menu related to the visualization: several variables are " |
|
|||
142 | "selected"); |
|
|||
143 | } |
|
|||
144 | } |
|
69 | } | |
145 |
|
70 | |||
146 | void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept |
|
71 | QString VisualizationWidget::name() const | |
147 | { |
|
|||
148 | // Calls the operation of removing all references to the variable in the visualization |
|
|||
149 | auto removeVariableOperation = RemoveVariableOperation{variable}; |
|
|||
150 | accept(&removeVariableOperation); |
|
|||
151 | } |
|
|||
152 |
|
||||
153 | void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable, |
|
|||
154 | const SqpRange &range) noexcept |
|
|||
155 | { |
|
|||
156 | // Calls the operation of rescaling all graph that contrains variable in the visualization |
|
|||
157 | auto rescaleVariableOperation = RescaleAxeOperation{variable, range}; |
|
|||
158 | accept(&rescaleVariableOperation); |
|
|||
159 | } |
|
|||
160 |
|
||||
161 | void VisualizationWidget::closeEvent(QCloseEvent *event) |
|
|||
162 | { |
|
72 | { | |
163 | // Closes tabs in the widget |
|
73 | return QStringLiteral("MainView"); | |
164 | for (auto i = 0; i < ui->tabWidget->count(); ++i) { |
|
|||
165 | if (auto visualizationTabWidget |
|
|||
166 | = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) { |
|
|||
167 | visualizationTabWidget->close(); |
|
|||
168 | } |
|
|||
169 | } |
|
|||
170 |
|
||||
171 | QWidget::closeEvent(event); |
|
|||
172 | } |
|
74 | } |
@@ -1,87 +1,12 | |||||
1 | #include "Visualization/VisualizationZoneWidget.h" |
|
1 | #include "Visualization/VisualizationZoneWidget.h" | |
2 |
|
||||
3 | #include "Visualization/IVisualizationWidgetVisitor.h" |
|
|||
4 | #include "Visualization/QCustomPlotSynchronizer.h" |
|
|||
5 | #include "Visualization/VisualizationGraphWidget.h" |
|
|||
6 | #include "ui_VisualizationZoneWidget.h" |
|
2 | #include "ui_VisualizationZoneWidget.h" | |
7 |
|
3 | |||
8 | #include <Data/SqpRange.h> |
|
4 | #include "Visualization/VisualizationGraphWidget.h" | |
9 | #include <Variable/Variable.h> |
|
|||
10 | #include <Variable/VariableController.h> |
|
|||
11 |
|
||||
12 | #include <QUuid> |
|
|||
13 | #include <SqpApplication.h> |
|
|||
14 | #include <cmath> |
|
|||
15 |
|
||||
16 | Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget") |
|
|||
17 |
|
||||
18 | namespace { |
|
|||
19 |
|
||||
20 | /// Minimum height for graph added in zones (in pixels) |
|
|||
21 | const auto GRAPH_MINIMUM_HEIGHT = 300; |
|
|||
22 |
|
||||
23 | /// Generates a default name for a new graph, according to the number of graphs already displayed in |
|
|||
24 | /// the zone |
|
|||
25 | QString defaultGraphName(const QLayout &layout) |
|
|||
26 | { |
|
|||
27 | auto count = 0; |
|
|||
28 | for (auto i = 0; i < layout.count(); ++i) { |
|
|||
29 | if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) { |
|
|||
30 | count++; |
|
|||
31 | } |
|
|||
32 | } |
|
|||
33 |
|
||||
34 | return QObject::tr("Graph %1").arg(count + 1); |
|
|||
35 | } |
|
|||
36 |
|
||||
37 | /** |
|
|||
38 | * Applies a function to all graphs of the zone represented by its layout |
|
|||
39 | * @param layout the layout that contains graphs |
|
|||
40 | * @param fun the function to apply to each graph |
|
|||
41 | */ |
|
|||
42 | template <typename Fun> |
|
|||
43 | void processGraphs(QLayout &layout, Fun fun) |
|
|||
44 | { |
|
|||
45 | for (auto i = 0; i < layout.count(); ++i) { |
|
|||
46 | if (auto item = layout.itemAt(i)) { |
|
|||
47 | if (auto visualizationGraphWidget |
|
|||
48 | = dynamic_cast<VisualizationGraphWidget *>(item->widget())) { |
|
|||
49 | fun(*visualizationGraphWidget); |
|
|||
50 | } |
|
|||
51 | } |
|
|||
52 | } |
|
|||
53 | } |
|
|||
54 |
|
||||
55 | } // namespace |
|
|||
56 |
|
||||
57 | struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate { |
|
|||
58 |
|
||||
59 | explicit VisualizationZoneWidgetPrivate() |
|
|||
60 | : m_SynchronisationGroupId{QUuid::createUuid()}, |
|
|||
61 | m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()} |
|
|||
62 | { |
|
|||
63 | } |
|
|||
64 | QUuid m_SynchronisationGroupId; |
|
|||
65 | std::unique_ptr<IGraphSynchronizer> m_Synchronizer; |
|
|||
66 | }; |
|
|||
67 |
|
5 | |||
68 |
VisualizationZoneWidget::VisualizationZoneWidget( |
|
6 | VisualizationZoneWidget::VisualizationZoneWidget(QWidget *parent) | |
69 | : QWidget{parent}, |
|
7 | : QWidget{parent}, ui{new Ui::VisualizationZoneWidget} | |
70 | ui{new Ui::VisualizationZoneWidget}, |
|
|||
71 | impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()} |
|
|||
72 | { |
|
8 | { | |
73 | ui->setupUi(this); |
|
9 | ui->setupUi(this); | |
74 |
|
||||
75 | ui->zoneNameLabel->setText(name); |
|
|||
76 |
|
||||
77 | // 'Close' options : widget is deleted when closed |
|
|||
78 | setAttribute(Qt::WA_DeleteOnClose); |
|
|||
79 | connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close); |
|
|||
80 | ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton)); |
|
|||
81 |
|
||||
82 | // Synchronisation id |
|
|||
83 | QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId", |
|
|||
84 | Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId)); |
|
|||
85 | } |
|
10 | } | |
86 |
|
11 | |||
87 | VisualizationZoneWidget::~VisualizationZoneWidget() |
|
12 | VisualizationZoneWidget::~VisualizationZoneWidget() | |
@@ -91,212 +16,33 VisualizationZoneWidget::~VisualizationZoneWidget() | |||||
91 |
|
16 | |||
92 | void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget) |
|
17 | void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget) | |
93 | { |
|
18 | { | |
94 | // Synchronize new graph with others in the zone |
|
|||
95 | impl->m_Synchronizer->addGraph(*graphWidget); |
|
|||
96 |
|
||||
97 | ui->visualizationZoneFrame->layout()->addWidget(graphWidget); |
|
19 | ui->visualizationZoneFrame->layout()->addWidget(graphWidget); | |
98 | } |
|
20 | } | |
99 |
|
21 | |||
100 |
VisualizationGraphWidget *VisualizationZoneWidget::createGraph( |
|
22 | VisualizationGraphWidget *VisualizationZoneWidget::createGraph() | |
101 | { |
|
23 | { | |
102 | auto graphWidget = new VisualizationGraphWidget{ |
|
24 | auto graphWidget = new VisualizationGraphWidget{this}; | |
103 | defaultGraphName(*ui->visualizationZoneFrame->layout()), this}; |
|
|||
104 |
|
||||
105 |
|
||||
106 | // Set graph properties |
|
|||
107 | graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); |
|
|||
108 | graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT); |
|
|||
109 |
|
||||
110 |
|
||||
111 | // Lambda to synchronize zone widget |
|
|||
112 | auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange, |
|
|||
113 | const SqpRange &oldGraphRange) { |
|
|||
114 |
|
||||
115 | auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange); |
|
|||
116 | auto frameLayout = ui->visualizationZoneFrame->layout(); |
|
|||
117 | for (auto i = 0; i < frameLayout->count(); ++i) { |
|
|||
118 | auto graphChild |
|
|||
119 | = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget()); |
|
|||
120 | if (graphChild && (graphChild != graphWidget)) { |
|
|||
121 |
|
||||
122 | auto graphChildRange = graphChild->graphRange(); |
|
|||
123 | switch (zoomType) { |
|
|||
124 | case AcquisitionZoomType::ZoomIn: { |
|
|||
125 | auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart; |
|
|||
126 | auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd; |
|
|||
127 | graphChildRange.m_TStart += deltaLeft; |
|
|||
128 | graphChildRange.m_TEnd -= deltaRight; |
|
|||
129 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn"); |
|
|||
130 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft") |
|
|||
131 | << deltaLeft; |
|
|||
132 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight") |
|
|||
133 | << deltaRight; |
|
|||
134 | qCDebug(LOG_VisualizationZoneWidget()) |
|
|||
135 | << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart; |
|
|||
136 |
|
||||
137 | break; |
|
|||
138 | } |
|
|||
139 |
|
||||
140 | case AcquisitionZoomType::ZoomOut: { |
|
|||
141 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut"); |
|
|||
142 | auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart; |
|
|||
143 | auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd; |
|
|||
144 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft") |
|
|||
145 | << deltaLeft; |
|
|||
146 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight") |
|
|||
147 | << deltaRight; |
|
|||
148 | qCDebug(LOG_VisualizationZoneWidget()) |
|
|||
149 | << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart; |
|
|||
150 | graphChildRange.m_TStart -= deltaLeft; |
|
|||
151 | graphChildRange.m_TEnd += deltaRight; |
|
|||
152 | break; |
|
|||
153 | } |
|
|||
154 | case AcquisitionZoomType::PanRight: { |
|
|||
155 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight"); |
|
|||
156 | auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd; |
|
|||
157 | graphChildRange.m_TStart += deltaRight; |
|
|||
158 | graphChildRange.m_TEnd += deltaRight; |
|
|||
159 | qCDebug(LOG_VisualizationZoneWidget()) |
|
|||
160 | << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart; |
|
|||
161 | break; |
|
|||
162 | } |
|
|||
163 | case AcquisitionZoomType::PanLeft: { |
|
|||
164 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft"); |
|
|||
165 | auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart; |
|
|||
166 | graphChildRange.m_TStart -= deltaLeft; |
|
|||
167 | graphChildRange.m_TEnd -= deltaLeft; |
|
|||
168 | break; |
|
|||
169 | } |
|
|||
170 | case AcquisitionZoomType::Unknown: { |
|
|||
171 | qCDebug(LOG_VisualizationZoneWidget()) |
|
|||
172 | << tr("Impossible to synchronize: zoom type unknown"); |
|
|||
173 | break; |
|
|||
174 | } |
|
|||
175 | default: |
|
|||
176 | qCCritical(LOG_VisualizationZoneWidget()) |
|
|||
177 | << tr("Impossible to synchronize: zoom type not take into account"); |
|
|||
178 | // No action |
|
|||
179 | break; |
|
|||
180 | } |
|
|||
181 | graphChild->enableAcquisition(false); |
|
|||
182 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ") |
|
|||
183 | << graphChild->graphRange(); |
|
|||
184 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ") |
|
|||
185 | << graphChildRange; |
|
|||
186 | qCDebug(LOG_VisualizationZoneWidget()) |
|
|||
187 | << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart; |
|
|||
188 | graphChild->setGraphRange(graphChildRange); |
|
|||
189 | graphChild->enableAcquisition(true); |
|
|||
190 | } |
|
|||
191 | } |
|
|||
192 | }; |
|
|||
193 |
|
||||
194 | // connection for synchronization |
|
|||
195 | connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget); |
|
|||
196 | connect(graphWidget, &VisualizationGraphWidget::variableAdded, this, |
|
|||
197 | &VisualizationZoneWidget::onVariableAdded); |
|
|||
198 | connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this, |
|
|||
199 | &VisualizationZoneWidget::onVariableAboutToBeRemoved); |
|
|||
200 |
|
||||
201 | auto range = SqpRange{}; |
|
|||
202 |
|
||||
203 | // Apply visitor to graph children |
|
|||
204 | auto layout = ui->visualizationZoneFrame->layout(); |
|
|||
205 | if (layout->count() > 0) { |
|
|||
206 | // Case of a new graph in a existant zone |
|
|||
207 | if (auto visualizationGraphWidget |
|
|||
208 | = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) { |
|
|||
209 | range = visualizationGraphWidget->graphRange(); |
|
|||
210 | } |
|
|||
211 | } |
|
|||
212 | else { |
|
|||
213 | // Case of a new graph as the first of the zone |
|
|||
214 | range = variable->range(); |
|
|||
215 | } |
|
|||
216 |
|
||||
217 | this->addGraph(graphWidget); |
|
25 | this->addGraph(graphWidget); | |
218 |
|
26 | |||
219 | graphWidget->addVariable(variable, range); |
|
|||
220 |
|
||||
221 | // get y using variable range |
|
|||
222 | if (auto dataSeries = variable->dataSeries()) { |
|
|||
223 | dataSeries->lockRead(); |
|
|||
224 | auto valuesBounds |
|
|||
225 | = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd); |
|
|||
226 | auto end = dataSeries->cend(); |
|
|||
227 | if (valuesBounds.first != end && valuesBounds.second != end) { |
|
|||
228 | auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; }; |
|
|||
229 |
|
||||
230 | auto minValue = rangeValue(valuesBounds.first->minValue()); |
|
|||
231 | auto maxValue = rangeValue(valuesBounds.second->maxValue()); |
|
|||
232 |
|
||||
233 | graphWidget->setYRange(SqpRange{minValue, maxValue}); |
|
|||
234 | } |
|
|||
235 | dataSeries->unlock(); |
|
|||
236 | } |
|
|||
237 |
|
||||
238 | return graphWidget; |
|
27 | return graphWidget; | |
239 | } |
|
28 | } | |
240 |
|
29 | |||
241 |
void VisualizationZoneWidget:: |
|
30 | void VisualizationZoneWidget::removeGraph(VisualizationGraphWidget *graph) | |
242 | { |
|
31 | { | |
243 | if (visitor) { |
|
|||
244 | visitor->visitEnter(this); |
|
|||
245 |
|
||||
246 | // Apply visitor to graph children: widgets different from graphs are not visited (no |
|
|||
247 | // action) |
|
|||
248 | processGraphs( |
|
|||
249 | *ui->visualizationZoneFrame->layout(), |
|
|||
250 | [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); }); |
|
|||
251 |
|
||||
252 | visitor->visitLeave(this); |
|
|||
253 | } |
|
|||
254 | else { |
|
|||
255 | qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null"); |
|
|||
256 | } |
|
|||
257 | } |
|
32 | } | |
258 |
|
33 | |||
259 | bool VisualizationZoneWidget::canDrop(const Variable &variable) const |
|
34 | void VisualizationZoneWidget::accept(IVisualizationWidget *visitor) | |
260 | { |
|
35 | { | |
261 | // A tab can always accomodate a variable |
|
36 | // TODO: manage the visitor | |
262 | Q_UNUSED(variable); |
|
|||
263 | return true; |
|
|||
264 | } |
|
37 | } | |
265 |
|
38 | |||
266 | bool VisualizationZoneWidget::contains(const Variable &variable) const |
|
39 | void VisualizationZoneWidget::close() | |
267 | { |
|
40 | { | |
268 | Q_UNUSED(variable); |
|
41 | // The main view cannot be directly closed. | |
269 |
return |
|
42 | return; | |
270 | } |
|
43 | } | |
271 |
|
44 | |||
272 | QString VisualizationZoneWidget::name() const |
|
45 | QString VisualizationZoneWidget::name() const | |
273 | { |
|
46 | { | |
274 | return ui->zoneNameLabel->text(); |
|
47 | return QStringLiteral("MainView"); | |
275 | } |
|
|||
276 |
|
||||
277 | void VisualizationZoneWidget::closeEvent(QCloseEvent *event) |
|
|||
278 | { |
|
|||
279 | // Closes graphs in the zone |
|
|||
280 | processGraphs(*ui->visualizationZoneFrame->layout(), |
|
|||
281 | [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); }); |
|
|||
282 |
|
||||
283 | // Delete synchronization group from variable controller |
|
|||
284 | QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId", |
|
|||
285 | Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId)); |
|
|||
286 |
|
||||
287 | QWidget::closeEvent(event); |
|
|||
288 | } |
|
|||
289 |
|
||||
290 | void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable) |
|
|||
291 | { |
|
|||
292 | QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized", |
|
|||
293 | Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable), |
|
|||
294 | Q_ARG(QUuid, impl->m_SynchronisationGroupId)); |
|
|||
295 | } |
|
|||
296 |
|
||||
297 | void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable) |
|
|||
298 | { |
|
|||
299 | QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection, |
|
|||
300 | Q_ARG(std::shared_ptr<Variable>, variable), |
|
|||
301 | Q_ARG(QUuid, impl->m_SynchronisationGroupId)); |
|
|||
302 | } |
|
48 | } |
This diff has been collapsed as it changes many lines, (1350 lines changed) Show them Hide them | |||||
@@ -2102,8 +2102,8 bool QCPRange::validRange(const QCPRange &range) | |||||
2102 | /* end of 'src/axis/range.cpp' */ |
|
2102 | /* end of 'src/axis/range.cpp' */ | |
2103 |
|
2103 | |||
2104 |
|
2104 | |||
2105 |
/* including file 'src/selection.cpp', size 21 |
|
2105 | /* including file 'src/selection.cpp', size 21898 */ | |
2106 | /* commit 820d2282db70144c358c13433cd74b4175f9252b 2017-07-24 00:24:17 +0200 */ |
|
2106 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
2107 |
|
2107 | |||
2108 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2108 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
2109 | //////////////////// QCPDataRange |
|
2109 | //////////////////// QCPDataRange | |
@@ -2406,7 +2406,7 QCPDataSelection &QCPDataSelection::operator+=(const QCPDataRange &other) | |||||
2406 | } |
|
2406 | } | |
2407 |
|
2407 | |||
2408 | /*! |
|
2408 | /*! | |
2409 |
Removes all data point indices that are described by \a other from this data |
|
2409 | Removes all data point indices that are described by \a other from this data range. | |
2410 | */ |
|
2410 | */ | |
2411 | QCPDataSelection &QCPDataSelection::operator-=(const QCPDataSelection &other) |
|
2411 | QCPDataSelection &QCPDataSelection::operator-=(const QCPDataSelection &other) | |
2412 | { |
|
2412 | { | |
@@ -2417,7 +2417,7 QCPDataSelection &QCPDataSelection::operator-=(const QCPDataSelection &other) | |||||
2417 | } |
|
2417 | } | |
2418 |
|
2418 | |||
2419 | /*! |
|
2419 | /*! | |
2420 |
Removes all data point indices that are described by \a other from this data |
|
2420 | Removes all data point indices that are described by \a other from this data range. | |
2421 | */ |
|
2421 | */ | |
2422 | QCPDataSelection &QCPDataSelection::operator-=(const QCPDataRange &other) |
|
2422 | QCPDataSelection &QCPDataSelection::operator-=(const QCPDataRange &other) | |
2423 | { |
|
2423 | { | |
@@ -2930,8 +2930,8 void QCPSelectionRect::draw(QCPPainter *painter) | |||||
2930 | /* end of 'src/selectionrect.cpp' */ |
|
2930 | /* end of 'src/selectionrect.cpp' */ | |
2931 |
|
2931 | |||
2932 |
|
2932 | |||
2933 |
/* including file 'src/layout.cpp', size 74 |
|
2933 | /* including file 'src/layout.cpp', size 74302 */ | |
2934 | /* commit a872eb91ec087561efd83dd9cb041a26ab95ce55 2017-07-31 00:21:41 +0200 */ |
|
2934 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
2935 |
|
2935 | |||
2936 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2936 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
2937 | //////////////////// QCPMarginGroup |
|
2937 | //////////////////// QCPMarginGroup | |
@@ -3572,13 +3572,12 QCPLayout::QCPLayout() | |||||
3572 | } |
|
3572 | } | |
3573 |
|
3573 | |||
3574 | /*! |
|
3574 | /*! | |
3575 | If \a phase is \ref upLayout, calls \ref updateLayout, which subclasses may reimplement to |
|
3575 | First calls the QCPLayoutElement::update base class implementation to update the margins on this | |
3576 | reposition and resize their cells. |
|
3576 | layout. | |
3577 |
|
3577 | |||
3578 | Finally, the call is propagated down to all child \ref QCPLayoutElement "QCPLayoutElements". |
|
3578 | Then calls \ref updateLayout which subclasses reimplement to reposition and resize their cells. | |
3579 |
|
3579 | |||
3580 | For details about this method and the update phases, see the documentation of \ref |
|
3580 | Finally, \ref update is called on all child elements. | |
3581 | QCPLayoutElement::update. |
|
|||
3582 | */ |
|
3581 | */ | |
3583 | void QCPLayout::update(UpdatePhase phase) |
|
3582 | void QCPLayout::update(UpdatePhase phase) | |
3584 | { |
|
3583 | { | |
@@ -4243,7 +4242,7 void QCPLayoutGrid::setWrap(int count) | |||||
4243 |
|
4242 | |||
4244 | If you want to have all current elements arranged in the new order, set \a rearrange to true. The |
|
4243 | If you want to have all current elements arranged in the new order, set \a rearrange to true. The | |
4245 | elements will be rearranged in a way that tries to preserve their linear index. However, empty |
|
4244 | elements will be rearranged in a way that tries to preserve their linear index. However, empty | |
4246 |
cells are skipped during build-up of the new cell order, which shifts the succe |
|
4245 | cells are skipped during build-up of the new cell order, which shifts the succeding element's | |
4247 | index. The rearranging is performed even if the specified \a order is already the current fill |
|
4246 | index. The rearranging is performed even if the specified \a order is already the current fill | |
4248 | order. Thus this method can be used to re-wrap the current elements. |
|
4247 | order. Thus this method can be used to re-wrap the current elements. | |
4249 |
|
4248 | |||
@@ -4338,8 +4337,7 void QCPLayoutGrid::insertRow(int newIndex) | |||||
4338 |
|
4337 | |||
4339 | /*! |
|
4338 | /*! | |
4340 | Inserts a new column with empty cells at the column index \a newIndex. Valid values for \a |
|
4339 | Inserts a new column with empty cells at the column index \a newIndex. Valid values for \a | |
4341 |
newIndex range from 0 (inserts a |
|
4340 | newIndex range from 0 (inserts a row at the left) to \a rowCount (appends a row at the right). | |
4342 | right). |
|
|||
4343 |
|
4341 | |||
4344 | \see insertRow |
|
4342 | \see insertRow | |
4345 | */ |
|
4343 | */ | |
@@ -4413,9 +4411,7 void QCPLayoutGrid::indexToRowCol(int index, int &row, int &column) const | |||||
4413 | { |
|
4411 | { | |
4414 | row = -1; |
|
4412 | row = -1; | |
4415 | column = -1; |
|
4413 | column = -1; | |
4416 | const int nCols = columnCount(); |
|
4414 | if (columnCount() == 0 || rowCount() == 0) | |
4417 | const int nRows = rowCount(); |
|
|||
4418 | if (nCols == 0 || nRows == 0) |
|
|||
4419 | return; |
|
4415 | return; | |
4420 | if (index < 0 || index >= elementCount()) { |
|
4416 | if (index < 0 || index >= elementCount()) { | |
4421 | qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; |
|
4417 | qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; | |
@@ -4424,13 +4420,13 void QCPLayoutGrid::indexToRowCol(int index, int &row, int &column) const | |||||
4424 |
|
4420 | |||
4425 | switch (mFillOrder) { |
|
4421 | switch (mFillOrder) { | |
4426 | case foRowsFirst: { |
|
4422 | case foRowsFirst: { | |
4427 |
column = index / |
|
4423 | column = index / rowCount(); | |
4428 |
row = index % |
|
4424 | row = index % rowCount(); | |
4429 | break; |
|
4425 | break; | |
4430 | } |
|
4426 | } | |
4431 | case foColumnsFirst: { |
|
4427 | case foColumnsFirst: { | |
4432 |
row = index / |
|
4428 | row = index / columnCount(); | |
4433 |
column = index % |
|
4429 | column = index % columnCount(); | |
4434 | break; |
|
4430 | break; | |
4435 | } |
|
4431 | } | |
4436 | } |
|
4432 | } | |
@@ -4596,8 +4592,9 QSize QCPLayoutGrid::minimumSizeHint() const | |||||
4596 | result.rwidth() += minColWidths.at(i); |
|
4592 | result.rwidth() += minColWidths.at(i); | |
4597 | for (int i = 0; i < minRowHeights.size(); ++i) |
|
4593 | for (int i = 0; i < minRowHeights.size(); ++i) | |
4598 | result.rheight() += minRowHeights.at(i); |
|
4594 | result.rheight() += minRowHeights.at(i); | |
4599 | result.rwidth() += qMax(0, columnCount() - 1) * mColumnSpacing; |
|
4595 | result.rwidth() | |
4600 | result.rheight() += qMax(0, rowCount() - 1) * mRowSpacing; |
|
4596 | += qMax(0, columnCount() - 1) * mColumnSpacing + mMargins.left() + mMargins.right(); | |
|
4597 | result.rheight() += qMax(0, rowCount() - 1) * mRowSpacing + mMargins.top() + mMargins.bottom(); | |||
4601 | return result; |
|
4598 | return result; | |
4602 | } |
|
4599 | } | |
4603 |
|
4600 | |||
@@ -4612,8 +4609,9 QSize QCPLayoutGrid::maximumSizeHint() const | |||||
4612 | result.setWidth(qMin(result.width() + maxColWidths.at(i), QWIDGETSIZE_MAX)); |
|
4609 | result.setWidth(qMin(result.width() + maxColWidths.at(i), QWIDGETSIZE_MAX)); | |
4613 | for (int i = 0; i < maxRowHeights.size(); ++i) |
|
4610 | for (int i = 0; i < maxRowHeights.size(); ++i) | |
4614 | result.setHeight(qMin(result.height() + maxRowHeights.at(i), QWIDGETSIZE_MAX)); |
|
4611 | result.setHeight(qMin(result.height() + maxRowHeights.at(i), QWIDGETSIZE_MAX)); | |
4615 | result.rwidth() += qMax(0, columnCount() - 1) * mColumnSpacing; |
|
4612 | result.rwidth() | |
4616 | result.rheight() += qMax(0, rowCount() - 1) * mRowSpacing; |
|
4613 | += qMax(0, columnCount() - 1) * mColumnSpacing + mMargins.left() + mMargins.right(); | |
|
4614 | result.rheight() += qMax(0, rowCount() - 1) * mRowSpacing + mMargins.top() + mMargins.bottom(); | |||
4617 | return result; |
|
4615 | return result; | |
4618 | } |
|
4616 | } | |
4619 |
|
4617 | |||
@@ -4622,9 +4620,8 QSize QCPLayoutGrid::maximumSizeHint() const | |||||
4622 | Places the minimum column widths and row heights into \a minColWidths and \a minRowHeights |
|
4620 | Places the minimum column widths and row heights into \a minColWidths and \a minRowHeights | |
4623 | respectively. |
|
4621 | respectively. | |
4624 |
|
4622 | |||
4625 |
The minimum height of a row is the largest minimum height of any element |
|
4623 | The minimum height of a row is the largest minimum height of any element in that row. The minimum | |
4626 |
|
|
4624 | width of a column is the largest minimum width of any element in that column. | |
4627 | that column. |
|
|||
4628 |
|
4625 | |||
4629 | This is a helper function for \ref updateLayout. |
|
4626 | This is a helper function for \ref updateLayout. | |
4630 |
|
4627 | |||
@@ -4637,13 +4634,11 void QCPLayoutGrid::getMinimumRowColSizes(QVector<int> *minColWidths, | |||||
4637 | *minRowHeights = QVector<int>(rowCount(), 0); |
|
4634 | *minRowHeights = QVector<int>(rowCount(), 0); | |
4638 | for (int row = 0; row < rowCount(); ++row) { |
|
4635 | for (int row = 0; row < rowCount(); ++row) { | |
4639 | for (int col = 0; col < columnCount(); ++col) { |
|
4636 | for (int col = 0; col < columnCount(); ++col) { | |
4640 |
if ( |
|
4637 | if (mElements.at(row).at(col)) { | |
4641 | QSize minHint = el->minimumSizeHint(); |
|
4638 | QSize minHint = mElements.at(row).at(col)->minimumSizeHint(); | |
4642 | QSize min = el->minimumSize(); |
|
4639 | QSize min = mElements.at(row).at(col)->minimumSize(); | |
4643 | QSize final(min.width() > 0 ? min.width() : minHint.width(), |
|
4640 | QSize final(min.width() > 0 ? min.width() : minHint.width(), | |
4644 | min.height() > 0 ? min.height() : minHint.height()); |
|
4641 | min.height() > 0 ? min.height() : minHint.height()); | |
4645 | final += QSize(el->margins().left() + el->margins().right(), |
|
|||
4646 | el->margins().top() + el->margins().bottom()); |
|
|||
4647 | if (minColWidths->at(col) < final.width()) |
|
4642 | if (minColWidths->at(col) < final.width()) | |
4648 | (*minColWidths)[col] = final.width(); |
|
4643 | (*minColWidths)[col] = final.width(); | |
4649 | if (minRowHeights->at(row) < final.height()) |
|
4644 | if (minRowHeights->at(row) < final.height()) | |
@@ -4658,9 +4653,8 void QCPLayoutGrid::getMinimumRowColSizes(QVector<int> *minColWidths, | |||||
4658 | Places the maximum column widths and row heights into \a maxColWidths and \a maxRowHeights |
|
4653 | Places the maximum column widths and row heights into \a maxColWidths and \a maxRowHeights | |
4659 | respectively. |
|
4654 | respectively. | |
4660 |
|
4655 | |||
4661 |
The maximum height of a row is the smallest maximum height of any element |
|
4656 | The maximum height of a row is the smallest maximum height of any element in that row. The | |
4662 |
|
|
4657 | maximum width of a column is the smallest maximum width of any element in that column. | |
4663 | that column. |
|
|||
4664 |
|
4658 | |||
4665 | This is a helper function for \ref updateLayout. |
|
4659 | This is a helper function for \ref updateLayout. | |
4666 |
|
4660 | |||
@@ -4673,13 +4667,11 void QCPLayoutGrid::getMaximumRowColSizes(QVector<int> *maxColWidths, | |||||
4673 | *maxRowHeights = QVector<int>(rowCount(), QWIDGETSIZE_MAX); |
|
4667 | *maxRowHeights = QVector<int>(rowCount(), QWIDGETSIZE_MAX); | |
4674 | for (int row = 0; row < rowCount(); ++row) { |
|
4668 | for (int row = 0; row < rowCount(); ++row) { | |
4675 | for (int col = 0; col < columnCount(); ++col) { |
|
4669 | for (int col = 0; col < columnCount(); ++col) { | |
4676 |
if ( |
|
4670 | if (mElements.at(row).at(col)) { | |
4677 | QSize maxHint = el->maximumSizeHint(); |
|
4671 | QSize maxHint = mElements.at(row).at(col)->maximumSizeHint(); | |
4678 | QSize max = el->maximumSize(); |
|
4672 | QSize max = mElements.at(row).at(col)->maximumSize(); | |
4679 | QSize final(max.width() < QWIDGETSIZE_MAX ? max.width() : maxHint.width(), |
|
4673 | QSize final(max.width() < QWIDGETSIZE_MAX ? max.width() : maxHint.width(), | |
4680 | max.height() < QWIDGETSIZE_MAX ? max.height() : maxHint.height()); |
|
4674 | max.height() < QWIDGETSIZE_MAX ? max.height() : maxHint.height()); | |
4681 | final += QSize(el->margins().left() + el->margins().right(), |
|
|||
4682 | el->margins().top() + el->margins().bottom()); |
|
|||
4683 | if (maxColWidths->at(col) > final.width()) |
|
4675 | if (maxColWidths->at(col) > final.width()) | |
4684 | (*maxColWidths)[col] = final.width(); |
|
4676 | (*maxColWidths)[col] = final.width(); | |
4685 | if (maxRowHeights->at(row) > final.height()) |
|
4677 | if (maxRowHeights->at(row) > final.height()) | |
@@ -4828,25 +4820,22 void QCPLayoutInset::setInsetRect(int index, const QRectF &rect) | |||||
4828 | void QCPLayoutInset::updateLayout() |
|
4820 | void QCPLayoutInset::updateLayout() | |
4829 | { |
|
4821 | { | |
4830 | for (int i = 0; i < mElements.size(); ++i) { |
|
4822 | for (int i = 0; i < mElements.size(); ++i) { | |
4831 | QCPLayoutElement *el = mElements.at(i); |
|
|||
4832 | QRect insetRect; |
|
4823 | QRect insetRect; | |
4833 | QSize finalMinSize, finalMaxSize; |
|
4824 | QSize finalMinSize, finalMaxSize; | |
4834 |
QSize minSizeHint = |
|
4825 | QSize minSizeHint = mElements.at(i)->minimumSizeHint(); | |
4835 |
QSize maxSizeHint = |
|
4826 | QSize maxSizeHint = mElements.at(i)->maximumSizeHint(); | |
4836 |
finalMinSize.setWidth( |
|
4827 | finalMinSize.setWidth(mElements.at(i)->minimumSize().width() > 0 | |
4837 |
|
|
4828 | ? mElements.at(i)->minimumSize().width() | |
4838 | finalMinSize.setHeight(el->minimumSize().height() > 0 ? el->minimumSize().height() |
|
4829 | : minSizeHint.width()); | |
4839 | : minSizeHint.height()); |
|
4830 | finalMinSize.setHeight(mElements.at(i)->minimumSize().height() > 0 | |
4840 | finalMaxSize.setWidth(el->maximumSize().width() < QWIDGETSIZE_MAX |
|
4831 | ? mElements.at(i)->minimumSize().height() | |
4841 |
|
|
4832 | : minSizeHint.height()); | |
|
4833 | finalMaxSize.setWidth(mElements.at(i)->maximumSize().width() < QWIDGETSIZE_MAX | |||
|
4834 | ? mElements.at(i)->maximumSize().width() | |||
4842 | : maxSizeHint.width()); |
|
4835 | : maxSizeHint.width()); | |
4843 |
finalMaxSize.setHeight( |
|
4836 | finalMaxSize.setHeight(mElements.at(i)->maximumSize().height() < QWIDGETSIZE_MAX | |
4844 |
? |
|
4837 | ? mElements.at(i)->maximumSize().height() | |
4845 | : maxSizeHint.height()); |
|
4838 | : maxSizeHint.height()); | |
4846 | finalMinSize += QSize(el->margins().left() + el->margins().right(), |
|
|||
4847 | el->margins().top() + el->margins().bottom()); |
|
|||
4848 | finalMaxSize += QSize(el->margins().left() + el->margins().right(), |
|
|||
4849 | el->margins().top() + el->margins().bottom()); |
|
|||
4850 | if (mInsetPlacement.at(i) == ipFree) { |
|
4839 | if (mInsetPlacement.at(i) == ipFree) { | |
4851 | insetRect = QRect(rect().x() + rect().width() * mInsetRect.at(i).x(), |
|
4840 | insetRect = QRect(rect().x() + rect().width() * mInsetRect.at(i).x(), | |
4852 | rect().y() + rect().height() * mInsetRect.at(i).y(), |
|
4841 | rect().y() + rect().height() * mInsetRect.at(i).y(), | |
@@ -7161,8 +7150,8 QVector<double> QCPAxisTickerLog::createTickVector(double tickStep, const QCPRan | |||||
7161 | /* end of 'src/axis/axistickerlog.cpp' */ |
|
7150 | /* end of 'src/axis/axistickerlog.cpp' */ | |
7162 |
|
7151 | |||
7163 |
|
7152 | |||
7164 |
/* including file 'src/axis/axis.cpp', size 9 |
|
7153 | /* including file 'src/axis/axis.cpp', size 94458 */ | |
7165 | /* commit 0cc4d9f61f7bf45321a88fec89d909b020ffa26f 2017-08-14 00:43:29 +0200 */ |
|
7154 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
7166 |
|
7155 | |||
7167 |
|
7156 | |||
7168 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
7157 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
@@ -8654,11 +8643,11 double QCPAxis::coordToPixel(double value) const | |||||
8654 | } |
|
8643 | } | |
8655 | else // mScaleType == stLogarithmic |
|
8644 | else // mScaleType == stLogarithmic | |
8656 | { |
|
8645 | { | |
8657 |
if (value >= 0 |
|
8646 | if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it | |
8658 |
|
|
8647 | // outside visible range | |
8659 | return !mRangeReversed ? mAxisRect->right() + 200 : mAxisRect->left() - 200; |
|
8648 | return !mRangeReversed ? mAxisRect->right() + 200 : mAxisRect->left() - 200; | |
8660 |
else if (value <= 0 |
|
8649 | else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just | |
8661 |
|
|
8650 | // draw it outside visible range | |
8662 | return !mRangeReversed ? mAxisRect->left() - 200 : mAxisRect->right() + 200; |
|
8651 | return !mRangeReversed ? mAxisRect->left() - 200 : mAxisRect->right() + 200; | |
8663 | else { |
|
8652 | else { | |
8664 | if (!mRangeReversed) |
|
8653 | if (!mRangeReversed) | |
@@ -8684,11 +8673,11 double QCPAxis::coordToPixel(double value) const | |||||
8684 | } |
|
8673 | } | |
8685 | else // mScaleType == stLogarithmic |
|
8674 | else // mScaleType == stLogarithmic | |
8686 | { |
|
8675 | { | |
8687 |
if (value >= 0 |
|
8676 | if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it | |
8688 |
|
|
8677 | // outside visible range | |
8689 | return !mRangeReversed ? mAxisRect->top() - 200 : mAxisRect->bottom() + 200; |
|
8678 | return !mRangeReversed ? mAxisRect->top() - 200 : mAxisRect->bottom() + 200; | |
8690 |
else if (value <= 0 |
|
8679 | else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just | |
8691 |
|
|
8680 | // draw it outside visible range | |
8692 | return !mRangeReversed ? mAxisRect->bottom() + 200 : mAxisRect->top() - 200; |
|
8681 | return !mRangeReversed ? mAxisRect->bottom() + 200 : mAxisRect->top() - 200; | |
8693 | else { |
|
8682 | else { | |
8694 | if (!mRangeReversed) |
|
8683 | if (!mRangeReversed) | |
@@ -8879,132 +8868,6 void QCPAxis::deselectEvent(bool *selectionStateChanged) | |||||
8879 |
|
8868 | |||
8880 | /*! \internal |
|
8869 | /*! \internal | |
8881 |
|
8870 | |||
8882 | This mouse event reimplementation provides the functionality to let the user drag individual axes |
|
|||
8883 | exclusively, by startig the drag on top of the axis. |
|
|||
8884 |
|
||||
8885 | For the axis to accept this event and perform the single axis drag, the parent \ref QCPAxisRect |
|
|||
8886 | must be configured accordingly, i.e. it must allow range dragging in the orientation of this axis |
|
|||
8887 | (\ref QCPAxisRect::setRangeDrag) and this axis must be a draggable axis (\ref |
|
|||
8888 | QCPAxisRect::setRangeDragAxes) |
|
|||
8889 |
|
||||
8890 | \seebaseclassmethod |
|
|||
8891 |
|
||||
8892 | \note The dragging of possibly multiple axes at once by starting the drag anywhere in the axis |
|
|||
8893 | rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::mousePressEvent. |
|
|||
8894 | */ |
|
|||
8895 | void QCPAxis::mousePressEvent(QMouseEvent *event, const QVariant &details) |
|
|||
8896 | { |
|
|||
8897 | Q_UNUSED(details) |
|
|||
8898 | if (!mParentPlot->interactions().testFlag(QCP::iRangeDrag) |
|
|||
8899 | || !mAxisRect->rangeDrag().testFlag(orientation()) |
|
|||
8900 | || !mAxisRect->rangeDragAxes(orientation()).contains(this)) { |
|
|||
8901 | event->ignore(); |
|
|||
8902 | return; |
|
|||
8903 | } |
|
|||
8904 |
|
||||
8905 | if (event->buttons() & Qt::LeftButton) { |
|
|||
8906 | mDragging = true; |
|
|||
8907 | // initialize antialiasing backup in case we start dragging: |
|
|||
8908 | if (mParentPlot->noAntialiasingOnDrag()) { |
|
|||
8909 | mAADragBackup = mParentPlot->antialiasedElements(); |
|
|||
8910 | mNotAADragBackup = mParentPlot->notAntialiasedElements(); |
|
|||
8911 | } |
|
|||
8912 | // Mouse range dragging interaction: |
|
|||
8913 | if (mParentPlot->interactions().testFlag(QCP::iRangeDrag)) |
|
|||
8914 | mDragStartRange = mRange; |
|
|||
8915 | } |
|
|||
8916 | } |
|
|||
8917 |
|
||||
8918 | /*! \internal |
|
|||
8919 |
|
||||
8920 | This mouse event reimplementation provides the functionality to let the user drag individual axes |
|
|||
8921 | exclusively, by startig the drag on top of the axis. |
|
|||
8922 |
|
||||
8923 | \seebaseclassmethod |
|
|||
8924 |
|
||||
8925 | \note The dragging of possibly multiple axes at once by starting the drag anywhere in the axis |
|
|||
8926 | rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::mousePressEvent. |
|
|||
8927 |
|
||||
8928 | \see QCPAxis::mousePressEvent |
|
|||
8929 | */ |
|
|||
8930 | void QCPAxis::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) |
|
|||
8931 | { |
|
|||
8932 | if (mDragging) { |
|
|||
8933 | const double startPixel = orientation() == Qt::Horizontal ? startPos.x() : startPos.y(); |
|
|||
8934 | const double currentPixel |
|
|||
8935 | = orientation() == Qt::Horizontal ? event->pos().x() : event->pos().y(); |
|
|||
8936 | if (mScaleType == QCPAxis::stLinear) { |
|
|||
8937 | const double diff = pixelToCoord(startPixel) - pixelToCoord(currentPixel); |
|
|||
8938 | setRange(mDragStartRange.lower + diff, mDragStartRange.upper + diff); |
|
|||
8939 | } |
|
|||
8940 | else if (mScaleType == QCPAxis::stLogarithmic) { |
|
|||
8941 | const double diff = pixelToCoord(startPixel) / pixelToCoord(currentPixel); |
|
|||
8942 | setRange(mDragStartRange.lower * diff, mDragStartRange.upper * diff); |
|
|||
8943 | } |
|
|||
8944 |
|
||||
8945 | if (mParentPlot->noAntialiasingOnDrag()) |
|
|||
8946 | mParentPlot->setNotAntialiasedElements(QCP::aeAll); |
|
|||
8947 | mParentPlot->replot(QCustomPlot::rpQueuedReplot); |
|
|||
8948 | } |
|
|||
8949 | } |
|
|||
8950 |
|
||||
8951 | /*! \internal |
|
|||
8952 |
|
||||
8953 | This mouse event reimplementation provides the functionality to let the user drag individual axes |
|
|||
8954 | exclusively, by startig the drag on top of the axis. |
|
|||
8955 |
|
||||
8956 | \seebaseclassmethod |
|
|||
8957 |
|
||||
8958 | \note The dragging of possibly multiple axes at once by starting the drag anywhere in the axis |
|
|||
8959 | rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::mousePressEvent. |
|
|||
8960 |
|
||||
8961 | \see QCPAxis::mousePressEvent |
|
|||
8962 | */ |
|
|||
8963 | void QCPAxis::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) |
|
|||
8964 | { |
|
|||
8965 | Q_UNUSED(event) |
|
|||
8966 | Q_UNUSED(startPos) |
|
|||
8967 | mDragging = false; |
|
|||
8968 | if (mParentPlot->noAntialiasingOnDrag()) { |
|
|||
8969 | mParentPlot->setAntialiasedElements(mAADragBackup); |
|
|||
8970 | mParentPlot->setNotAntialiasedElements(mNotAADragBackup); |
|
|||
8971 | } |
|
|||
8972 | } |
|
|||
8973 |
|
||||
8974 | /*! \internal |
|
|||
8975 |
|
||||
8976 | This mouse event reimplementation provides the functionality to let the user zoom individual axes |
|
|||
8977 | exclusively, by performing the wheel event on top of the axis. |
|
|||
8978 |
|
||||
8979 | For the axis to accept this event and perform the single axis zoom, the parent \ref QCPAxisRect |
|
|||
8980 | must be configured accordingly, i.e. it must allow range zooming in the orientation of this axis |
|
|||
8981 | (\ref QCPAxisRect::setRangeZoom) and this axis must be a zoomable axis (\ref |
|
|||
8982 | QCPAxisRect::setRangeZoomAxes) |
|
|||
8983 |
|
||||
8984 | \seebaseclassmethod |
|
|||
8985 |
|
||||
8986 | \note The zooming of possibly multiple axes at once by performing the wheel event anywhere in the |
|
|||
8987 | axis rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::wheelEvent. |
|
|||
8988 | */ |
|
|||
8989 | void QCPAxis::wheelEvent(QWheelEvent *event) |
|
|||
8990 | { |
|
|||
8991 | // Mouse range zooming interaction: |
|
|||
8992 | if (!mParentPlot->interactions().testFlag(QCP::iRangeZoom) |
|
|||
8993 | || !mAxisRect->rangeZoom().testFlag(orientation()) |
|
|||
8994 | || !mAxisRect->rangeZoomAxes(orientation()).contains(this)) { |
|
|||
8995 | event->ignore(); |
|
|||
8996 | return; |
|
|||
8997 | } |
|
|||
8998 |
|
||||
8999 | const double wheelSteps = event->delta() / 120.0; // a single step delta is +/-120 usually |
|
|||
9000 | const double factor = qPow(mAxisRect->rangeZoomFactor(orientation()), wheelSteps); |
|
|||
9001 | scaleRange(factor, |
|
|||
9002 | pixelToCoord(orientation() == Qt::Horizontal ? event->pos().x() : event->pos().y())); |
|
|||
9003 | mParentPlot->replot(); |
|
|||
9004 | } |
|
|||
9005 |
|
||||
9006 | /*! \internal |
|
|||
9007 |
|
||||
9008 | A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter |
|
8871 | A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter | |
9009 | before drawing axis lines. |
|
8872 | before drawing axis lines. | |
9010 |
|
8873 | |||
@@ -9661,15 +9524,12 void QCPAxisPainterPrivate::placeTickLabel(QCPPainter *painter, double position, | |||||
9661 | cachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size() |
|
9524 | cachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size() | |
9662 | * mParentPlot->bufferDevicePixelRatio()); |
|
9525 | * mParentPlot->bufferDevicePixelRatio()); | |
9663 | #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED |
|
9526 | #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED | |
9664 | #ifdef QCP_DEVICEPIXELRATIO_FLOAT |
|
|||
9665 | cachedLabel->pixmap.setDevicePixelRatio(mParentPlot->devicePixelRatioF()); |
|
|||
9666 | #else |
|
|||
9667 | cachedLabel->pixmap.setDevicePixelRatio(mParentPlot->devicePixelRatio()); |
|
9527 | cachedLabel->pixmap.setDevicePixelRatio(mParentPlot->devicePixelRatio()); | |
9668 | #endif |
|
9528 | #endif | |
9669 | #endif |
|
|||
9670 | } |
|
9529 | } | |
9671 | else |
|
9530 | else | |
9672 | cachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size()); |
|
9531 | cachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size()); | |
|
9532 | cachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size()); | |||
9673 | cachedLabel->pixmap.fill(Qt::transparent); |
|
9533 | cachedLabel->pixmap.fill(Qt::transparent); | |
9674 | QCPPainter cachePainter(&cachedLabel->pixmap); |
|
9534 | QCPPainter cachePainter(&cachedLabel->pixmap); | |
9675 | cachePainter.setPen(painter->pen()); |
|
9535 | cachePainter.setPen(painter->pen()); | |
@@ -10034,8 +9894,8 void QCPAxisPainterPrivate::getMaxTickLabelSize(const QFont &font, const QString | |||||
10034 | /* end of 'src/axis/axis.cpp' */ |
|
9894 | /* end of 'src/axis/axis.cpp' */ | |
10035 |
|
9895 | |||
10036 |
|
9896 | |||
10037 |
/* including file 'src/scatterstyle.cpp', size 174 |
|
9897 | /* including file 'src/scatterstyle.cpp', size 17420 */ | |
10038 | /* commit 820d2282db70144c358c13433cd74b4175f9252b 2017-07-24 00:24:17 +0200 */ |
|
9898 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
10039 |
|
9899 | |||
10040 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
9900 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
10041 | //////////////////// QCPScatterStyle |
|
9901 | //////////////////// QCPScatterStyle | |
@@ -10205,8 +10065,8 QCPScatterStyle::QCPScatterStyle(const QPixmap &pixmap) | |||||
10205 |
|
10065 | |||
10206 | The custom shape line will be drawn with \a pen and filled with \a brush. The size has a slightly |
|
10066 | The custom shape line will be drawn with \a pen and filled with \a brush. The size has a slightly | |
10207 | different meaning than for built-in scatter points: The custom path will be drawn scaled by a |
|
10067 | different meaning than for built-in scatter points: The custom path will be drawn scaled by a | |
10208 |
factor of \a size/6.0. Since the default \a size is 6, the custom path will appear |
|
10068 | factor of \a size/6.0. Since the default \a size is 6, the custom path will appear at a its | |
10209 |
|
|
10069 | natural size by default. To double the size of the path for example, set \a size to 12. | |
10210 | */ |
|
10070 | */ | |
10211 | QCPScatterStyle::QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, |
|
10071 | QCPScatterStyle::QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, | |
10212 | const QBrush &brush, double size) |
|
10072 | const QBrush &brush, double size) | |
@@ -10393,9 +10253,10 void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const | |||||
10393 | break; |
|
10253 | break; | |
10394 | } |
|
10254 | } | |
10395 | case ssDiamond: { |
|
10255 | case ssDiamond: { | |
10396 | QPointF lineArray[4] |
|
10256 | painter->drawLine(QLineF(x - w, y, x, y - w)); | |
10397 | = {QPointF(x - w, y), QPointF(x, y - w), QPointF(x + w, y), QPointF(x, y + w)}; |
|
10257 | painter->drawLine(QLineF(x, y - w, x + w, y)); | |
10398 |
painter->draw |
|
10258 | painter->drawLine(QLineF(x + w, y, x, y + w)); | |
|
10259 | painter->drawLine(QLineF(x, y + w, x - w, y)); | |||
10399 | break; |
|
10260 | break; | |
10400 | } |
|
10261 | } | |
10401 | case ssStar: { |
|
10262 | case ssStar: { | |
@@ -10406,46 +10267,46 void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const | |||||
10406 | break; |
|
10267 | break; | |
10407 | } |
|
10268 | } | |
10408 | case ssTriangle: { |
|
10269 | case ssTriangle: { | |
10409 |
|
|
10270 | painter->drawLine(QLineF(x - w, y + 0.755 * w, x + w, y + 0.755 * w)); | |
10410 | QPointF(x, y - 0.977 * w)}; |
|
10271 | painter->drawLine(QLineF(x + w, y + 0.755 * w, x, y - 0.977 * w)); | |
10411 | painter->drawPolygon(lineArray, 3); |
|
10272 | painter->drawLine(QLineF(x, y - 0.977 * w, x - w, y + 0.755 * w)); | |
10412 | break; |
|
10273 | break; | |
10413 | } |
|
10274 | } | |
10414 | case ssTriangleInverted: { |
|
10275 | case ssTriangleInverted: { | |
10415 |
|
|
10276 | painter->drawLine(QLineF(x - w, y - 0.755 * w, x + w, y - 0.755 * w)); | |
10416 | QPointF(x, y + 0.977 * w)}; |
|
10277 | painter->drawLine(QLineF(x + w, y - 0.755 * w, x, y + 0.977 * w)); | |
10417 | painter->drawPolygon(lineArray, 3); |
|
10278 | painter->drawLine(QLineF(x, y + 0.977 * w, x - w, y - 0.755 * w)); | |
10418 | break; |
|
10279 | break; | |
10419 | } |
|
10280 | } | |
10420 | case ssCrossSquare: { |
|
10281 | case ssCrossSquare: { | |
10421 | painter->drawRect(QRectF(x - w, y - w, mSize, mSize)); |
|
|||
10422 | painter->drawLine(QLineF(x - w, y - w, x + w * 0.95, y + w * 0.95)); |
|
10282 | painter->drawLine(QLineF(x - w, y - w, x + w * 0.95, y + w * 0.95)); | |
10423 | painter->drawLine(QLineF(x - w, y + w * 0.95, x + w * 0.95, y - w)); |
|
10283 | painter->drawLine(QLineF(x - w, y + w * 0.95, x + w * 0.95, y - w)); | |
|
10284 | painter->drawRect(QRectF(x - w, y - w, mSize, mSize)); | |||
10424 | break; |
|
10285 | break; | |
10425 | } |
|
10286 | } | |
10426 | case ssPlusSquare: { |
|
10287 | case ssPlusSquare: { | |
10427 | painter->drawRect(QRectF(x - w, y - w, mSize, mSize)); |
|
|||
10428 | painter->drawLine(QLineF(x - w, y, x + w * 0.95, y)); |
|
10288 | painter->drawLine(QLineF(x - w, y, x + w * 0.95, y)); | |
10429 | painter->drawLine(QLineF(x, y + w, x, y - w)); |
|
10289 | painter->drawLine(QLineF(x, y + w, x, y - w)); | |
|
10290 | painter->drawRect(QRectF(x - w, y - w, mSize, mSize)); | |||
10430 | break; |
|
10291 | break; | |
10431 | } |
|
10292 | } | |
10432 | case ssCrossCircle: { |
|
10293 | case ssCrossCircle: { | |
10433 | painter->drawEllipse(QPointF(x, y), w, w); |
|
|||
10434 | painter->drawLine(QLineF(x - w * 0.707, y - w * 0.707, x + w * 0.670, y + w * 0.670)); |
|
10294 | painter->drawLine(QLineF(x - w * 0.707, y - w * 0.707, x + w * 0.670, y + w * 0.670)); | |
10435 | painter->drawLine(QLineF(x - w * 0.707, y + w * 0.670, x + w * 0.670, y - w * 0.707)); |
|
10295 | painter->drawLine(QLineF(x - w * 0.707, y + w * 0.670, x + w * 0.670, y - w * 0.707)); | |
|
10296 | painter->drawEllipse(QPointF(x, y), w, w); | |||
10436 | break; |
|
10297 | break; | |
10437 | } |
|
10298 | } | |
10438 | case ssPlusCircle: { |
|
10299 | case ssPlusCircle: { | |
10439 | painter->drawEllipse(QPointF(x, y), w, w); |
|
|||
10440 | painter->drawLine(QLineF(x - w, y, x + w, y)); |
|
10300 | painter->drawLine(QLineF(x - w, y, x + w, y)); | |
10441 | painter->drawLine(QLineF(x, y + w, x, y - w)); |
|
10301 | painter->drawLine(QLineF(x, y + w, x, y - w)); | |
|
10302 | painter->drawEllipse(QPointF(x, y), w, w); | |||
10442 | break; |
|
10303 | break; | |
10443 | } |
|
10304 | } | |
10444 | case ssPeace: { |
|
10305 | case ssPeace: { | |
10445 | painter->drawEllipse(QPointF(x, y), w, w); |
|
|||
10446 | painter->drawLine(QLineF(x, y - w, x, y + w)); |
|
10306 | painter->drawLine(QLineF(x, y - w, x, y + w)); | |
10447 | painter->drawLine(QLineF(x, y, x - w * 0.707, y + w * 0.707)); |
|
10307 | painter->drawLine(QLineF(x, y, x - w * 0.707, y + w * 0.707)); | |
10448 | painter->drawLine(QLineF(x, y, x + w * 0.707, y + w * 0.707)); |
|
10308 | painter->drawLine(QLineF(x, y, x + w * 0.707, y + w * 0.707)); | |
|
10309 | painter->drawEllipse(QPointF(x, y), w, w); | |||
10449 | break; |
|
10310 | break; | |
10450 | } |
|
10311 | } | |
10451 | case ssPixmap: { |
|
10312 | case ssPixmap: { | |
@@ -10476,8 +10337,8 void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const | |||||
10476 |
|
10337 | |||
10477 | // amalgamation: add datacontainer.cpp |
|
10338 | // amalgamation: add datacontainer.cpp | |
10478 |
|
10339 | |||
10479 |
/* including file 'src/plottable.cpp', size 388 |
|
10340 | /* including file 'src/plottable.cpp', size 38861 */ | |
10480 | /* commit b0bed12626f942821097f43091126b6fb7163122 2017-08-13 17:17:33 +0200 */ |
|
10341 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
10481 |
|
10342 | |||
10482 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
10343 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
10483 | //////////////////// QCPSelectionDecorator |
|
10344 | //////////////////// QCPSelectionDecorator | |
@@ -10515,8 +10376,8 void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const | |||||
10515 | QCPSelectionDecorator::QCPSelectionDecorator() |
|
10376 | QCPSelectionDecorator::QCPSelectionDecorator() | |
10516 | : mPen(QColor(80, 80, 255), 2.5), |
|
10377 | : mPen(QColor(80, 80, 255), 2.5), | |
10517 | mBrush(Qt::NoBrush), |
|
10378 | mBrush(Qt::NoBrush), | |
10518 | mScatterStyle(), |
|
10379 | mScatterStyle(QCPScatterStyle::ssNone, QPen(Qt::blue, 2), Qt::NoBrush, 6.0), | |
10519 |
mUsedScatterProperties(QCPScatterStyle::sp |
|
10380 | mUsedScatterProperties(QCPScatterStyle::spPen), | |
10520 | mPlottable(0) |
|
10381 | mPlottable(0) | |
10521 | { |
|
10382 | { | |
10522 | } |
|
10383 | } | |
@@ -10559,8 +10420,6 void QCPSelectionDecorator::setScatterStyle(const QCPScatterStyle &scatterStyle, | |||||
10559 | Use this method to define which properties of the scatter style (set via \ref setScatterStyle) |
|
10420 | Use this method to define which properties of the scatter style (set via \ref setScatterStyle) | |
10560 | will be used for selected data segments. All properties of the scatter style that are not |
|
10421 | will be used for selected data segments. All properties of the scatter style that are not | |
10561 | specified in \a properties will remain as specified in the plottable's original scatter style. |
|
10422 | specified in \a properties will remain as specified in the plottable's original scatter style. | |
10562 |
|
||||
10563 | \see QCPScatterStyle::ScatterProperty |
|
|||
10564 | */ |
|
10423 | */ | |
10565 | void QCPSelectionDecorator::setUsedScatterProperties( |
|
10424 | void QCPSelectionDecorator::setUsedScatterProperties( | |
10566 | const QCPScatterStyle::ScatterProperties &properties) |
|
10425 | const QCPScatterStyle::ScatterProperties &properties) | |
@@ -12765,8 +12624,8 QCP::Interaction QCPAbstractItem::selectionCategory() const | |||||
12765 | /* end of 'src/item.cpp' */ |
|
12624 | /* end of 'src/item.cpp' */ | |
12766 |
|
12625 | |||
12767 |
|
12626 | |||
12768 |
/* including file 'src/core.cpp', size 12 |
|
12627 | /* including file 'src/core.cpp', size 124243 */ | |
12769 | /* commit 9ede7553208db59867d1ea9f1988cd90e3c7ffed 2017-08-13 17:25:24 +0200 */ |
|
12628 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
12770 |
|
12629 | |||
12771 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
12630 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
12772 | //////////////////// QCustomPlot |
|
12631 | //////////////////// QCustomPlot | |
@@ -13110,7 +12969,6 QCustomPlot::QCustomPlot(QWidget *parent) | |||||
13110 | mOpenGl(false), |
|
12969 | mOpenGl(false), | |
13111 | mMouseHasMoved(false), |
|
12970 | mMouseHasMoved(false), | |
13112 | mMouseEventLayerable(0), |
|
12971 | mMouseEventLayerable(0), | |
13113 | mMouseSignalLayerable(0), |
|
|||
13114 | mReplotting(false), |
|
12972 | mReplotting(false), | |
13115 | mReplotQueued(false), |
|
12973 | mReplotQueued(false), | |
13116 | mOpenGlMultisamples(16), |
|
12974 | mOpenGlMultisamples(16), | |
@@ -13125,12 +12983,8 QCustomPlot::QCustomPlot(QWidget *parent) | |||||
13125 | currentLocale.setNumberOptions(QLocale::OmitGroupSeparator); |
|
12983 | currentLocale.setNumberOptions(QLocale::OmitGroupSeparator); | |
13126 | setLocale(currentLocale); |
|
12984 | setLocale(currentLocale); | |
13127 | #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED |
|
12985 | #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED | |
13128 | #ifdef QCP_DEVICEPIXELRATIO_FLOAT |
|
|||
13129 | setBufferDevicePixelRatio(QWidget::devicePixelRatioF()); |
|
|||
13130 | #else |
|
|||
13131 | setBufferDevicePixelRatio(QWidget::devicePixelRatio()); |
|
12986 | setBufferDevicePixelRatio(QWidget::devicePixelRatio()); | |
13132 | #endif |
|
12987 | #endif | |
13133 | #endif |
|
|||
13134 |
|
12988 | |||
13135 | mOpenGlAntialiasedElementsBackup = mAntialiasedElements; |
|
12989 | mOpenGlAntialiasedElementsBackup = mAntialiasedElements; | |
13136 | mOpenGlCacheLabelsBackup = mPlottingHints.testFlag(QCP::phCacheLabels); |
|
12990 | mOpenGlCacheLabelsBackup = mPlottingHints.testFlag(QCP::phCacheLabels); | |
@@ -13532,10 +13386,6 void QCustomPlot::setSelectionRect(QCPSelectionRect *selectionRect) | |||||
13532 | } |
|
13386 | } | |
13533 |
|
13387 | |||
13534 | /*! |
|
13388 | /*! | |
13535 | \warning This is still an experimental feature and its performance depends on the system that it |
|
|||
13536 | runs on. Having multiple QCustomPlot widgets in one application with enabled OpenGL rendering |
|
|||
13537 | might cause context conflicts on some systems. |
|
|||
13538 |
|
||||
13539 | This method allows to enable OpenGL plot rendering, for increased plotting performance of |
|
13389 | This method allows to enable OpenGL plot rendering, for increased plotting performance of | |
13540 | graphically demanding plots (thick lines, translucent fills, etc.). |
|
13390 | graphically demanding plots (thick lines, translucent fills, etc.). | |
13541 |
|
13391 | |||
@@ -15084,20 +14934,12 void QCustomPlot::mousePressEvent(QMouseEvent *event) | |||||
15084 | mSelectionRect->startSelection(event); |
|
14934 | mSelectionRect->startSelection(event); | |
15085 | } |
|
14935 | } | |
15086 | else { |
|
14936 | else { | |
15087 |
// no selection rect interaction, |
|
14937 | // no selection rect interaction, so forward event to layerable under the cursor: | |
15088 | // layerable under the cursor: |
|
|||
15089 | QList<QVariant> details; |
|
14938 | QList<QVariant> details; | |
15090 | QList<QCPLayerable *> candidates = layerableListAt(mMousePressPos, false, &details); |
|
14939 | QList<QCPLayerable *> candidates = layerableListAt(mMousePressPos, false, &details); | |
15091 | if (!candidates.isEmpty()) { |
|
|||
15092 | mMouseSignalLayerable = candidates.first(); // candidate for signal emission is always |
|
|||
15093 | // topmost hit layerable (signal emitted in |
|
|||
15094 | // release event) |
|
|||
15095 | mMouseSignalLayerableDetails = details.first(); |
|
|||
15096 | } |
|
|||
15097 | // forward event to topmost candidate which accepts the event: |
|
|||
15098 | for (int i = 0; i < candidates.size(); ++i) { |
|
14940 | for (int i = 0; i < candidates.size(); ++i) { | |
15099 |
event->accept(); // default impl of QCPLayerable's mouse events |
|
14941 | event->accept(); // default impl of QCPLayerable's mouse events ignore the event, in | |
15100 |
// |
|
14942 | // that case propagate to next candidate in list | |
15101 | candidates.at(i)->mousePressEvent(event, details.at(i)); |
|
14943 | candidates.at(i)->mousePressEvent(event, details.at(i)); | |
15102 | if (event->isAccepted()) { |
|
14944 | if (event->isAccepted()) { | |
15103 | mMouseEventLayerable = candidates.at(i); |
|
14945 | mMouseEventLayerable = candidates.at(i); | |
@@ -15168,25 +15010,22 void QCustomPlot::mouseReleaseEvent(QMouseEvent *event) | |||||
15168 | processPointSelection(event); |
|
15010 | processPointSelection(event); | |
15169 |
|
15011 | |||
15170 | // emit specialized click signals of QCustomPlot instance: |
|
15012 | // emit specialized click signals of QCustomPlot instance: | |
15171 | if (QCPAbstractPlottable *ap |
|
15013 | if (QCPAbstractPlottable *ap = qobject_cast<QCPAbstractPlottable *>(mMouseEventLayerable)) { | |
15172 | = qobject_cast<QCPAbstractPlottable *>(mMouseSignalLayerable)) { |
|
|||
15173 | int dataIndex = 0; |
|
15014 | int dataIndex = 0; | |
15174 |
if (!mMouse |
|
15015 | if (!mMouseEventLayerableDetails.value<QCPDataSelection>().isEmpty()) | |
15175 | dataIndex |
|
15016 | dataIndex | |
15176 |
= mMouse |
|
15017 | = mMouseEventLayerableDetails.value<QCPDataSelection>().dataRange().begin(); | |
15177 | emit plottableClick(ap, dataIndex, event); |
|
15018 | emit plottableClick(ap, dataIndex, event); | |
15178 | } |
|
15019 | } | |
15179 |
else if (QCPAxis *ax = qobject_cast<QCPAxis *>(mMouse |
|
15020 | else if (QCPAxis *ax = qobject_cast<QCPAxis *>(mMouseEventLayerable)) | |
15180 |
emit axisClick(ax, mMouse |
|
15021 | emit axisClick(ax, mMouseEventLayerableDetails.value<QCPAxis::SelectablePart>(), event); | |
15181 | event); |
|
15022 | else if (QCPAbstractItem *ai = qobject_cast<QCPAbstractItem *>(mMouseEventLayerable)) | |
15182 | else if (QCPAbstractItem *ai = qobject_cast<QCPAbstractItem *>(mMouseSignalLayerable)) |
|
|||
15183 | emit itemClick(ai, event); |
|
15023 | emit itemClick(ai, event); | |
15184 |
else if (QCPLegend *lg = qobject_cast<QCPLegend *>(mMouse |
|
15024 | else if (QCPLegend *lg = qobject_cast<QCPLegend *>(mMouseEventLayerable)) | |
15185 | emit legendClick(lg, 0, event); |
|
15025 | emit legendClick(lg, 0, event); | |
15186 | else if (QCPAbstractLegendItem *li |
|
15026 | else if (QCPAbstractLegendItem *li | |
15187 |
= qobject_cast<QCPAbstractLegendItem *>(mMouse |
|
15027 | = qobject_cast<QCPAbstractLegendItem *>(mMouseEventLayerable)) | |
15188 | emit legendClick(li->parentLegend(), li, event); |
|
15028 | emit legendClick(li->parentLegend(), li, event); | |
15189 | mMouseSignalLayerable = 0; |
|
|||
15190 | } |
|
15029 | } | |
15191 |
|
15030 | |||
15192 | if (mSelectionRect && mSelectionRect->isActive()) // Note: if a click was detected above, the |
|
15031 | if (mSelectionRect && mSelectionRect->isActive()) // Note: if a click was detected above, the | |
@@ -16958,8 +16797,8 QCPSelectionDecoratorBracket::getPixelCoordinates(const QCPPlottableInterface1D | |||||
16958 | /* end of 'src/selectiondecorator-bracket.cpp' */ |
|
16797 | /* end of 'src/selectiondecorator-bracket.cpp' */ | |
16959 |
|
16798 | |||
16960 |
|
16799 | |||
16961 |
/* including file 'src/layoutelements/layoutelement-axisrect.cpp', size 475 |
|
16800 | /* including file 'src/layoutelements/layoutelement-axisrect.cpp', size 47509 */ | |
16962 | /* commit 77ba168312f935543fc31d1ae9b4cdcf34aae4f9 2017-08-13 18:29:48 +0200 */ |
|
16801 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
16963 |
|
16802 | |||
16964 |
|
16803 | |||
16965 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
16804 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
@@ -17213,7 +17052,7 QList<QCPAxis *> QCPAxisRect::axes() const | |||||
17213 | new QCPAxis instance is created internally. QCustomPlot owns the returned axis, so if you want to |
|
17052 | new QCPAxis instance is created internally. QCustomPlot owns the returned axis, so if you want to | |
17214 | remove an axis, use \ref removeAxis instead of deleting it manually. |
|
17053 | remove an axis, use \ref removeAxis instead of deleting it manually. | |
17215 |
|
17054 | |||
17216 |
You may inject QCPAxis instances (or sub |
|
17055 | You may inject QCPAxis instances (or sublasses of QCPAxis) by setting \a axis to an axis that was | |
17217 | previously created outside QCustomPlot. It is important to note that QCustomPlot takes ownership |
|
17056 | previously created outside QCustomPlot. It is important to note that QCustomPlot takes ownership | |
17218 | of the axis, so you may not delete it afterwards. Further, the \a axis must have been created |
|
17057 | of the axis, so you may not delete it afterwards. Further, the \a axis must have been created | |
17219 | with this axis rect as parent and with the same axis type as specified in \a type. If this is not |
|
17058 | with this axis rect as parent and with the same axis type as specified in \a type. If this is not | |
@@ -17326,12 +17165,6 bool QCPAxisRect::removeAxis(QCPAxis *axis) | |||||
17326 | while (it.hasNext()) { |
|
17165 | while (it.hasNext()) { | |
17327 | it.next(); |
|
17166 | it.next(); | |
17328 | if (it.value().contains(axis)) { |
|
17167 | if (it.value().contains(axis)) { | |
17329 | if (it.value().first() == axis && it.value().size() > 1) // if removing first axis, |
|
|||
17330 | // transfer axis offset to the |
|
|||
17331 | // new first axis (which at |
|
|||
17332 | // this point is the second |
|
|||
17333 | // axis, if it exists) |
|
|||
17334 | it.value()[1]->setOffset(axis->offset()); |
|
|||
17335 | mAxes[it.key()].removeOne(axis); |
|
17168 | mAxes[it.key()].removeOne(axis); | |
17336 | if (qobject_cast<QCustomPlot *>(parentPlot())) // make sure this isn't called from |
|
17169 | if (qobject_cast<QCustomPlot *>(parentPlot())) // make sure this isn't called from | |
17337 | // QObject dtor when QCustomPlot is |
|
17170 | // QObject dtor when QCustomPlot is | |
@@ -18101,6 +17934,9 void QCPAxisRect::layoutChanged() | |||||
18101 | void QCPAxisRect::mousePressEvent(QMouseEvent *event, const QVariant &details) |
|
17934 | void QCPAxisRect::mousePressEvent(QMouseEvent *event, const QVariant &details) | |
18102 | { |
|
17935 | { | |
18103 | Q_UNUSED(details) |
|
17936 | Q_UNUSED(details) | |
|
17937 | mDragStart = event->pos(); // need this even when not LeftButton is pressed, to determine in | |||
|
17938 | // releaseEvent whether it was a full click (no position change | |||
|
17939 | // between press and release) | |||
18104 | if (event->buttons() & Qt::LeftButton) { |
|
17940 | if (event->buttons() & Qt::LeftButton) { | |
18105 | mDragging = true; |
|
17941 | mDragging = true; | |
18106 | // initialize antialiasing backup in case we start dragging: |
|
17942 | // initialize antialiasing backup in case we start dragging: | |
@@ -18146,13 +17982,13 void QCPAxisRect::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) | |||||
18146 | break; |
|
17982 | break; | |
18147 | if (ax->mScaleType == QCPAxis::stLinear) { |
|
17983 | if (ax->mScaleType == QCPAxis::stLinear) { | |
18148 | double diff |
|
17984 | double diff | |
18149 |
= ax->pixelToCoord( |
|
17985 | = ax->pixelToCoord(mDragStart.x()) - ax->pixelToCoord(event->pos().x()); | |
18150 | ax->setRange(mDragStartHorzRange.at(i).lower + diff, |
|
17986 | ax->setRange(mDragStartHorzRange.at(i).lower + diff, | |
18151 | mDragStartHorzRange.at(i).upper + diff); |
|
17987 | mDragStartHorzRange.at(i).upper + diff); | |
18152 | } |
|
17988 | } | |
18153 | else if (ax->mScaleType == QCPAxis::stLogarithmic) { |
|
17989 | else if (ax->mScaleType == QCPAxis::stLogarithmic) { | |
18154 | double diff |
|
17990 | double diff | |
18155 |
= ax->pixelToCoord( |
|
17991 | = ax->pixelToCoord(mDragStart.x()) / ax->pixelToCoord(event->pos().x()); | |
18156 | ax->setRange(mDragStartHorzRange.at(i).lower * diff, |
|
17992 | ax->setRange(mDragStartHorzRange.at(i).lower * diff, | |
18157 | mDragStartHorzRange.at(i).upper * diff); |
|
17993 | mDragStartHorzRange.at(i).upper * diff); | |
18158 | } |
|
17994 | } | |
@@ -18168,13 +18004,13 void QCPAxisRect::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) | |||||
18168 | break; |
|
18004 | break; | |
18169 | if (ax->mScaleType == QCPAxis::stLinear) { |
|
18005 | if (ax->mScaleType == QCPAxis::stLinear) { | |
18170 | double diff |
|
18006 | double diff | |
18171 |
= ax->pixelToCoord( |
|
18007 | = ax->pixelToCoord(mDragStart.y()) - ax->pixelToCoord(event->pos().y()); | |
18172 | ax->setRange(mDragStartVertRange.at(i).lower + diff, |
|
18008 | ax->setRange(mDragStartVertRange.at(i).lower + diff, | |
18173 | mDragStartVertRange.at(i).upper + diff); |
|
18009 | mDragStartVertRange.at(i).upper + diff); | |
18174 | } |
|
18010 | } | |
18175 | else if (ax->mScaleType == QCPAxis::stLogarithmic) { |
|
18011 | else if (ax->mScaleType == QCPAxis::stLogarithmic) { | |
18176 | double diff |
|
18012 | double diff | |
18177 |
= ax->pixelToCoord( |
|
18013 | = ax->pixelToCoord(mDragStart.y()) / ax->pixelToCoord(event->pos().y()); | |
18178 | ax->setRange(mDragStartVertRange.at(i).lower * diff, |
|
18014 | ax->setRange(mDragStartVertRange.at(i).lower * diff, | |
18179 | mDragStartVertRange.at(i).upper * diff); |
|
18015 | mDragStartVertRange.at(i).upper * diff); | |
18180 | } |
|
18016 | } | |
@@ -18185,7 +18021,7 void QCPAxisRect::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) | |||||
18185 | { |
|
18021 | { | |
18186 | if (mParentPlot->noAntialiasingOnDrag()) |
|
18022 | if (mParentPlot->noAntialiasingOnDrag()) | |
18187 | mParentPlot->setNotAntialiasedElements(QCP::aeAll); |
|
18023 | mParentPlot->setNotAntialiasedElements(QCP::aeAll); | |
18188 |
mParentPlot->replot( |
|
18024 | mParentPlot->replot(); | |
18189 | } |
|
18025 | } | |
18190 | } |
|
18026 | } | |
18191 | } |
|
18027 | } | |
@@ -18246,8 +18082,8 void QCPAxisRect::wheelEvent(QWheelEvent *event) | |||||
18246 | /* end of 'src/layoutelements/layoutelement-axisrect.cpp' */ |
|
18082 | /* end of 'src/layoutelements/layoutelement-axisrect.cpp' */ | |
18247 |
|
18083 | |||
18248 |
|
18084 | |||
18249 |
/* including file 'src/layoutelements/layoutelement-legend.cpp', size 309 |
|
18085 | /* including file 'src/layoutelements/layoutelement-legend.cpp', size 30933 */ | |
18250 | /* commit 305808813c9c6451dca8399c2fc66d68ebd24b5e 2017-08-15 23:03:07 +0200 */ |
|
18086 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
18251 |
|
18087 | |||
18252 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
18088 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
18253 | //////////////////// QCPAbstractLegendItem |
|
18089 | //////////////////// QCPAbstractLegendItem | |
@@ -18450,7 +18286,9 void QCPAbstractLegendItem::deselectEvent(bool *selectionStateChanged) | |||||
18450 | QCPLegend::setIconBorderPen and \ref QCPLegend::setIconTextPadding. |
|
18286 | QCPLegend::setIconBorderPen and \ref QCPLegend::setIconTextPadding. | |
18451 |
|
18287 | |||
18452 | The function \ref QCPAbstractPlottable::addToLegend/\ref QCPAbstractPlottable::removeFromLegend |
|
18288 | The function \ref QCPAbstractPlottable::addToLegend/\ref QCPAbstractPlottable::removeFromLegend | |
18453 | creates/removes legend items of this type. |
|
18289 | creates/removes legend items of this type in the default implementation. However, these functions | |
|
18290 | may be reimplemented such that a different kind of legend item (e.g a direct subclass of | |||
|
18291 | QCPAbstractLegendItem) is used for that plottable. | |||
18454 |
|
18292 | |||
18455 | Since QCPLegend is based on QCPLayoutGrid, a legend item itself is just a subclass of |
|
18293 | Since QCPLegend is based on QCPLayoutGrid, a legend item itself is just a subclass of | |
18456 | QCPLayoutElement. While it could be added to a legend (or any other layout) via the normal layout |
|
18294 | QCPLayoutElement. While it could be added to a legend (or any other layout) via the normal layout | |
@@ -18557,8 +18395,10 QSize QCPPlottableLegendItem::minimumSizeHint() const | |||||
18557 | QSize iconSize = mParentLegend->iconSize(); |
|
18395 | QSize iconSize = mParentLegend->iconSize(); | |
18558 | textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, |
|
18396 | textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, | |
18559 | mPlottable->name()); |
|
18397 | mPlottable->name()); | |
18560 |
result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width() |
|
18398 | result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width() | |
18561 | result.setHeight(qMax(textRect.height(), iconSize.height())); |
|
18399 | + mMargins.left() + mMargins.right()); | |
|
18400 | result.setHeight(qMax(textRect.height(), iconSize.height()) + mMargins.top() | |||
|
18401 | + mMargins.bottom()); | |||
18562 | return result; |
|
18402 | return result; | |
18563 | } |
|
18403 | } | |
18564 |
|
18404 | |||
@@ -18572,14 +18412,10 QSize QCPPlottableLegendItem::minimumSizeHint() const | |||||
18572 |
|
18412 | |||
18573 | A legend is a small box somewhere in the plot which lists plottables with their name and icon. |
|
18413 | A legend is a small box somewhere in the plot which lists plottables with their name and icon. | |
18574 |
|
18414 | |||
18575 |
|
|
18415 | Normally, the legend is populated by calling \ref QCPAbstractPlottable::addToLegend. The | |
18576 | plottable, for which a legend item shall be created. In the case of the main legend (\ref |
|
18416 | respective legend item can be removed with \ref QCPAbstractPlottable::removeFromLegend. However, | |
18577 | QCustomPlot::legend), simply adding plottables to the plot while \ref |
|
18417 | QCPLegend also offers an interface to add and manipulate legend items directly: \ref item, \ref | |
18578 | QCustomPlot::setAutoAddPlottableToLegend is set to true (the default) creates corresponding |
|
18418 | itemWithPlottable, \ref itemCount, \ref addItem, \ref removeItem, etc. | |
18579 | legend items. The legend item associated with a certain plottable can be removed with \ref |
|
|||
18580 | QCPAbstractPlottable::removeFromLegend. However, QCPLegend also offers an interface to add and |
|
|||
18581 | manipulate legend items directly: \ref item, \ref itemWithPlottable, \ref itemCount, \ref |
|
|||
18582 | addItem, \ref removeItem, etc. |
|
|||
18583 |
|
18419 | |||
18584 | Since \ref QCPLegend derives from \ref QCPLayoutGrid, it can be placed in any position a \ref |
|
18420 | Since \ref QCPLegend derives from \ref QCPLayoutGrid, it can be placed in any position a \ref | |
18585 | QCPLayoutElement may be positioned. The legend items are themselves \ref QCPLayoutElement |
|
18421 | QCPLayoutElement may be positioned. The legend items are themselves \ref QCPLayoutElement | |
@@ -19176,8 +19012,8 void QCPLegend::parentPlotInitialized(QCustomPlot *parentPlot) | |||||
19176 | /* end of 'src/layoutelements/layoutelement-legend.cpp' */ |
|
19012 | /* end of 'src/layoutelements/layoutelement-legend.cpp' */ | |
19177 |
|
19013 | |||
19178 |
|
19014 | |||
19179 |
/* including file 'src/layoutelements/layoutelement-textelement.cpp', size 12 |
|
19015 | /* including file 'src/layoutelements/layoutelement-textelement.cpp', size 12759 */ | |
19180 | /* commit a872eb91ec087561efd83dd9cb041a26ab95ce55 2017-07-31 00:21:41 +0200 */ |
|
19016 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
19181 |
|
19017 | |||
19182 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
19018 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
19183 | //////////////////// QCPTextElement |
|
19019 | //////////////////// QCPTextElement | |
@@ -19463,7 +19299,10 void QCPTextElement::draw(QCPPainter *painter) | |||||
19463 | QSize QCPTextElement::minimumSizeHint() const |
|
19299 | QSize QCPTextElement::minimumSizeHint() const | |
19464 | { |
|
19300 | { | |
19465 | QFontMetrics metrics(mFont); |
|
19301 | QFontMetrics metrics(mFont); | |
19466 |
|
|
19302 | QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size(); | |
|
19303 | result.rwidth() += mMargins.left() + mMargins.right(); | |||
|
19304 | result.rheight() += mMargins.top() + mMargins.bottom(); | |||
|
19305 | return result; | |||
19467 | } |
|
19306 | } | |
19468 |
|
19307 | |||
19469 | /* inherits documentation from base class */ |
|
19308 | /* inherits documentation from base class */ | |
@@ -19471,6 +19310,7 QSize QCPTextElement::maximumSizeHint() const | |||||
19471 | { |
|
19310 | { | |
19472 | QFontMetrics metrics(mFont); |
|
19311 | QFontMetrics metrics(mFont); | |
19473 | QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size(); |
|
19312 | QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size(); | |
|
19313 | result.rheight() += mMargins.top() + mMargins.bottom(); | |||
19474 | result.setWidth(QWIDGETSIZE_MAX); |
|
19314 | result.setWidth(QWIDGETSIZE_MAX); | |
19475 | return result; |
|
19315 | return result; | |
19476 | } |
|
19316 | } | |
@@ -20260,8 +20100,8 void QCPColorScaleAxisRectPrivate::axisSelectableChanged(QCPAxis::SelectablePart | |||||
20260 | /* end of 'src/layoutelements/layoutelement-colorscale.cpp' */ |
|
20100 | /* end of 'src/layoutelements/layoutelement-colorscale.cpp' */ | |
20261 |
|
20101 | |||
20262 |
|
20102 | |||
20263 |
/* including file 'src/plottables/plottable-graph.cpp', size 7 |
|
20103 | /* including file 'src/plottables/plottable-graph.cpp', size 72363 */ | |
20264 | /* commit 7e7381ef4f218e004d72a218820634fff0959d1b 2017-08-02 00:02:36 +0200 */ |
|
20104 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
20265 |
|
20105 | |||
20266 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
20106 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
20267 | //////////////////// QCPGraphData |
|
20107 | //////////////////// QCPGraphData | |
@@ -20809,12 +20649,6 void QCPGraph::getLines(QVector<QPointF> *lines, const QCPDataRange &dataRange) | |||||
20809 | if (mLineStyle != lsNone) |
|
20649 | if (mLineStyle != lsNone) | |
20810 | getOptimizedLineData(&lineData, begin, end); |
|
20650 | getOptimizedLineData(&lineData, begin, end); | |
20811 |
|
20651 | |||
20812 | if (mKeyAxis->rangeReversed() |
|
|||
20813 | != (mKeyAxis->orientation() == Qt::Vertical)) // make sure key pixels are sorted ascending |
|
|||
20814 | // in lineData (significantly simplifies |
|
|||
20815 | // following processing) |
|
|||
20816 | std::reverse(lineData.begin(), lineData.end()); |
|
|||
20817 |
|
||||
20818 | switch (mLineStyle) { |
|
20652 | switch (mLineStyle) { | |
20819 | case lsNone: |
|
20653 | case lsNone: | |
20820 | lines->clear(); |
|
20654 | lines->clear(); | |
@@ -20870,13 +20704,6 void QCPGraph::getScatters(QVector<QPointF> *scatters, const QCPDataRange &dataR | |||||
20870 |
|
20704 | |||
20871 | QVector<QCPGraphData> data; |
|
20705 | QVector<QCPGraphData> data; | |
20872 | getOptimizedScatterData(&data, begin, end); |
|
20706 | getOptimizedScatterData(&data, begin, end); | |
20873 |
|
||||
20874 | if (mKeyAxis->rangeReversed() |
|
|||
20875 | != (mKeyAxis->orientation() == Qt::Vertical)) // make sure key pixels are sorted ascending |
|
|||
20876 | // in data (significantly simplifies following |
|
|||
20877 | // processing) |
|
|||
20878 | std::reverse(data.begin(), data.end()); |
|
|||
20879 |
|
||||
20880 | scatters->resize(data.size()); |
|
20707 | scatters->resize(data.size()); | |
20881 | if (keyAxis->orientation() == Qt::Vertical) { |
|
20708 | if (keyAxis->orientation() == Qt::Vertical) { | |
20882 | for (int i = 0; i < data.size(); ++i) { |
|
20709 | for (int i = 0; i < data.size(); ++i) { | |
@@ -20917,6 +20744,8 QVector<QPointF> QCPGraph::dataToLines(const QVector<QCPGraphData> &data) const | |||||
20917 | return result; |
|
20744 | return result; | |
20918 | } |
|
20745 | } | |
20919 |
|
20746 | |||
|
20747 | result.reserve(data.size() + 2); // added 2 to reserve memory for lower/upper fill base points | |||
|
20748 | // that might be needed for fill | |||
20920 | result.resize(data.size()); |
|
20749 | result.resize(data.size()); | |
20921 |
|
20750 | |||
20922 | // transform data points to pixels: |
|
20751 | // transform data points to pixels: | |
@@ -20957,6 +20786,8 QVector<QPointF> QCPGraph::dataToStepLeftLines(const QVector<QCPGraphData> &data | |||||
20957 | return result; |
|
20786 | return result; | |
20958 | } |
|
20787 | } | |
20959 |
|
20788 | |||
|
20789 | result.reserve(data.size() * 2 + 2); // added 2 to reserve memory for lower/upper fill base | |||
|
20790 | // points that might be needed for fill | |||
20960 | result.resize(data.size() * 2); |
|
20791 | result.resize(data.size() * 2); | |
20961 |
|
20792 | |||
20962 | // calculate steps from data and transform to pixel coordinates: |
|
20793 | // calculate steps from data and transform to pixel coordinates: | |
@@ -21007,6 +20838,8 QVector<QPointF> QCPGraph::dataToStepRightLines(const QVector<QCPGraphData> &dat | |||||
21007 | return result; |
|
20838 | return result; | |
21008 | } |
|
20839 | } | |
21009 |
|
20840 | |||
|
20841 | result.reserve(data.size() * 2 + 2); // added 2 to reserve memory for lower/upper fill base | |||
|
20842 | // points that might be needed for fill | |||
21010 | result.resize(data.size() * 2); |
|
20843 | result.resize(data.size() * 2); | |
21011 |
|
20844 | |||
21012 | // calculate steps from data and transform to pixel coordinates: |
|
20845 | // calculate steps from data and transform to pixel coordinates: | |
@@ -21057,6 +20890,8 QVector<QPointF> QCPGraph::dataToStepCenterLines(const QVector<QCPGraphData> &da | |||||
21057 | return result; |
|
20890 | return result; | |
21058 | } |
|
20891 | } | |
21059 |
|
20892 | |||
|
20893 | result.reserve(data.size() * 2 + 2); // added 2 to reserve memory for lower/upper fill base | |||
|
20894 | // points that might be needed for fill | |||
21060 | result.resize(data.size() * 2); |
|
20895 | result.resize(data.size() * 2); | |
21061 |
|
20896 | |||
21062 | // calculate steps from data and transform to pixel coordinates: |
|
20897 | // calculate steps from data and transform to pixel coordinates: | |
@@ -21119,7 +20954,8 QVector<QPointF> QCPGraph::dataToImpulseLines(const QVector<QCPGraphData> &data) | |||||
21119 | return result; |
|
20954 | return result; | |
21120 | } |
|
20955 | } | |
21121 |
|
20956 | |||
21122 |
result.resize(data.size() |
|
20957 | result.resize(data.size() | |
|
20958 | * 2); // no need to reserve 2 extra points because impulse plot has no fill | |||
21123 |
|
20959 | |||
21124 | // transform data points to pixels: |
|
20960 | // transform data points to pixels: | |
21125 | if (keyAxis->orientation() == Qt::Vertical) { |
|
20961 | if (keyAxis->orientation() == Qt::Vertical) { | |
@@ -21148,16 +20984,15 QVector<QPointF> QCPGraph::dataToImpulseLines(const QVector<QCPGraphData> &data) | |||||
21148 |
|
20984 | |||
21149 | Draws the fill of the graph using the specified \a painter, with the currently set brush. |
|
20985 | Draws the fill of the graph using the specified \a painter, with the currently set brush. | |
21150 |
|
20986 | |||
21151 | Depending on whether a normal fill or a channel fill (\ref setChannelFillGraph) is needed, \ref |
|
20987 | \a lines contains the points of the graph line, in pixel coordinates. | |
21152 | getFillPolygon or \ref getChannelFillPolygon are used to find the according fill polygons. |
|
|||
21153 |
|
20988 | |||
21154 | In order to handle NaN Data points correctly (the fill needs to be split into disjoint areas), |
|
20989 | If the fill is a normal fill towards the zero-value-line, only the points in \a lines are | |
21155 | this method first determines a list of non-NaN segments with \ref getNonNanSegments, on which to |
|
20990 | required and two extra points at the zero-value-line, which are added by \ref addFillBasePoints | |
21156 | operate. In the channel fill case, \ref getOverlappingSegments is used to consolidate the non-NaN |
|
20991 | and removed by \ref removeFillBasePoints after the fill drawing is done. | |
21157 | segments of the two involved graphs, before passing the overlapping pairs to \ref |
|
|||
21158 | getChannelFillPolygon. |
|
|||
21159 |
|
20992 | |||
21160 | Pass the points of this graph's line as \a lines, in pixel coordinates. |
|
20993 | On the other hand if the fill is a channel fill between this QCPGraph and another QCPGraph (\a | |
|
20994 | mChannelFillGraph), the more complex polygon is calculated with the \ref getChannelFillPolygon | |||
|
20995 | function, and then drawn. | |||
21161 |
|
20996 | |||
21162 | \see drawLinePlot, drawImpulsePlot, drawScatterPlot |
|
20997 | \see drawLinePlot, drawImpulsePlot, drawScatterPlot | |
21163 | */ |
|
20998 | */ | |
@@ -21169,25 +21004,15 void QCPGraph::drawFill(QCPPainter *painter, QVector<QPointF> *lines) const | |||||
21169 | return; |
|
21004 | return; | |
21170 |
|
21005 | |||
21171 | applyFillAntialiasingHint(painter); |
|
21006 | applyFillAntialiasingHint(painter); | |
21172 | QVector<QCPDataRange> segments = getNonNanSegments(lines, keyAxis()->orientation()); |
|
|||
21173 | if (!mChannelFillGraph) { |
|
21007 | if (!mChannelFillGraph) { | |
21174 | // draw base fill under graph, fill goes all the way to the zero-value-line: |
|
21008 | // draw base fill under graph, fill goes all the way to the zero-value-line: | |
21175 | for (int i = 0; i < segments.size(); ++i) |
|
21009 | addFillBasePoints(lines); | |
21176 |
|
|
21010 | painter->drawPolygon(QPolygonF(*lines)); | |
|
21011 | removeFillBasePoints(lines); | |||
21177 | } |
|
21012 | } | |
21178 | else { |
|
21013 | else { | |
21179 | // draw fill between this graph and mChannelFillGraph: |
|
21014 | // draw channel fill between this graph and mChannelFillGraph: | |
21180 | QVector<QPointF> otherLines; |
|
21015 | painter->drawPolygon(getChannelFillPolygon(lines)); | |
21181 | mChannelFillGraph->getLines(&otherLines, QCPDataRange(0, mChannelFillGraph->dataCount())); |
|
|||
21182 | if (!otherLines.isEmpty()) { |
|
|||
21183 | QVector<QCPDataRange> otherSegments |
|
|||
21184 | = getNonNanSegments(&otherLines, mChannelFillGraph->keyAxis()->orientation()); |
|
|||
21185 | QVector<QPair<QCPDataRange, QCPDataRange> > segmentPairs |
|
|||
21186 | = getOverlappingSegments(segments, lines, otherSegments, &otherLines); |
|
|||
21187 | for (int i = 0; i < segmentPairs.size(); ++i) |
|
|||
21188 | painter->drawPolygon(getChannelFillPolygon(lines, segmentPairs.at(i).first, |
|
|||
21189 | &otherLines, segmentPairs.at(i).second)); |
|
|||
21190 | } |
|
|||
21191 | } |
|
21016 | } | |
21192 | } |
|
21017 | } | |
21193 |
|
21018 | |||
@@ -21380,8 +21205,12 void QCPGraph::getOptimizedLineData(QVector<QCPGraphData> *lineData, | |||||
21380 | else // don't use adaptive sampling algorithm, transfer points one-to-one from the data |
|
21205 | else // don't use adaptive sampling algorithm, transfer points one-to-one from the data | |
21381 | // container into the output |
|
21206 | // container into the output | |
21382 | { |
|
21207 | { | |
21383 | lineData->resize(dataCount); |
|
21208 | QCPGraphDataContainer::const_iterator it = begin; | |
21384 | std::copy(begin, end, lineData->begin()); |
|
21209 | lineData->reserve(dataCount + 2); // +2 for possible fill end points | |
|
21210 | while (it != end) { | |||
|
21211 | lineData->append(*it); | |||
|
21212 | ++it; | |||
|
21213 | } | |||
21385 | } |
|
21214 | } | |
21386 | } |
|
21215 | } | |
21387 |
|
21216 | |||
@@ -21650,177 +21479,151 void QCPGraph::getVisibleDataBounds(QCPGraphDataContainer::const_iterator &begin | |||||
21650 | } |
|
21479 | } | |
21651 | } |
|
21480 | } | |
21652 |
|
21481 | |||
21653 |
/*! |
|
21482 | /*! \internal | |
21654 |
|
21483 | |||
21655 | This method goes through the passed points in \a lineData and returns a list of the segments |
|
21484 | The line vector generated by e.g. \ref getLines describes only the line that connects the data | |
21656 | which don't contain NaN data points. |
|
21485 | points. If the graph needs to be filled, two additional points need to be added at the | |
|
21486 | value-zero-line in the lower and upper key positions of the graph. This function calculates these | |||
|
21487 | points and adds them to the end of \a lineData. Since the fill is typically drawn before the line | |||
|
21488 | stroke, these added points need to be removed again after the fill is done, with the | |||
|
21489 | removeFillBasePoints function. | |||
21657 |
|
21490 | |||
21658 | \a keyOrientation defines whether the \a x or \a y member of the passed QPointF is used to check |
|
21491 | The expanding of \a lines by two points will not cause unnecessary memory reallocations, because | |
21659 | for NaN. If \a keyOrientation is \c Qt::Horizontal, the \a y member is checked, if it is \c |
|
21492 | the data vector generation functions (e.g. \ref getLines) reserve two extra points when they | |
21660 | Qt::Vertical, the \a x member is checked. |
|
21493 | allocate memory for \a lines. | |
21661 |
|
21494 | |||
21662 | \see getOverlappingSegments, drawFill |
|
21495 | \see removeFillBasePoints, lowerFillBasePoint, upperFillBasePoint | |
21663 | */ |
|
21496 | */ | |
21664 | QVector<QCPDataRange> QCPGraph::getNonNanSegments(const QVector<QPointF> *lineData, |
|
21497 | void QCPGraph::addFillBasePoints(QVector<QPointF> *lines) const | |
21665 | Qt::Orientation keyOrientation) const |
|
|||
21666 | { |
|
21498 | { | |
21667 | QVector<QCPDataRange> result; |
|
21499 | if (!mKeyAxis) { | |
21668 | const int n = lineData->size(); |
|
21500 | qDebug() << Q_FUNC_INFO << "invalid key axis"; | |
21669 |
|
21501 | return; | ||
21670 | QCPDataRange currentSegment(-1, -1); |
|
21502 | } | |
21671 | int i = 0; |
|
21503 | if (!lines) { | |
|
21504 | qDebug() << Q_FUNC_INFO << "passed null as lineData"; | |||
|
21505 | return; | |||
|
21506 | } | |||
|
21507 | if (lines->isEmpty()) | |||
|
21508 | return; | |||
21672 |
|
21509 | |||
21673 | if (keyOrientation == Qt::Horizontal) { |
|
21510 | // append points that close the polygon fill at the key axis: | |
21674 | while (i < n) { |
|
21511 | if (mKeyAxis.data()->orientation() == Qt::Vertical) { | |
21675 | while (i < n && qIsNaN(lineData->at(i).y())) // seek next non-NaN data point |
|
21512 | *lines << upperFillBasePoint(lines->last().y()); | |
21676 | ++i; |
|
21513 | *lines << lowerFillBasePoint(lines->first().y()); | |
21677 | if (i == n) |
|
|||
21678 | break; |
|
|||
21679 | currentSegment.setBegin(i++); |
|
|||
21680 | while (i < n && !qIsNaN(lineData->at(i).y())) // seek next NaN data point or end of data |
|
|||
21681 | ++i; |
|
|||
21682 | currentSegment.setEnd(i++); |
|
|||
21683 | result.append(currentSegment); |
|
|||
21684 | } |
|
|||
21685 | } |
|
21514 | } | |
21686 | else // keyOrientation == Qt::Vertical |
|
21515 | else { | |
21687 | { |
|
21516 | *lines << upperFillBasePoint(lines->last().x()); | |
21688 | while (i < n) { |
|
21517 | *lines << lowerFillBasePoint(lines->first().x()); | |
21689 | while (i < n && qIsNaN(lineData->at(i).x())) // seek next non-NaN data point |
|
|||
21690 | ++i; |
|
|||
21691 | if (i == n) |
|
|||
21692 | break; |
|
|||
21693 | currentSegment.setBegin(i++); |
|
|||
21694 | while (i < n && !qIsNaN(lineData->at(i).x())) // seek next NaN data point or end of data |
|
|||
21695 | ++i; |
|
|||
21696 | currentSegment.setEnd(i++); |
|
|||
21697 | result.append(currentSegment); |
|
|||
21698 | } |
|
|||
21699 | } |
|
21518 | } | |
21700 | return result; |
|
|||
21701 | } |
|
21519 | } | |
21702 |
|
21520 | |||
21703 |
/*! |
|
21521 | /*! \internal | |
21704 |
|
||||
21705 | This method takes two segment lists (e.g. created by \ref getNonNanSegments) \a thisSegments and |
|
|||
21706 | \a otherSegments, and their associated point data \a thisData and \a otherData. |
|
|||
21707 |
|
||||
21708 | It returns all pairs of segments (the first from \a thisSegments, the second from \a |
|
|||
21709 | otherSegments), which overlap in plot coordinates. |
|
|||
21710 |
|
||||
21711 | This method is useful in the case of a channel fill between two graphs, when only those non-NaN |
|
|||
21712 | segments which actually overlap in their key coordinate shall be considered for drawing a channel |
|
|||
21713 | fill polygon. |
|
|||
21714 |
|
21522 | |||
21715 | It is assumed that the passed segments in \a thisSegments are ordered ascending by index, and |
|
21523 | removes the two points from \a lines that were added by \ref addFillBasePoints. | |
21716 | that the segments don't overlap themselves. The same is assumed for the segments in \a |
|
|||
21717 | otherSegments. This is fulfilled when the segments are obtained via \ref getNonNanSegments. |
|
|||
21718 |
|
21524 | |||
21719 | \see getNonNanSegments, segmentsIntersect, drawFill, getChannelFillPolygon |
|
21525 | \see addFillBasePoints, lowerFillBasePoint, upperFillBasePoint | |
21720 | */ |
|
21526 | */ | |
21721 | QVector<QPair<QCPDataRange, QCPDataRange> > QCPGraph::getOverlappingSegments( |
|
21527 | void QCPGraph::removeFillBasePoints(QVector<QPointF> *lines) const | |
21722 | QVector<QCPDataRange> thisSegments, const QVector<QPointF> *thisData, |
|
|||
21723 | QVector<QCPDataRange> otherSegments, const QVector<QPointF> *otherData) const |
|
|||
21724 | { |
|
21528 | { | |
21725 | QVector<QPair<QCPDataRange, QCPDataRange> > result; |
|
21529 | if (!lines) { | |
21726 | if (thisData->isEmpty() || otherData->isEmpty() || thisSegments.isEmpty() |
|
21530 | qDebug() << Q_FUNC_INFO << "passed null as lineData"; | |
21727 | || otherSegments.isEmpty()) |
|
21531 | return; | |
21728 | return result; |
|
|||
21729 |
|
||||
21730 | int thisIndex = 0; |
|
|||
21731 | int otherIndex = 0; |
|
|||
21732 | const bool verticalKey = mKeyAxis->orientation() == Qt::Vertical; |
|
|||
21733 | while (thisIndex < thisSegments.size() && otherIndex < otherSegments.size()) { |
|
|||
21734 | if (thisSegments.at(thisIndex).size() |
|
|||
21735 | < 2) // segments with fewer than two points won't have a fill anyhow |
|
|||
21736 | { |
|
|||
21737 | ++thisIndex; |
|
|||
21738 | continue; |
|
|||
21739 | } |
|
|||
21740 | if (otherSegments.at(otherIndex).size() |
|
|||
21741 | < 2) // segments with fewer than two points won't have a fill anyhow |
|
|||
21742 | { |
|
|||
21743 | ++otherIndex; |
|
|||
21744 | continue; |
|
|||
21745 | } |
|
|||
21746 | double thisLower, thisUpper, otherLower, otherUpper; |
|
|||
21747 | if (!verticalKey) { |
|
|||
21748 | thisLower = thisData->at(thisSegments.at(thisIndex).begin()).x(); |
|
|||
21749 | thisUpper = thisData->at(thisSegments.at(thisIndex).end() - 1).x(); |
|
|||
21750 | otherLower = otherData->at(otherSegments.at(otherIndex).begin()).x(); |
|
|||
21751 | otherUpper = otherData->at(otherSegments.at(otherIndex).end() - 1).x(); |
|
|||
21752 | } |
|
|||
21753 | else { |
|
|||
21754 | thisLower = thisData->at(thisSegments.at(thisIndex).begin()).y(); |
|
|||
21755 | thisUpper = thisData->at(thisSegments.at(thisIndex).end() - 1).y(); |
|
|||
21756 | otherLower = otherData->at(otherSegments.at(otherIndex).begin()).y(); |
|
|||
21757 | otherUpper = otherData->at(otherSegments.at(otherIndex).end() - 1).y(); |
|
|||
21758 | } |
|
|||
21759 |
|
||||
21760 | int bPrecedence; |
|
|||
21761 | if (segmentsIntersect(thisLower, thisUpper, otherLower, otherUpper, bPrecedence)) |
|
|||
21762 | result.append(QPair<QCPDataRange, QCPDataRange>(thisSegments.at(thisIndex), |
|
|||
21763 | otherSegments.at(otherIndex))); |
|
|||
21764 |
|
||||
21765 | if (bPrecedence <= 0) // otherSegment doesn't reach as far as thisSegment, so continue with |
|
|||
21766 | // next otherSegment, keeping current thisSegment |
|
|||
21767 | ++otherIndex; |
|
|||
21768 | else // otherSegment reaches further than thisSegment, so continue with next thisSegment, |
|
|||
21769 | // keeping current otherSegment |
|
|||
21770 | ++thisIndex; |
|
|||
21771 | } |
|
21532 | } | |
|
21533 | if (lines->isEmpty()) | |||
|
21534 | return; | |||
21772 |
|
21535 | |||
21773 | return result; |
|
21536 | lines->remove(lines->size() - 2, 2); | |
21774 | } |
|
21537 | } | |
21775 |
|
21538 | |||
21776 |
/*! |
|
21539 | /*! \internal | |
21777 |
|
||||
21778 | Returns whether the segments defined by the coordinates (aLower, aUpper) and (bLower, bUpper) |
|
|||
21779 | have overlap. |
|
|||
21780 |
|
21540 | |||
21781 | The output parameter \a bPrecedence indicates whether the \a b segment reaches farther than the |
|
21541 | called by \ref addFillBasePoints to conveniently assign the point which closes the fill polygon | |
21782 | \a a segment or not. If \a bPrecedence returns 1, segment \a b reaches the farthest to higher |
|
21542 | on the lower side of the zero-value-line parallel to the key axis. The logarithmic axis scale | |
21783 | coordinates (i.e. bUpper > aUpper). If it returns -1, segment \a a reaches the farthest. Only if |
|
21543 | case is a bit special, since the zero-value-line in pixel coordinates is in positive or negative | |
21784 | both segment's upper bounds are identical, 0 is returned as \a bPrecedence. |
|
21544 | infinity. So this case is handled separately by just closing the fill polygon on the axis which | |
|
21545 | lies in the direction towards the zero value. | |||
21785 |
|
21546 | |||
21786 | It is assumed that the lower bounds always have smaller or equal values than the upper bounds. |
|
21547 | \a lowerKey will be the the key (in pixels) of the returned point. Depending on whether the key | |
|
21548 | axis is horizontal or vertical, \a lowerKey will end up as the x or y value of the returned | |||
|
21549 | point, respectively. | |||
21787 |
|
21550 | |||
21788 | \see getOverlappingSegments |
|
21551 | \see upperFillBasePoint, addFillBasePoints | |
21789 | */ |
|
21552 | */ | |
21790 | bool QCPGraph::segmentsIntersect(double aLower, double aUpper, double bLower, double bUpper, |
|
21553 | QPointF QCPGraph::lowerFillBasePoint(double lowerKey) const | |
21791 | int &bPrecedence) const |
|
|||
21792 | { |
|
21554 | { | |
21793 | bPrecedence = 0; |
|
21555 | QCPAxis *keyAxis = mKeyAxis.data(); | |
21794 | if (aLower > bUpper) { |
|
21556 | QCPAxis *valueAxis = mValueAxis.data(); | |
21795 | bPrecedence = -1; |
|
21557 | if (!keyAxis || !valueAxis) { | |
21796 | return false; |
|
21558 | qDebug() << Q_FUNC_INFO << "invalid key or value axis"; | |
21797 | } |
|
21559 | return QPointF(); | |
21798 | else if (bLower > aUpper) { |
|
|||
21799 | bPrecedence = 1; |
|
|||
21800 | return false; |
|
|||
21801 | } |
|
21560 | } | |
21802 | else { |
|
|||
21803 | if (aUpper > bUpper) |
|
|||
21804 | bPrecedence = -1; |
|
|||
21805 | else if (aUpper < bUpper) |
|
|||
21806 | bPrecedence = 1; |
|
|||
21807 |
|
21561 | |||
21808 | return true; |
|
21562 | QPointF point; | |
|
21563 | if (valueAxis->scaleType() == QCPAxis::stLinear) { | |||
|
21564 | if (keyAxis->axisType() == QCPAxis::atLeft) { | |||
|
21565 | point.setX(valueAxis->coordToPixel(0)); | |||
|
21566 | point.setY(lowerKey); | |||
|
21567 | } | |||
|
21568 | else if (keyAxis->axisType() == QCPAxis::atRight) { | |||
|
21569 | point.setX(valueAxis->coordToPixel(0)); | |||
|
21570 | point.setY(lowerKey); | |||
|
21571 | } | |||
|
21572 | else if (keyAxis->axisType() == QCPAxis::atTop) { | |||
|
21573 | point.setX(lowerKey); | |||
|
21574 | point.setY(valueAxis->coordToPixel(0)); | |||
|
21575 | } | |||
|
21576 | else if (keyAxis->axisType() == QCPAxis::atBottom) { | |||
|
21577 | point.setX(lowerKey); | |||
|
21578 | point.setY(valueAxis->coordToPixel(0)); | |||
|
21579 | } | |||
21809 | } |
|
21580 | } | |
|
21581 | else // valueAxis->mScaleType == QCPAxis::stLogarithmic | |||
|
21582 | { | |||
|
21583 | // In logarithmic scaling we can't just draw to value zero so we just fill all the way | |||
|
21584 | // to the axis which is in the direction towards zero | |||
|
21585 | if (keyAxis->orientation() == Qt::Vertical) { | |||
|
21586 | if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) | |||
|
21587 | || (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is | |||
|
21588 | // negative, zero | |||
|
21589 | // is on opposite | |||
|
21590 | // side of key axis | |||
|
21591 | point.setX(keyAxis->axisRect()->right()); | |||
|
21592 | else | |||
|
21593 | point.setX(keyAxis->axisRect()->left()); | |||
|
21594 | point.setY(lowerKey); | |||
|
21595 | } | |||
|
21596 | else if (keyAxis->axisType() == QCPAxis::atTop | |||
|
21597 | || keyAxis->axisType() == QCPAxis::atBottom) { | |||
|
21598 | point.setX(lowerKey); | |||
|
21599 | if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) | |||
|
21600 | || (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is | |||
|
21601 | // negative, zero | |||
|
21602 | // is on opposite | |||
|
21603 | // side of key axis | |||
|
21604 | point.setY(keyAxis->axisRect()->top()); | |||
|
21605 | else | |||
|
21606 | point.setY(keyAxis->axisRect()->bottom()); | |||
|
21607 | } | |||
|
21608 | } | |||
|
21609 | return point; | |||
21810 | } |
|
21610 | } | |
21811 |
|
21611 | |||
21812 | /*! \internal |
|
21612 | /*! \internal | |
21813 |
|
21613 | |||
21814 | Returns the point which closes the fill polygon on the zero-value-line parallel to the key axis. |
|
21614 | called by \ref addFillBasePoints to conveniently assign the point which closes the fill | |
21815 | The logarithmic axis scale case is a bit special, since the zero-value-line in pixel coordinates |
|
21615 | polygon on the upper side of the zero-value-line parallel to the key axis. The logarithmic axis | |
21816 | is in positive or negative infinity. So this case is handled separately by just closing the fill |
|
21616 | scale case is a bit special, since the zero-value-line in pixel coordinates is in positive or | |
21817 | polygon on the axis which lies in the direction towards the zero value. |
|
21617 | negative infinity. So this case is handled separately by just closing the fill polygon on the | |
|
21618 | axis which lies in the direction towards the zero value. | |||
|
21619 | ||||
|
21620 | \a upperKey will be the the key (in pixels) of the returned point. Depending on whether the key | |||
|
21621 | axis is horizontal or vertical, \a upperKey will end up as the x or y value of the returned | |||
|
21622 | point, respectively. | |||
21818 |
|
21623 | |||
21819 | \a matchingDataPoint will provide the key (in pixels) of the returned point. Depending on whether |
|
21624 | \see lowerFillBasePoint, addFillBasePoints | |
21820 | the key axis of this graph is horizontal or vertical, \a matchingDataPoint will provide the x or |
|
|||
21821 | y value of the returned point, respectively. |
|
|||
21822 | */ |
|
21625 | */ | |
21823 |
QPointF QCPGraph:: |
|
21626 | QPointF QCPGraph::upperFillBasePoint(double upperKey) const | |
21824 | { |
|
21627 | { | |
21825 | QCPAxis *keyAxis = mKeyAxis.data(); |
|
21628 | QCPAxis *keyAxis = mKeyAxis.data(); | |
21826 | QCPAxis *valueAxis = mValueAxis.data(); |
|
21629 | QCPAxis *valueAxis = mValueAxis.data(); | |
@@ -21829,16 +21632,23 QPointF QCPGraph::getFillBasePoint(QPointF matchingDataPoint) const | |||||
21829 | return QPointF(); |
|
21632 | return QPointF(); | |
21830 | } |
|
21633 | } | |
21831 |
|
21634 | |||
21832 |
QPointF |
|
21635 | QPointF point; | |
21833 | if (valueAxis->scaleType() == QCPAxis::stLinear) { |
|
21636 | if (valueAxis->scaleType() == QCPAxis::stLinear) { | |
21834 |
if (keyAxis-> |
|
21637 | if (keyAxis->axisType() == QCPAxis::atLeft) { | |
21835 | result.setX(matchingDataPoint.x()); |
|
21638 | point.setX(valueAxis->coordToPixel(0)); | |
21836 | result.setY(valueAxis->coordToPixel(0)); |
|
21639 | point.setY(upperKey); | |
21837 | } |
|
21640 | } | |
21838 |
else |
|
21641 | else if (keyAxis->axisType() == QCPAxis::atRight) { | |
21839 | { |
|
21642 | point.setX(valueAxis->coordToPixel(0)); | |
21840 | result.setX(valueAxis->coordToPixel(0)); |
|
21643 | point.setY(upperKey); | |
21841 | result.setY(matchingDataPoint.y()); |
|
21644 | } | |
|
21645 | else if (keyAxis->axisType() == QCPAxis::atTop) { | |||
|
21646 | point.setX(upperKey); | |||
|
21647 | point.setY(valueAxis->coordToPixel(0)); | |||
|
21648 | } | |||
|
21649 | else if (keyAxis->axisType() == QCPAxis::atBottom) { | |||
|
21650 | point.setX(upperKey); | |||
|
21651 | point.setY(valueAxis->coordToPixel(0)); | |||
21842 | } |
|
21652 | } | |
21843 | } |
|
21653 | } | |
21844 | else // valueAxis->mScaleType == QCPAxis::stLogarithmic |
|
21654 | else // valueAxis->mScaleType == QCPAxis::stLogarithmic | |
@@ -21851,80 +21661,40 QPointF QCPGraph::getFillBasePoint(QPointF matchingDataPoint) const | |||||
21851 | // negative, zero |
|
21661 | // negative, zero | |
21852 | // is on opposite |
|
21662 | // is on opposite | |
21853 | // side of key axis |
|
21663 | // side of key axis | |
21854 |
|
|
21664 | point.setX(keyAxis->axisRect()->right()); | |
21855 | else |
|
21665 | else | |
21856 |
|
|
21666 | point.setX(keyAxis->axisRect()->left()); | |
21857 | result.setY(matchingDataPoint.y()); |
|
21667 | point.setY(upperKey); | |
21858 | } |
|
21668 | } | |
21859 | else if (keyAxis->axisType() == QCPAxis::atTop |
|
21669 | else if (keyAxis->axisType() == QCPAxis::atTop | |
21860 | || keyAxis->axisType() == QCPAxis::atBottom) { |
|
21670 | || keyAxis->axisType() == QCPAxis::atBottom) { | |
21861 | result.setX(matchingDataPoint.x()); |
|
21671 | point.setX(upperKey); | |
21862 | if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) |
|
21672 | if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) | |
21863 | || (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is |
|
21673 | || (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is | |
21864 | // negative, zero |
|
21674 | // negative, zero | |
21865 | // is on opposite |
|
21675 | // is on opposite | |
21866 | // side of key axis |
|
21676 | // side of key axis | |
21867 |
|
|
21677 | point.setY(keyAxis->axisRect()->top()); | |
21868 | else |
|
21678 | else | |
21869 |
|
|
21679 | point.setY(keyAxis->axisRect()->bottom()); | |
21870 | } |
|
21680 | } | |
21871 | } |
|
21681 | } | |
21872 |
return |
|
21682 | return point; | |
21873 | } |
|
21683 | } | |
21874 |
|
21684 | |||
21875 | /*! \internal |
|
21685 | /*! \internal | |
21876 |
|
21686 | |||
21877 |
|
|
21687 | Generates the polygon needed for drawing channel fills between this graph and the graph specified | |
21878 |
|
21688 | in \a mChannelFillGraph (see \ref setChannelFillGraph). The data points representing the line of | ||
21879 | Pass the graph's data points (in pixel coordinates) as \a lineData, and specify the \a segment |
|
21689 | this graph in pixel coordinates must be passed in \a lines, the corresponding points of the other | |
21880 | which shall be used for the fill. The collection of \a lineData points described by \a segment |
|
21690 | graph are generated by calling its \ref getLines method. | |
21881 | must not contain NaN data points (see \ref getNonNanSegments). |
|
|||
21882 |
|
21691 | |||
21883 | The returned fill polygon will be closed at the key axis (the zero-value line) for linear value |
|
21692 | This method may return an empty polygon if the key ranges of the two graphs have no overlap of if | |
21884 | axes. For logarithmic value axes the polygon will reach just beyond the corresponding axis rect |
|
21693 | they don't have the same orientation (e.g. one key axis vertical, the other horizontal). For | |
21885 | side (see \ref getFillBasePoint). |
|
21694 | increased performance (due to implicit sharing), it is recommended to keep the returned QPolygonF | |
21886 |
|
21695 | const. | ||
21887 | For increased performance (due to implicit sharing), keep the returned QPolygonF const. |
|
|||
21888 |
|
||||
21889 | \see drawFill, getNonNanSegments |
|
|||
21890 | */ |
|
21696 | */ | |
21891 |
const QPolygonF QCPGraph::getFillPolygon(const QVector<QPointF> *line |
|
21697 | const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *lines) const | |
21892 | QCPDataRange segment) const |
|
|||
21893 | { |
|
|||
21894 | if (segment.size() < 2) |
|
|||
21895 | return QPolygonF(); |
|
|||
21896 | QPolygonF result(segment.size() + 2); |
|
|||
21897 |
|
||||
21898 | result[0] = getFillBasePoint(lineData->at(segment.begin())); |
|
|||
21899 | std::copy(lineData->constBegin() + segment.begin(), lineData->constBegin() + segment.end(), |
|
|||
21900 | result.begin() + 1); |
|
|||
21901 | result[result.size() - 1] = getFillBasePoint(lineData->at(segment.end() - 1)); |
|
|||
21902 |
|
||||
21903 | return result; |
|
|||
21904 | } |
|
|||
21905 |
|
||||
21906 | /*! \internal |
|
|||
21907 |
|
||||
21908 | Returns the polygon needed for drawing (partial) channel fills between this graph and the graph |
|
|||
21909 | specified by \ref setChannelFillGraph. |
|
|||
21910 |
|
||||
21911 | The data points of this graph are passed as pixel coordinates via \a thisData, the data of the |
|
|||
21912 | other graph as \a otherData. The returned polygon will be calculated for the specified data |
|
|||
21913 | segments \a thisSegment and \a otherSegment, pertaining to the respective \a thisData and \a |
|
|||
21914 | otherData, respectively. |
|
|||
21915 |
|
||||
21916 | The passed \a thisSegment and \a otherSegment should correspond to the segment pairs returned by |
|
|||
21917 | \ref getOverlappingSegments, to make sure only segments that actually have key coordinate overlap |
|
|||
21918 | need to be processed here. |
|
|||
21919 |
|
||||
21920 | For increased performance due to implicit sharing, keep the returned QPolygonF const. |
|
|||
21921 |
|
||||
21922 | \see drawFill, getOverlappingSegments, getNonNanSegments |
|
|||
21923 | */ |
|
|||
21924 | const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *thisData, |
|
|||
21925 | QCPDataRange thisSegment, |
|
|||
21926 | const QVector<QPointF> *otherData, |
|
|||
21927 | QCPDataRange otherSegment) const |
|
|||
21928 | { |
|
21698 | { | |
21929 | if (!mChannelFillGraph) |
|
21699 | if (!mChannelFillGraph) | |
21930 | return QPolygonF(); |
|
21700 | return QPolygonF(); | |
@@ -21945,35 +21715,55 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *thisData | |||||
21945 | // fits, valueAxis will fit too, because it's always orthogonal to |
|
21715 | // fits, valueAxis will fit too, because it's always orthogonal to | |
21946 | // keyAxis) |
|
21716 | // keyAxis) | |
21947 |
|
21717 | |||
21948 |
if ( |
|
21718 | if (lines->isEmpty()) | |
|
21719 | return QPolygonF(); | |||
|
21720 | QVector<QPointF> otherData; | |||
|
21721 | mChannelFillGraph.data()->getLines(&otherData, | |||
|
21722 | QCPDataRange(0, mChannelFillGraph.data()->dataCount())); | |||
|
21723 | if (otherData.isEmpty()) | |||
21949 | return QPolygonF(); |
|
21724 | return QPolygonF(); | |
21950 |
QVector<QPointF> this |
|
21725 | QVector<QPointF> thisData; | |
21951 | QVector<QPointF> otherSegmentData(otherSegment.size()); |
|
21726 | thisData.reserve( | |
21952 | std::copy(thisData->constBegin() + thisSegment.begin(), |
|
21727 | lines->size() | |
21953 | thisData->constBegin() + thisSegment.end(), thisSegmentData.begin()); |
|
21728 | + otherData.size()); // because we will join both vectors at end of this function | |
21954 | std::copy(otherData->constBegin() + otherSegment.begin(), |
|
21729 | for (int i = 0; i < lines->size(); ++i) // don't use the vector<<(vector), it squeezes | |
21955 | otherData->constBegin() + otherSegment.end(), otherSegmentData.begin()); |
|
21730 | // internally, which ruins the performance tuning with | |
|
21731 | // reserve() | |||
|
21732 | thisData << lines->at(i); | |||
|
21733 | ||||
21956 | // pointers to be able to swap them, depending which data range needs cropping: |
|
21734 | // pointers to be able to swap them, depending which data range needs cropping: | |
21957 |
QVector<QPointF> *staticData = &this |
|
21735 | QVector<QPointF> *staticData = &thisData; | |
21958 |
QVector<QPointF> *croppedData = &other |
|
21736 | QVector<QPointF> *croppedData = &otherData; | |
21959 |
|
21737 | |||
21960 | // crop both vectors to ranges in which the keys overlap (which coord is key, depends on |
|
21738 | // crop both vectors to ranges in which the keys overlap (which coord is key, depends on | |
21961 | // axisType): |
|
21739 | // axisType): | |
21962 | if (keyAxis->orientation() == Qt::Horizontal) { |
|
21740 | if (keyAxis->orientation() == Qt::Horizontal) { | |
21963 | // x is key |
|
21741 | // x is key | |
|
21742 | // if an axis range is reversed, the data point keys will be descending. Reverse them, since | |||
|
21743 | // following algorithm assumes ascending keys: | |||
|
21744 | if (staticData->first().x() > staticData->last().x()) { | |||
|
21745 | int size = staticData->size(); | |||
|
21746 | for (int i = 0; i < size / 2; ++i) | |||
|
21747 | qSwap((*staticData)[i], (*staticData)[size - 1 - i]); | |||
|
21748 | } | |||
|
21749 | if (croppedData->first().x() > croppedData->last().x()) { | |||
|
21750 | int size = croppedData->size(); | |||
|
21751 | for (int i = 0; i < size / 2; ++i) | |||
|
21752 | qSwap((*croppedData)[i], (*croppedData)[size - 1 - i]); | |||
|
21753 | } | |||
21964 | // crop lower bound: |
|
21754 | // crop lower bound: | |
21965 | if (staticData->first().x() < croppedData->first().x()) // other one must be cropped |
|
21755 | if (staticData->first().x() < croppedData->first().x()) // other one must be cropped | |
21966 | qSwap(staticData, croppedData); |
|
21756 | qSwap(staticData, croppedData); | |
21967 |
|
|
21757 | int lowBound = findIndexBelowX(croppedData, staticData->first().x()); | |
21968 | if (lowBound == -1) |
|
21758 | if (lowBound == -1) | |
21969 | return QPolygonF(); // key ranges have no overlap |
|
21759 | return QPolygonF(); // key ranges have no overlap | |
21970 | croppedData->remove(0, lowBound); |
|
21760 | croppedData->remove(0, lowBound); | |
21971 |
// set lowest point of cropped data to fit exactly key position of first static data |
|
21761 | // set lowest point of cropped data to fit exactly key position of first static data | |
21972 | // via linear interpolation: |
|
21762 | // point via linear interpolation: | |
21973 | if (croppedData->size() < 2) |
|
21763 | if (croppedData->size() < 2) | |
21974 | return QPolygonF(); // need at least two points for interpolation |
|
21764 | return QPolygonF(); // need at least two points for interpolation | |
21975 | double slope; |
|
21765 | double slope; | |
21976 |
if |
|
21766 | if (croppedData->at(1).x() - croppedData->at(0).x() != 0) | |
21977 | slope = (croppedData->at(1).y() - croppedData->at(0).y()) |
|
21767 | slope = (croppedData->at(1).y() - croppedData->at(0).y()) | |
21978 | / (croppedData->at(1).x() - croppedData->at(0).x()); |
|
21768 | / (croppedData->at(1).x() - croppedData->at(0).x()); | |
21979 | else |
|
21769 | else | |
@@ -21989,12 +21779,12 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *thisData | |||||
21989 | if (highBound == -1) |
|
21779 | if (highBound == -1) | |
21990 | return QPolygonF(); // key ranges have no overlap |
|
21780 | return QPolygonF(); // key ranges have no overlap | |
21991 | croppedData->remove(highBound + 1, croppedData->size() - (highBound + 1)); |
|
21781 | croppedData->remove(highBound + 1, croppedData->size() - (highBound + 1)); | |
21992 |
// set highest point of cropped data to fit exactly key position of last static data |
|
21782 | // set highest point of cropped data to fit exactly key position of last static data | |
21993 | // via linear interpolation: |
|
21783 | // point via linear interpolation: | |
21994 | if (croppedData->size() < 2) |
|
21784 | if (croppedData->size() < 2) | |
21995 |
return QPolygonF(); |
|
21785 | return QPolygonF(); // need at least two points for interpolation | |
21996 |
|
|
21786 | int li = croppedData->size() - 1; // last index | |
21997 |
if |
|
21787 | if (croppedData->at(li).x() - croppedData->at(li - 1).x() != 0) | |
21998 | slope = (croppedData->at(li).y() - croppedData->at(li - 1).y()) |
|
21788 | slope = (croppedData->at(li).y() - croppedData->at(li - 1).y()) | |
21999 | / (croppedData->at(li).x() - croppedData->at(li - 1).x()); |
|
21789 | / (croppedData->at(li).x() - croppedData->at(li - 1).x()); | |
22000 | else |
|
21790 | else | |
@@ -22006,20 +21796,36 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *thisData | |||||
22006 | else // mKeyAxis->orientation() == Qt::Vertical |
|
21796 | else // mKeyAxis->orientation() == Qt::Vertical | |
22007 | { |
|
21797 | { | |
22008 | // y is key |
|
21798 | // y is key | |
|
21799 | // similar to "x is key" but switched x,y. Further, lower/upper meaning is inverted compared | |||
|
21800 | // to x, | |||
|
21801 | // because in pixel coordinates, y increases from top to bottom, not bottom to top like data | |||
|
21802 | // coordinate. | |||
|
21803 | // if an axis range is reversed, the data point keys will be descending. Reverse them, since | |||
|
21804 | // following algorithm assumes ascending keys: | |||
|
21805 | if (staticData->first().y() < staticData->last().y()) { | |||
|
21806 | int size = staticData->size(); | |||
|
21807 | for (int i = 0; i < size / 2; ++i) | |||
|
21808 | qSwap((*staticData)[i], (*staticData)[size - 1 - i]); | |||
|
21809 | } | |||
|
21810 | if (croppedData->first().y() < croppedData->last().y()) { | |||
|
21811 | int size = croppedData->size(); | |||
|
21812 | for (int i = 0; i < size / 2; ++i) | |||
|
21813 | qSwap((*croppedData)[i], (*croppedData)[size - 1 - i]); | |||
|
21814 | } | |||
22009 | // crop lower bound: |
|
21815 | // crop lower bound: | |
22010 |
if (staticData->first().y() |
|
21816 | if (staticData->first().y() > croppedData->first().y()) // other one must be cropped | |
22011 | qSwap(staticData, croppedData); |
|
21817 | qSwap(staticData, croppedData); | |
22012 |
int lowBound = findIndex |
|
21818 | int lowBound = findIndexAboveY(croppedData, staticData->first().y()); | |
22013 | if (lowBound == -1) |
|
21819 | if (lowBound == -1) | |
22014 | return QPolygonF(); // key ranges have no overlap |
|
21820 | return QPolygonF(); // key ranges have no overlap | |
22015 | croppedData->remove(0, lowBound); |
|
21821 | croppedData->remove(0, lowBound); | |
22016 |
// set lowest point of cropped data to fit exactly key position of first static data |
|
21822 | // set lowest point of cropped data to fit exactly key position of first static data | |
22017 | // via linear interpolation: |
|
21823 | // point via linear interpolation: | |
22018 | if (croppedData->size() < 2) |
|
21824 | if (croppedData->size() < 2) | |
22019 | return QPolygonF(); // need at least two points for interpolation |
|
21825 | return QPolygonF(); // need at least two points for interpolation | |
22020 | double slope; |
|
21826 | double slope; | |
22021 |
if |
|
21827 | if (croppedData->at(1).y() - croppedData->at(0).y() | |
22022 |
|
|
21828 | != 0) // avoid division by zero in step plots | |
22023 | slope = (croppedData->at(1).x() - croppedData->at(0).x()) |
|
21829 | slope = (croppedData->at(1).x() - croppedData->at(0).x()) | |
22024 | / (croppedData->at(1).y() - croppedData->at(0).y()); |
|
21830 | / (croppedData->at(1).y() - croppedData->at(0).y()); | |
22025 | else |
|
21831 | else | |
@@ -22029,19 +21835,19 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *thisData | |||||
22029 | (*croppedData)[0].setY(staticData->first().y()); |
|
21835 | (*croppedData)[0].setY(staticData->first().y()); | |
22030 |
|
21836 | |||
22031 | // crop upper bound: |
|
21837 | // crop upper bound: | |
22032 |
if (staticData->last().y() |
|
21838 | if (staticData->last().y() < croppedData->last().y()) // other one must be cropped | |
22033 | qSwap(staticData, croppedData); |
|
21839 | qSwap(staticData, croppedData); | |
22034 |
int highBound = findIndex |
|
21840 | int highBound = findIndexBelowY(croppedData, staticData->last().y()); | |
22035 | if (highBound == -1) |
|
21841 | if (highBound == -1) | |
22036 | return QPolygonF(); // key ranges have no overlap |
|
21842 | return QPolygonF(); // key ranges have no overlap | |
22037 | croppedData->remove(highBound + 1, croppedData->size() - (highBound + 1)); |
|
21843 | croppedData->remove(highBound + 1, croppedData->size() - (highBound + 1)); | |
22038 |
// set highest point of cropped data to fit exactly key position of last static data |
|
21844 | // set highest point of cropped data to fit exactly key position of last static data | |
22039 | // via linear interpolation: |
|
21845 | // point via linear interpolation: | |
22040 | if (croppedData->size() < 2) |
|
21846 | if (croppedData->size() < 2) | |
22041 | return QPolygonF(); // need at least two points for interpolation |
|
21847 | return QPolygonF(); // need at least two points for interpolation | |
22042 | int li = croppedData->size() - 1; // last index |
|
21848 | int li = croppedData->size() - 1; // last index | |
22043 |
if |
|
21849 | if (croppedData->at(li).y() - croppedData->at(li - 1).y() | |
22044 |
|
|
21850 | != 0) // avoid division by zero in step plots | |
22045 | slope = (croppedData->at(li).x() - croppedData->at(li - 1).x()) |
|
21851 | slope = (croppedData->at(li).x() - croppedData->at(li - 1).x()) | |
22046 | / (croppedData->at(li).y() - croppedData->at(li - 1).y()); |
|
21852 | / (croppedData->at(li).y() - croppedData->at(li - 1).y()); | |
22047 | else |
|
21853 | else | |
@@ -22052,17 +21858,16 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *thisData | |||||
22052 | } |
|
21858 | } | |
22053 |
|
21859 | |||
22054 | // return joined: |
|
21860 | // return joined: | |
22055 |
for (int i = other |
|
21861 | for (int i = otherData.size() - 1; i >= 0; | |
22056 | --i) // insert reversed, otherwise the polygon will be twisted |
|
21862 | --i) // insert reversed, otherwise the polygon will be twisted | |
22057 |
this |
|
21863 | thisData << otherData.at(i); | |
22058 |
return QPolygonF(this |
|
21864 | return QPolygonF(thisData); | |
22059 | } |
|
21865 | } | |
22060 |
|
21866 | |||
22061 | /*! \internal |
|
21867 | /*! \internal | |
22062 |
|
21868 | |||
22063 | Finds the smallest index of \a data, whose points x value is just above \a x. Assumes x values in |
|
21869 | Finds the smallest index of \a data, whose points x value is just above \a x. Assumes x values in | |
22064 | \a data points are ordered ascending, as is ensured by \ref getLines/\ref getScatters if the key |
|
21870 | \a data points are ordered ascending, as is the case when plotting with horizontal key axis. | |
22065 | axis is horizontal. |
|
|||
22066 |
|
21871 | |||
22067 | Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. |
|
21872 | Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. | |
22068 | */ |
|
21873 | */ | |
@@ -22082,8 +21887,7 int QCPGraph::findIndexAboveX(const QVector<QPointF> *data, double x) const | |||||
22082 | /*! \internal |
|
21887 | /*! \internal | |
22083 |
|
21888 | |||
22084 | Finds the highest index of \a data, whose points x value is just below \a x. Assumes x values in |
|
21889 | Finds the highest index of \a data, whose points x value is just below \a x. Assumes x values in | |
22085 | \a data points are ordered ascending, as is ensured by \ref getLines/\ref getScatters if the key |
|
21890 | \a data points are ordered ascending, as is the case when plotting with horizontal key axis. | |
22086 | axis is horizontal. |
|
|||
22087 |
|
21891 | |||
22088 | Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. |
|
21892 | Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. | |
22089 | */ |
|
21893 | */ | |
@@ -22103,19 +21907,18 int QCPGraph::findIndexBelowX(const QVector<QPointF> *data, double x) const | |||||
22103 | /*! \internal |
|
21907 | /*! \internal | |
22104 |
|
21908 | |||
22105 | Finds the smallest index of \a data, whose points y value is just above \a y. Assumes y values in |
|
21909 | Finds the smallest index of \a data, whose points y value is just above \a y. Assumes y values in | |
22106 | \a data points are ordered ascending, as is ensured by \ref getLines/\ref getScatters if the key |
|
21910 | \a data points are ordered descending, as is the case when plotting with vertical key axis. | |
22107 | axis is vertical. |
|
|||
22108 |
|
21911 | |||
22109 | Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. |
|
21912 | Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. | |
22110 | */ |
|
21913 | */ | |
22111 | int QCPGraph::findIndexAboveY(const QVector<QPointF> *data, double y) const |
|
21914 | int QCPGraph::findIndexAboveY(const QVector<QPointF> *data, double y) const | |
22112 | { |
|
21915 | { | |
22113 |
for (int i = data->size() |
|
21916 | for (int i = 0; i < data->size(); ++i) { | |
22114 | if (data->at(i).y() < y) { |
|
21917 | if (data->at(i).y() < y) { | |
22115 |
if (i |
|
21918 | if (i > 0) | |
22116 |
return i |
|
21919 | return i - 1; | |
22117 | else |
|
21920 | else | |
22118 |
return |
|
21921 | return 0; | |
22119 | } |
|
21922 | } | |
22120 | } |
|
21923 | } | |
22121 | return -1; |
|
21924 | return -1; | |
@@ -22191,19 +21994,19 double QCPGraph::pointDistance(const QPointF &pixelPoint, | |||||
22191 | /*! \internal |
|
21994 | /*! \internal | |
22192 |
|
21995 | |||
22193 | Finds the highest index of \a data, whose points y value is just below \a y. Assumes y values in |
|
21996 | Finds the highest index of \a data, whose points y value is just below \a y. Assumes y values in | |
22194 | \a data points are ordered ascending, as is ensured by \ref getLines/\ref getScatters if the key |
|
21997 | \a data points are ordered descending, as is the case when plotting with vertical key axis (since | |
22195 | axis is vertical. |
|
21998 | keys are ordered ascending). | |
22196 |
|
21999 | |||
22197 | Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. |
|
22000 | Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. | |
22198 | */ |
|
22001 | */ | |
22199 | int QCPGraph::findIndexBelowY(const QVector<QPointF> *data, double y) const |
|
22002 | int QCPGraph::findIndexBelowY(const QVector<QPointF> *data, double y) const | |
22200 | { |
|
22003 | { | |
22201 |
for (int i = |
|
22004 | for (int i = data->size() - 1; i >= 0; --i) { | |
22202 | if (data->at(i).y() > y) { |
|
22005 | if (data->at(i).y() > y) { | |
22203 |
if (i > |
|
22006 | if (i < data->size() - 1) | |
22204 |
return i |
|
22007 | return i + 1; | |
22205 | else |
|
22008 | else | |
22206 |
return |
|
22009 | return data->size() - 1; | |
22207 | } |
|
22010 | } | |
22208 | } |
|
22011 | } | |
22209 | return -1; |
|
22012 | return -1; | |
@@ -22211,8 +22014,8 int QCPGraph::findIndexBelowY(const QVector<QPointF> *data, double y) const | |||||
22211 | /* end of 'src/plottables/plottable-graph.cpp' */ |
|
22014 | /* end of 'src/plottables/plottable-graph.cpp' */ | |
22212 |
|
22015 | |||
22213 |
|
22016 | |||
22214 |
/* including file 'src/plottables/plottable-curve.cpp', size 6 |
|
22017 | /* including file 'src/plottables/plottable-curve.cpp', size 60009 */ | |
22215 | /* commit 63bcca79007f7f56dce5dd035560f2e871d1dfc1 2017-07-20 18:02:21 +0200 */ |
|
22018 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
22216 |
|
22019 | |||
22217 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
22020 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
22218 | //////////////////// QCPCurveData |
|
22021 | //////////////////// QCPCurveData | |
@@ -22376,7 +22179,6 QCPCurve::QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis) | |||||
22376 |
|
22179 | |||
22377 | setScatterStyle(QCPScatterStyle()); |
|
22180 | setScatterStyle(QCPScatterStyle()); | |
22378 | setLineStyle(lsLine); |
|
22181 | setLineStyle(lsLine); | |
22379 | setScatterSkip(0); |
|
|||
22380 | } |
|
22182 | } | |
22381 |
|
22183 | |||
22382 | QCPCurve::~QCPCurve() |
|
22184 | QCPCurve::~QCPCurve() | |
@@ -23079,74 +22881,54 QPointF QCPCurve::getOptimizedPoint(int otherRegion, double otherKey, double oth | |||||
23079 | double value, double keyMin, double valueMax, double keyMax, |
|
22881 | double value, double keyMin, double valueMax, double keyMax, | |
23080 | double valueMin) const |
|
22882 | double valueMin) const | |
23081 | { |
|
22883 | { | |
23082 | // The intersection point interpolation here is done in pixel coordinates, so we don't need to |
|
22884 | double intersectKey = keyMin; // initial value is just fail-safe | |
23083 | // differentiate between different axis scale types. Note that the nomenclature |
|
22885 | double intersectValue = valueMax; // initial value is just fail-safe | |
23084 | // top/left/bottom/right/min/max is with respect to the rect in plot coordinates, wich may be |
|
|||
23085 | // different in pixel coordinates (horz/vert key axes, reversed ranges) |
|
|||
23086 |
|
||||
23087 | const double keyMinPx = mKeyAxis->coordToPixel(keyMin); |
|
|||
23088 | const double keyMaxPx = mKeyAxis->coordToPixel(keyMax); |
|
|||
23089 | const double valueMinPx = mValueAxis->coordToPixel(valueMin); |
|
|||
23090 | const double valueMaxPx = mValueAxis->coordToPixel(valueMax); |
|
|||
23091 | const double otherValuePx = mValueAxis->coordToPixel(otherValue); |
|
|||
23092 | const double valuePx = mValueAxis->coordToPixel(value); |
|
|||
23093 | const double otherKeyPx = mKeyAxis->coordToPixel(otherKey); |
|
|||
23094 | const double keyPx = mKeyAxis->coordToPixel(key); |
|
|||
23095 | double intersectKeyPx = keyMinPx; // initial key just a fail-safe |
|
|||
23096 | double intersectValuePx = valueMinPx; // initial value just a fail-safe |
|
|||
23097 | switch (otherRegion) { |
|
22886 | switch (otherRegion) { | |
23098 | case 1: // top and left edge |
|
22887 | case 1: // top and left edge | |
23099 | { |
|
22888 | { | |
23100 |
intersectValue |
|
22889 | intersectValue = valueMax; | |
23101 |
intersectKey |
|
22890 | intersectKey | |
23102 | + (keyPx - otherKeyPx) / (valuePx - otherValuePx) |
|
22891 | = otherKey | |
23103 |
|
|
22892 | + (key - otherKey) / (value - otherValue) * (intersectValue - otherValue); | |
23104 |
if (intersectKey |
|
22893 | if (intersectKey < keyMin | |
23105 | || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether top edge is not |
|
22894 | || intersectKey > keyMax) // doesn't intersect, so must intersect other: | |
23106 | // intersected, then it must be left |
|
|||
23107 | // edge (qMin/qMax necessary since |
|
|||
23108 | // axes may be reversed) |
|
|||
23109 | { |
|
22895 | { | |
23110 |
intersectKey |
|
22896 | intersectKey = keyMin; | |
23111 |
intersectValue |
|
22897 | intersectValue | |
23112 | + (valuePx - otherValuePx) / (keyPx - otherKeyPx) |
|
22898 | = otherValue | |
23113 |
|
|
22899 | + (value - otherValue) / (key - otherKey) * (intersectKey - otherKey); | |
23114 | } |
|
22900 | } | |
23115 | break; |
|
22901 | break; | |
23116 | } |
|
22902 | } | |
23117 | case 2: // left edge |
|
22903 | case 2: // left edge | |
23118 | { |
|
22904 | { | |
23119 |
intersectKey |
|
22905 | intersectKey = keyMin; | |
23120 |
intersectValue |
|
22906 | intersectValue | |
23121 | = otherValuePx |
|
22907 | = otherValue + (value - otherValue) / (key - otherKey) * (intersectKey - otherKey); | |
23122 | + (valuePx - otherValuePx) / (keyPx - otherKeyPx) * (intersectKeyPx - otherKeyPx); |
|
|||
23123 | break; |
|
22908 | break; | |
23124 | } |
|
22909 | } | |
23125 | case 3: // bottom and left edge |
|
22910 | case 3: // bottom and left edge | |
23126 | { |
|
22911 | { | |
23127 |
intersectValue |
|
22912 | intersectValue = valueMin; | |
23128 |
intersectKey |
|
22913 | intersectKey | |
23129 | + (keyPx - otherKeyPx) / (valuePx - otherValuePx) |
|
22914 | = otherKey | |
23130 |
|
|
22915 | + (key - otherKey) / (value - otherValue) * (intersectValue - otherValue); | |
23131 |
if (intersectKey |
|
22916 | if (intersectKey < keyMin | |
23132 | || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether bottom edge is not |
|
22917 | || intersectKey > keyMax) // doesn't intersect, so must intersect other: | |
23133 | // intersected, then it must be left |
|
|||
23134 | // edge (qMin/qMax necessary since |
|
|||
23135 | // axes may be reversed) |
|
|||
23136 | { |
|
22918 | { | |
23137 |
intersectKey |
|
22919 | intersectKey = keyMin; | |
23138 |
intersectValue |
|
22920 | intersectValue | |
23139 | + (valuePx - otherValuePx) / (keyPx - otherKeyPx) |
|
22921 | = otherValue | |
23140 |
|
|
22922 | + (value - otherValue) / (key - otherKey) * (intersectKey - otherKey); | |
23141 | } |
|
22923 | } | |
23142 | break; |
|
22924 | break; | |
23143 | } |
|
22925 | } | |
23144 | case 4: // top edge |
|
22926 | case 4: // top edge | |
23145 | { |
|
22927 | { | |
23146 |
intersectValue |
|
22928 | intersectValue = valueMax; | |
23147 |
intersectKey |
|
22929 | intersectKey | |
23148 | + (keyPx - otherKeyPx) / (valuePx - otherValuePx) |
|
22930 | = otherKey | |
23149 |
|
|
22931 | + (key - otherKey) / (value - otherValue) * (intersectValue - otherValue); | |
23150 | break; |
|
22932 | break; | |
23151 | } |
|
22933 | } | |
23152 | case 5: { |
|
22934 | case 5: { | |
@@ -23155,63 +22937,53 QPointF QCPCurve::getOptimizedPoint(int otherRegion, double otherKey, double oth | |||||
23155 | } |
|
22937 | } | |
23156 | case 6: // bottom edge |
|
22938 | case 6: // bottom edge | |
23157 | { |
|
22939 | { | |
23158 |
intersectValue |
|
22940 | intersectValue = valueMin; | |
23159 |
intersectKey |
|
22941 | intersectKey | |
23160 | + (keyPx - otherKeyPx) / (valuePx - otherValuePx) |
|
22942 | = otherKey | |
23161 |
|
|
22943 | + (key - otherKey) / (value - otherValue) * (intersectValue - otherValue); | |
23162 | break; |
|
22944 | break; | |
23163 | } |
|
22945 | } | |
23164 | case 7: // top and right edge |
|
22946 | case 7: // top and right edge | |
23165 | { |
|
22947 | { | |
23166 |
intersectValue |
|
22948 | intersectValue = valueMax; | |
23167 |
intersectKey |
|
22949 | intersectKey | |
23168 | + (keyPx - otherKeyPx) / (valuePx - otherValuePx) |
|
22950 | = otherKey | |
23169 |
|
|
22951 | + (key - otherKey) / (value - otherValue) * (intersectValue - otherValue); | |
23170 |
if (intersectKey |
|
22952 | if (intersectKey < keyMin | |
23171 | || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether top edge is not |
|
22953 | || intersectKey > keyMax) // doesn't intersect, so must intersect other: | |
23172 | // intersected, then it must be right |
|
|||
23173 | // edge (qMin/qMax necessary since |
|
|||
23174 | // axes may be reversed) |
|
|||
23175 | { |
|
22954 | { | |
23176 |
intersectKey |
|
22955 | intersectKey = keyMax; | |
23177 |
intersectValue |
|
22956 | intersectValue | |
23178 | + (valuePx - otherValuePx) / (keyPx - otherKeyPx) |
|
22957 | = otherValue | |
23179 |
|
|
22958 | + (value - otherValue) / (key - otherKey) * (intersectKey - otherKey); | |
23180 | } |
|
22959 | } | |
23181 | break; |
|
22960 | break; | |
23182 | } |
|
22961 | } | |
23183 | case 8: // right edge |
|
22962 | case 8: // right edge | |
23184 | { |
|
22963 | { | |
23185 |
intersectKey |
|
22964 | intersectKey = keyMax; | |
23186 |
intersectValue |
|
22965 | intersectValue | |
23187 | = otherValuePx |
|
22966 | = otherValue + (value - otherValue) / (key - otherKey) * (intersectKey - otherKey); | |
23188 | + (valuePx - otherValuePx) / (keyPx - otherKeyPx) * (intersectKeyPx - otherKeyPx); |
|
|||
23189 | break; |
|
22967 | break; | |
23190 | } |
|
22968 | } | |
23191 | case 9: // bottom and right edge |
|
22969 | case 9: // bottom and right edge | |
23192 | { |
|
22970 | { | |
23193 |
intersectValue |
|
22971 | intersectValue = valueMin; | |
23194 |
intersectKey |
|
22972 | intersectKey | |
23195 | + (keyPx - otherKeyPx) / (valuePx - otherValuePx) |
|
22973 | = otherKey | |
23196 |
|
|
22974 | + (key - otherKey) / (value - otherValue) * (intersectValue - otherValue); | |
23197 |
if (intersectKey |
|
22975 | if (intersectKey < keyMin | |
23198 | || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether bottom edge is not |
|
22976 | || intersectKey > keyMax) // doesn't intersect, so must intersect other: | |
23199 | // intersected, then it must be right |
|
|||
23200 | // edge (qMin/qMax necessary since |
|
|||
23201 | // axes may be reversed) |
|
|||
23202 | { |
|
22977 | { | |
23203 |
intersectKey |
|
22978 | intersectKey = keyMax; | |
23204 |
intersectValue |
|
22979 | intersectValue | |
23205 | + (valuePx - otherValuePx) / (keyPx - otherKeyPx) |
|
22980 | = otherValue | |
23206 |
|
|
22981 | + (value - otherValue) / (key - otherKey) * (intersectKey - otherKey); | |
23207 | } |
|
22982 | } | |
23208 | break; |
|
22983 | break; | |
23209 | } |
|
22984 | } | |
23210 | } |
|
22985 | } | |
23211 | if (mKeyAxis->orientation() == Qt::Horizontal) |
|
22986 | return coordsToPixels(intersectKey, intersectValue); | |
23212 | return QPointF(intersectKeyPx, intersectValuePx); |
|
|||
23213 | else |
|
|||
23214 | return QPointF(intersectValuePx, intersectKeyPx); |
|
|||
23215 | } |
|
22987 | } | |
23216 |
|
22988 | |||
23217 | /*! \internal |
|
22989 | /*! \internal | |
@@ -23724,79 +23496,44 bool QCPCurve::getTraverse(double prevKey, double prevValue, double key, double | |||||
23724 | double keyMin, double valueMax, double keyMax, double valueMin, |
|
23496 | double keyMin, double valueMax, double keyMax, double valueMin, | |
23725 | QPointF &crossA, QPointF &crossB) const |
|
23497 | QPointF &crossA, QPointF &crossB) const | |
23726 | { |
|
23498 | { | |
23727 | // The intersection point interpolation here is done in pixel coordinates, so we don't need to |
|
23499 | QList<QPointF> intersections; // x of QPointF corresponds to key and y to value | |
23728 | // differentiate between different axis scale types. Note that the nomenclature |
|
|||
23729 | // top/left/bottom/right/min/max is with respect to the rect in plot coordinates, wich may be |
|
|||
23730 | // different in pixel coordinates (horz/vert key axes, reversed ranges) |
|
|||
23731 |
|
||||
23732 | QList<QPointF> intersections; |
|
|||
23733 | const double valueMinPx = mValueAxis->coordToPixel(valueMin); |
|
|||
23734 | const double valueMaxPx = mValueAxis->coordToPixel(valueMax); |
|
|||
23735 | const double keyMinPx = mKeyAxis->coordToPixel(keyMin); |
|
|||
23736 | const double keyMaxPx = mKeyAxis->coordToPixel(keyMax); |
|
|||
23737 | const double keyPx = mKeyAxis->coordToPixel(key); |
|
|||
23738 | const double valuePx = mValueAxis->coordToPixel(value); |
|
|||
23739 | const double prevKeyPx = mKeyAxis->coordToPixel(prevKey); |
|
|||
23740 | const double prevValuePx = mValueAxis->coordToPixel(prevValue); |
|
|||
23741 | if (qFuzzyIsNull(key - prevKey)) // line is parallel to value axis |
|
23500 | if (qFuzzyIsNull(key - prevKey)) // line is parallel to value axis | |
23742 | { |
|
23501 | { | |
23743 |
// due to region filter in mayTraverse(), if line is parallel to value or key axis, |
|
23502 | // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is | |
23744 |
// |
|
23503 | // traversed here | |
23745 | intersections.append( |
|
23504 | intersections.append( | |
23746 | mKeyAxis->orientation() == Qt::Horizontal |
|
23505 | QPointF(key, valueMin)); // direction will be taken care of at end of method | |
23747 |
|
|
23506 | intersections.append(QPointF(key, valueMax)); | |
23748 | : QPointF(valueMinPx, keyPx)); // direction will be taken care of at end of method |
|
|||
23749 | intersections.append(mKeyAxis->orientation() == Qt::Horizontal |
|
|||
23750 | ? QPointF(keyPx, valueMaxPx) |
|
|||
23751 | : QPointF(valueMaxPx, keyPx)); |
|
|||
23752 | } |
|
23507 | } | |
23753 | else if (qFuzzyIsNull(value - prevValue)) // line is parallel to key axis |
|
23508 | else if (qFuzzyIsNull(value - prevValue)) // line is parallel to key axis | |
23754 | { |
|
23509 | { | |
23755 |
// due to region filter in mayTraverse(), if line is parallel to value or key axis, |
|
23510 | // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is | |
23756 |
// |
|
23511 | // traversed here | |
23757 | intersections.append( |
|
23512 | intersections.append( | |
23758 | mKeyAxis->orientation() == Qt::Horizontal |
|
23513 | QPointF(keyMin, value)); // direction will be taken care of at end of method | |
23759 |
|
|
23514 | intersections.append(QPointF(keyMax, value)); | |
23760 | : QPointF(valuePx, keyMinPx)); // direction will be taken care of at end of method |
|
|||
23761 | intersections.append(mKeyAxis->orientation() == Qt::Horizontal |
|
|||
23762 | ? QPointF(keyMaxPx, valuePx) |
|
|||
23763 | : QPointF(valuePx, keyMaxPx)); |
|
|||
23764 | } |
|
23515 | } | |
23765 | else // line is skewed |
|
23516 | else // line is skewed | |
23766 | { |
|
23517 | { | |
23767 | double gamma; |
|
23518 | double gamma; | |
23768 |
double keyPerValue |
|
23519 | double keyPerValue = (key - prevKey) / (value - prevValue); | |
23769 | // check top of rect: |
|
23520 | // check top of rect: | |
23770 |
gamma = prevKey |
|
23521 | gamma = prevKey + (valueMax - prevValue) * keyPerValue; | |
23771 |
if (gamma >= |
|
23522 | if (gamma >= keyMin && gamma <= keyMax) | |
23772 | && gamma <= qMax(keyMinPx, keyMaxPx)) // qMin/qMax necessary since axes may be reversed |
|
23523 | intersections.append(QPointF(gamma, valueMax)); | |
23773 | intersections.append(mKeyAxis->orientation() == Qt::Horizontal |
|
|||
23774 | ? QPointF(gamma, valueMaxPx) |
|
|||
23775 | : QPointF(valueMaxPx, gamma)); |
|
|||
23776 | // check bottom of rect: |
|
23524 | // check bottom of rect: | |
23777 |
gamma = prevKey |
|
23525 | gamma = prevKey + (valueMin - prevValue) * keyPerValue; | |
23778 |
if (gamma >= |
|
23526 | if (gamma >= keyMin && gamma <= keyMax) | |
23779 | && gamma <= qMax(keyMinPx, keyMaxPx)) // qMin/qMax necessary since axes may be reversed |
|
23527 | intersections.append(QPointF(gamma, valueMin)); | |
23780 | intersections.append(mKeyAxis->orientation() == Qt::Horizontal |
|
23528 | double valuePerKey = 1.0 / keyPerValue; | |
23781 | ? QPointF(gamma, valueMinPx) |
|
|||
23782 | : QPointF(valueMinPx, gamma)); |
|
|||
23783 | const double valuePerKeyPx = 1.0 / keyPerValuePx; |
|
|||
23784 | // check left of rect: |
|
23529 | // check left of rect: | |
23785 |
gamma = prevValue |
|
23530 | gamma = prevValue + (keyMin - prevKey) * valuePerKey; | |
23786 |
if (gamma >= |
|
23531 | if (gamma >= valueMin && gamma <= valueMax) | |
23787 | && gamma <= qMax(valueMinPx, |
|
23532 | intersections.append(QPointF(keyMin, gamma)); | |
23788 | valueMaxPx)) // qMin/qMax necessary since axes may be reversed |
|
|||
23789 | intersections.append(mKeyAxis->orientation() == Qt::Horizontal |
|
|||
23790 | ? QPointF(keyMinPx, gamma) |
|
|||
23791 | : QPointF(gamma, keyMinPx)); |
|
|||
23792 | // check right of rect: |
|
23533 | // check right of rect: | |
23793 |
gamma = prevValue |
|
23534 | gamma = prevValue + (keyMax - prevKey) * valuePerKey; | |
23794 |
if (gamma >= |
|
23535 | if (gamma >= valueMin && gamma <= valueMax) | |
23795 | && gamma <= qMax(valueMinPx, |
|
23536 | intersections.append(QPointF(keyMax, gamma)); | |
23796 | valueMaxPx)) // qMin/qMax necessary since axes may be reversed |
|
|||
23797 | intersections.append(mKeyAxis->orientation() == Qt::Horizontal |
|
|||
23798 | ? QPointF(keyMaxPx, gamma) |
|
|||
23799 | : QPointF(gamma, keyMaxPx)); |
|
|||
23800 | } |
|
23537 | } | |
23801 |
|
23538 | |||
23802 | // handle cases where found points isn't exactly 2: |
|
23539 | // handle cases where found points isn't exactly 2: | |
@@ -23825,16 +23562,12 bool QCPCurve::getTraverse(double prevKey, double prevValue, double key, double | |||||
23825 | } |
|
23562 | } | |
23826 |
|
23563 | |||
23827 | // possibly re-sort points so optimized point segment has same direction as original segment: |
|
23564 | // possibly re-sort points so optimized point segment has same direction as original segment: | |
23828 | double xDelta = keyPx - prevKeyPx; |
|
23565 | if ((key - prevKey) * (intersections.at(1).x() - intersections.at(0).x()) | |
23829 | double yDelta = valuePx - prevValuePx; |
|
23566 | + (value - prevValue) * (intersections.at(1).y() - intersections.at(0).y()) | |
23830 | if (mKeyAxis->orientation() != Qt::Horizontal) |
|
|||
23831 | qSwap(xDelta, yDelta); |
|
|||
23832 | if (xDelta * (intersections.at(1).x() - intersections.at(0).x()) |
|
|||
23833 | + yDelta * (intersections.at(1).y() - intersections.at(0).y()) |
|
|||
23834 | < 0) // scalar product of both segments < 0 -> opposite direction |
|
23567 | < 0) // scalar product of both segments < 0 -> opposite direction | |
23835 | intersections.move(0, 1); |
|
23568 | intersections.move(0, 1); | |
23836 | crossA = intersections.at(0); |
|
23569 | crossA = coordsToPixels(intersections.at(0).x(), intersections.at(0).y()); | |
23837 | crossB = intersections.at(1); |
|
23570 | crossB = coordsToPixels(intersections.at(1).x(), intersections.at(1).y()); | |
23838 | return true; |
|
23571 | return true; | |
23839 | } |
|
23572 | } | |
23840 |
|
23573 | |||
@@ -25945,8 +25678,8 QCPStatisticalBox::getWhiskerBarLines(QCPStatisticalBoxDataContainer::const_iter | |||||
25945 | /* end of 'src/plottables/plottable-statisticalbox.cpp' */ |
|
25678 | /* end of 'src/plottables/plottable-statisticalbox.cpp' */ | |
25946 |
|
25679 | |||
25947 |
|
25680 | |||
25948 |
/* including file 'src/plottables/plottable-colormap.cpp', size 47 |
|
25681 | /* including file 'src/plottables/plottable-colormap.cpp', size 47531 */ | |
25949 | /* commit 83a770151292397b3ba4984108d7ed167a9aec65 2017-08-13 16:22:21 +0200 */ |
|
25682 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
25950 |
|
25683 | |||
25951 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
25684 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
25952 | //////////////////// QCPColorMapData |
|
25685 | //////////////////// QCPColorMapData | |
@@ -26617,7 +26350,6 QCPColorMap::QCPColorMap(QCPAxis *keyAxis, QCPAxis *valueAxis) | |||||
26617 | : QCPAbstractPlottable(keyAxis, valueAxis), |
|
26350 | : QCPAbstractPlottable(keyAxis, valueAxis), | |
26618 | mDataScaleType(QCPAxis::stLinear), |
|
26351 | mDataScaleType(QCPAxis::stLinear), | |
26619 | mMapData(new QCPColorMapData(10, 10, QCPRange(0, 5), QCPRange(0, 5))), |
|
26352 | mMapData(new QCPColorMapData(10, 10, QCPRange(0, 5), QCPRange(0, 5))), | |
26620 | mGradient(QCPColorGradient::gpCold), |
|
|||
26621 | mInterpolate(true), |
|
26353 | mInterpolate(true), | |
26622 | mTightBoundary(false), |
|
26354 | mTightBoundary(false), | |
26623 | mMapImageInvalidated(true) |
|
26355 | mMapImageInvalidated(true) | |
@@ -26977,82 +26709,74 void QCPColorMap::updateMapImage() | |||||
26977 | mMapImage = QImage( |
|
26709 | mMapImage = QImage( | |
26978 | QSize(valueSize * valueOversamplingFactor, keySize * keyOversamplingFactor), format); |
|
26710 | QSize(valueSize * valueOversamplingFactor, keySize * keyOversamplingFactor), format); | |
26979 |
|
26711 | |||
26980 | if (mMapImage.isNull()) { |
|
26712 | QImage *localMapImage = &mMapImage; // this is the image on which the colorization operates. | |
26981 | qDebug() << Q_FUNC_INFO << "Couldn't create map image (possibly too large for memory)"; |
|
26713 | // Either the final mMapImage, or if we need oversampling, | |
26982 | mMapImage = QImage(QSize(10, 10), format); |
|
26714 | // mUndersampledMapImage | |
26983 | mMapImage.fill(Qt::black); |
|
26715 | if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1) { | |
26984 | } |
|
26716 | // resize undersampled map image to actual key/value cell sizes: | |
26985 | else { |
|
26717 | if (keyAxis->orientation() == Qt::Horizontal | |
26986 | QImage *localMapImage = &mMapImage; // this is the image on which the colorization operates. |
|
26718 | && (mUndersampledMapImage.width() != keySize | |
26987 | // Either the final mMapImage, or if we need |
|
26719 | || mUndersampledMapImage.height() != valueSize)) | |
26988 | // oversampling, mUndersampledMapImage |
|
26720 | mUndersampledMapImage = QImage(QSize(keySize, valueSize), format); | |
26989 | if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1) { |
|
26721 | else if (keyAxis->orientation() == Qt::Vertical | |
26990 | // resize undersampled map image to actual key/value cell sizes: |
|
26722 | && (mUndersampledMapImage.width() != valueSize | |
26991 | if (keyAxis->orientation() == Qt::Horizontal |
|
26723 | || mUndersampledMapImage.height() != keySize)) | |
26992 |
|
|
26724 | mUndersampledMapImage = QImage(QSize(valueSize, keySize), format); | |
26993 | || mUndersampledMapImage.height() != valueSize)) |
|
26725 | localMapImage | |
26994 | mUndersampledMapImage = QImage(QSize(keySize, valueSize), format); |
|
26726 | = &mUndersampledMapImage; // make the colorization run on the undersampled image | |
26995 | else if (keyAxis->orientation() == Qt::Vertical |
|
26727 | } | |
26996 | && (mUndersampledMapImage.width() != valueSize |
|
26728 | else if (!mUndersampledMapImage.isNull()) | |
26997 | || mUndersampledMapImage.height() != keySize)) |
|
26729 | mUndersampledMapImage = QImage(); // don't need oversampling mechanism anymore (map size has | |
26998 | mUndersampledMapImage = QImage(QSize(valueSize, keySize), format); |
|
26730 | // changed) but mUndersampledMapImage still has nonzero | |
26999 | localMapImage |
|
26731 | // size, free it | |
27000 | = &mUndersampledMapImage; // make the colorization run on the undersampled image |
|
26732 | ||
27001 | } |
|
26733 | const double *rawData = mMapData->mData; | |
27002 | else if (!mUndersampledMapImage.isNull()) |
|
26734 | const unsigned char *rawAlpha = mMapData->mAlpha; | |
27003 | mUndersampledMapImage = QImage(); // don't need oversampling mechanism anymore (map size |
|
26735 | if (keyAxis->orientation() == Qt::Horizontal) { | |
27004 | // has changed) but mUndersampledMapImage still has |
|
26736 | const int lineCount = valueSize; | |
27005 | // nonzero size, free it |
|
26737 | const int rowCount = keySize; | |
27006 |
|
26738 | for (int line = 0; line < lineCount; ++line) { | ||
27007 | const double *rawData = mMapData->mData; |
|
26739 | QRgb *pixels = reinterpret_cast<QRgb *>(localMapImage->scanLine( | |
27008 | const unsigned char *rawAlpha = mMapData->mAlpha; |
|
26740 | lineCount - 1 - line)); // invert scanline index because QImage counts scanlines | |
27009 | if (keyAxis->orientation() == Qt::Horizontal) { |
|
26741 | // from top, but our vertical index counts from bottom | |
27010 | const int lineCount = valueSize; |
|
26742 | // (mathematical coordinate system) | |
27011 | const int rowCount = keySize; |
|
26743 | if (rawAlpha) | |
27012 | for (int line = 0; line < lineCount; ++line) { |
|
26744 | mGradient.colorize(rawData + line * rowCount, rawAlpha + line * rowCount, | |
27013 | QRgb *pixels = reinterpret_cast<QRgb *>(localMapImage->scanLine( |
|
26745 | mDataRange, pixels, rowCount, 1, | |
27014 | lineCount - 1 - line)); // invert scanline index because QImage counts scanlines |
|
26746 | mDataScaleType == QCPAxis::stLogarithmic); | |
27015 | // from top, but our vertical index counts from bottom |
|
26747 | else | |
27016 | // (mathematical coordinate system) |
|
26748 | mGradient.colorize(rawData + line * rowCount, mDataRange, pixels, rowCount, 1, | |
27017 | if (rawAlpha) |
|
26749 | mDataScaleType == QCPAxis::stLogarithmic); | |
27018 | mGradient.colorize(rawData + line * rowCount, rawAlpha + line * rowCount, |
|
|||
27019 | mDataRange, pixels, rowCount, 1, |
|
|||
27020 | mDataScaleType == QCPAxis::stLogarithmic); |
|
|||
27021 | else |
|
|||
27022 | mGradient.colorize(rawData + line * rowCount, mDataRange, pixels, rowCount, 1, |
|
|||
27023 | mDataScaleType == QCPAxis::stLogarithmic); |
|
|||
27024 | } |
|
|||
27025 | } |
|
|||
27026 | else // keyAxis->orientation() == Qt::Vertical |
|
|||
27027 | { |
|
|||
27028 | const int lineCount = keySize; |
|
|||
27029 | const int rowCount = valueSize; |
|
|||
27030 | for (int line = 0; line < lineCount; ++line) { |
|
|||
27031 | QRgb *pixels = reinterpret_cast<QRgb *>(localMapImage->scanLine( |
|
|||
27032 | lineCount - 1 - line)); // invert scanline index because QImage counts scanlines |
|
|||
27033 | // from top, but our vertical index counts from bottom |
|
|||
27034 | // (mathematical coordinate system) |
|
|||
27035 | if (rawAlpha) |
|
|||
27036 | mGradient.colorize(rawData + line, rawAlpha + line, mDataRange, pixels, |
|
|||
27037 | rowCount, lineCount, |
|
|||
27038 | mDataScaleType == QCPAxis::stLogarithmic); |
|
|||
27039 | else |
|
|||
27040 | mGradient.colorize(rawData + line, mDataRange, pixels, rowCount, lineCount, |
|
|||
27041 | mDataScaleType == QCPAxis::stLogarithmic); |
|
|||
27042 | } |
|
|||
27043 | } |
|
26750 | } | |
27044 |
|
26751 | } | ||
27045 | if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1) { |
|
26752 | else // keyAxis->orientation() == Qt::Vertical | |
27046 | if (keyAxis->orientation() == Qt::Horizontal) |
|
26753 | { | |
27047 | mMapImage = mUndersampledMapImage.scaled( |
|
26754 | const int lineCount = keySize; | |
27048 | keySize * keyOversamplingFactor, valueSize * valueOversamplingFactor, |
|
26755 | const int rowCount = valueSize; | |
27049 | Qt::IgnoreAspectRatio, Qt::FastTransformation); |
|
26756 | for (int line = 0; line < lineCount; ++line) { | |
|
26757 | QRgb *pixels = reinterpret_cast<QRgb *>(localMapImage->scanLine( | |||
|
26758 | lineCount - 1 - line)); // invert scanline index because QImage counts scanlines | |||
|
26759 | // from top, but our vertical index counts from bottom | |||
|
26760 | // (mathematical coordinate system) | |||
|
26761 | if (rawAlpha) | |||
|
26762 | mGradient.colorize(rawData + line, rawAlpha + line, mDataRange, pixels, rowCount, | |||
|
26763 | lineCount, mDataScaleType == QCPAxis::stLogarithmic); | |||
27050 | else |
|
26764 | else | |
27051 | mMapImage = mUndersampledMapImage.scaled( |
|
26765 | mGradient.colorize(rawData + line, mDataRange, pixels, rowCount, lineCount, | |
27052 | valueSize * valueOversamplingFactor, keySize * keyOversamplingFactor, |
|
26766 | mDataScaleType == QCPAxis::stLogarithmic); | |
27053 | Qt::IgnoreAspectRatio, Qt::FastTransformation); |
|
|||
27054 | } |
|
26767 | } | |
27055 | } |
|
26768 | } | |
|
26769 | ||||
|
26770 | if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1) { | |||
|
26771 | if (keyAxis->orientation() == Qt::Horizontal) | |||
|
26772 | mMapImage = mUndersampledMapImage.scaled(keySize * keyOversamplingFactor, | |||
|
26773 | valueSize * valueOversamplingFactor, | |||
|
26774 | Qt::IgnoreAspectRatio, Qt::FastTransformation); | |||
|
26775 | else | |||
|
26776 | mMapImage = mUndersampledMapImage.scaled(valueSize * valueOversamplingFactor, | |||
|
26777 | keySize * keyOversamplingFactor, | |||
|
26778 | Qt::IgnoreAspectRatio, Qt::FastTransformation); | |||
|
26779 | } | |||
27056 | mMapData->mDataModified = false; |
|
26780 | mMapData->mDataModified = false; | |
27057 | mMapImageInvalidated = false; |
|
26781 | mMapImageInvalidated = false; | |
27058 | } |
|
26782 | } | |
@@ -28215,8 +27939,8 QRectF QCPFinancial::selectionHitBox(QCPFinancialDataContainer::const_iterator i | |||||
28215 | /* end of 'src/plottables/plottable-financial.cpp' */ |
|
27939 | /* end of 'src/plottables/plottable-financial.cpp' */ | |
28216 |
|
27940 | |||
28217 |
|
27941 | |||
28218 |
/* including file 'src/plottables/plottable-errorbar.cpp', size 37 |
|
27942 | /* including file 'src/plottables/plottable-errorbar.cpp', size 37210 */ | |
28219 | /* commit 6f159843e9ec9ea6431b26591937aea13a9f2751 2017-07-25 11:13:32 +0200 */ |
|
27943 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
28220 |
|
27944 | |||
28221 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
27945 | //////////////////////////////////////////////////////////////////////////////////////////////////// | |
28222 | //////////////////// QCPErrorBarsData |
|
27946 | //////////////////// QCPErrorBarsData | |
@@ -28947,8 +28671,8 void QCPErrorBars::getErrorBarLines(QCPErrorBarsDataContainer::const_iterator it | |||||
28947 | QPointF centerPixel = mDataPlottable->interface1D()->dataPixelPosition(index); |
|
28671 | QPointF centerPixel = mDataPlottable->interface1D()->dataPixelPosition(index); | |
28948 | if (qIsNaN(centerPixel.x()) || qIsNaN(centerPixel.y())) |
|
28672 | if (qIsNaN(centerPixel.x()) || qIsNaN(centerPixel.y())) | |
28949 | return; |
|
28673 | return; | |
28950 |
QCPAxis *errorAxis = mErrorType == etValueError ? mValueAxis |
|
28674 | QCPAxis *errorAxis = mErrorType == etValueError ? mValueAxis : mKeyAxis; | |
28951 |
QCPAxis *orthoAxis = mErrorType == etValueError ? mKeyAxis |
|
28675 | QCPAxis *orthoAxis = mErrorType == etValueError ? mKeyAxis : mValueAxis; | |
28952 | const double centerErrorAxisPixel |
|
28676 | const double centerErrorAxisPixel | |
28953 | = errorAxis->orientation() == Qt::Horizontal ? centerPixel.x() : centerPixel.y(); |
|
28677 | = errorAxis->orientation() == Qt::Horizontal ? centerPixel.x() : centerPixel.y(); | |
28954 | const double centerOrthoAxisPixel |
|
28678 | const double centerOrthoAxisPixel | |
@@ -29082,10 +28806,6 double QCPErrorBars::pointDistance(const QPointF &pixelPoint, | |||||
29082 | closestData = mDataContainer->constEnd(); |
|
28806 | closestData = mDataContainer->constEnd(); | |
29083 | if (!mDataPlottable || mDataContainer->isEmpty()) |
|
28807 | if (!mDataPlottable || mDataContainer->isEmpty()) | |
29084 | return -1.0; |
|
28808 | return -1.0; | |
29085 | if (!mKeyAxis || !mValueAxis) { |
|
|||
29086 | qDebug() << Q_FUNC_INFO << "invalid key or value axis"; |
|
|||
29087 | return -1.0; |
|
|||
29088 | } |
|
|||
29089 |
|
28809 | |||
29090 | QCPErrorBarsDataContainer::const_iterator begin, end; |
|
28810 | QCPErrorBarsDataContainer::const_iterator begin, end; | |
29091 | getVisibleDataBounds(begin, end, QCPDataRange(0, dataCount())); |
|
28811 | getVisibleDataBounds(begin, end, QCPDataRange(0, dataCount())); |
@@ -14,10 +14,19 | |||||
14 | <string>Data sources</string> |
|
14 | <string>Data sources</string> | |
15 | </property> |
|
15 | </property> | |
16 | <layout class="QGridLayout" name="gridLayout"> |
|
16 | <layout class="QGridLayout" name="gridLayout"> | |
|
17 | <property name="topMargin"> | |||
|
18 | <number>0</number> | |||
|
19 | </property> | |||
|
20 | <property name="rightMargin"> | |||
|
21 | <number>0</number> | |||
|
22 | </property> | |||
|
23 | <property name="bottomMargin"> | |||
|
24 | <number>0</number> | |||
|
25 | </property> | |||
|
26 | <property name="spacing"> | |||
|
27 | <number>0</number> | |||
|
28 | </property> | |||
17 | <item row="0" column="0"> |
|
29 | <item row="0" column="0"> | |
18 | <widget class="QLineEdit" name="filterLineEdit"/> |
|
|||
19 | </item> |
|
|||
20 | <item row="1" column="0"> |
|
|||
21 | <widget class="QTreeWidget" name="treeWidget"> |
|
30 | <widget class="QTreeWidget" name="treeWidget"> | |
22 | <column> |
|
31 | <column> | |
23 | <property name="text"> |
|
32 | <property name="text"> |
1 | NO CONTENT: file renamed from gui/ui/SidePane/SqpSidePane.ui to gui/ui/Sidepane/SqpSidePane.ui |
|
NO CONTENT: file renamed from gui/ui/SidePane/SqpSidePane.ui to gui/ui/Sidepane/SqpSidePane.ui |
@@ -14,27 +14,8 | |||||
14 | <string>Form</string> |
|
14 | <string>Form</string> | |
15 | </property> |
|
15 | </property> | |
16 | <layout class="QVBoxLayout" name="verticalLayout"> |
|
16 | <layout class="QVBoxLayout" name="verticalLayout"> | |
17 | <property name="leftMargin"> |
|
|||
18 | <number>0</number> |
|
|||
19 | </property> |
|
|||
20 | <property name="topMargin"> |
|
|||
21 | <number>0</number> |
|
|||
22 | </property> |
|
|||
23 | <property name="rightMargin"> |
|
|||
24 | <number>0</number> |
|
|||
25 | </property> |
|
|||
26 | <property name="bottomMargin"> |
|
|||
27 | <number>0</number> |
|
|||
28 | </property> |
|
|||
29 | <item> |
|
17 | <item> | |
30 | <widget class="QCustomPlot" name="widget" native="true"> |
|
18 | <widget class="QCustomPlot" name="widget" native="true"/> | |
31 | <property name="sizePolicy"> |
|
|||
32 | <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> |
|
|||
33 | <horstretch>0</horstretch> |
|
|||
34 | <verstretch>0</verstretch> |
|
|||
35 | </sizepolicy> |
|
|||
36 | </property> |
|
|||
37 | </widget> |
|
|||
38 | </item> |
|
19 | </item> | |
39 | </layout> |
|
20 | </layout> | |
40 | </widget> |
|
21 | </widget> |
@@ -13,60 +13,7 | |||||
13 | <property name="windowTitle"> |
|
13 | <property name="windowTitle"> | |
14 | <string>Form</string> |
|
14 | <string>Form</string> | |
15 | </property> |
|
15 | </property> | |
16 | <layout class="QVBoxLayout" name="verticalLayout"> |
|
16 | <layout class="QVBoxLayout" name="verticalLayout"/> | |
17 | <property name="leftMargin"> |
|
|||
18 | <number>0</number> |
|
|||
19 | </property> |
|
|||
20 | <property name="topMargin"> |
|
|||
21 | <number>0</number> |
|
|||
22 | </property> |
|
|||
23 | <property name="rightMargin"> |
|
|||
24 | <number>0</number> |
|
|||
25 | </property> |
|
|||
26 | <property name="bottomMargin"> |
|
|||
27 | <number>0</number> |
|
|||
28 | </property> |
|
|||
29 | <item> |
|
|||
30 | <widget class="QScrollArea" name="scrollArea"> |
|
|||
31 | <property name="frameShape"> |
|
|||
32 | <enum>QFrame::NoFrame</enum> |
|
|||
33 | </property> |
|
|||
34 | <property name="frameShadow"> |
|
|||
35 | <enum>QFrame::Sunken</enum> |
|
|||
36 | </property> |
|
|||
37 | <property name="widgetResizable"> |
|
|||
38 | <bool>true</bool> |
|
|||
39 | </property> |
|
|||
40 | <widget class="QWidget" name="scrollAreaWidgetContents"> |
|
|||
41 | <property name="geometry"> |
|
|||
42 | <rect> |
|
|||
43 | <x>0</x> |
|
|||
44 | <y>0</y> |
|
|||
45 | <width>400</width> |
|
|||
46 | <height>300</height> |
|
|||
47 | </rect> |
|
|||
48 | </property> |
|
|||
49 | <layout class="QVBoxLayout" name="verticalLayout_3"> |
|
|||
50 | <property name="spacing"> |
|
|||
51 | <number>3</number> |
|
|||
52 | </property> |
|
|||
53 | <property name="leftMargin"> |
|
|||
54 | <number>0</number> |
|
|||
55 | </property> |
|
|||
56 | <property name="topMargin"> |
|
|||
57 | <number>0</number> |
|
|||
58 | </property> |
|
|||
59 | <property name="rightMargin"> |
|
|||
60 | <number>0</number> |
|
|||
61 | </property> |
|
|||
62 | <property name="bottomMargin"> |
|
|||
63 | <number>0</number> |
|
|||
64 | </property> |
|
|||
65 | </layout> |
|
|||
66 | </widget> |
|
|||
67 | </widget> |
|
|||
68 | </item> |
|
|||
69 | </layout> |
|
|||
70 | </widget> |
|
17 | </widget> | |
71 | <resources/> |
|
18 | <resources/> | |
72 | <connections/> |
|
19 | <connections/> |
@@ -14,27 +14,28 | |||||
14 | <string>Form</string> |
|
14 | <string>Form</string> | |
15 | </property> |
|
15 | </property> | |
16 | <layout class="QVBoxLayout" name="verticalLayout"> |
|
16 | <layout class="QVBoxLayout" name="verticalLayout"> | |
17 | <property name="leftMargin"> |
|
|||
18 | <number>0</number> |
|
|||
19 | </property> |
|
|||
20 | <property name="topMargin"> |
|
|||
21 | <number>0</number> |
|
|||
22 | </property> |
|
|||
23 | <property name="rightMargin"> |
|
|||
24 | <number>0</number> |
|
|||
25 | </property> |
|
|||
26 | <property name="bottomMargin"> |
|
|||
27 | <number>0</number> |
|
|||
28 | </property> |
|
|||
29 | <item> |
|
17 | <item> | |
30 | <widget class="QTabWidget" name="tabWidget"> |
|
18 | <widget class="QTabWidget" name="tabWidget"> | |
31 | <property name="currentIndex"> |
|
19 | <property name="currentIndex"> | |
32 |
<number> |
|
20 | <number>0</number> | |
33 | </property> |
|
21 | </property> | |
|
22 | <widget class="VisualizationTabWidget" name="firstView"> | |||
|
23 | <attribute name="title"> | |||
|
24 | <string>View 1</string> | |||
|
25 | </attribute> | |||
|
26 | </widget> | |||
34 | </widget> |
|
27 | </widget> | |
35 | </item> |
|
28 | </item> | |
36 | </layout> |
|
29 | </layout> | |
37 | </widget> |
|
30 | </widget> | |
|
31 | <customwidgets> | |||
|
32 | <customwidget> | |||
|
33 | <class>VisualizationTabWidget</class> | |||
|
34 | <extends>QWidget</extends> | |||
|
35 | <header location="global">Visualization/VisualizationTabWidget.h</header> | |||
|
36 | <container>1</container> | |||
|
37 | </customwidget> | |||
|
38 | </customwidgets> | |||
38 | <resources/> |
|
39 | <resources/> | |
39 | <connections/> |
|
40 | <connections/> | |
40 | </ui> |
|
41 | </ui> |
@@ -14,100 +14,15 | |||||
14 | <string>Form</string> |
|
14 | <string>Form</string> | |
15 | </property> |
|
15 | </property> | |
16 | <layout class="QVBoxLayout" name="verticalLayout_2"> |
|
16 | <layout class="QVBoxLayout" name="verticalLayout_2"> | |
17 | <property name="spacing"> |
|
|||
18 | <number>0</number> |
|
|||
19 | </property> |
|
|||
20 | <property name="leftMargin"> |
|
|||
21 | <number>0</number> |
|
|||
22 | </property> |
|
|||
23 | <property name="topMargin"> |
|
|||
24 | <number>0</number> |
|
|||
25 | </property> |
|
|||
26 | <property name="rightMargin"> |
|
|||
27 | <number>0</number> |
|
|||
28 | </property> |
|
|||
29 | <property name="bottomMargin"> |
|
|||
30 | <number>0</number> |
|
|||
31 | </property> |
|
|||
32 | <item> |
|
|||
33 | <widget class="QWidget" name="infobar" native="true"> |
|
|||
34 | <property name="sizePolicy"> |
|
|||
35 | <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> |
|
|||
36 | <horstretch>0</horstretch> |
|
|||
37 | <verstretch>0</verstretch> |
|
|||
38 | </sizepolicy> |
|
|||
39 | </property> |
|
|||
40 | <layout class="QHBoxLayout" name="horizontalLayout"> |
|
|||
41 | <property name="spacing"> |
|
|||
42 | <number>0</number> |
|
|||
43 | </property> |
|
|||
44 | <property name="leftMargin"> |
|
|||
45 | <number>0</number> |
|
|||
46 | </property> |
|
|||
47 | <property name="topMargin"> |
|
|||
48 | <number>0</number> |
|
|||
49 | </property> |
|
|||
50 | <property name="rightMargin"> |
|
|||
51 | <number>0</number> |
|
|||
52 | </property> |
|
|||
53 | <property name="bottomMargin"> |
|
|||
54 | <number>0</number> |
|
|||
55 | </property> |
|
|||
56 | <item> |
|
|||
57 | <widget class="QLabel" name="zoneNameLabel"> |
|
|||
58 | <property name="styleSheet"> |
|
|||
59 | <string notr="true">color: rgb(127, 127, 127); |
|
|||
60 | </string> |
|
|||
61 | </property> |
|
|||
62 | <property name="text"> |
|
|||
63 | <string>TextLabel</string> |
|
|||
64 | </property> |
|
|||
65 | </widget> |
|
|||
66 | </item> |
|
|||
67 | <item> |
|
|||
68 | <widget class="QToolButton" name="closeButton"> |
|
|||
69 | <property name="styleSheet"> |
|
|||
70 | <string notr="true">background-color: transparent;</string> |
|
|||
71 | </property> |
|
|||
72 | <property name="text"> |
|
|||
73 | <string>Close</string> |
|
|||
74 | </property> |
|
|||
75 | </widget> |
|
|||
76 | </item> |
|
|||
77 | </layout> |
|
|||
78 | </widget> |
|
|||
79 | </item> |
|
|||
80 | <item> |
|
17 | <item> | |
81 | <widget class="QFrame" name="visualizationZoneFrame"> |
|
18 | <widget class="QFrame" name="visualizationZoneFrame"> | |
82 | <property name="sizePolicy"> |
|
|||
83 | <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> |
|
|||
84 | <horstretch>0</horstretch> |
|
|||
85 | <verstretch>0</verstretch> |
|
|||
86 | </sizepolicy> |
|
|||
87 | </property> |
|
|||
88 | <property name="frameShape"> |
|
19 | <property name="frameShape"> | |
89 |
<enum>QFrame:: |
|
20 | <enum>QFrame::StyledPanel</enum> | |
90 | </property> |
|
21 | </property> | |
91 | <property name="frameShadow"> |
|
22 | <property name="frameShadow"> | |
92 | <enum>QFrame::Raised</enum> |
|
23 | <enum>QFrame::Raised</enum> | |
93 | </property> |
|
24 | </property> | |
94 | <property name="lineWidth"> |
|
25 | <layout class="QVBoxLayout" name="verticalLayout"/> | |
95 | <number>1</number> |
|
|||
96 | </property> |
|
|||
97 | <layout class="QVBoxLayout" name="verticalLayout"> |
|
|||
98 | <property name="leftMargin"> |
|
|||
99 | <number>0</number> |
|
|||
100 | </property> |
|
|||
101 | <property name="topMargin"> |
|
|||
102 | <number>0</number> |
|
|||
103 | </property> |
|
|||
104 | <property name="rightMargin"> |
|
|||
105 | <number>0</number> |
|
|||
106 | </property> |
|
|||
107 | <property name="bottomMargin"> |
|
|||
108 | <number>0</number> |
|
|||
109 | </property> |
|
|||
110 | </layout> |
|
|||
111 | </widget> |
|
26 | </widget> | |
112 | </item> |
|
27 | </item> | |
113 | </layout> |
|
28 | </layout> |
@@ -6,4 +6,6 qcustomplot\.cpp:\d+:.IPSIS | |||||
6 | SqpApplication\.h:\d+:.IPSIS_S03.*found: sqpApp |
|
6 | SqpApplication\.h:\d+:.IPSIS_S03.*found: sqpApp | |
7 | SqpApplication\.h:\d+:.IPSIS_S04_VARIABLE.*found: sqpApp |
|
7 | SqpApplication\.h:\d+:.IPSIS_S04_VARIABLE.*found: sqpApp | |
8 |
|
8 | |||
|
9 | # Ignore false positive relative to unnamed namespace | |||
|
10 | DataSourceTreeWidgetItem\.cpp:\d+:.*IPSIS_F13.* | |||
9 |
|
11 |
@@ -19,12 +19,6 FILE (GLOB_RECURSE MODULE_SOURCES | |||||
19 |
|
19 | |||
20 | ADD_LIBRARY(${SQPPLUGIN_LIBRARY_NAME} ${MODULE_SOURCES}) |
|
20 | ADD_LIBRARY(${SQPPLUGIN_LIBRARY_NAME} ${MODULE_SOURCES}) | |
21 |
|
21 | |||
22 | INSTALL(TARGETS ${SQPPLUGIN_LIBRARY_NAME} |
|
|||
23 | RUNTIME DESTINATION ${INSTALL_BINARY_DIR} |
|
|||
24 | LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR} |
|
|||
25 | ARCHIVE DESTINATION ${INSTALL_LIBRARY_DIR} |
|
|||
26 | ) |
|
|||
27 |
|
||||
28 |
|
22 | |||
29 | # Add the files to the list of files to be analyzed |
|
23 | # Add the files to the list of files to be analyzed | |
30 | LIST(APPEND CHECKSTYLE_INPUT_FILES ${MODULE_SOURCES}) |
|
24 | LIST(APPEND CHECKSTYLE_INPUT_FILES ${MODULE_SOURCES}) |
@@ -4,7 +4,6 SET(SQPMOCKPLUGIN_LIBRARY_NAME "${LIBRARY_PREFFIX}_mockplugin${DEBUG_SUFFIX}") | |||||
4 | SET(SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src") |
|
4 | SET(SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src") | |
5 | SET(INCLUDES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include") |
|
5 | SET(INCLUDES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include") | |
6 | SET(RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources") |
|
6 | SET(RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources") | |
7 | SET(TESTS_RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests-resources") |
|
|||
8 |
|
7 | |||
9 | # Include mockplugin directory |
|
8 | # Include mockplugin directory | |
10 | INCLUDE_DIRECTORIES(${INCLUDES_DIR}) |
|
9 | INCLUDE_DIRECTORIES(${INCLUDES_DIR}) | |
@@ -33,33 +32,23 find_package(sciqlop-gui) | |||||
33 | INCLUDE_DIRECTORIES(${SCIQLOP-GUI_INCLUDE_DIR}) |
|
32 | INCLUDE_DIRECTORIES(${SCIQLOP-GUI_INCLUDE_DIR}) | |
34 | list(APPEND LIBRARIES ${SCIQLOP-GUI_LIBRARIES}) |
|
33 | list(APPEND LIBRARIES ${SCIQLOP-GUI_LIBRARIES}) | |
35 |
|
34 | |||
36 | # Description file |
|
35 | # Resources files | |
37 |
FILE (GLOB_RECURSE P |
|
36 | FILE (GLOB_RECURSE PROJECT_RESOURCES ${RESOURCES_DIR}/*.json) | |
38 |
|
37 | |||
39 | # |
|
38 | # | |
40 | # Compile the library |
|
39 | # Compile the library | |
41 | # |
|
40 | # | |
42 |
|
||||
43 | ADD_DEFINITIONS(-DMOCKPLUGIN_LIB) |
|
|||
44 |
|
||||
45 | FILE (GLOB_RECURSE MODULE_SOURCES |
|
41 | FILE (GLOB_RECURSE MODULE_SOURCES | |
46 | ${INCLUDES_DIR}/*.h |
|
42 | ${INCLUDES_DIR}/*.h | |
47 | ${SOURCES_DIR}/*.c |
|
43 | ${SOURCES_DIR}/*.c | |
48 | ${SOURCES_DIR}/*.cpp |
|
44 | ${SOURCES_DIR}/*.cpp | |
49 | ${SOURCES_DIR}/*.h |
|
45 | ${SOURCES_DIR}/*.h | |
50 | ${PLUGIN_FILE}) |
|
46 | ${PROJECT_RESOURCES}) | |
51 |
|
47 | |||
52 | ADD_LIBRARY(${SQPMOCKPLUGIN_LIBRARY_NAME} ${MODULE_SOURCES}) |
|
48 | ADD_LIBRARY(${SQPMOCKPLUGIN_LIBRARY_NAME} ${MODULE_SOURCES}) | |
53 | set_property(TARGET ${SQPMOCKPLUGIN_LIBRARY_NAME} PROPERTY CXX_STANDARD 14) |
|
49 | set_property(TARGET ${SQPMOCKPLUGIN_LIBRARY_NAME} PROPERTY CXX_STANDARD 14) | |
54 | set_property(TARGET ${SQPMOCKPLUGIN_LIBRARY_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) |
|
50 | set_property(TARGET ${SQPMOCKPLUGIN_LIBRARY_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) | |
55 |
|
51 | |||
56 | INSTALL(TARGETS ${SQPMOCKPLUGIN_LIBRARY_NAME} |
|
|||
57 | RUNTIME DESTINATION ${INSTALL_BINARY_DIR} |
|
|||
58 | LIBRARY DESTINATION ${INSTALL_PLUGINS_LIBRARY_DIR} |
|
|||
59 | ARCHIVE DESTINATION ${INSTALL_PLUGINS_LIBRARY_DIR} |
|
|||
60 | ) |
|
|||
61 |
|
||||
62 |
|
||||
63 | TARGET_LINK_LIBRARIES(${SQPMOCKPLUGIN_LIBRARY_NAME} ${LIBRARIES}) |
|
52 | TARGET_LINK_LIBRARIES(${SQPMOCKPLUGIN_LIBRARY_NAME} ${LIBRARIES}) | |
64 | qt5_use_modules(${SQPMOCKPLUGIN_LIBRARY_NAME} Core Widgets) |
|
53 | qt5_use_modules(${SQPMOCKPLUGIN_LIBRARY_NAME} Core Widgets) | |
65 |
|
54 | |||
@@ -88,6 +77,12 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_INPUT_FILES) | |||||
88 | #LIST(APPEND CHECKSTYLE_EXCLUSION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/vera-exclusions/exclusions.txt) |
|
77 | #LIST(APPEND CHECKSTYLE_EXCLUSION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/vera-exclusions/exclusions.txt) | |
89 | SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_EXCLUSION_FILES) |
|
78 | SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_EXCLUSION_FILES) | |
90 |
|
79 | |||
|
80 | # Temporary target to copy to plugins dir | |||
|
81 | find_package(sciqlop-mockplugin) | |||
|
82 | ADD_CUSTOM_TARGET(plugins | |||
|
83 | COMMAND ${CMAKE_COMMAND} -E copy ${SCIQLOP-MOCKPLUGIN_LIBRARIES} "${LIBRARY_OUTPUT_PATH}/plugins/${SCIQLOP-MOCKPLUGIN_LIBRARIES_NAME}" | |||
|
84 | ) | |||
|
85 | ||||
91 | # |
|
86 | # | |
92 | # Compile the tests |
|
87 | # Compile the tests | |
93 | # |
|
88 | # | |
@@ -95,7 +90,7 IF(BUILD_TESTS) | |||||
95 | INCLUDE_DIRECTORIES(${SOURCES_DIR}) |
|
90 | INCLUDE_DIRECTORIES(${SOURCES_DIR}) | |
96 | FILE (GLOB_RECURSE TESTS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test*.cpp) |
|
91 | FILE (GLOB_RECURSE TESTS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test*.cpp) | |
97 | FILE (GLOB_RECURSE TESTS_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/Test*.h) |
|
92 | FILE (GLOB_RECURSE TESTS_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/Test*.h) | |
98 |
SET( TEST_LIBRARIES ${SQP |
|
93 | SET( TEST_LIBRARIES ${SQPGUI_LIBRARY_NAME}) | |
99 |
|
94 | |||
100 | FOREACH( testFile ${TESTS_SOURCES} ) |
|
95 | FOREACH( testFile ${TESTS_SOURCES} ) | |
101 | GET_FILENAME_COMPONENT( testDirectory ${testFile} DIRECTORY ) |
|
96 | GET_FILENAME_COMPONENT( testDirectory ${testFile} DIRECTORY ) | |
@@ -125,8 +120,6 IF(BUILD_TESTS) | |||||
125 | LIST(APPEND testFilesToFormat ${TESTS_HEADERS}) |
|
120 | LIST(APPEND testFilesToFormat ${TESTS_HEADERS}) | |
126 | LIST(APPEND FORMATTING_INPUT_FILES ${testFilesToFormat}) |
|
121 | LIST(APPEND FORMATTING_INPUT_FILES ${testFilesToFormat}) | |
127 | SCIQLOP_SET_TO_PARENT_SCOPE(FORMATTING_INPUT_FILES) |
|
122 | SCIQLOP_SET_TO_PARENT_SCOPE(FORMATTING_INPUT_FILES) | |
128 |
|
||||
129 | ADD_DEFINITIONS(-DMOCKPLUGIN_TESTS_RESOURCES_DIR="${TESTS_RESOURCES_DIR}") |
|
|||
130 | ENDIF(BUILD_TESTS) |
|
123 | ENDIF(BUILD_TESTS) | |
131 |
|
124 | |||
132 | # |
|
125 | # |
@@ -1,29 +1,27 | |||||
1 | #ifndef SCIQLOP_MOCKPLUGIN_H |
|
1 | #ifndef SCIQLOP_MOCKPLUGIN_H | |
2 | #define SCIQLOP_MOCKPLUGIN_H |
|
2 | #define SCIQLOP_MOCKPLUGIN_H | |
3 |
|
3 | |||
4 | #include "MockPluginGlobal.h" |
|
|||
5 |
|
||||
6 | #include <Plugin/IPlugin.h> |
|
4 | #include <Plugin/IPlugin.h> | |
7 |
|
5 | |||
8 | #include <QLoggingCategory> |
|
6 | #include <QLoggingCategory> | |
9 |
|
7 | |||
10 | #include <memory> |
|
8 | #include <memory> | |
11 |
|
9 | |||
12 | #ifndef PLUGIN_JSON_FILE_PATH |
|
|||
13 | #define PLUGIN_JSON_FILE_PATH "mockplugin.json" |
|
|||
14 | #endif |
|
|||
15 |
|
||||
16 | Q_DECLARE_LOGGING_CATEGORY(LOG_MockPlugin) |
|
10 | Q_DECLARE_LOGGING_CATEGORY(LOG_MockPlugin) | |
17 |
|
11 | |||
18 | class DataSourceItem; |
|
12 | class DataSourceItem; | |
19 |
|
13 | |||
20 |
class |
|
14 | class MockPlugin : public QObject, public IPlugin { | |
21 | Q_OBJECT |
|
15 | Q_OBJECT | |
22 | Q_INTERFACES(IPlugin) |
|
16 | Q_INTERFACES(IPlugin) | |
23 |
Q_PLUGIN_METADATA(IID "sciqlop.plugin.IPlugin" FILE |
|
17 | Q_PLUGIN_METADATA(IID "sciqlop.plugin.IPlugin" FILE "mockplugin.json") | |
24 | public: |
|
18 | public: | |
25 | /// @sa IPlugin::initialize() |
|
19 | /// @sa IPlugin::initialize() | |
26 | void initialize() override; |
|
20 | void initialize() override; | |
|
21 | ||||
|
22 | private: | |||
|
23 | /// Creates the data source item relative to the plugin | |||
|
24 | std::unique_ptr<DataSourceItem> createDataSourceItem() const noexcept; | |||
27 | }; |
|
25 | }; | |
28 |
|
26 | |||
29 | #endif // SCIQLOP_MOCKPLUGIN_H |
|
27 | #endif // SCIQLOP_MOCKPLUGIN_H |
@@ -1,9 +1,7 | |||||
1 |
#include |
|
1 | #include <MockPlugin.h> | |
2 | #include "CosinusProvider.h" |
|
|||
3 |
|
2 | |||
4 | #include <DataSource/DataSourceController.h> |
|
3 | #include <DataSource/DataSourceController.h> | |
5 | #include <DataSource/DataSourceItem.h> |
|
4 | #include <DataSource/DataSourceItem.h> | |
6 | #include <DataSource/DataSourceItemAction.h> |
|
|||
7 |
|
5 | |||
8 | #include <SqpApplication.h> |
|
6 | #include <SqpApplication.h> | |
9 |
|
7 | |||
@@ -14,66 +12,44 namespace { | |||||
14 | /// Name of the data source |
|
12 | /// Name of the data source | |
15 | const auto DATA_SOURCE_NAME = QStringLiteral("MMS"); |
|
13 | const auto DATA_SOURCE_NAME = QStringLiteral("MMS"); | |
16 |
|
14 | |||
17 | /// Creates the data provider relative to the plugin |
|
15 | } // namespace | |
18 | std::unique_ptr<IDataProvider> createDataProvider() noexcept |
|
|||
19 | { |
|
|||
20 | return std::make_unique<CosinusProvider>(); |
|
|||
21 | } |
|
|||
22 |
|
16 | |||
23 | std::unique_ptr<DataSourceItem> createProductItem(const QString &productName, |
|
17 | void MockPlugin::initialize() | |
24 | const QUuid &dataSourceUid) |
|
|||
25 | { |
|
18 | { | |
26 | auto result = std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, productName); |
|
19 | if (auto app = sqpApp) { | |
27 |
|
20 | // Registers to the data source controller | ||
28 | // Add action to load product from DataSourceController |
|
21 | auto &dataSourceController = app->dataSourceController(); | |
29 | result->addAction(std::make_unique<DataSourceItemAction>( |
|
22 | auto dataSourceUid = dataSourceController.registerDataSource(DATA_SOURCE_NAME); | |
30 | QObject::tr("Load %1 product").arg(productName), |
|
|||
31 | [productName, dataSourceUid](DataSourceItem &item) { |
|
|||
32 | if (auto app = sqpApp) { |
|
|||
33 | app->dataSourceController().loadProductItem(dataSourceUid, item); |
|
|||
34 | } |
|
|||
35 | })); |
|
|||
36 |
|
23 | |||
37 | return result; |
|
24 | dataSourceController.setDataSourceItem(dataSourceUid, createDataSourceItem()); | |
|
25 | } | |||
|
26 | else { | |||
|
27 | qCWarning(LOG_MockPlugin()) << tr("Can't access to SciQlop application"); | |||
|
28 | } | |||
38 | } |
|
29 | } | |
39 |
|
30 | |||
40 | /// Creates the data source item relative to the plugin |
|
31 | std::unique_ptr<DataSourceItem> MockPlugin::createDataSourceItem() const noexcept | |
41 | std::unique_ptr<DataSourceItem> createDataSourceItem(const QUuid &dataSourceUid) noexcept |
|
|||
42 | { |
|
32 | { | |
43 | // Magnetic field products |
|
33 | // Magnetic field products | |
44 |
auto |
|
34 | auto fgmProduct = std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, | |
45 |
|
|
35 | QVector<QVariant>{QStringLiteral("FGM")}); | |
46 | magneticFieldFolder->appendChild(createProductItem(QStringLiteral("FGM"), dataSourceUid)); |
|
36 | auto scProduct = std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, | |
47 | magneticFieldFolder->appendChild(createProductItem(QStringLiteral("SC"), dataSourceUid)); |
|
37 | QVector<QVariant>{QStringLiteral("SC")}); | |
|
38 | ||||
|
39 | auto magneticFieldFolder = std::make_unique<DataSourceItem>( | |||
|
40 | DataSourceItemType::NODE, QVector<QVariant>{QStringLiteral("Magnetic field")}); | |||
|
41 | magneticFieldFolder->appendChild(std::move(fgmProduct)); | |||
|
42 | magneticFieldFolder->appendChild(std::move(scProduct)); | |||
48 |
|
43 | |||
49 | // Electric field products |
|
44 | // Electric field products | |
50 |
auto electricFieldFolder = std::make_unique<DataSourceItem>( |
|
45 | auto electricFieldFolder = std::make_unique<DataSourceItem>( | |
51 | QStringLiteral("Electric field")); |
|
46 | DataSourceItemType::NODE, QVector<QVariant>{QStringLiteral("Electric field")}); | |
52 |
|
47 | |||
53 | // Root |
|
48 | // Root | |
54 |
auto root = std::make_unique<DataSourceItem>(DataSourceItemType::NODE, |
|
49 | auto root = std::make_unique<DataSourceItem>(DataSourceItemType::NODE, | |
|
50 | QVector<QVariant>{DATA_SOURCE_NAME}); | |||
55 | root->appendChild(std::move(magneticFieldFolder)); |
|
51 | root->appendChild(std::move(magneticFieldFolder)); | |
56 | root->appendChild(std::move(electricFieldFolder)); |
|
52 | root->appendChild(std::move(electricFieldFolder)); | |
57 |
|
53 | |||
58 | return root; |
|
54 | return std::move(root); | |
59 | } |
|
|||
60 |
|
||||
61 | } // namespace |
|
|||
62 |
|
||||
63 | void MockPlugin::initialize() |
|
|||
64 | { |
|
|||
65 | if (auto app = sqpApp) { |
|
|||
66 | // Registers to the data source controller |
|
|||
67 | auto &dataSourceController = app->dataSourceController(); |
|
|||
68 | auto dataSourceUid = dataSourceController.registerDataSource(DATA_SOURCE_NAME); |
|
|||
69 |
|
||||
70 | // Sets data source tree |
|
|||
71 | dataSourceController.setDataSourceItem(dataSourceUid, createDataSourceItem(dataSourceUid)); |
|
|||
72 |
|
||||
73 | // Sets data provider |
|
|||
74 | dataSourceController.setDataProvider(dataSourceUid, createDataProvider()); |
|
|||
75 | } |
|
|||
76 | else { |
|
|||
77 | qCWarning(LOG_MockPlugin()) << tr("Can't access to SciQlop application"); |
|
|||
78 | } |
|
|||
79 | } |
|
55 | } |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed | ||
This diff has been collapsed as it changes many lines, (674 lines changed) Show them Hide them |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed | ||
This diff has been collapsed as it changes many lines, (636 lines changed) Show them Hide them |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed | ||
This diff has been collapsed as it changes many lines, (22288 lines changed) Show them Hide them |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed | ||
This diff has been collapsed as it changes many lines, (29129 lines changed) Show them Hide them |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed | ||
This diff has been collapsed as it changes many lines, (10802 lines changed) Show them Hide them |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed | ||
This diff has been collapsed as it changes many lines, (360000 lines changed) Show them Hide them |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 1