##// END OF EJS Templates
Ported Mock plugin to new IDataProvider interface compatible with...
jeandet -
r1350:09a8c8a01145
parent child
Show More
@@ -1,1 +1,1
1 Subproject commit de55e7be90966d1efbd34a10df9a3231c50e245b
1 Subproject commit c08d1b8ad2976824def52cf0fca26a72b1069356
@@ -1,308 +1,308
1 #include "DragAndDrop/DragDropGuiController.h"
1 #include "DragAndDrop/DragDropGuiController.h"
2 #include "DragAndDrop/DragDropScroller.h"
2 #include "DragAndDrop/DragDropScroller.h"
3 #include "DragAndDrop/DragDropTabSwitcher.h"
3 #include "DragAndDrop/DragDropTabSwitcher.h"
4 #include "SqpApplication.h"
4 #include "SqpApplication.h"
5 #include "Visualization/VisualizationDragDropContainer.h"
5 #include "Visualization/VisualizationDragDropContainer.h"
6 #include "Visualization/VisualizationDragWidget.h"
6 #include "Visualization/VisualizationDragWidget.h"
7 #include "Visualization/VisualizationWidget.h"
7 #include "Visualization/VisualizationWidget.h"
8 #include "Visualization/operations/FindVariableOperation.h"
8 #include "Visualization/operations/FindVariableOperation.h"
9
9
10 #include "DataSource/DataSourceController.h"
10 #include "DataSource/DataSourceController.h"
11 #include "Variable/Variable.h"
11 #include "Variable/Variable.h"
12 #include "Variable/VariableController2.h"
12 #include "Variable/VariableController2.h"
13
13
14 #include "Common/MimeTypesDef.h"
14 #include "Common/MimeTypesDef.h"
15 #include "Common/VisualizationDef.h"
15 #include "Common/VisualizationDef.h"
16
16
17 #include <QDir>
17 #include <QDir>
18 #include <QLabel>
18 #include <QLabel>
19 #include <QUrl>
19 #include <QUrl>
20 #include <QVBoxLayout>
20 #include <QVBoxLayout>
21
21
22
22
23 Q_LOGGING_CATEGORY(LOG_DragDropGuiController, "DragDropGuiController")
23 Q_LOGGING_CATEGORY(LOG_DragDropGuiController, "DragDropGuiController")
24
24
25
25
26 struct DragDropGuiController::DragDropGuiControllerPrivate {
26 struct DragDropGuiController::DragDropGuiControllerPrivate {
27
27
28 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
28 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
29 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
29 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
30 QLabel *m_PlaceHolderLabel;
30 QLabel *m_PlaceHolderLabel;
31 QWidget *m_PlaceBackground;
31 QWidget *m_PlaceBackground;
32 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
32 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
33 std::unique_ptr<DragDropTabSwitcher> m_DragDropTabSwitcher = nullptr;
33 std::unique_ptr<DragDropTabSwitcher> m_DragDropTabSwitcher = nullptr;
34 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
34 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
35 // QTemporaryFile to have a name which is not generated.
35 // QTemporaryFile to have a name which is not generated.
36
36
37 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
37 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
38
38
39 QMetaObject::Connection m_DragWidgetDestroyedConnection;
39 QMetaObject::Connection m_DragWidgetDestroyedConnection;
40 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
40 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
41
41
42 QList<QWidget *> m_WidgetToClose;
42 QList<QWidget *> m_WidgetToClose;
43
43
44 explicit DragDropGuiControllerPrivate()
44 explicit DragDropGuiControllerPrivate()
45 : m_PlaceHolder{std::make_unique<QWidget>()},
45 : m_PlaceHolder{std::make_unique<QWidget>()},
46 m_DragDropScroller{std::make_unique<DragDropScroller>()},
46 m_DragDropScroller{std::make_unique<DragDropScroller>()},
47 m_DragDropTabSwitcher{std::make_unique<DragDropTabSwitcher>()}
47 m_DragDropTabSwitcher{std::make_unique<DragDropTabSwitcher>()}
48 {
48 {
49
49
50 auto layout = new QVBoxLayout{m_PlaceHolder.get()};
50 auto layout = new QVBoxLayout{m_PlaceHolder.get()};
51 layout->setSpacing(0);
51 layout->setSpacing(0);
52 layout->setContentsMargins(0, 0, 0, 0);
52 layout->setContentsMargins(0, 0, 0, 0);
53
53
54 m_PlaceHolderLabel = new QLabel{"", m_PlaceHolder.get()};
54 m_PlaceHolderLabel = new QLabel{"", m_PlaceHolder.get()};
55 m_PlaceHolderLabel->setMinimumHeight(25);
55 m_PlaceHolderLabel->setMinimumHeight(25);
56 layout->addWidget(m_PlaceHolderLabel);
56 layout->addWidget(m_PlaceHolderLabel);
57
57
58 m_PlaceBackground = new QWidget{m_PlaceHolder.get()};
58 m_PlaceBackground = new QWidget{m_PlaceHolder.get()};
59 m_PlaceBackground->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
59 m_PlaceBackground->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
60 layout->addWidget(m_PlaceBackground);
60 layout->addWidget(m_PlaceBackground);
61
61
62 sqpApp->installEventFilter(m_DragDropScroller.get());
62 sqpApp->installEventFilter(m_DragDropScroller.get());
63 sqpApp->installEventFilter(m_DragDropTabSwitcher.get());
63 sqpApp->installEventFilter(m_DragDropTabSwitcher.get());
64
64
65 m_ImageTempUrl = QDir::temp().absoluteFilePath("Sciqlop_graph.png");
65 m_ImageTempUrl = QDir::temp().absoluteFilePath("Sciqlop_graph.png");
66 }
66 }
67
67
68 void preparePlaceHolder(DragDropGuiController::PlaceHolderType type,
68 void preparePlaceHolder(DragDropGuiController::PlaceHolderType type,
69 const QString &topLabelText) const
69 const QString &topLabelText) const
70 {
70 {
71 if (m_CurrentDragWidget) {
71 if (m_CurrentDragWidget) {
72 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
72 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
73 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
73 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
74 }
74 }
75 else {
75 else {
76 // Configuration of the placeHolder when there is no dragWidget
76 // Configuration of the placeHolder when there is no dragWidget
77 // (for instance with a drag from a variable)
77 // (for instance with a drag from a variable)
78
78
79 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
79 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
80 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
80 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
81 }
81 }
82
82
83 switch (type) {
83 switch (type) {
84 case DragDropGuiController::PlaceHolderType::Graph:
84 case DragDropGuiController::PlaceHolderType::Graph:
85 m_PlaceBackground->setStyleSheet(
85 m_PlaceBackground->setStyleSheet(
86 "background-color: #BBD5EE; border: 1px solid #2A7FD4");
86 "background-color: #BBD5EE; border: 1px solid #2A7FD4");
87 break;
87 break;
88 case DragDropGuiController::PlaceHolderType::Zone:
88 case DragDropGuiController::PlaceHolderType::Zone:
89 case DragDropGuiController::PlaceHolderType::Default:
89 case DragDropGuiController::PlaceHolderType::Default:
90 m_PlaceBackground->setStyleSheet(
90 m_PlaceBackground->setStyleSheet(
91 "background-color: #BBD5EE; border: 2px solid #2A7FD4");
91 "background-color: #BBD5EE; border: 2px solid #2A7FD4");
92 m_PlaceHolderLabel->setStyleSheet("color: #2A7FD4");
92 m_PlaceHolderLabel->setStyleSheet("color: #2A7FD4");
93 break;
93 break;
94 }
94 }
95
95
96 m_PlaceHolderLabel->setText(topLabelText);
96 m_PlaceHolderLabel->setText(topLabelText);
97 m_PlaceHolderLabel->setVisible(!topLabelText.isEmpty());
97 m_PlaceHolderLabel->setVisible(!topLabelText.isEmpty());
98 }
98 }
99 };
99 };
100
100
101
101
102 DragDropGuiController::DragDropGuiController()
102 DragDropGuiController::DragDropGuiController()
103 : impl{spimpl::make_unique_impl<DragDropGuiControllerPrivate>()}
103 : impl{spimpl::make_unique_impl<DragDropGuiControllerPrivate>()}
104 {
104 {
105 }
105 }
106
106
107 DragDropGuiController::~DragDropGuiController()
107 DragDropGuiController::~DragDropGuiController()
108 {
108 {
109 QFile::remove(impl->m_ImageTempUrl);
109 QFile::remove(impl->m_ImageTempUrl);
110 }
110 }
111
111
112 void DragDropGuiController::resetDragAndDrop()
112 void DragDropGuiController::resetDragAndDrop()
113 {
113 {
114 setCurrentDragWidget(nullptr);
114 setCurrentDragWidget(nullptr);
115 impl->m_HighlightedDragWidget = nullptr;
115 impl->m_HighlightedDragWidget = nullptr;
116 }
116 }
117
117
118 void DragDropGuiController::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
118 void DragDropGuiController::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
119 {
119 {
120 if (impl->m_CurrentDragWidget) {
120 if (impl->m_CurrentDragWidget) {
121
121
122 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
122 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
123 }
123 }
124
124
125 if (dragWidget) {
125 if (dragWidget) {
126 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
126 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
127 impl->m_DragWidgetDestroyedConnection
127 impl->m_DragWidgetDestroyedConnection
128 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
128 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
129 [this]() { impl->m_CurrentDragWidget = nullptr; });
129 [this]() { impl->m_CurrentDragWidget = nullptr; });
130 }
130 }
131
131
132 impl->m_CurrentDragWidget = dragWidget;
132 impl->m_CurrentDragWidget = dragWidget;
133 }
133 }
134
134
135 VisualizationDragWidget *DragDropGuiController::getCurrentDragWidget() const
135 VisualizationDragWidget *DragDropGuiController::getCurrentDragWidget() const
136 {
136 {
137 return impl->m_CurrentDragWidget;
137 return impl->m_CurrentDragWidget;
138 }
138 }
139
139
140 QWidget &DragDropGuiController::placeHolder() const
140 QWidget &DragDropGuiController::placeHolder() const
141 {
141 {
142 return *impl->m_PlaceHolder;
142 return *impl->m_PlaceHolder;
143 }
143 }
144
144
145 void DragDropGuiController::insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
145 void DragDropGuiController::insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
146 const QString &topLabelText)
146 const QString &topLabelText)
147 {
147 {
148 removePlaceHolder();
148 removePlaceHolder();
149 impl->preparePlaceHolder(type, topLabelText);
149 impl->preparePlaceHolder(type, topLabelText);
150 layout->insertWidget(index, impl->m_PlaceHolder.get());
150 layout->insertWidget(index, impl->m_PlaceHolder.get());
151 impl->m_PlaceHolder->show();
151 impl->m_PlaceHolder->show();
152 }
152 }
153
153
154 void DragDropGuiController::removePlaceHolder()
154 void DragDropGuiController::removePlaceHolder()
155 {
155 {
156 auto parentWidget = impl->m_PlaceHolder->parentWidget();
156 auto parentWidget = impl->m_PlaceHolder->parentWidget();
157 if (parentWidget) {
157 if (parentWidget) {
158 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
158 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
159 impl->m_PlaceHolder->setParent(nullptr);
159 impl->m_PlaceHolder->setParent(nullptr);
160 impl->m_PlaceHolder->hide();
160 impl->m_PlaceHolder->hide();
161 }
161 }
162 }
162 }
163
163
164 bool DragDropGuiController::isPlaceHolderSet() const
164 bool DragDropGuiController::isPlaceHolderSet() const
165 {
165 {
166 return impl->m_PlaceHolder->parentWidget();
166 return impl->m_PlaceHolder->parentWidget();
167 }
167 }
168
168
169 void DragDropGuiController::addDragDropScrollArea(QScrollArea *scrollArea)
169 void DragDropGuiController::addDragDropScrollArea(QScrollArea *scrollArea)
170 {
170 {
171 impl->m_DragDropScroller->addScrollArea(scrollArea);
171 impl->m_DragDropScroller->addScrollArea(scrollArea);
172 }
172 }
173
173
174 void DragDropGuiController::removeDragDropScrollArea(QScrollArea *scrollArea)
174 void DragDropGuiController::removeDragDropScrollArea(QScrollArea *scrollArea)
175 {
175 {
176 impl->m_DragDropScroller->removeScrollArea(scrollArea);
176 impl->m_DragDropScroller->removeScrollArea(scrollArea);
177 }
177 }
178
178
179 void DragDropGuiController::addDragDropTabBar(QTabBar *tabBar)
179 void DragDropGuiController::addDragDropTabBar(QTabBar *tabBar)
180 {
180 {
181 impl->m_DragDropTabSwitcher->addTabBar(tabBar);
181 impl->m_DragDropTabSwitcher->addTabBar(tabBar);
182 }
182 }
183
183
184 void DragDropGuiController::removeDragDropTabBar(QTabBar *tabBar)
184 void DragDropGuiController::removeDragDropTabBar(QTabBar *tabBar)
185 {
185 {
186 impl->m_DragDropTabSwitcher->removeTabBar(tabBar);
186 impl->m_DragDropTabSwitcher->removeTabBar(tabBar);
187 }
187 }
188
188
189 QUrl DragDropGuiController::imageTemporaryUrl(const QImage &image) const
189 QUrl DragDropGuiController::imageTemporaryUrl(const QImage &image) const
190 {
190 {
191 image.save(impl->m_ImageTempUrl);
191 image.save(impl->m_ImageTempUrl);
192 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
192 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
193 }
193 }
194
194
195 void DragDropGuiController::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
195 void DragDropGuiController::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
196 {
196 {
197 if (impl->m_HighlightedDragWidget) {
197 if (impl->m_HighlightedDragWidget) {
198 impl->m_HighlightedDragWidget->highlightForMerge(false);
198 impl->m_HighlightedDragWidget->highlightForMerge(false);
199 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
199 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
200 }
200 }
201
201
202 if (dragWidget) {
202 if (dragWidget) {
203 dragWidget->highlightForMerge(true);
203 dragWidget->highlightForMerge(true);
204
204
205 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
205 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
206 impl->m_DragWidgetDestroyedConnection
206 impl->m_DragWidgetDestroyedConnection
207 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
207 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
208 [this]() { impl->m_HighlightedDragWidget = nullptr; });
208 [this]() { impl->m_HighlightedDragWidget = nullptr; });
209 }
209 }
210
210
211 impl->m_HighlightedDragWidget = dragWidget;
211 impl->m_HighlightedDragWidget = dragWidget;
212 }
212 }
213
213
214 VisualizationDragWidget *DragDropGuiController::getHightlightedDragWidget() const
214 VisualizationDragWidget *DragDropGuiController::getHightlightedDragWidget() const
215 {
215 {
216 return impl->m_HighlightedDragWidget;
216 return impl->m_HighlightedDragWidget;
217 }
217 }
218
218
219 void DragDropGuiController::delayedCloseWidget(QWidget *widget)
219 void DragDropGuiController::delayedCloseWidget(QWidget *widget)
220 {
220 {
221 widget->hide();
221 widget->hide();
222 impl->m_WidgetToClose << widget;
222 impl->m_WidgetToClose << widget;
223 }
223 }
224
224
225 void DragDropGuiController::doCloseWidgets()
225 void DragDropGuiController::doCloseWidgets()
226 {
226 {
227 for (auto widget : impl->m_WidgetToClose) {
227 for (auto widget : impl->m_WidgetToClose) {
228 widget->close();
228 widget->close();
229 }
229 }
230
230
231 impl->m_WidgetToClose.clear();
231 impl->m_WidgetToClose.clear();
232 }
232 }
233
233
234 bool DragDropGuiController::checkMimeDataForVisualization(
234 bool DragDropGuiController::checkMimeDataForVisualization(
235 const QMimeData *mimeData, VisualizationDragDropContainer *dropContainer)
235 const QMimeData *mimeData, VisualizationDragDropContainer *dropContainer)
236 {
236 {
237 if (!mimeData || !dropContainer) {
237 if (!mimeData || !dropContainer) {
238 qCWarning(LOG_DragDropGuiController()) << QObject::tr(
238 qCWarning(LOG_DragDropGuiController()) << QObject::tr(
239 "DragDropGuiController::checkMimeDataForVisualization, invalid input parameters.");
239 "DragDropGuiController::checkMimeDataForVisualization, invalid input parameters.");
240 Q_ASSERT(false);
240 Q_ASSERT(false);
241 return false;
241 return false;
242 }
242 }
243
243
244 auto result = false;
244 auto result = false;
245
245
246 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
246 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
247 auto variables = sqpApp->variableController().variables(
247 auto variables = sqpApp->variableController().variables(
248 mimeData->data(MIME_TYPE_VARIABLE_LIST));
248 Variable::variablesIDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
249
249
250 if (variables.size() == 1) {
250 if (variables.size() == 1) {
251
251
252 auto variable = variables[0];
252 auto variable = variables[0];
253 if (variable->dataSeries() != nullptr) {
253 if (variable->dataSeries() != nullptr) {
254
254
255 // Check that the variable is not already in a graph
255 // Check that the variable is not already in a graph
256
256
257 auto parent = dropContainer->parentWidget();
257 auto parent = dropContainer->parentWidget();
258 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
258 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
259 parent = parent->parentWidget(); // Search for the top level VisualizationWidget
259 parent = parent->parentWidget(); // Search for the top level VisualizationWidget
260 }
260 }
261
261
262 if (parent) {
262 if (parent) {
263 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
263 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
264
264
265 FindVariableOperation findVariableOperation{variable};
265 FindVariableOperation findVariableOperation{variable};
266 visualizationWidget->accept(&findVariableOperation);
266 visualizationWidget->accept(&findVariableOperation);
267 auto variableContainers = findVariableOperation.result();
267 auto variableContainers = findVariableOperation.result();
268 if (variableContainers.empty()) {
268 if (variableContainers.empty()) {
269 result = true;
269 result = true;
270 }
270 }
271 else {
271 else {
272 // result = false: the variable already exist in the visualisation
272 // result = false: the variable already exist in the visualisation
273 }
273 }
274 }
274 }
275 else {
275 else {
276 qCWarning(LOG_DragDropGuiController()) << QObject::tr(
276 qCWarning(LOG_DragDropGuiController()) << QObject::tr(
277 "DragDropGuiController::checkMimeDataForVisualization, the parent "
277 "DragDropGuiController::checkMimeDataForVisualization, the parent "
278 "VisualizationWidget cannot be found. Cannot check if the variable is "
278 "VisualizationWidget cannot be found. Cannot check if the variable is "
279 "already used or not.");
279 "already used or not.");
280 }
280 }
281 }
281 }
282 else {
282 else {
283 // result = false: the variable is not fully loaded
283 // result = false: the variable is not fully loaded
284 }
284 }
285 }
285 }
286 else {
286 else {
287 // result = false: cannot drop multiple variables in the visualisation
287 // result = false: cannot drop multiple variables in the visualisation
288 }
288 }
289 }
289 }
290 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
290 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
291 auto productDataList = sqpApp->dataSourceController().productsDataForMimeData(
291 auto productDataList = sqpApp->dataSourceController().productsDataForMimeData(
292 mimeData->data(MIME_TYPE_PRODUCT_LIST));
292 mimeData->data(MIME_TYPE_PRODUCT_LIST));
293 if (productDataList.count() == 1) {
293 if (productDataList.count() == 1) {
294 result = true;
294 result = true;
295 }
295 }
296 else {
296 else {
297 // result = false: cannot drop multiple products in the visualisation
297 // result = false: cannot drop multiple products in the visualisation
298 }
298 }
299 }
299 }
300 else {
300 else {
301 // Other MIME data
301 // Other MIME data
302 // no special rules, accepted by default
302 // no special rules, accepted by default
303 result = true;
303 result = true;
304 }
304 }
305
305
306
306
307 return result;
307 return result;
308 }
308 }
@@ -1,200 +1,199
1 #include "SqpApplication.h"
1 #include "SqpApplication.h"
2
2
3 #include <Actions/ActionsGuiController.h>
3 #include <Actions/ActionsGuiController.h>
4 #include <Catalogue/CatalogueController.h>
4 #include <Catalogue/CatalogueController.h>
5 #include <Data/IDataProvider.h>
5 #include <Data/IDataProvider.h>
6 #include <DataSource/DataSourceController.h>
6 #include <DataSource/DataSourceController.h>
7 #include <DragAndDrop/DragDropGuiController.h>
7 #include <DragAndDrop/DragDropGuiController.h>
8 #include <Network/NetworkController.h>
8 #include <Network/NetworkController.h>
9 #include <QThread>
9 #include <QThread>
10 #include <Time/TimeController.h>
10 #include <Time/TimeController.h>
11 #include <Variable/Variable.h>
11 #include <Variable/Variable.h>
12 #include <Variable/VariableController2.h>
12 #include <Variable/VariableController2.h>
13 #include <Variable/VariableModel2.h>
13 #include <Variable/VariableModel2.h>
14 #include <Visualization/VisualizationController.h>
14 #include <Visualization/VisualizationController.h>
15
15
16 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
16 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
17
17
18 class SqpApplication::SqpApplicationPrivate {
18 class SqpApplication::SqpApplicationPrivate {
19 public:
19 public:
20 SqpApplicationPrivate()
20 SqpApplicationPrivate()
21 : m_VariableController{std::make_shared<VariableController2>()},
21 : m_VariableController{std::make_shared<VariableController2>()},
22 m_VariableModel{m_VariableController},
23 m_PlotInterractionMode(SqpApplication::PlotsInteractionMode::None),
22 m_PlotInterractionMode(SqpApplication::PlotsInteractionMode::None),
24 m_PlotCursorMode(SqpApplication::PlotsCursorMode::NoCursor)
23 m_PlotCursorMode(SqpApplication::PlotsCursorMode::NoCursor)
25 {
24 {
26 // /////////////////////////////// //
25 // /////////////////////////////// //
27 // Connections between controllers //
26 // Connections between controllers //
28 // /////////////////////////////// //
27 // /////////////////////////////// //
29
28
30 // VariableController <-> DataSourceController
29 // VariableController <-> DataSourceController
31 connect(&m_DataSourceController,
30 connect(&m_DataSourceController,
32 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
31 &DataSourceController::createVariable,[](const QString &variableName,
33 std::shared_ptr<IDataProvider>)),
32 const QVariantHash &variableMetadata,
34 m_VariableController.get(),
33 std::shared_ptr<IDataProvider> variableProvider)
35 SLOT(createVariable(const QString &, const QVariantHash &,
34 {
36 std::shared_ptr<IDataProvider>)));
35 sqpApp->variableController().createVariable(variableName,variableMetadata,variableProvider,sqpApp->timeController().dateTime());
36 });
37
37
38 // connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
38 // connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
39 // m_DataSourceController.get(), &DataSourceController::requestVariable);
39 // m_DataSourceController.get(), &DataSourceController::requestVariable);
40
40
41 // VariableController <-> VisualizationController
41 // VariableController <-> VisualizationController
42 // connect(m_VariableController.get(),
42 // connect(m_VariableController.get(),
43 // SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
43 // SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
44 // m_VisualizationController.get(),
44 // m_VisualizationController.get(),
45 // SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
45 // SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
46
46
47 // connect(m_VariableController.get(),
47 // connect(m_VariableController.get(),
48 // SIGNAL(rangeChanged(std::shared_ptr<Variable>, const DateTimeRange &)),
48 // SIGNAL(rangeChanged(std::shared_ptr<Variable>, const DateTimeRange &)),
49 // m_VisualizationController.get(),
49 // m_VisualizationController.get(),
50 // SIGNAL(rangeChanged(std::shared_ptr<Variable>, const DateTimeRange &)));
50 // SIGNAL(rangeChanged(std::shared_ptr<Variable>, const DateTimeRange &)));
51
51
52
52
53 m_DataSourceController.moveToThread(&m_DataSourceControllerThread);
53 m_DataSourceController.moveToThread(&m_DataSourceControllerThread);
54 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
54 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
55 m_NetworkController.moveToThread(&m_NetworkControllerThread);
55 m_NetworkController.moveToThread(&m_NetworkControllerThread);
56 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
56 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
57 m_VisualizationController.moveToThread(&m_VisualizationControllerThread);
57 m_VisualizationController.moveToThread(&m_VisualizationControllerThread);
58 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
58 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
59
59
60 // Additionnal init
60 // Additionnal init
61 //m_VariableController->setTimeController(m_TimeController.get());
61 //m_VariableController->setTimeController(m_TimeController.get());
62 }
62 }
63
63
64 virtual ~SqpApplicationPrivate()
64 virtual ~SqpApplicationPrivate()
65 {
65 {
66 m_DataSourceControllerThread.quit();
66 m_DataSourceControllerThread.quit();
67 m_DataSourceControllerThread.wait();
67 m_DataSourceControllerThread.wait();
68
68
69 m_NetworkControllerThread.quit();
69 m_NetworkControllerThread.quit();
70 m_NetworkControllerThread.wait();
70 m_NetworkControllerThread.wait();
71
71
72 m_VisualizationControllerThread.quit();
72 m_VisualizationControllerThread.quit();
73 m_VisualizationControllerThread.wait();
73 m_VisualizationControllerThread.wait();
74 }
74 }
75
75
76 DataSourceController m_DataSourceController;
76 DataSourceController m_DataSourceController;
77 std::shared_ptr<VariableController2> m_VariableController;
77 std::shared_ptr<VariableController2> m_VariableController;
78 TimeController m_TimeController;
78 TimeController m_TimeController;
79 NetworkController m_NetworkController;
79 NetworkController m_NetworkController;
80 VisualizationController m_VisualizationController;
80 VisualizationController m_VisualizationController;
81 CatalogueController m_CatalogueController;
81 CatalogueController m_CatalogueController;
82 VariableModel2 m_VariableModel;
83
82
84 QThread m_DataSourceControllerThread;
83 QThread m_DataSourceControllerThread;
85 QThread m_NetworkControllerThread;
84 QThread m_NetworkControllerThread;
86 QThread m_VisualizationControllerThread;
85 QThread m_VisualizationControllerThread;
87
86
88 DragDropGuiController m_DragDropGuiController;
87 DragDropGuiController m_DragDropGuiController;
89 ActionsGuiController m_ActionsGuiController;
88 ActionsGuiController m_ActionsGuiController;
90
89
91 SqpApplication::PlotsInteractionMode m_PlotInterractionMode;
90 SqpApplication::PlotsInteractionMode m_PlotInterractionMode;
92 SqpApplication::PlotsCursorMode m_PlotCursorMode;
91 SqpApplication::PlotsCursorMode m_PlotCursorMode;
93 };
92 };
94
93
95
94
96 SqpApplication::SqpApplication(int &argc, char **argv)
95 SqpApplication::SqpApplication(int &argc, char **argv)
97 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
96 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
98 {
97 {
99 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
98 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
100
99
101 QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
100 QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
102
101
103 connect(&impl->m_DataSourceControllerThread, &QThread::started,
102 connect(&impl->m_DataSourceControllerThread, &QThread::started,
104 &impl->m_DataSourceController, &DataSourceController::initialize);
103 &impl->m_DataSourceController, &DataSourceController::initialize);
105 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
104 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
106 &impl->m_DataSourceController, &DataSourceController::finalize);
105 &impl->m_DataSourceController, &DataSourceController::finalize);
107
106
108 connect(&impl->m_NetworkControllerThread, &QThread::started, &impl->m_NetworkController,
107 connect(&impl->m_NetworkControllerThread, &QThread::started, &impl->m_NetworkController,
109 &NetworkController::initialize);
108 &NetworkController::initialize);
110 connect(&impl->m_NetworkControllerThread, &QThread::finished, &impl->m_NetworkController,
109 connect(&impl->m_NetworkControllerThread, &QThread::finished, &impl->m_NetworkController,
111 &NetworkController::finalize);
110 &NetworkController::finalize);
112
111
113 connect(&impl->m_VisualizationControllerThread, &QThread::started,
112 connect(&impl->m_VisualizationControllerThread, &QThread::started,
114 &impl->m_VisualizationController, &VisualizationController::initialize);
113 &impl->m_VisualizationController, &VisualizationController::initialize);
115 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
114 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
116 &impl->m_VisualizationController, &VisualizationController::finalize);
115 &impl->m_VisualizationController, &VisualizationController::finalize);
117
116
118 impl->m_DataSourceControllerThread.start();
117 impl->m_DataSourceControllerThread.start();
119 impl->m_NetworkControllerThread.start();
118 impl->m_NetworkControllerThread.start();
120 impl->m_VisualizationControllerThread.start();
119 impl->m_VisualizationControllerThread.start();
121 impl->m_CatalogueController.initialize();
120 impl->m_CatalogueController.initialize();
122 }
121 }
123
122
124 SqpApplication::~SqpApplication()
123 SqpApplication::~SqpApplication()
125 {
124 {
126 }
125 }
127
126
128 void SqpApplication::initialize()
127 void SqpApplication::initialize()
129 {
128 {
130 }
129 }
131
130
132 DataSourceController &SqpApplication::dataSourceController() noexcept
131 DataSourceController &SqpApplication::dataSourceController() noexcept
133 {
132 {
134 return impl->m_DataSourceController;
133 return impl->m_DataSourceController;
135 }
134 }
136
135
137 NetworkController &SqpApplication::networkController() noexcept
136 NetworkController &SqpApplication::networkController() noexcept
138 {
137 {
139 return impl->m_NetworkController;
138 return impl->m_NetworkController;
140 }
139 }
141
140
142 TimeController &SqpApplication::timeController() noexcept
141 TimeController &SqpApplication::timeController() noexcept
143 {
142 {
144 return impl->m_TimeController;
143 return impl->m_TimeController;
145 }
144 }
146
145
147 VariableController2 &SqpApplication::variableController() noexcept
146 VariableController2 &SqpApplication::variableController() noexcept
148 {
147 {
149 return *impl->m_VariableController;
148 return *impl->m_VariableController;
150 }
149 }
151
150
152 std::shared_ptr<VariableController2> SqpApplication::variableControllerOwner() noexcept
151 std::shared_ptr<VariableController2> SqpApplication::variableControllerOwner() noexcept
153 {
152 {
154 return impl->m_VariableController;
153 return impl->m_VariableController;
155 }
154 }
156
155
157 //VariableModel2 &SqpApplication::variableModel() noexcept
156 //VariableModel2 &SqpApplication::variableModel() noexcept
158 //{
157 //{
159 // return impl->m_VariableModel;
158 // return impl->m_VariableModel;
160 //}
159 //}
161
160
162 VisualizationController &SqpApplication::visualizationController() noexcept
161 VisualizationController &SqpApplication::visualizationController() noexcept
163 {
162 {
164 return impl->m_VisualizationController;
163 return impl->m_VisualizationController;
165 }
164 }
166
165
167 CatalogueController &SqpApplication::catalogueController() noexcept
166 CatalogueController &SqpApplication::catalogueController() noexcept
168 {
167 {
169 return impl->m_CatalogueController;
168 return impl->m_CatalogueController;
170 }
169 }
171
170
172 DragDropGuiController &SqpApplication::dragDropGuiController() noexcept
171 DragDropGuiController &SqpApplication::dragDropGuiController() noexcept
173 {
172 {
174 return impl->m_DragDropGuiController;
173 return impl->m_DragDropGuiController;
175 }
174 }
176
175
177 ActionsGuiController &SqpApplication::actionsGuiController() noexcept
176 ActionsGuiController &SqpApplication::actionsGuiController() noexcept
178 {
177 {
179 return impl->m_ActionsGuiController;
178 return impl->m_ActionsGuiController;
180 }
179 }
181
180
182 SqpApplication::PlotsInteractionMode SqpApplication::plotsInteractionMode() const
181 SqpApplication::PlotsInteractionMode SqpApplication::plotsInteractionMode() const
183 {
182 {
184 return impl->m_PlotInterractionMode;
183 return impl->m_PlotInterractionMode;
185 }
184 }
186
185
187 void SqpApplication::setPlotsInteractionMode(SqpApplication::PlotsInteractionMode mode)
186 void SqpApplication::setPlotsInteractionMode(SqpApplication::PlotsInteractionMode mode)
188 {
187 {
189 impl->m_PlotInterractionMode = mode;
188 impl->m_PlotInterractionMode = mode;
190 }
189 }
191
190
192 SqpApplication::PlotsCursorMode SqpApplication::plotsCursorMode() const
191 SqpApplication::PlotsCursorMode SqpApplication::plotsCursorMode() const
193 {
192 {
194 return impl->m_PlotCursorMode;
193 return impl->m_PlotCursorMode;
195 }
194 }
196
195
197 void SqpApplication::setPlotsCursorMode(SqpApplication::PlotsCursorMode mode)
196 void SqpApplication::setPlotsCursorMode(SqpApplication::PlotsCursorMode mode)
198 {
197 {
199 impl->m_PlotCursorMode = mode;
198 impl->m_PlotCursorMode = mode;
200 }
199 }
@@ -1,241 +1,251
1 #include <Variable/RenameVariableDialog.h>
1 #include <Variable/RenameVariableDialog.h>
2 #include <Variable/Variable.h>
2 #include <Variable/Variable.h>
3 #include <Variable/VariableController2.h>
3 #include <Variable/VariableController2.h>
4 #include <Variable/VariableInspectorWidget.h>
4 #include <Variable/VariableInspectorWidget.h>
5 #include <Variable/VariableMenuHeaderWidget.h>
5 #include <Variable/VariableMenuHeaderWidget.h>
6 #include <Variable/VariableModel2.h>
6 #include <Variable/VariableModel2.h>
7 #include <DataSource/DataSourceController.h>
7
8
8 #include <ui_VariableInspectorWidget.h>
9 #include <ui_VariableInspectorWidget.h>
9
10
10 #include <QMouseEvent>
11 #include <QMouseEvent>
11 #include <QSortFilterProxyModel>
12 #include <QSortFilterProxyModel>
12 #include <QStyledItemDelegate>
13 #include <QStyledItemDelegate>
13 #include <QWidgetAction>
14 #include <QWidgetAction>
14
15
15 #include <DragAndDrop/DragDropGuiController.h>
16 #include <DragAndDrop/DragDropGuiController.h>
16 #include <SqpApplication.h>
17 #include <SqpApplication.h>
17
18
18 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
19 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
19
20
20
21
21 class QProgressBarItemDelegate : public QStyledItemDelegate {
22 class QProgressBarItemDelegate : public QStyledItemDelegate {
22
23
23 public:
24 public:
24 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
25 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
25
26
26 void paint(QPainter *painter, const QStyleOptionViewItem &option,
27 void paint(QPainter *painter, const QStyleOptionViewItem &option,
27 const QModelIndex &index) const
28 const QModelIndex &index) const
28 {
29 {
29 auto data = index.data(Qt::DisplayRole);
30 auto data = index.data(Qt::DisplayRole);
30 auto progressData = index.data(VariableRoles::ProgressRole);
31 auto progressData = index.data(VariableRoles::ProgressRole);
31 if (data.isValid() && progressData.isValid()) {
32 if (data.isValid() && progressData.isValid()) {
32 auto name = data.value<QString>();
33 auto name = data.value<QString>();
33 auto progress = progressData.value<double>();
34 auto progress = progressData.value<double>();
34 if (progress > 0) {
35 if (progress > 0) {
35 auto cancelButtonWidth = 20;
36 auto cancelButtonWidth = 20;
36 auto progressBarOption = QStyleOptionProgressBar{};
37 auto progressBarOption = QStyleOptionProgressBar{};
37 auto progressRect = option.rect;
38 auto progressRect = option.rect;
38 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
39 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
39 progressBarOption.rect = progressRect;
40 progressBarOption.rect = progressRect;
40 progressBarOption.minimum = 0;
41 progressBarOption.minimum = 0;
41 progressBarOption.maximum = 100;
42 progressBarOption.maximum = 100;
42 progressBarOption.progress = progress;
43 progressBarOption.progress = progress;
43 progressBarOption.text
44 progressBarOption.text
44 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
45 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
45 progressBarOption.textVisible = true;
46 progressBarOption.textVisible = true;
46 progressBarOption.textAlignment = Qt::AlignCenter;
47 progressBarOption.textAlignment = Qt::AlignCenter;
47
48
48
49
49 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
50 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
50 painter);
51 painter);
51
52
52 // Cancel button
53 // Cancel button
53 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
54 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
54 option.rect.height());
55 option.rect.height());
55 auto buttonOption = QStyleOptionButton{};
56 auto buttonOption = QStyleOptionButton{};
56 buttonOption.rect = buttonRect;
57 buttonOption.rect = buttonRect;
57 buttonOption.text = "X";
58 buttonOption.text = "X";
58
59
59 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
60 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
60 }
61 }
61 else {
62 else {
62 QStyledItemDelegate::paint(painter, option, index);
63 QStyledItemDelegate::paint(painter, option, index);
63 }
64 }
64 }
65 }
65 else {
66 else {
66 QStyledItemDelegate::paint(painter, option, index);
67 QStyledItemDelegate::paint(painter, option, index);
67 }
68 }
68 }
69 }
69
70
70 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
71 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
71 const QModelIndex &index)
72 const QModelIndex &index)
72 {
73 {
73 if (event->type() == QEvent::MouseButtonRelease) {
74 if (event->type() == QEvent::MouseButtonRelease) {
74 auto data = index.data(Qt::DisplayRole);
75 auto data = index.data(Qt::DisplayRole);
75 auto progressData = index.data(VariableRoles::ProgressRole);
76 auto progressData = index.data(VariableRoles::ProgressRole);
76 if (data.isValid() && progressData.isValid()) {
77 if (data.isValid() && progressData.isValid()) {
77 auto cancelButtonWidth = 20;
78 auto cancelButtonWidth = 20;
78 auto progressRect = option.rect;
79 auto progressRect = option.rect;
79 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
80 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
80 // Cancel button
81 // Cancel button
81 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
82 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
82 option.rect.height());
83 option.rect.height());
83
84
84 auto e = (QMouseEvent *)event;
85 auto e = (QMouseEvent *)event;
85 auto clickX = e->x();
86 auto clickX = e->x();
86 auto clickY = e->y();
87 auto clickY = e->y();
87
88
88 auto x = buttonRect.left(); // the X coordinate
89 auto x = buttonRect.left(); // the X coordinate
89 auto y = buttonRect.top(); // the Y coordinate
90 auto y = buttonRect.top(); // the Y coordinate
90 auto w = buttonRect.width(); // button width
91 auto w = buttonRect.width(); // button width
91 auto h = buttonRect.height(); // button height
92 auto h = buttonRect.height(); // button height
92
93
93 if (clickX > x && clickX < x + w) {
94 if (clickX > x && clickX < x + w) {
94 if (clickY > y && clickY < y + h) {
95 if (clickY > y && clickY < y + h) {
95 //auto& variableModel = sqpApp->variableModel();
96 //auto& variableModel = sqpApp->variableModel();
96 //variableModel->abortProgress(index);
97 //variableModel->abortProgress(index);
97 }
98 }
98 return true;
99 return true;
99 }
100 }
100 else {
101 else {
101 return QStyledItemDelegate::editorEvent(event, model, option, index);
102 return QStyledItemDelegate::editorEvent(event, model, option, index);
102 }
103 }
103 }
104 }
104 else {
105 else {
105 return QStyledItemDelegate::editorEvent(event, model, option, index);
106 return QStyledItemDelegate::editorEvent(event, model, option, index);
106 }
107 }
107 }
108 }
108 else {
109 else {
109 return QStyledItemDelegate::editorEvent(event, model, option, index);
110 return QStyledItemDelegate::editorEvent(event, model, option, index);
110 }
111 }
111
112
112
113
113 return QStyledItemDelegate::editorEvent(event, model, option, index);
114 return QStyledItemDelegate::editorEvent(event, model, option, index);
114 }
115 }
115 };
116 };
116
117
117 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
118 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
118 : QWidget{parent},
119 : QWidget{parent},
119 ui{new Ui::VariableInspectorWidget},
120 ui{new Ui::VariableInspectorWidget},
120 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
121 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
121 {
122 {
122 ui->setupUi(this);
123 ui->setupUi(this);
123
124
124 // Sets model for table
125 // Sets model for table
125 // auto sortFilterModel = new QSortFilterProxyModel{this};
126 // auto sortFilterModel = new QSortFilterProxyModel{this};
126 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
127 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
127
128
128 m_model = new VariableModel2(sqpApp->variableControllerOwner());
129 m_model = new VariableModel2();
129 ui->tableView->setModel(m_model);
130 ui->tableView->setModel(m_model);
131 connect(m_model, &VariableModel2::createVariable,
132 [](const QVariantHash &productData)
133 {
134 sqpApp->dataSourceController().requestVariable(productData);
135 });
136 auto vc = &(sqpApp->variableController());
137 connect(vc, &VariableController2::variableAdded, m_model, &VariableModel2::variableAdded);
138 connect(vc, &VariableController2::variableDeleted, m_model, &VariableModel2::variableDeleted);
139 connect(m_model, &VariableModel2::asyncChangeRange, vc, &VariableController2::asyncChangeRange);
130
140
131 // Adds extra signal/slot between view and model, so the view can be updated instantly when
141 // Adds extra signal/slot between view and model, so the view can be updated instantly when
132 // there is a change of data in the model
142 // there is a change of data in the model
133 connect(m_model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
143 //connect(m_model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
134 SLOT(refresh()));
144 // SLOT(refresh()));
135
145
136 //ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
146 //ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
137 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
147 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
138
148
139 // Fixes column sizes
149 // Fixes column sizes
140 auto model = ui->tableView->model();
150 auto model = ui->tableView->model();
141 const auto count = model->columnCount();
151 const auto count = model->columnCount();
142 for (auto i = 0; i < count; ++i) {
152 for (auto i = 0; i < count; ++i) {
143 ui->tableView->setColumnWidth(
153 ui->tableView->setColumnWidth(
144 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
154 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
145 }
155 }
146
156
147 // Sets selection options
157 // Sets selection options
148 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
158 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
149 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
159 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
150
160
151 // Connection to show a menu when right clicking on the tree
161 // Connection to show a menu when right clicking on the tree
152 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
162 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
153 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
163 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
154 &VariableInspectorWidget::onTableMenuRequested);
164 &VariableInspectorWidget::onTableMenuRequested);
155 }
165 }
156
166
157 VariableInspectorWidget::~VariableInspectorWidget()
167 VariableInspectorWidget::~VariableInspectorWidget()
158 {
168 {
159 delete ui;
169 delete ui;
160 }
170 }
161
171
162 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
172 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
163 {
173 {
164 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
174 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
165
175
166 // Gets the model to retrieve the underlying selected variables
176 // Gets the model to retrieve the underlying selected variables
167 auto& vc = sqpApp->variableController();
177 auto& vc = sqpApp->variableController();
168 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
178 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
169 for (const auto &selectedRow : qAsConst(selectedRows)) {
179 for (const auto &selectedRow : qAsConst(selectedRows)) {
170 if (auto selectedVariable = vc[selectedRow.row()]) {
180 if (auto selectedVariable = vc[selectedRow.row()]) {
171 selectedVariables.push_back(selectedVariable);
181 selectedVariables.push_back(selectedVariable);
172 }
182 }
173 }
183 }
174
184
175 QMenu tableMenu{};
185 QMenu tableMenu{};
176
186
177 // Emits a signal so that potential receivers can populate the menu before displaying it
187 // Emits a signal so that potential receivers can populate the menu before displaying it
178 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
188 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
179
189
180 // Adds menu-specific actions
190 // Adds menu-specific actions
181 if (!selectedVariables.isEmpty()) {
191 if (!selectedVariables.isEmpty()) {
182 tableMenu.addSeparator();
192 tableMenu.addSeparator();
183
193
184 // 'Rename' and 'Duplicate' actions (only if one variable selected)
194 // 'Rename' and 'Duplicate' actions (only if one variable selected)
185 if (selectedVariables.size() == 1) {
195 if (selectedVariables.size() == 1) {
186 auto selectedVariable = selectedVariables.front();
196 auto selectedVariable = selectedVariables.front();
187
197
188 auto duplicateFun = [varW = std::weak_ptr<Variable>(selectedVariable)]()
198 auto duplicateFun = [varW = std::weak_ptr<Variable>(selectedVariable)]()
189 {
199 {
190 if (auto var = varW.lock()) {
200 if (auto var = varW.lock()) {
191 sqpApp->variableController().cloneVariable(var);
201 sqpApp->variableController().cloneVariable(var);
192 }
202 }
193 };
203 };
194
204
195 tableMenu.addAction(tr("Duplicate"), duplicateFun);
205 tableMenu.addAction(tr("Duplicate"), duplicateFun);
196
206
197 auto renameFun = [ varW = std::weak_ptr<Variable>(selectedVariable), this ]()
207 auto renameFun = [ varW = std::weak_ptr<Variable>(selectedVariable), this ]()
198 {
208 {
199 if (auto var = varW.lock()) {
209 if (auto var = varW.lock()) {
200 // Generates forbidden names (names associated to existing variables)
210 // Generates forbidden names (names associated to existing variables)
201 auto allVariables = sqpApp->variableController().variables();
211 auto allVariables = sqpApp->variableController().variables();
202 auto forbiddenNames = QVector<QString>(allVariables.size());
212 auto forbiddenNames = QVector<QString>(allVariables.size());
203 std::transform(allVariables.cbegin(), allVariables.cend(),
213 std::transform(allVariables.cbegin(), allVariables.cend(),
204 forbiddenNames.begin(),
214 forbiddenNames.begin(),
205 [](const auto &variable) { return variable->name(); });
215 [](const auto &variable) { return variable->name(); });
206
216
207 RenameVariableDialog dialog{var->name(), forbiddenNames, this};
217 RenameVariableDialog dialog{var->name(), forbiddenNames, this};
208 if (dialog.exec() == QDialog::Accepted) {
218 if (dialog.exec() == QDialog::Accepted) {
209 var->setName(dialog.name());
219 var->setName(dialog.name());
210 }
220 }
211 }
221 }
212 };
222 };
213
223
214 tableMenu.addAction(tr("Rename..."), renameFun);
224 tableMenu.addAction(tr("Rename..."), renameFun);
215 }
225 }
216
226
217 // 'Delete' action
227 // 'Delete' action
218 auto deleteFun = [&selectedVariables]() {
228 auto deleteFun = [&selectedVariables]() {
219 for(const auto& var:selectedVariables)
229 for(const auto& var:selectedVariables)
220 sqpApp->variableController().deleteVariable(var);
230 sqpApp->variableController().deleteVariable(var);
221 };
231 };
222
232
223 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
233 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
224 }
234 }
225
235
226 if (!tableMenu.isEmpty()) {
236 if (!tableMenu.isEmpty()) {
227 // Generates menu header (inserted before first action)
237 // Generates menu header (inserted before first action)
228 auto firstAction = tableMenu.actions().first();
238 auto firstAction = tableMenu.actions().first();
229 auto headerAction = new QWidgetAction{&tableMenu};
239 auto headerAction = new QWidgetAction{&tableMenu};
230 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
240 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
231 tableMenu.insertAction(firstAction, headerAction);
241 tableMenu.insertAction(firstAction, headerAction);
232
242
233 // Displays menu
243 // Displays menu
234 tableMenu.exec(QCursor::pos());
244 tableMenu.exec(QCursor::pos());
235 }
245 }
236 }
246 }
237
247
238 void VariableInspectorWidget::refresh() noexcept
248 void VariableInspectorWidget::refresh() noexcept
239 {
249 {
240 ui->tableView->viewport()->update();
250 ui->tableView->viewport()->update();
241 }
251 }
@@ -1,389 +1,389
1 #include "Visualization/VisualizationTabWidget.h"
1 #include "Visualization/VisualizationTabWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "ui_VisualizationTabWidget.h"
3 #include "ui_VisualizationTabWidget.h"
4
4
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7
7
8 #include "Visualization/MacScrollBarStyle.h"
8 #include "Visualization/MacScrollBarStyle.h"
9
9
10 #include "DataSource/DataSourceController.h"
10 #include "DataSource/DataSourceController.h"
11 #include "Variable/VariableController2.h"
11 #include "Variable/VariableController2.h"
12
12
13 #include "Common/MimeTypesDef.h"
13 #include "Common/MimeTypesDef.h"
14
14
15 #include "DragAndDrop/DragDropGuiController.h"
15 #include "DragAndDrop/DragDropGuiController.h"
16 #include "SqpApplication.h"
16 #include "SqpApplication.h"
17
17
18 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
18 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
19
19
20 namespace {
20 namespace {
21
21
22 /**
22 /**
23 * Applies a function to all zones of the tab represented by its layout
23 * Applies a function to all zones of the tab represented by its layout
24 * @param layout the layout that contains zones
24 * @param layout the layout that contains zones
25 * @param fun the function to apply to each zone
25 * @param fun the function to apply to each zone
26 */
26 */
27 template <typename Fun>
27 template <typename Fun>
28 void processZones(QLayout &layout, Fun fun)
28 void processZones(QLayout &layout, Fun fun)
29 {
29 {
30 for (auto i = 0; i < layout.count(); ++i) {
30 for (auto i = 0; i < layout.count(); ++i) {
31 if (auto item = layout.itemAt(i)) {
31 if (auto item = layout.itemAt(i)) {
32 if (auto visualizationZoneWidget
32 if (auto visualizationZoneWidget
33 = qobject_cast<VisualizationZoneWidget *>(item->widget())) {
33 = qobject_cast<VisualizationZoneWidget *>(item->widget())) {
34 fun(*visualizationZoneWidget);
34 fun(*visualizationZoneWidget);
35 }
35 }
36 }
36 }
37 }
37 }
38 }
38 }
39
39
40 /// Generates a default name for a new zone, according to the number of zones already displayed in
40 /// Generates a default name for a new zone, according to the number of zones already displayed in
41 /// the tab
41 /// the tab
42 QString defaultZoneName(QLayout &layout)
42 QString defaultZoneName(QLayout &layout)
43 {
43 {
44 QSet<QString> existingNames;
44 QSet<QString> existingNames;
45 processZones(layout,
45 processZones(layout,
46 [&existingNames](auto &zoneWidget) { existingNames.insert(zoneWidget.name()); });
46 [&existingNames](auto &zoneWidget) { existingNames.insert(zoneWidget.name()); });
47
47
48 int zoneNum = 1;
48 int zoneNum = 1;
49 QString name;
49 QString name;
50 do {
50 do {
51 name = QObject::tr("Zone ").append(QString::number(zoneNum));
51 name = QObject::tr("Zone ").append(QString::number(zoneNum));
52 ++zoneNum;
52 ++zoneNum;
53 } while (existingNames.contains(name));
53 } while (existingNames.contains(name));
54
54
55 return name;
55 return name;
56 }
56 }
57
57
58 } // namespace
58 } // namespace
59
59
60 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
60 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
61 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
61 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
62
62
63 QString m_Name;
63 QString m_Name;
64
64
65 #ifdef Q_OS_MAC
65 #ifdef Q_OS_MAC
66 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
66 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
67 #endif
67 #endif
68
68
69 void dropGraph(int index, VisualizationTabWidget *tabWidget);
69 void dropGraph(int index, VisualizationTabWidget *tabWidget);
70 void dropZone(int index, VisualizationTabWidget *tabWidget);
70 void dropZone(int index, VisualizationTabWidget *tabWidget);
71 void dropVariables(const std::vector<std::shared_ptr<Variable> > &variables, int index,
71 void dropVariables(const std::vector<std::shared_ptr<Variable> > &variables, int index,
72 VisualizationTabWidget *tabWidget);
72 VisualizationTabWidget *tabWidget);
73 void dropProducts(const QVariantList &productsMetaData, int index,
73 void dropProducts(const QVariantList &productsMetaData, int index,
74 VisualizationTabWidget *tabWidget);
74 VisualizationTabWidget *tabWidget);
75 };
75 };
76
76
77 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
77 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
78 : QWidget{parent},
78 : QWidget{parent},
79 ui{new Ui::VisualizationTabWidget},
79 ui{new Ui::VisualizationTabWidget},
80 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
80 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
81 {
81 {
82 ui->setupUi(this);
82 ui->setupUi(this);
83
83
84 #ifdef Q_OS_MAC
84 #ifdef Q_OS_MAC
85 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
85 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
86 #endif
86 #endif
87
87
88 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Zone, "Zone");
88 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Zone, "Zone");
89 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
89 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
90 ui->dragDropContainer->layout()->setSpacing(0);
90 ui->dragDropContainer->layout()->setSpacing(0);
91 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
91 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
92 VisualizationDragDropContainer::DropBehavior::Inserted);
92 VisualizationDragDropContainer::DropBehavior::Inserted);
93 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
93 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
94 VisualizationDragDropContainer::DropBehavior::Inserted);
94 VisualizationDragDropContainer::DropBehavior::Inserted);
95 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
95 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
96 VisualizationDragDropContainer::DropBehavior::Inserted);
96 VisualizationDragDropContainer::DropBehavior::Inserted);
97 ui->dragDropContainer->setMimeType(MIME_TYPE_PRODUCT_LIST,
97 ui->dragDropContainer->setMimeType(MIME_TYPE_PRODUCT_LIST,
98 VisualizationDragDropContainer::DropBehavior::Inserted);
98 VisualizationDragDropContainer::DropBehavior::Inserted);
99
99
100 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
100 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
101 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
101 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
102 ui->dragDropContainer);
102 ui->dragDropContainer);
103 });
103 });
104
104
105 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
105 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
106 &VisualizationTabWidget::dropMimeData);
106 &VisualizationTabWidget::dropMimeData);
107
107
108 sqpApp->dragDropGuiController().addDragDropScrollArea(ui->scrollArea);
108 sqpApp->dragDropGuiController().addDragDropScrollArea(ui->scrollArea);
109
109
110 // Widget is deleted when closed
110 // Widget is deleted when closed
111 setAttribute(Qt::WA_DeleteOnClose);
111 setAttribute(Qt::WA_DeleteOnClose);
112 }
112 }
113
113
114 VisualizationTabWidget::~VisualizationTabWidget()
114 VisualizationTabWidget::~VisualizationTabWidget()
115 {
115 {
116 sqpApp->dragDropGuiController().removeDragDropScrollArea(ui->scrollArea);
116 sqpApp->dragDropGuiController().removeDragDropScrollArea(ui->scrollArea);
117 delete ui;
117 delete ui;
118 }
118 }
119
119
120 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
120 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
121 {
121 {
122 ui->dragDropContainer->addDragWidget(zoneWidget);
122 ui->dragDropContainer->addDragWidget(zoneWidget);
123 }
123 }
124
124
125 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
125 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
126 {
126 {
127 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
127 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
128 }
128 }
129
129
130 QStringList VisualizationTabWidget::availableZoneWidgets() const
130 QStringList VisualizationTabWidget::availableZoneWidgets() const
131 {
131 {
132 QStringList zones;
132 QStringList zones;
133 processZones(tabLayout(),
133 processZones(tabLayout(),
134 [&zones](VisualizationZoneWidget &zoneWidget) { zones << zoneWidget.name(); });
134 [&zones](VisualizationZoneWidget &zoneWidget) { zones << zoneWidget.name(); });
135
135
136 return zones;
136 return zones;
137 }
137 }
138
138
139 VisualizationZoneWidget *VisualizationTabWidget::getZoneWithName(const QString &zoneName)
139 VisualizationZoneWidget *VisualizationTabWidget::getZoneWithName(const QString &zoneName)
140 {
140 {
141 VisualizationZoneWidget *result = nullptr;
141 VisualizationZoneWidget *result = nullptr;
142 processZones(tabLayout(), [&zoneName, &result](VisualizationZoneWidget &zoneWidget) {
142 processZones(tabLayout(), [&zoneName, &result](VisualizationZoneWidget &zoneWidget) {
143 if (!result && zoneWidget.name() == zoneName) {
143 if (!result && zoneWidget.name() == zoneName) {
144 result = &zoneWidget;
144 result = &zoneWidget;
145 }
145 }
146 });
146 });
147
147
148 return result;
148 return result;
149 }
149 }
150
150
151 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
151 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
152 {
152 {
153 return createZone({variable}, -1);
153 return createZone({variable}, -1);
154 }
154 }
155
155
156 VisualizationZoneWidget *
156 VisualizationZoneWidget *
157 VisualizationTabWidget::createZone(const std::vector<std::shared_ptr<Variable> > &variables, int index)
157 VisualizationTabWidget::createZone(const std::vector<std::shared_ptr<Variable> > &variables, int index)
158 {
158 {
159 auto zoneWidget = createEmptyZone(index);
159 auto zoneWidget = createEmptyZone(index);
160
160
161 // Creates a new graph into the zone
161 // Creates a new graph into the zone
162 zoneWidget->createGraph(variables, index);
162 zoneWidget->createGraph(variables, index);
163
163
164 return zoneWidget;
164 return zoneWidget;
165 }
165 }
166
166
167 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
167 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
168 {
168 {
169 auto zoneWidget
169 auto zoneWidget
170 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
170 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
171 this->insertZone(index, zoneWidget);
171 this->insertZone(index, zoneWidget);
172
172
173 return zoneWidget;
173 return zoneWidget;
174 }
174 }
175
175
176 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
176 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
177 {
177 {
178 if (visitor) {
178 if (visitor) {
179 visitor->visitEnter(this);
179 visitor->visitEnter(this);
180
180
181 // Apply visitor to zone children: widgets different from zones are not visited (no action)
181 // Apply visitor to zone children: widgets different from zones are not visited (no action)
182 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
182 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
183 zoneWidget.accept(visitor);
183 zoneWidget.accept(visitor);
184 });
184 });
185
185
186 visitor->visitLeave(this);
186 visitor->visitLeave(this);
187 }
187 }
188 else {
188 else {
189 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
189 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
190 }
190 }
191 }
191 }
192
192
193 bool VisualizationTabWidget::canDrop(const Variable &variable) const
193 bool VisualizationTabWidget::canDrop(const Variable &variable) const
194 {
194 {
195 // A tab can always accomodate a variable
195 // A tab can always accomodate a variable
196 Q_UNUSED(variable);
196 Q_UNUSED(variable);
197 return true;
197 return true;
198 }
198 }
199
199
200 bool VisualizationTabWidget::contains(const Variable &variable) const
200 bool VisualizationTabWidget::contains(const Variable &variable) const
201 {
201 {
202 Q_UNUSED(variable);
202 Q_UNUSED(variable);
203 return false;
203 return false;
204 }
204 }
205
205
206 QString VisualizationTabWidget::name() const
206 QString VisualizationTabWidget::name() const
207 {
207 {
208 return impl->m_Name;
208 return impl->m_Name;
209 }
209 }
210
210
211 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
211 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
212 {
212 {
213 // Closes zones in the tab
213 // Closes zones in the tab
214 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
214 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
215
215
216 QWidget::closeEvent(event);
216 QWidget::closeEvent(event);
217 }
217 }
218
218
219 QLayout &VisualizationTabWidget::tabLayout() const noexcept
219 QLayout &VisualizationTabWidget::tabLayout() const noexcept
220 {
220 {
221 return *ui->dragDropContainer->layout();
221 return *ui->dragDropContainer->layout();
222 }
222 }
223
223
224 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
224 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
225 {
225 {
226 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
226 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
227 impl->dropGraph(index, this);
227 impl->dropGraph(index, this);
228 }
228 }
229 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
229 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
230 impl->dropZone(index, this);
230 impl->dropZone(index, this);
231 }
231 }
232 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
232 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
233 auto variables = sqpApp->variableController().variables(
233 auto variables = sqpApp->variableController().variables(
234 mimeData->data(MIME_TYPE_VARIABLE_LIST));
234 Variable::variablesIDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
235 impl->dropVariables(variables, index, this);
235 impl->dropVariables(variables, index, this);
236 }
236 }
237 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
237 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
238 auto productsData = sqpApp->dataSourceController().productsDataForMimeData(
238 auto productsData = sqpApp->dataSourceController().productsDataForMimeData(
239 mimeData->data(MIME_TYPE_PRODUCT_LIST));
239 mimeData->data(MIME_TYPE_PRODUCT_LIST));
240 impl->dropProducts(productsData, index, this);
240 impl->dropProducts(productsData, index, this);
241 }
241 }
242 else {
242 else {
243 qCWarning(LOG_VisualizationZoneWidget())
243 qCWarning(LOG_VisualizationZoneWidget())
244 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
244 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
245 }
245 }
246 }
246 }
247
247
248 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
248 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
249 int index, VisualizationTabWidget *tabWidget)
249 int index, VisualizationTabWidget *tabWidget)
250 {
250 {
251 auto &helper = sqpApp->dragDropGuiController();
251 auto &helper = sqpApp->dragDropGuiController();
252
252
253 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
253 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
254 if (!graphWidget) {
254 if (!graphWidget) {
255 qCWarning(LOG_VisualizationZoneWidget())
255 qCWarning(LOG_VisualizationZoneWidget())
256 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
256 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
257 "found or invalid.");
257 "found or invalid.");
258 Q_ASSERT(false);
258 Q_ASSERT(false);
259 return;
259 return;
260 }
260 }
261
261
262 auto parentDragDropContainer
262 auto parentDragDropContainer
263 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
263 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
264 if (!parentDragDropContainer) {
264 if (!parentDragDropContainer) {
265 qCWarning(LOG_VisualizationZoneWidget())
265 qCWarning(LOG_VisualizationZoneWidget())
266 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
266 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
267 "the dropped graph is not found.");
267 "the dropped graph is not found.");
268 Q_ASSERT(false);
268 Q_ASSERT(false);
269 return;
269 return;
270 }
270 }
271
271
272 auto nbGraph = parentDragDropContainer->countDragWidget();
272 auto nbGraph = parentDragDropContainer->countDragWidget();
273
273
274 const auto &variables = graphWidget->variables();
274 const auto &variables = graphWidget->variables();
275
275
276 if (!variables.empty()) {
276 if (!variables.empty()) {
277 // Abort the requests for the variables (if any)
277 // Abort the requests for the variables (if any)
278 // Commented, because it's not sure if it's needed or not
278 // Commented, because it's not sure if it's needed or not
279 // for (const auto& var : variables)
279 // for (const auto& var : variables)
280 //{
280 //{
281 // sqpApp->variableController().onAbortProgressRequested(var);
281 // sqpApp->variableController().onAbortProgressRequested(var);
282 //}
282 //}
283
283
284 if (nbGraph == 1) {
284 if (nbGraph == 1) {
285 // This is the only graph in the previous zone, close the zone
285 // This is the only graph in the previous zone, close the zone
286 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
286 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
287 }
287 }
288 else {
288 else {
289 // Close the graph
289 // Close the graph
290 helper.delayedCloseWidget(graphWidget);
290 helper.delayedCloseWidget(graphWidget);
291 }
291 }
292
292
293 auto zoneWidget = tabWidget->createZone(variables, index);
293 auto zoneWidget = tabWidget->createZone(variables, index);
294 auto firstGraph = zoneWidget->firstGraph();
294 auto firstGraph = zoneWidget->firstGraph();
295 if (firstGraph) {
295 if (firstGraph) {
296 firstGraph->addSelectionZones(graphWidget->selectionZoneRanges());
296 firstGraph->addSelectionZones(graphWidget->selectionZoneRanges());
297 }
297 }
298 else {
298 else {
299 qCWarning(LOG_VisualizationZoneWidget())
299 qCWarning(LOG_VisualizationZoneWidget())
300 << tr("VisualizationTabWidget::dropGraph, no graph added in the widget.");
300 << tr("VisualizationTabWidget::dropGraph, no graph added in the widget.");
301 Q_ASSERT(false);
301 Q_ASSERT(false);
302 }
302 }
303 }
303 }
304 else {
304 else {
305 // The graph is empty, create an empty zone and move the graph inside
305 // The graph is empty, create an empty zone and move the graph inside
306
306
307 auto parentZoneWidget = graphWidget->parentZoneWidget();
307 auto parentZoneWidget = graphWidget->parentZoneWidget();
308
308
309 parentDragDropContainer->layout()->removeWidget(graphWidget);
309 parentDragDropContainer->layout()->removeWidget(graphWidget);
310
310
311 auto zoneWidget = tabWidget->createEmptyZone(index);
311 auto zoneWidget = tabWidget->createEmptyZone(index);
312 zoneWidget->addGraph(graphWidget);
312 zoneWidget->addGraph(graphWidget);
313
313
314 // Close the old zone if it was the only graph inside
314 // Close the old zone if it was the only graph inside
315 if (nbGraph == 1) {
315 if (nbGraph == 1) {
316 helper.delayedCloseWidget(parentZoneWidget);
316 helper.delayedCloseWidget(parentZoneWidget);
317 }
317 }
318 }
318 }
319 }
319 }
320
320
321 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
321 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
322 int index, VisualizationTabWidget *tabWidget)
322 int index, VisualizationTabWidget *tabWidget)
323 {
323 {
324 auto &helper = sqpApp->dragDropGuiController();
324 auto &helper = sqpApp->dragDropGuiController();
325
325
326 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
326 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
327 if (!zoneWidget) {
327 if (!zoneWidget) {
328 qCWarning(LOG_VisualizationZoneWidget())
328 qCWarning(LOG_VisualizationZoneWidget())
329 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
329 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
330 "found or invalid.");
330 "found or invalid.");
331 Q_ASSERT(false);
331 Q_ASSERT(false);
332 return;
332 return;
333 }
333 }
334
334
335 auto parentDragDropContainer
335 auto parentDragDropContainer
336 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
336 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
337 if (!parentDragDropContainer) {
337 if (!parentDragDropContainer) {
338 qCWarning(LOG_VisualizationZoneWidget())
338 qCWarning(LOG_VisualizationZoneWidget())
339 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
339 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
340 "the dropped zone is not found.");
340 "the dropped zone is not found.");
341 Q_ASSERT(false);
341 Q_ASSERT(false);
342 return;
342 return;
343 }
343 }
344
344
345 // Simple move of the zone, no variable operation associated
345 // Simple move of the zone, no variable operation associated
346 parentDragDropContainer->layout()->removeWidget(zoneWidget);
346 parentDragDropContainer->layout()->removeWidget(zoneWidget);
347 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
347 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
348 }
348 }
349
349
350 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
350 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
351 const std::vector<std::shared_ptr<Variable> > &variables, int index,
351 const std::vector<std::shared_ptr<Variable> > &variables, int index,
352 VisualizationTabWidget *tabWidget)
352 VisualizationTabWidget *tabWidget)
353 {
353 {
354 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
354 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
355 // compatible variable here
355 // compatible variable here
356 if (variables.size() > 1) {
356 if (variables.size() > 1) {
357 qCWarning(LOG_VisualizationZoneWidget())
357 qCWarning(LOG_VisualizationZoneWidget())
358 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
358 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
359 "aborted.");
359 "aborted.");
360 return;
360 return;
361 }
361 }
362
362
363 tabWidget->createZone(variables, index);
363 tabWidget->createZone(variables, index);
364 }
364 }
365
365
366 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropProducts(
366 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropProducts(
367 const QVariantList &productsMetaData, int index, VisualizationTabWidget *tabWidget)
367 const QVariantList &productsMetaData, int index, VisualizationTabWidget *tabWidget)
368 {
368 {
369 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
369 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
370 // compatible variable here
370 // compatible variable here
371 if (productsMetaData.count() != 1) {
371 if (productsMetaData.count() != 1) {
372 qCWarning(LOG_VisualizationZoneWidget())
372 qCWarning(LOG_VisualizationZoneWidget())
373 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
373 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
374 "aborted.");
374 "aborted.");
375 return;
375 return;
376 }
376 }
377
377
378 auto context = new QObject{tabWidget};
378 auto context = new QObject{tabWidget};
379 connect(&sqpApp->variableController(), &VariableController2::variableAdded, context,
379 connect(&sqpApp->variableController(), &VariableController2::variableAdded, context,
380 [this, index, tabWidget, context](auto variable) {
380 [this, index, tabWidget, context](auto variable) {
381 tabWidget->createZone({variable}, index);
381 tabWidget->createZone({variable}, index);
382 delete context; // removes the connection
382 delete context; // removes the connection
383 },
383 },
384 Qt::QueuedConnection);
384 Qt::QueuedConnection);
385
385
386 auto productData = productsMetaData.first().toHash();
386 auto productData = productsMetaData.first().toHash();
387 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
387 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
388 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
388 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
389 }
389 }
@@ -1,629 +1,629
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/VisualizationWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
8
8
9 #include "Common/MimeTypesDef.h"
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
10 #include "Common/VisualizationDef.h"
11
11
12 #include <Data/DateTimeRange.h>
12 #include <Data/DateTimeRange.h>
13 #include <Data/DateTimeRangeHelper.h>
13 #include <Data/DateTimeRangeHelper.h>
14 #include <DataSource/DataSourceController.h>
14 #include <DataSource/DataSourceController.h>
15 #include <Time/TimeController.h>
15 #include <Time/TimeController.h>
16 #include <Variable/Variable.h>
16 #include <Variable/Variable.h>
17 #include <Variable/VariableController2.h>
17 #include <Variable/VariableController2.h>
18
18
19 #include <Visualization/operations/FindVariableOperation.h>
19 #include <Visualization/operations/FindVariableOperation.h>
20
20
21 #include <DragAndDrop/DragDropGuiController.h>
21 #include <DragAndDrop/DragDropGuiController.h>
22 #include <QUuid>
22 #include <QUuid>
23 #include <SqpApplication.h>
23 #include <SqpApplication.h>
24 #include <cmath>
24 #include <cmath>
25
25
26 #include <QLayout>
26 #include <QLayout>
27 #include <QStyle>
27 #include <QStyle>
28
28
29 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
29 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
30
30
31 namespace {
31 namespace {
32
32
33 /**
33 /**
34 * Applies a function to all graphs of the zone represented by its layout
34 * Applies a function to all graphs of the zone represented by its layout
35 * @param layout the layout that contains graphs
35 * @param layout the layout that contains graphs
36 * @param fun the function to apply to each graph
36 * @param fun the function to apply to each graph
37 */
37 */
38 template <typename Fun>
38 template <typename Fun>
39 void processGraphs(QLayout &layout, Fun fun)
39 void processGraphs(QLayout &layout, Fun fun)
40 {
40 {
41 for (auto i = 0; i < layout.count(); ++i) {
41 for (auto i = 0; i < layout.count(); ++i) {
42 if (auto item = layout.itemAt(i)) {
42 if (auto item = layout.itemAt(i)) {
43 if (auto visualizationGraphWidget
43 if (auto visualizationGraphWidget
44 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
44 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
45 fun(*visualizationGraphWidget);
45 fun(*visualizationGraphWidget);
46 }
46 }
47 }
47 }
48 }
48 }
49 }
49 }
50
50
51 /// Generates a default name for a new graph, according to the number of graphs already displayed in
51 /// Generates a default name for a new graph, according to the number of graphs already displayed in
52 /// the zone
52 /// the zone
53 QString defaultGraphName(QLayout &layout)
53 QString defaultGraphName(QLayout &layout)
54 {
54 {
55 QSet<QString> existingNames;
55 QSet<QString> existingNames;
56 processGraphs(
56 processGraphs(
57 layout, [&existingNames](auto &graphWidget) { existingNames.insert(graphWidget.name()); });
57 layout, [&existingNames](auto &graphWidget) { existingNames.insert(graphWidget.name()); });
58
58
59 int zoneNum = 1;
59 int zoneNum = 1;
60 QString name;
60 QString name;
61 do {
61 do {
62 name = QObject::tr("Graph ").append(QString::number(zoneNum));
62 name = QObject::tr("Graph ").append(QString::number(zoneNum));
63 ++zoneNum;
63 ++zoneNum;
64 } while (existingNames.contains(name));
64 } while (existingNames.contains(name));
65
65
66 return name;
66 return name;
67 }
67 }
68
68
69 } // namespace
69 } // namespace
70
70
71 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
71 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
72
72
73 explicit VisualizationZoneWidgetPrivate()
73 explicit VisualizationZoneWidgetPrivate()
74 : m_SynchronisationGroupId{QUuid::createUuid()},
74 : m_SynchronisationGroupId{QUuid::createUuid()},
75 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
75 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
76 {
76 {
77 }
77 }
78 QUuid m_SynchronisationGroupId;
78 QUuid m_SynchronisationGroupId;
79 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
79 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
80
80
81 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
81 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
82 void dropVariables(const std::vector<std::shared_ptr<Variable> > &variables, int index,
82 void dropVariables(const std::vector<std::shared_ptr<Variable> > &variables, int index,
83 VisualizationZoneWidget *zoneWidget);
83 VisualizationZoneWidget *zoneWidget);
84 void dropProducts(const QVariantList &productsData, int index,
84 void dropProducts(const QVariantList &productsData, int index,
85 VisualizationZoneWidget *zoneWidget);
85 VisualizationZoneWidget *zoneWidget);
86 };
86 };
87
87
88 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
88 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
89 : VisualizationDragWidget{parent},
89 : VisualizationDragWidget{parent},
90 ui{new Ui::VisualizationZoneWidget},
90 ui{new Ui::VisualizationZoneWidget},
91 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
91 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
92 {
92 {
93 ui->setupUi(this);
93 ui->setupUi(this);
94
94
95 ui->zoneNameLabel->setText(name);
95 ui->zoneNameLabel->setText(name);
96
96
97 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
97 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
98 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
98 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
99 VisualizationDragDropContainer::DropBehavior::Inserted);
99 VisualizationDragDropContainer::DropBehavior::Inserted);
100 ui->dragDropContainer->setMimeType(
100 ui->dragDropContainer->setMimeType(
101 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
101 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
102 ui->dragDropContainer->setMimeType(
102 ui->dragDropContainer->setMimeType(
103 MIME_TYPE_PRODUCT_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
103 MIME_TYPE_PRODUCT_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
104 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
104 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
105 VisualizationDragDropContainer::DropBehavior::Merged);
105 VisualizationDragDropContainer::DropBehavior::Merged);
106 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
106 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
107 VisualizationDragDropContainer::DropBehavior::Forbidden);
107 VisualizationDragDropContainer::DropBehavior::Forbidden);
108 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
108 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
109 VisualizationDragDropContainer::DropBehavior::Forbidden);
109 VisualizationDragDropContainer::DropBehavior::Forbidden);
110 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
110 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
111 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
111 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
112 ui->dragDropContainer);
112 ui->dragDropContainer);
113 });
113 });
114
114
115 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
115 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
116 if (!mimeData) {
116 if (!mimeData) {
117 return false;
117 return false;
118 }
118 }
119
119
120 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
120 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
121 auto variables = sqpApp->variableController().variables(
121 auto variables = sqpApp->variableController().variables(
122 mimeData->data(MIME_TYPE_VARIABLE_LIST));
122 Variable::variablesIDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
123
123
124 if (variables.size() != 1) {
124 if (variables.size() != 1) {
125 return false;
125 return false;
126 }
126 }
127 auto variable = variables.front();
127 auto variable = variables.front();
128
128
129 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
129 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
130 return graphWidget->canDrop(*variable);
130 return graphWidget->canDrop(*variable);
131 }
131 }
132 }
132 }
133
133
134 return true;
134 return true;
135 };
135 };
136 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
136 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
137
137
138 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
138 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
139 &VisualizationZoneWidget::dropMimeData);
139 &VisualizationZoneWidget::dropMimeData);
140 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
140 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
141 &VisualizationZoneWidget::dropMimeDataOnGraph);
141 &VisualizationZoneWidget::dropMimeDataOnGraph);
142
142
143 // 'Close' options : widget is deleted when closed
143 // 'Close' options : widget is deleted when closed
144 setAttribute(Qt::WA_DeleteOnClose);
144 setAttribute(Qt::WA_DeleteOnClose);
145 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
145 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
146 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
146 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
147
147
148 // Synchronisation id
148 // Synchronisation id
149 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
149 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
150 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
150 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
151 }
151 }
152
152
153 VisualizationZoneWidget::~VisualizationZoneWidget()
153 VisualizationZoneWidget::~VisualizationZoneWidget()
154 {
154 {
155 delete ui;
155 delete ui;
156 }
156 }
157
157
158 void VisualizationZoneWidget::setZoneRange(const DateTimeRange &range)
158 void VisualizationZoneWidget::setZoneRange(const DateTimeRange &range)
159 {
159 {
160 if (auto graph = firstGraph()) {
160 if (auto graph = firstGraph()) {
161 graph->setGraphRange(range);
161 graph->setGraphRange(range);
162 }
162 }
163 else {
163 else {
164 qCWarning(LOG_VisualizationZoneWidget())
164 qCWarning(LOG_VisualizationZoneWidget())
165 << tr("setZoneRange:Cannot set the range of an empty zone.");
165 << tr("setZoneRange:Cannot set the range of an empty zone.");
166 }
166 }
167 }
167 }
168
168
169 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
169 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
170 {
170 {
171 // Synchronize new graph with others in the zone
171 // Synchronize new graph with others in the zone
172 impl->m_Synchronizer->addGraph(*graphWidget);
172 impl->m_Synchronizer->addGraph(*graphWidget);
173
173
174 ui->dragDropContainer->addDragWidget(graphWidget);
174 ui->dragDropContainer->addDragWidget(graphWidget);
175 }
175 }
176
176
177 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
177 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
178 {
178 {
179 // Synchronize new graph with others in the zone
179 // Synchronize new graph with others in the zone
180 impl->m_Synchronizer->addGraph(*graphWidget);
180 impl->m_Synchronizer->addGraph(*graphWidget);
181
181
182 ui->dragDropContainer->insertDragWidget(index, graphWidget);
182 ui->dragDropContainer->insertDragWidget(index, graphWidget);
183 }
183 }
184
184
185 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
185 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
186 {
186 {
187 return createGraph(variable, -1);
187 return createGraph(variable, -1);
188 }
188 }
189
189
190 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
190 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
191 int index)
191 int index)
192 {
192 {
193 auto graphWidget
193 auto graphWidget
194 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
194 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
195
195
196
196
197 // Set graph properties
197 // Set graph properties
198 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
198 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
199 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
199 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
200
200
201
201
202 // Lambda to synchronize zone widget
202 // Lambda to synchronize zone widget
203 auto synchronizeZoneWidget = [this, graphWidget](const DateTimeRange &graphRange,
203 auto synchronizeZoneWidget = [this, graphWidget](const DateTimeRange &graphRange,
204 const DateTimeRange &oldGraphRange) {
204 const DateTimeRange &oldGraphRange) {
205
205
206 auto zoomType = DateTimeRangeHelper::getTransformationType(oldGraphRange, graphRange);
206 auto zoomType = DateTimeRangeHelper::getTransformationType(oldGraphRange, graphRange);
207 auto frameLayout = ui->dragDropContainer->layout();
207 auto frameLayout = ui->dragDropContainer->layout();
208 for (auto i = 0; i < frameLayout->count(); ++i) {
208 for (auto i = 0; i < frameLayout->count(); ++i) {
209 auto graphChild
209 auto graphChild
210 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
210 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
211 if (graphChild && (graphChild != graphWidget)) {
211 if (graphChild && (graphChild != graphWidget)) {
212
212
213 auto graphChildRange = graphChild->graphRange();
213 auto graphChildRange = graphChild->graphRange();
214 switch (zoomType) {
214 switch (zoomType) {
215 case TransformationType::ZoomIn: {
215 case TransformationType::ZoomIn: {
216 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
216 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
217 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
217 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
218 graphChildRange.m_TStart += deltaLeft;
218 graphChildRange.m_TStart += deltaLeft;
219 graphChildRange.m_TEnd -= deltaRight;
219 graphChildRange.m_TEnd -= deltaRight;
220 break;
220 break;
221 }
221 }
222
222
223 case TransformationType::ZoomOut: {
223 case TransformationType::ZoomOut: {
224 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
224 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
225 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
225 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
226 graphChildRange.m_TStart -= deltaLeft;
226 graphChildRange.m_TStart -= deltaLeft;
227 graphChildRange.m_TEnd += deltaRight;
227 graphChildRange.m_TEnd += deltaRight;
228 break;
228 break;
229 }
229 }
230 case TransformationType::PanRight: {
230 case TransformationType::PanRight: {
231 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
231 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
232 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
232 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
233 graphChildRange.m_TStart += deltaLeft;
233 graphChildRange.m_TStart += deltaLeft;
234 graphChildRange.m_TEnd += deltaRight;
234 graphChildRange.m_TEnd += deltaRight;
235 break;
235 break;
236 }
236 }
237 case TransformationType::PanLeft: {
237 case TransformationType::PanLeft: {
238 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
238 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
239 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
239 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
240 graphChildRange.m_TStart -= deltaLeft;
240 graphChildRange.m_TStart -= deltaLeft;
241 graphChildRange.m_TEnd -= deltaRight;
241 graphChildRange.m_TEnd -= deltaRight;
242 break;
242 break;
243 }
243 }
244 case TransformationType::Unknown: {
244 case TransformationType::Unknown: {
245 break;
245 break;
246 }
246 }
247 default:
247 default:
248 qCCritical(LOG_VisualizationZoneWidget())
248 qCCritical(LOG_VisualizationZoneWidget())
249 << tr("Impossible to synchronize: zoom type not take into account");
249 << tr("Impossible to synchronize: zoom type not take into account");
250 // No action
250 // No action
251 break;
251 break;
252 }
252 }
253 graphChild->setFlags(GraphFlag::DisableAll);
253 graphChild->setFlags(GraphFlag::DisableAll);
254 graphChild->setGraphRange(graphChildRange);
254 graphChild->setGraphRange(graphChildRange);
255 graphChild->setFlags(GraphFlag::EnableAll);
255 graphChild->setFlags(GraphFlag::EnableAll);
256 }
256 }
257 }
257 }
258 };
258 };
259
259
260 // connection for synchronization
260 // connection for synchronization
261 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
261 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
262 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
262 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
263 &VisualizationZoneWidget::onVariableAdded);
263 &VisualizationZoneWidget::onVariableAdded);
264 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
264 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
265 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
265 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
266
266
267 auto range = DateTimeRange{};
267 auto range = DateTimeRange{};
268 if (auto firstGraph = this->firstGraph()) {
268 if (auto firstGraph = this->firstGraph()) {
269 // Case of a new graph in a existant zone
269 // Case of a new graph in a existant zone
270 range = firstGraph->graphRange();
270 range = firstGraph->graphRange();
271 }
271 }
272 else {
272 else {
273 // Case of a new graph as the first of the zone
273 // Case of a new graph as the first of the zone
274 range = variable->range();
274 range = variable->range();
275 }
275 }
276
276
277 this->insertGraph(index, graphWidget);
277 this->insertGraph(index, graphWidget);
278
278
279 graphWidget->addVariable(variable, range);
279 graphWidget->addVariable(variable, range);
280 graphWidget->setYRange(variable);
280 graphWidget->setYRange(variable);
281
281
282 return graphWidget;
282 return graphWidget;
283 }
283 }
284
284
285 VisualizationGraphWidget *
285 VisualizationGraphWidget *
286 VisualizationZoneWidget::createGraph(const std::vector<std::shared_ptr<Variable> > variables, int index)
286 VisualizationZoneWidget::createGraph(const std::vector<std::shared_ptr<Variable> > variables, int index)
287 {
287 {
288 if (variables.empty()) {
288 if (variables.empty()) {
289 return nullptr;
289 return nullptr;
290 }
290 }
291
291
292 auto graphWidget = createGraph(variables.front(), index);
292 auto graphWidget = createGraph(variables.front(), index);
293 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
293 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
294 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
294 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
295 }
295 }
296
296
297 return graphWidget;
297 return graphWidget;
298 }
298 }
299
299
300 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
300 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
301 {
301 {
302 VisualizationGraphWidget *firstGraph = nullptr;
302 VisualizationGraphWidget *firstGraph = nullptr;
303 auto layout = ui->dragDropContainer->layout();
303 auto layout = ui->dragDropContainer->layout();
304 if (layout->count() > 0) {
304 if (layout->count() > 0) {
305 if (auto visualizationGraphWidget
305 if (auto visualizationGraphWidget
306 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
306 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
307 firstGraph = visualizationGraphWidget;
307 firstGraph = visualizationGraphWidget;
308 }
308 }
309 }
309 }
310
310
311 return firstGraph;
311 return firstGraph;
312 }
312 }
313
313
314 void VisualizationZoneWidget::closeAllGraphs()
314 void VisualizationZoneWidget::closeAllGraphs()
315 {
315 {
316 processGraphs(*ui->dragDropContainer->layout(),
316 processGraphs(*ui->dragDropContainer->layout(),
317 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
317 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
318 }
318 }
319
319
320 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
320 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
321 {
321 {
322 if (visitor) {
322 if (visitor) {
323 visitor->visitEnter(this);
323 visitor->visitEnter(this);
324
324
325 // Apply visitor to graph children: widgets different from graphs are not visited (no
325 // Apply visitor to graph children: widgets different from graphs are not visited (no
326 // action)
326 // action)
327 processGraphs(
327 processGraphs(
328 *ui->dragDropContainer->layout(),
328 *ui->dragDropContainer->layout(),
329 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
329 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
330
330
331 visitor->visitLeave(this);
331 visitor->visitLeave(this);
332 }
332 }
333 else {
333 else {
334 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
334 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
335 }
335 }
336 }
336 }
337
337
338 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
338 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
339 {
339 {
340 // A tab can always accomodate a variable
340 // A tab can always accomodate a variable
341 Q_UNUSED(variable);
341 Q_UNUSED(variable);
342 return true;
342 return true;
343 }
343 }
344
344
345 bool VisualizationZoneWidget::contains(const Variable &variable) const
345 bool VisualizationZoneWidget::contains(const Variable &variable) const
346 {
346 {
347 Q_UNUSED(variable);
347 Q_UNUSED(variable);
348 return false;
348 return false;
349 }
349 }
350
350
351 QString VisualizationZoneWidget::name() const
351 QString VisualizationZoneWidget::name() const
352 {
352 {
353 return ui->zoneNameLabel->text();
353 return ui->zoneNameLabel->text();
354 }
354 }
355
355
356 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
356 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
357 {
357 {
358 Q_UNUSED(position);
358 Q_UNUSED(position);
359
359
360 auto mimeData = new QMimeData;
360 auto mimeData = new QMimeData;
361 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
361 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
362
362
363 if (auto firstGraph = this->firstGraph()) {
363 if (auto firstGraph = this->firstGraph()) {
364 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
364 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
365 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
365 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
366 }
366 }
367
367
368 return mimeData;
368 return mimeData;
369 }
369 }
370
370
371 bool VisualizationZoneWidget::isDragAllowed() const
371 bool VisualizationZoneWidget::isDragAllowed() const
372 {
372 {
373 return true;
373 return true;
374 }
374 }
375
375
376 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
376 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
377 const QPointF &plotPosition,
377 const QPointF &plotPosition,
378 VisualizationGraphWidget *graphWidget)
378 VisualizationGraphWidget *graphWidget)
379 {
379 {
380 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
380 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
381 VisualizationGraphWidget &processedGraph) {
381 VisualizationGraphWidget &processedGraph) {
382
382
383 switch (sqpApp->plotsCursorMode()) {
383 switch (sqpApp->plotsCursorMode()) {
384 case SqpApplication::PlotsCursorMode::Vertical:
384 case SqpApplication::PlotsCursorMode::Vertical:
385 processedGraph.removeHorizontalCursor();
385 processedGraph.removeHorizontalCursor();
386 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
386 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
387 break;
387 break;
388 case SqpApplication::PlotsCursorMode::Temporal:
388 case SqpApplication::PlotsCursorMode::Temporal:
389 processedGraph.addVerticalCursor(plotPosition.x());
389 processedGraph.addVerticalCursor(plotPosition.x());
390 processedGraph.removeHorizontalCursor();
390 processedGraph.removeHorizontalCursor();
391 break;
391 break;
392 case SqpApplication::PlotsCursorMode::Horizontal:
392 case SqpApplication::PlotsCursorMode::Horizontal:
393 processedGraph.removeVerticalCursor();
393 processedGraph.removeVerticalCursor();
394 if (&processedGraph == graphWidget) {
394 if (&processedGraph == graphWidget) {
395 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
395 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
396 }
396 }
397 else {
397 else {
398 processedGraph.removeHorizontalCursor();
398 processedGraph.removeHorizontalCursor();
399 }
399 }
400 break;
400 break;
401 case SqpApplication::PlotsCursorMode::Cross:
401 case SqpApplication::PlotsCursorMode::Cross:
402 if (&processedGraph == graphWidget) {
402 if (&processedGraph == graphWidget) {
403 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
403 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
404 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
404 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
405 }
405 }
406 else {
406 else {
407 processedGraph.removeHorizontalCursor();
407 processedGraph.removeHorizontalCursor();
408 processedGraph.removeVerticalCursor();
408 processedGraph.removeVerticalCursor();
409 }
409 }
410 break;
410 break;
411 case SqpApplication::PlotsCursorMode::NoCursor:
411 case SqpApplication::PlotsCursorMode::NoCursor:
412 processedGraph.removeHorizontalCursor();
412 processedGraph.removeHorizontalCursor();
413 processedGraph.removeVerticalCursor();
413 processedGraph.removeVerticalCursor();
414 break;
414 break;
415 }
415 }
416
416
417
417
418 });
418 });
419 }
419 }
420
420
421 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
421 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
422 {
422 {
423 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
423 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
424 processedGraph.removeHorizontalCursor();
424 processedGraph.removeHorizontalCursor();
425 processedGraph.removeVerticalCursor();
425 processedGraph.removeVerticalCursor();
426 });
426 });
427 }
427 }
428
428
429 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
429 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
430 {
430 {
431 // Closes graphs in the zone
431 // Closes graphs in the zone
432 processGraphs(*ui->dragDropContainer->layout(),
432 processGraphs(*ui->dragDropContainer->layout(),
433 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
433 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
434
434
435 // Delete synchronization group from variable controller
435 // Delete synchronization group from variable controller
436 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
436 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
437 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
437 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
438
438
439 QWidget::closeEvent(event);
439 QWidget::closeEvent(event);
440 }
440 }
441
441
442 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
442 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
443 {
443 {
444 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
444 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
445 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
445 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
446 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
446 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
447 }
447 }
448
448
449 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
449 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
450 {
450 {
451 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
451 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
452 Q_ARG(std::shared_ptr<Variable>, variable),
452 Q_ARG(std::shared_ptr<Variable>, variable),
453 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
453 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
454 }
454 }
455
455
456 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
456 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
457 {
457 {
458 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
458 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
459 impl->dropGraph(index, this);
459 impl->dropGraph(index, this);
460 }
460 }
461 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
461 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
462 auto variables = sqpApp->variableController().variables(
462 auto variables = sqpApp->variableController().variables(
463 mimeData->data(MIME_TYPE_VARIABLE_LIST));
463 Variable::variablesIDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
464 impl->dropVariables(variables, index, this);
464 impl->dropVariables(variables, index, this);
465 }
465 }
466 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
466 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
467 auto products = sqpApp->dataSourceController().productsDataForMimeData(
467 auto products = sqpApp->dataSourceController().productsDataForMimeData(
468 mimeData->data(MIME_TYPE_PRODUCT_LIST));
468 mimeData->data(MIME_TYPE_PRODUCT_LIST));
469 impl->dropProducts(products, index, this);
469 impl->dropProducts(products, index, this);
470 }
470 }
471 else {
471 else {
472 qCWarning(LOG_VisualizationZoneWidget())
472 qCWarning(LOG_VisualizationZoneWidget())
473 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
473 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
474 }
474 }
475 }
475 }
476
476
477 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
477 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
478 const QMimeData *mimeData)
478 const QMimeData *mimeData)
479 {
479 {
480 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
480 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
481 if (!graphWidget) {
481 if (!graphWidget) {
482 qCWarning(LOG_VisualizationZoneWidget())
482 qCWarning(LOG_VisualizationZoneWidget())
483 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
483 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
484 "drop aborted");
484 "drop aborted");
485 Q_ASSERT(false);
485 Q_ASSERT(false);
486 return;
486 return;
487 }
487 }
488
488
489 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
489 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
490 auto variables = sqpApp->variableController().variables(
490 auto variables = sqpApp->variableController().variables(
491 mimeData->data(MIME_TYPE_VARIABLE_LIST));
491 Variable::variablesIDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
492 for (const auto &var : variables) {
492 for (const auto &var : variables) {
493 graphWidget->addVariable(var, graphWidget->graphRange());
493 graphWidget->addVariable(var, graphWidget->graphRange());
494 }
494 }
495 }
495 }
496 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
496 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
497 auto products = sqpApp->dataSourceController().productsDataForMimeData(
497 auto products = sqpApp->dataSourceController().productsDataForMimeData(
498 mimeData->data(MIME_TYPE_PRODUCT_LIST));
498 mimeData->data(MIME_TYPE_PRODUCT_LIST));
499
499
500 auto context = new QObject{this};
500 auto context = new QObject{this};
501 connect(&sqpApp->variableController(), &VariableController2::variableAdded, context,
501 connect(&sqpApp->variableController(), &VariableController2::variableAdded, context,
502 [this, graphWidget, context](auto variable) {
502 [this, graphWidget, context](auto variable) {
503 graphWidget->addVariable(variable, graphWidget->graphRange());
503 graphWidget->addVariable(variable, graphWidget->graphRange());
504 delete context; // removes the connection
504 delete context; // removes the connection
505 },
505 },
506 Qt::QueuedConnection);
506 Qt::QueuedConnection);
507
507
508 auto productData = products.first().toHash();
508 auto productData = products.first().toHash();
509 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
509 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
510 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
510 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
511 }
511 }
512 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
512 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
513 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
513 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
514 graphWidget->setGraphRange(range);
514 graphWidget->setGraphRange(range);
515 }
515 }
516 else {
516 else {
517 qCWarning(LOG_VisualizationZoneWidget())
517 qCWarning(LOG_VisualizationZoneWidget())
518 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
518 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
519 }
519 }
520 }
520 }
521
521
522 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
522 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
523 int index, VisualizationZoneWidget *zoneWidget)
523 int index, VisualizationZoneWidget *zoneWidget)
524 {
524 {
525 auto &helper = sqpApp->dragDropGuiController();
525 auto &helper = sqpApp->dragDropGuiController();
526
526
527 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
527 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
528 if (!graphWidget) {
528 if (!graphWidget) {
529 qCWarning(LOG_VisualizationZoneWidget())
529 qCWarning(LOG_VisualizationZoneWidget())
530 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
530 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
531 "found or invalid.");
531 "found or invalid.");
532 Q_ASSERT(false);
532 Q_ASSERT(false);
533 return;
533 return;
534 }
534 }
535
535
536 auto parentDragDropContainer
536 auto parentDragDropContainer
537 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
537 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
538 if (!parentDragDropContainer) {
538 if (!parentDragDropContainer) {
539 qCWarning(LOG_VisualizationZoneWidget())
539 qCWarning(LOG_VisualizationZoneWidget())
540 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
540 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
541 "the dropped graph is not found.");
541 "the dropped graph is not found.");
542 Q_ASSERT(false);
542 Q_ASSERT(false);
543 return;
543 return;
544 }
544 }
545
545
546 const auto &variables = graphWidget->variables();
546 const auto &variables = graphWidget->variables();
547
547
548 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.empty()) {
548 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.empty()) {
549 // The drop didn't occur in the same zone
549 // The drop didn't occur in the same zone
550
550
551 // Abort the requests for the variables (if any)
551 // Abort the requests for the variables (if any)
552 // Commented, because it's not sure if it's needed or not
552 // Commented, because it's not sure if it's needed or not
553 // for (const auto& var : variables)
553 // for (const auto& var : variables)
554 //{
554 //{
555 // sqpApp->variableController().onAbortProgressRequested(var);
555 // sqpApp->variableController().onAbortProgressRequested(var);
556 //}
556 //}
557
557
558 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
558 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
559 auto nbGraph = parentDragDropContainer->countDragWidget();
559 auto nbGraph = parentDragDropContainer->countDragWidget();
560 if (nbGraph == 1) {
560 if (nbGraph == 1) {
561 // This is the only graph in the previous zone, close the zone
561 // This is the only graph in the previous zone, close the zone
562 helper.delayedCloseWidget(previousParentZoneWidget);
562 helper.delayedCloseWidget(previousParentZoneWidget);
563 }
563 }
564 else {
564 else {
565 // Close the graph
565 // Close the graph
566 helper.delayedCloseWidget(graphWidget);
566 helper.delayedCloseWidget(graphWidget);
567 }
567 }
568
568
569 // Creates the new graph in the zone
569 // Creates the new graph in the zone
570 auto newGraphWidget = zoneWidget->createGraph(variables, index);
570 auto newGraphWidget = zoneWidget->createGraph(variables, index);
571 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
571 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
572 }
572 }
573 else {
573 else {
574 // The drop occurred in the same zone or the graph is empty
574 // The drop occurred in the same zone or the graph is empty
575 // Simple move of the graph, no variable operation associated
575 // Simple move of the graph, no variable operation associated
576 parentDragDropContainer->layout()->removeWidget(graphWidget);
576 parentDragDropContainer->layout()->removeWidget(graphWidget);
577
577
578 if (variables.empty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
578 if (variables.empty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
579 // The graph is empty and dropped in a different zone.
579 // The graph is empty and dropped in a different zone.
580 // Take the range of the first graph in the zone (if existing).
580 // Take the range of the first graph in the zone (if existing).
581 auto layout = zoneWidget->ui->dragDropContainer->layout();
581 auto layout = zoneWidget->ui->dragDropContainer->layout();
582 if (layout->count() > 0) {
582 if (layout->count() > 0) {
583 if (auto visualizationGraphWidget
583 if (auto visualizationGraphWidget
584 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
584 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
585 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
585 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
586 }
586 }
587 }
587 }
588 }
588 }
589
589
590 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
590 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
591 }
591 }
592 }
592 }
593
593
594 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
594 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
595 const std::vector<std::shared_ptr<Variable> > &variables, int index,
595 const std::vector<std::shared_ptr<Variable> > &variables, int index,
596 VisualizationZoneWidget *zoneWidget)
596 VisualizationZoneWidget *zoneWidget)
597 {
597 {
598 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
598 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
599 // compatible variable here
599 // compatible variable here
600 if (variables.size() > 1) {
600 if (variables.size() > 1) {
601 return;
601 return;
602 }
602 }
603 zoneWidget->createGraph(variables, index);
603 zoneWidget->createGraph(variables, index);
604 }
604 }
605
605
606 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProducts(
606 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProducts(
607 const QVariantList &productsData, int index, VisualizationZoneWidget *zoneWidget)
607 const QVariantList &productsData, int index, VisualizationZoneWidget *zoneWidget)
608 {
608 {
609 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
609 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
610 // compatible variable here
610 // compatible variable here
611 if (productsData.count() != 1) {
611 if (productsData.count() != 1) {
612 qCWarning(LOG_VisualizationZoneWidget())
612 qCWarning(LOG_VisualizationZoneWidget())
613 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
613 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
614 "aborted.");
614 "aborted.");
615 return;
615 return;
616 }
616 }
617
617
618 auto context = new QObject{zoneWidget};
618 auto context = new QObject{zoneWidget};
619 connect(&sqpApp->variableController(), &VariableController2::variableAdded, context,
619 connect(&sqpApp->variableController(), &VariableController2::variableAdded, context,
620 [this, index, zoneWidget, context](auto variable) {
620 [this, index, zoneWidget, context](auto variable) {
621 zoneWidget->createGraph(variable, index);
621 zoneWidget->createGraph(variable, index);
622 delete context; // removes the connection
622 delete context; // removes the connection
623 },
623 },
624 Qt::QueuedConnection);
624 Qt::QueuedConnection);
625
625
626 auto productData = productsData.first().toHash();
626 auto productData = productsData.first().toHash();
627 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
627 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
628 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
628 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
629 }
629 }
@@ -1,41 +1,45
1 #ifndef SCIQLOP_COSINUSPROVIDER_H
1 #ifndef SCIQLOP_COSINUSPROVIDER_H
2 #define SCIQLOP_COSINUSPROVIDER_H
2 #define SCIQLOP_COSINUSPROVIDER_H
3
3
4 #include "MockPluginGlobal.h"
4 #include "MockPluginGlobal.h"
5
5
6 #include <Data/IDataProvider.h>
6 #include <Data/IDataProvider.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QUuid>
9 #include <QUuid>
10
10
11 #include <QHash>
11 #include <QHash>
12 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
13
13
14 /**
14 /**
15 * @brief The CosinusProvider class is an example of how a data provider can generate data
15 * @brief The CosinusProvider class is an example of how a data provider can generate data
16 */
16 */
17 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
17 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
18 public:
18 public:
19 std::shared_ptr<IDataProvider> clone() const override;
19 std::shared_ptr<IDataProvider> clone() const override;
20
20
21 /// @sa IDataProvider::requestDataLoading(). The current impl isn't thread safe.
21 /// @sa IDataProvider::requestDataLoading(). The current impl isn't thread safe.
22 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override;
22 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override;
23
23
24
24
25 virtual IDataSeries* getData(const DataProviderParameters &parameters) override;
26
25 /// @sa IDataProvider::requestDataAborting(). The current impl isn't thread safe.
27 /// @sa IDataProvider::requestDataAborting(). The current impl isn't thread safe.
26 void requestDataAborting(QUuid acqIdentifier) override;
28 void requestDataAborting(QUuid acqIdentifier) override;
27
29
28
30
29 /// Provide data
31 /// Provide data
30 std::shared_ptr<IDataSeries> provideDataSeries(const DateTimeRange &dataRangeRequested,
32 std::shared_ptr<IDataSeries> provideDataSeries(const DateTimeRange &dataRangeRequested,
31 const QVariantHash &data);
33 const QVariantHash &data);
32
34
33
35
34 private:
36 private:
35 std::shared_ptr<IDataSeries>
37 std::shared_ptr<IDataSeries>
36 retrieveData(QUuid acqIdentifier, const DateTimeRange &dataRangeRequested, const QVariantHash &data);
38 retrieveData(QUuid acqIdentifier, const DateTimeRange &dataRangeRequested, const QVariantHash &data);
37
39
40 IDataSeries* _generate(const DateTimeRange &range, const QVariantHash &metaData);
41
38 QHash<QUuid, bool> m_VariableToEnableProvider;
42 QHash<QUuid, bool> m_VariableToEnableProvider;
39 };
43 };
40
44
41 #endif // SCIQLOP_COSINUSPROVIDER_H
45 #endif // SCIQLOP_COSINUSPROVIDER_H
@@ -1,291 +1,332
1 #include "CosinusProvider.h"
1 #include "CosinusProvider.h"
2 #include "MockDefs.h"
2 #include "MockDefs.h"
3
3
4 #include <Data/DataProviderParameters.h>
4 #include <Data/DataProviderParameters.h>
5 #include <Data/ScalarSeries.h>
5 #include <Data/ScalarSeries.h>
6 #include <Data/SpectrogramSeries.h>
6 #include <Data/SpectrogramSeries.h>
7 #include <Data/VectorSeries.h>
7 #include <Data/VectorSeries.h>
8
8
9 #include <cmath>
9 #include <cmath>
10 #include <set>
10 #include <set>
11
11
12 #include <QFuture>
12 #include <QFuture>
13 #include <QThread>
13 #include <QThread>
14 #include <QtConcurrent/QtConcurrent>
14 #include <QtConcurrent/QtConcurrent>
15
15
16 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
16 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
17
17
18 namespace {
18 namespace {
19
19
20 /// Number of bands generated for a spectrogram
20 /// Number of bands generated for a spectrogram
21 const auto SPECTROGRAM_NUMBER_BANDS = 30;
21 const auto SPECTROGRAM_NUMBER_BANDS = 30;
22
22
23 /// Bands for which to generate NaN values for a spectrogram
23 /// Bands for which to generate NaN values for a spectrogram
24 const auto SPECTROGRAM_NAN_BANDS = std::set<int>{1, 3, 10, 20};
24 const auto SPECTROGRAM_NAN_BANDS = std::set<int>{1, 3, 10, 20};
25
25
26 /// Bands for which to generate zeros for a spectrogram
26 /// Bands for which to generate zeros for a spectrogram
27 const auto SPECTROGRAM_ZERO_BANDS = std::set<int>{2, 15, 19, 29};
27 const auto SPECTROGRAM_ZERO_BANDS = std::set<int>{2, 15, 19, 29};
28
28
29 /// Abstract cosinus type
29 /// Abstract cosinus type
30 struct ICosinusType {
30 struct ICosinusType {
31 virtual ~ICosinusType() = default;
31 virtual ~ICosinusType() = default;
32 /// @return the number of components generated for the type
32 /// @return the number of components generated for the type
33 virtual int componentCount() const = 0;
33 virtual std::size_t componentCount() const = 0;
34 /// @return the data series created for the type
34 /// @return the data series created for the type
35 virtual std::shared_ptr<IDataSeries> createDataSeries(std::vector<double> xAxisData,
35 virtual IDataSeries* createDataSeries(std::vector<double> xAxisData,
36 std::vector<double> valuesData) const = 0;
36 std::vector<double> valuesData) const = 0;
37 /// Generates values (one value per component)
37 /// Generates values (one value per component)
38 /// @param x the x-axis data used to generate values
38 /// @param x the x-axis data used to generate values
39 /// @param values the vector in which to insert the generated values
39 /// @param values the vector in which to insert the generated values
40 /// @param dataIndex the index of insertion of the generated values
40 /// @param dataIndex the index of insertion of the generated values
41 ///
41 ///
42 virtual void generateValues(double x, std::vector<double> &values, int dataIndex) const = 0;
42 virtual void generateValues(double x, std::vector<double> &values, int dataIndex) const = 0;
43 };
43 };
44
44
45 struct ScalarCosinus : public ICosinusType {
45 struct ScalarCosinus : public ICosinusType {
46 int componentCount() const override { return 1; }
46 std::size_t componentCount() const override { return 1; }
47
47
48 std::shared_ptr<IDataSeries> createDataSeries(std::vector<double> xAxisData,
48 IDataSeries* createDataSeries(std::vector<double> xAxisData,
49 std::vector<double> valuesData) const override
49 std::vector<double> valuesData) const override
50 {
50 {
51 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
51 return new ScalarSeries(std::move(xAxisData), std::move(valuesData),
52 Unit{QStringLiteral("t"), true}, Unit{});
52 Unit{QStringLiteral("t"), true}, Unit{});
53 }
53 }
54
54
55 void generateValues(double x, std::vector<double> &values, int dataIndex) const override
55 void generateValues(double x, std::vector<double> &values, int dataIndex) const override
56 {
56 {
57 values[dataIndex] = std::cos(x);
57 values[dataIndex] = std::cos(x);
58 }
58 }
59 };
59 };
60
60
61 struct SpectrogramCosinus : public ICosinusType {
61 struct SpectrogramCosinus : public ICosinusType {
62 /// Ctor with y-axis
62 /// Ctor with y-axis
63 explicit SpectrogramCosinus(std::vector<double> yAxisData, Unit yAxisUnit, Unit valuesUnit)
63 explicit SpectrogramCosinus(std::vector<double> yAxisData, Unit yAxisUnit, Unit valuesUnit)
64 : m_YAxisData{std::move(yAxisData)},
64 : m_YAxisData{std::move(yAxisData)},
65 m_YAxisUnit{std::move(yAxisUnit)},
65 m_YAxisUnit{std::move(yAxisUnit)},
66 m_ValuesUnit{std::move(valuesUnit)}
66 m_ValuesUnit{std::move(valuesUnit)}
67 {
67 {
68 }
68 }
69
69
70 int componentCount() const override { return m_YAxisData.size(); }
70 std::size_t componentCount() const override { return m_YAxisData.size(); }
71
71
72 std::shared_ptr<IDataSeries> createDataSeries(std::vector<double> xAxisData,
72 IDataSeries* createDataSeries(std::vector<double> xAxisData,
73 std::vector<double> valuesData) const override
73 std::vector<double> valuesData) const override
74 {
74 {
75 return std::make_shared<SpectrogramSeries>(
75 return new SpectrogramSeries(
76 std::move(xAxisData), m_YAxisData, std::move(valuesData),
76 std::move(xAxisData), m_YAxisData, std::move(valuesData),
77 Unit{QStringLiteral("t"), true}, m_YAxisUnit, m_ValuesUnit);
77 Unit{QStringLiteral("t"), true}, m_YAxisUnit, m_ValuesUnit);
78 }
78 }
79
79
80 void generateValues(double x, std::vector<double> &values, int dataIndex) const override
80 void generateValues(double x, std::vector<double> &values, int dataIndex) const override
81 {
81 {
82 auto componentCount = this->componentCount();
82 auto componentCount = this->componentCount();
83 for (int i = 0; i < componentCount; ++i) {
83 for (int i = 0; i < componentCount; ++i) {
84 auto y = m_YAxisData[i];
84 auto y = m_YAxisData[i];
85
85
86 double value;
86 double value;
87
87
88 if (SPECTROGRAM_ZERO_BANDS.find(y) != SPECTROGRAM_ZERO_BANDS.end()) {
88 if (SPECTROGRAM_ZERO_BANDS.find(y) != SPECTROGRAM_ZERO_BANDS.end()) {
89 value = 0.;
89 value = 0.;
90 }
90 }
91 else if (SPECTROGRAM_NAN_BANDS.find(y) != SPECTROGRAM_NAN_BANDS.end()) {
91 else if (SPECTROGRAM_NAN_BANDS.find(y) != SPECTROGRAM_NAN_BANDS.end()) {
92 value = std::numeric_limits<double>::quiet_NaN();
92 value = std::numeric_limits<double>::quiet_NaN();
93 }
93 }
94 else {
94 else {
95 // Generates value for non NaN/zero bands
95 // Generates value for non NaN/zero bands
96 auto r = 3 * std::sqrt(x * x + y * y) + 1e-2;
96 auto r = 3 * std::sqrt(x * x + y * y) + 1e-2;
97 value = 2 * x * (std::cos(r + 2) / r - std::sin(r + 2) / r);
97 value = 2 * x * (std::cos(r + 2) / r - std::sin(r + 2) / r);
98 }
98 }
99
99
100 values[componentCount * dataIndex + i] = value;
100 values[componentCount * dataIndex + i] = value;
101 }
101 }
102 }
102 }
103
103
104 std::vector<double> m_YAxisData;
104 std::vector<double> m_YAxisData;
105 Unit m_YAxisUnit;
105 Unit m_YAxisUnit;
106 Unit m_ValuesUnit;
106 Unit m_ValuesUnit;
107 };
107 };
108
108
109 struct VectorCosinus : public ICosinusType {
109 struct VectorCosinus : public ICosinusType {
110 int componentCount() const override { return 3; }
110 std::size_t componentCount() const override { return 3; }
111
111
112 std::shared_ptr<IDataSeries> createDataSeries(std::vector<double> xAxisData,
112 IDataSeries* createDataSeries(std::vector<double> xAxisData,
113 std::vector<double> valuesData) const override
113 std::vector<double> valuesData) const override
114 {
114 {
115 return std::make_shared<VectorSeries>(std::move(xAxisData), std::move(valuesData),
115 return new VectorSeries(std::move(xAxisData), std::move(valuesData),
116 Unit{QStringLiteral("t"), true}, Unit{});
116 Unit{QStringLiteral("t"), true}, Unit{});
117 }
117 }
118
118
119 void generateValues(double x, std::vector<double> &values, int dataIndex) const override
119 void generateValues(double x, std::vector<double> &values, int dataIndex) const override
120 {
120 {
121 // Generates value for each component: cos(x), cos(x)/2, cos(x)/3
121 // Generates value for each component: cos(x), cos(x)/2, cos(x)/3
122 auto xValue = std::cos(x);
122 auto xValue = std::cos(x);
123 auto componentCount = this->componentCount();
123 auto componentCount = this->componentCount();
124 for (auto i = 0; i < componentCount; ++i) {
124 for (auto i = 0; i < componentCount; ++i) {
125 values[componentCount * dataIndex + i] = xValue / (i + 1);
125 values[componentCount * dataIndex + i] = xValue / (i + 1);
126 }
126 }
127 }
127 }
128 };
128 };
129
129
130 /// Converts string to cosinus type
130 /// Converts string to cosinus type
131 /// @return the cosinus type if the string could be converted, nullptr otherwise
131 /// @return the cosinus type if the string could be converted, nullptr otherwise
132 std::unique_ptr<ICosinusType> cosinusType(const QString &type) noexcept
132 std::unique_ptr<ICosinusType> cosinusType(const QString &type) noexcept
133 {
133 {
134 if (type.compare(QStringLiteral("scalar"), Qt::CaseInsensitive) == 0) {
134 if (type.compare(QStringLiteral("scalar"), Qt::CaseInsensitive) == 0) {
135 return std::make_unique<ScalarCosinus>();
135 return std::make_unique<ScalarCosinus>();
136 }
136 }
137 else if (type.compare(QStringLiteral("spectrogram"), Qt::CaseInsensitive) == 0) {
137 else if (type.compare(QStringLiteral("spectrogram"), Qt::CaseInsensitive) == 0) {
138 // Generates default y-axis data for spectrogram [0., 1., 2., ...]
138 // Generates default y-axis data for spectrogram [0., 1., 2., ...]
139 std::vector<double> yAxisData(SPECTROGRAM_NUMBER_BANDS);
139 std::vector<double> yAxisData(SPECTROGRAM_NUMBER_BANDS);
140 std::iota(yAxisData.begin(), yAxisData.end(), 0.);
140 std::iota(yAxisData.begin(), yAxisData.end(), 0.);
141
141
142 return std::make_unique<SpectrogramCosinus>(std::move(yAxisData), Unit{"eV"},
142 return std::make_unique<SpectrogramCosinus>(std::move(yAxisData), Unit{"eV"},
143 Unit{"eV/(cm^2-s-sr-eV)"});
143 Unit{"eV/(cm^2-s-sr-eV)"});
144 }
144 }
145 else if (type.compare(QStringLiteral("vector"), Qt::CaseInsensitive) == 0) {
145 else if (type.compare(QStringLiteral("vector"), Qt::CaseInsensitive) == 0) {
146 return std::make_unique<VectorCosinus>();
146 return std::make_unique<VectorCosinus>();
147 }
147 }
148 else {
148 else {
149 return nullptr;
149 return nullptr;
150 }
150 }
151 }
151 }
152
152
153 } // namespace
153 } // namespace
154
154
155 std::shared_ptr<IDataProvider> CosinusProvider::clone() const
155 std::shared_ptr<IDataProvider> CosinusProvider::clone() const
156 {
156 {
157 // No copy is made in clone
157 // No copy is made in clone
158 return std::make_shared<CosinusProvider>();
158 return std::make_shared<CosinusProvider>();
159 }
159 }
160
160
161 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(QUuid acqIdentifier,
161 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(QUuid acqIdentifier,
162 const DateTimeRange &dataRangeRequested,
162 const DateTimeRange &dataRangeRequested,
163 const QVariantHash &data)
163 const QVariantHash &data)
164 {
164 {
165 // TODO: Add Mutex
165 // TODO: Add Mutex
166 auto dataIndex = 0;
166 auto dataIndex = 0;
167
167
168 // Retrieves cosinus type
168 // Retrieves cosinus type
169 auto typeVariant = data.value(COSINUS_TYPE_KEY, COSINUS_TYPE_DEFAULT_VALUE);
169 auto typeVariant = data.value(COSINUS_TYPE_KEY, COSINUS_TYPE_DEFAULT_VALUE);
170 if (!typeVariant.canConvert<QString>()) {
170 if (!typeVariant.canConvert<QString>()) {
171 qCCritical(LOG_CosinusProvider()) << tr("Can't retrieve data: invalid type");
171 qCCritical(LOG_CosinusProvider()) << tr("Can't retrieve data: invalid type");
172 return nullptr;
172 return nullptr;
173 }
173 }
174
174
175 auto type = cosinusType(typeVariant.toString());
175 auto type = cosinusType(typeVariant.toString());
176 if (!type) {
176 if (!type) {
177 qCCritical(LOG_CosinusProvider()) << tr("Can't retrieve data: unknown type");
177 qCCritical(LOG_CosinusProvider()) << tr("Can't retrieve data: unknown type");
178 return nullptr;
178 return nullptr;
179 }
179 }
180
180
181 // Retrieves frequency
181 // Retrieves frequency
182 auto freqVariant = data.value(COSINUS_FREQUENCY_KEY, COSINUS_FREQUENCY_DEFAULT_VALUE);
182 auto freqVariant = data.value(COSINUS_FREQUENCY_KEY, COSINUS_FREQUENCY_DEFAULT_VALUE);
183 if (!freqVariant.canConvert<double>()) {
183 if (!freqVariant.canConvert<double>()) {
184 qCCritical(LOG_CosinusProvider()) << tr("Can't retrieve data: invalid frequency");
184 qCCritical(LOG_CosinusProvider()) << tr("Can't retrieve data: invalid frequency");
185 return nullptr;
185 return nullptr;
186 }
186 }
187
187
188 // Gets the timerange from the parameters
188 // Gets the timerange from the parameters
189 double freq = freqVariant.toDouble();
189 double freq = freqVariant.toDouble();
190 double start = std::ceil(dataRangeRequested.m_TStart * freq);
190 double start = std::ceil(dataRangeRequested.m_TStart * freq);
191 double end = std::floor(dataRangeRequested.m_TEnd * freq);
191 double end = std::floor(dataRangeRequested.m_TEnd * freq);
192
192
193 // We assure that timerange is valid
193 // We assure that timerange is valid
194 if (end < start) {
194 if (end < start) {
195 std::swap(start, end);
195 std::swap(start, end);
196 }
196 }
197
197
198 // Generates scalar series containing cosinus values (one value per second, end value is
198 // Generates scalar series containing cosinus values (one value per second, end value is
199 // included)
199 // included)
200 auto dataCount = end - start + 1;
200 auto dataCount = end - start + 1;
201
201
202 // Number of components (depending on the cosinus type)
202 // Number of components (depending on the cosinus type)
203 auto componentCount = type->componentCount();
203 auto componentCount = type->componentCount();
204
204
205 auto xAxisData = std::vector<double>{};
205 auto xAxisData = std::vector<double>{};
206 xAxisData.resize(dataCount);
206 xAxisData.resize(dataCount);
207
207
208 auto valuesData = std::vector<double>{};
208 auto valuesData = std::vector<double>{};
209 valuesData.resize(dataCount * componentCount);
209 valuesData.resize(dataCount * componentCount);
210
210
211 int progress = 0;
211 int progress = 0;
212 auto progressEnd = dataCount;
212 auto progressEnd = dataCount;
213 for (auto time = start; time <= end; ++time, ++dataIndex) {
213 for (auto time = start; time <= end; ++time, ++dataIndex) {
214 auto it = m_VariableToEnableProvider.find(acqIdentifier);
214 auto it = m_VariableToEnableProvider.find(acqIdentifier);
215 if (it != m_VariableToEnableProvider.end() && it.value()) {
215 if (it != m_VariableToEnableProvider.end() && it.value()) {
216 const auto x = time / freq;
216 const auto x = time / freq;
217
217
218 xAxisData[dataIndex] = x;
218 xAxisData[dataIndex] = x;
219
219
220 // Generates values (depending on the type)
220 // Generates values (depending on the type)
221 type->generateValues(x, valuesData, dataIndex);
221 type->generateValues(x, valuesData, dataIndex);
222
222
223 // progression
223 // progression
224 int currentProgress = (time - start) * 100.0 / progressEnd;
224 int currentProgress = (time - start) * 100.0 / progressEnd;
225 if (currentProgress != progress) {
225 if (currentProgress != progress) {
226 progress = currentProgress;
226 progress = currentProgress;
227
227
228 emit dataProvidedProgress(acqIdentifier, progress);
228 emit dataProvidedProgress(acqIdentifier, progress);
229 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::retrieveData"
229 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::retrieveData"
230 << QThread::currentThread()->objectName()
230 << QThread::currentThread()->objectName()
231 << progress;
231 << progress;
232 // NOTE: Try to use multithread if possible
232 // NOTE: Try to use multithread if possible
233 }
233 }
234 }
234 }
235 else {
235 else {
236 if (!it.value()) {
236 if (!it.value()) {
237 qCDebug(LOG_CosinusProvider())
237 qCDebug(LOG_CosinusProvider())
238 << "CosinusProvider::retrieveData: ARRET De l'acquisition detecté"
238 << "CosinusProvider::retrieveData: ARRET De l'acquisition detecté"
239 << end - time;
239 << end - time;
240 }
240 }
241 }
241 }
242 }
242 }
243 if (progress != 100) {
243 if (progress != 100) {
244 // We can close progression beacause all data has been retrieved
244 // We can close progression beacause all data has been retrieved
245 emit dataProvidedProgress(acqIdentifier, 100);
245 emit dataProvidedProgress(acqIdentifier, 100);
246 }
246 }
247 return std::shared_ptr<IDataSeries>(type->createDataSeries(std::move(xAxisData), std::move(valuesData)));
248 }
249
250 IDataSeries *CosinusProvider::_generate(const DateTimeRange &range, const QVariantHash &metaData)
251 {
252 auto dataIndex = 0;
253
254 // Retrieves cosinus type
255 auto typeVariant = metaData.value(COSINUS_TYPE_KEY, COSINUS_TYPE_DEFAULT_VALUE);
256 auto type = cosinusType(typeVariant.toString());
257 auto freqVariant = metaData.value(COSINUS_FREQUENCY_KEY, COSINUS_FREQUENCY_DEFAULT_VALUE);
258 double freq = freqVariant.toDouble();
259 double start = std::ceil(range.m_TStart * freq);
260 double end = std::floor(range.m_TEnd * freq);
261 if (end < start) {
262 std::swap(start, end);
263 }
264 std::size_t dataCount = static_cast<std::size_t>(end - start + 1);
265 std::size_t componentCount = type->componentCount();
266
267 auto xAxisData = std::vector<double>{};
268 xAxisData.resize(dataCount);
269
270 auto valuesData = std::vector<double>{};
271 valuesData.resize(dataCount * componentCount);
272
273 int progress = 0;
274 auto progressEnd = dataCount;
275 for (auto time = start; time <= end; ++time, ++dataIndex)
276 {
277 const auto x = time / freq;
278 xAxisData[dataIndex] = x;
279 // Generates values (depending on the type)
280 type->generateValues(x, valuesData, dataIndex);
281 }
247 return type->createDataSeries(std::move(xAxisData), std::move(valuesData));
282 return type->createDataSeries(std::move(xAxisData), std::move(valuesData));
248 }
283 }
249
284
250 void CosinusProvider::requestDataLoading(QUuid acqIdentifier,
285 void CosinusProvider::requestDataLoading(QUuid acqIdentifier,
251 const DataProviderParameters &parameters)
286 const DataProviderParameters &parameters)
252 {
287 {
253 // TODO: Add Mutex
288 // TODO: Add Mutex
254 m_VariableToEnableProvider[acqIdentifier] = true;
289 m_VariableToEnableProvider[acqIdentifier] = true;
255 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::requestDataLoading"
290 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::requestDataLoading"
256 << QThread::currentThread()->objectName();
291 << QThread::currentThread()->objectName();
257 // NOTE: Try to use multithread if possible
292 // NOTE: Try to use multithread if possible
258 const auto times = parameters.m_Times;
293 const auto times = parameters.m_Times;
259
294
260 for (const auto &dateTime : qAsConst(times)) {
295 for (const auto &dateTime : qAsConst(times)) {
261 if (m_VariableToEnableProvider[acqIdentifier]) {
296 if (m_VariableToEnableProvider[acqIdentifier]) {
262 auto scalarSeries = this->retrieveData(acqIdentifier, dateTime, parameters.m_Data);
297 auto scalarSeries = this->retrieveData(acqIdentifier, dateTime, parameters.m_Data);
263 emit dataProvided(acqIdentifier, scalarSeries, dateTime);
298 emit dataProvided(acqIdentifier, scalarSeries, dateTime);
264 }
299 }
265 }
300 }
266 }
301 }
267
302
303 IDataSeries* CosinusProvider::getData(const DataProviderParameters &parameters)
304 {
305 return _generate(parameters.m_Times.front(),parameters.m_Data);
306 }
307
308
268 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
309 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
269 {
310 {
270 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << acqIdentifier
311 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << acqIdentifier
271 << QThread::currentThread()->objectName();
312 << QThread::currentThread()->objectName();
272 auto it = m_VariableToEnableProvider.find(acqIdentifier);
313 auto it = m_VariableToEnableProvider.find(acqIdentifier);
273 if (it != m_VariableToEnableProvider.end()) {
314 if (it != m_VariableToEnableProvider.end()) {
274 it.value() = false;
315 it.value() = false;
275 }
316 }
276 else {
317 else {
277 qCDebug(LOG_CosinusProvider())
318 qCDebug(LOG_CosinusProvider())
278 << tr("Aborting progression of inexistant identifier detected !!!");
319 << tr("Aborting progression of inexistant identifier detected !!!");
279 }
320 }
280 }
321 }
281
322
282 std::shared_ptr<IDataSeries> CosinusProvider::provideDataSeries(const DateTimeRange &dataRangeRequested,
323 std::shared_ptr<IDataSeries> CosinusProvider::provideDataSeries(const DateTimeRange &dataRangeRequested,
283 const QVariantHash &data)
324 const QVariantHash &data)
284 {
325 {
285 auto uid = QUuid::createUuid();
326 auto uid = QUuid::createUuid();
286 m_VariableToEnableProvider[uid] = true;
327 m_VariableToEnableProvider[uid] = true;
287 auto dataSeries = this->retrieveData(uid, dataRangeRequested, data);
328 auto dataSeries = this->retrieveData(uid, dataRangeRequested, data);
288
329
289 m_VariableToEnableProvider.remove(uid);
330 m_VariableToEnableProvider.remove(uid);
290 return dataSeries;
331 return dataSeries;
291 }
332 }
General Comments 0
You need to be logged in to leave comments. Login now