##// END OF EJS Templates
Ensures graph and zone names are not duplicated in the visualization
trabillard -
r1170:030ee50565df
parent child
Show More
@@ -1,338 +1,342
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 "Variable/VariableController.h"
10 #include "Variable/VariableController.h"
11
11
12 #include "Common/MimeTypesDef.h"
12 #include "Common/MimeTypesDef.h"
13
13
14 #include "DragAndDrop/DragDropGuiController.h"
14 #include "DragAndDrop/DragDropGuiController.h"
15 #include "SqpApplication.h"
15 #include "SqpApplication.h"
16
16
17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
18
18
19 namespace {
19 namespace {
20
20
21 /// Generates a default name for a new zone, according to the number of zones already displayed in
22 /// the tab
23 QString defaultZoneName(const QLayout &layout)
24 {
25 auto count = 0;
26 for (auto i = 0; i < layout.count(); ++i) {
27 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
28 count++;
29 }
30 }
31
32 return QObject::tr("Zone %1").arg(count + 1);
33 }
34
35 /**
21 /**
36 * Applies a function to all zones of the tab represented by its layout
22 * Applies a function to all zones of the tab represented by its layout
37 * @param layout the layout that contains zones
23 * @param layout the layout that contains zones
38 * @param fun the function to apply to each zone
24 * @param fun the function to apply to each zone
39 */
25 */
40 template <typename Fun>
26 template <typename Fun>
41 void processZones(QLayout &layout, Fun fun)
27 void processZones(QLayout &layout, Fun fun)
42 {
28 {
43 for (auto i = 0; i < layout.count(); ++i) {
29 for (auto i = 0; i < layout.count(); ++i) {
44 if (auto item = layout.itemAt(i)) {
30 if (auto item = layout.itemAt(i)) {
45 if (auto visualizationZoneWidget
31 if (auto visualizationZoneWidget
46 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
32 = qobject_cast<VisualizationZoneWidget *>(item->widget())) {
47 fun(*visualizationZoneWidget);
33 fun(*visualizationZoneWidget);
48 }
34 }
49 }
35 }
50 }
36 }
51 }
37 }
52
38
39 /// Generates a default name for a new zone, according to the number of zones already displayed in
40 /// the tab
41 QString defaultZoneName(QLayout &layout)
42 {
43 QSet<QString> existingNames;
44 processZones(layout,
45 [&existingNames](auto &zoneWidget) { existingNames.insert(zoneWidget.name()); });
46
47 int zoneNum = 1;
48 QString name;
49 do {
50 name = QObject::tr("Zone ").append(QString::number(zoneNum));
51 ++zoneNum;
52 } while (existingNames.contains(name));
53
54 return name;
55 }
56
53 } // namespace
57 } // namespace
54
58
55 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
59 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
56 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
60 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
57
61
58 QString m_Name;
62 QString m_Name;
59
63
60 #ifdef Q_OS_MAC
64 #ifdef Q_OS_MAC
61 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
65 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
62 #endif
66 #endif
63
67
64 void dropGraph(int index, VisualizationTabWidget *tabWidget);
68 void dropGraph(int index, VisualizationTabWidget *tabWidget);
65 void dropZone(int index, VisualizationTabWidget *tabWidget);
69 void dropZone(int index, VisualizationTabWidget *tabWidget);
66 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
70 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
67 VisualizationTabWidget *tabWidget);
71 VisualizationTabWidget *tabWidget);
68 };
72 };
69
73
70 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
74 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
71 : QWidget{parent},
75 : QWidget{parent},
72 ui{new Ui::VisualizationTabWidget},
76 ui{new Ui::VisualizationTabWidget},
73 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
77 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
74 {
78 {
75 ui->setupUi(this);
79 ui->setupUi(this);
76
80
77 #ifdef Q_OS_MAC
81 #ifdef Q_OS_MAC
78 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
82 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
79 #endif
83 #endif
80
84
81 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Zone, "Zone");
85 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Zone, "Zone");
82 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
86 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
83 ui->dragDropContainer->layout()->setSpacing(0);
87 ui->dragDropContainer->layout()->setSpacing(0);
84 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
88 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
85 VisualizationDragDropContainer::DropBehavior::Inserted);
89 VisualizationDragDropContainer::DropBehavior::Inserted);
86 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
90 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
87 VisualizationDragDropContainer::DropBehavior::Inserted);
91 VisualizationDragDropContainer::DropBehavior::Inserted);
88 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
92 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
89 VisualizationDragDropContainer::DropBehavior::Inserted);
93 VisualizationDragDropContainer::DropBehavior::Inserted);
90
94
91 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
95 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
92 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
96 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
93 ui->dragDropContainer);
97 ui->dragDropContainer);
94 });
98 });
95
99
96 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
100 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
97 &VisualizationTabWidget::dropMimeData);
101 &VisualizationTabWidget::dropMimeData);
98
102
99 sqpApp->dragDropGuiController().addDragDropScrollArea(ui->scrollArea);
103 sqpApp->dragDropGuiController().addDragDropScrollArea(ui->scrollArea);
100
104
101 // Widget is deleted when closed
105 // Widget is deleted when closed
102 setAttribute(Qt::WA_DeleteOnClose);
106 setAttribute(Qt::WA_DeleteOnClose);
103 }
107 }
104
108
105 VisualizationTabWidget::~VisualizationTabWidget()
109 VisualizationTabWidget::~VisualizationTabWidget()
106 {
110 {
107 sqpApp->dragDropGuiController().removeDragDropScrollArea(ui->scrollArea);
111 sqpApp->dragDropGuiController().removeDragDropScrollArea(ui->scrollArea);
108 delete ui;
112 delete ui;
109 }
113 }
110
114
111 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
115 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
112 {
116 {
113 ui->dragDropContainer->addDragWidget(zoneWidget);
117 ui->dragDropContainer->addDragWidget(zoneWidget);
114 }
118 }
115
119
116 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
120 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
117 {
121 {
118 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
122 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
119 }
123 }
120
124
121 QStringList VisualizationTabWidget::availableZoneWidgets() const
125 QStringList VisualizationTabWidget::availableZoneWidgets() const
122 {
126 {
123 QStringList zones;
127 QStringList zones;
124 processZones(tabLayout(),
128 processZones(tabLayout(),
125 [&zones](VisualizationZoneWidget &zoneWidget) { zones << zoneWidget.name(); });
129 [&zones](VisualizationZoneWidget &zoneWidget) { zones << zoneWidget.name(); });
126
130
127 return zones;
131 return zones;
128 }
132 }
129
133
130 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
134 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
131 {
135 {
132 return createZone({variable}, -1);
136 return createZone({variable}, -1);
133 }
137 }
134
138
135 VisualizationZoneWidget *
139 VisualizationZoneWidget *
136 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
140 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
137 {
141 {
138 auto zoneWidget = createEmptyZone(index);
142 auto zoneWidget = createEmptyZone(index);
139
143
140 // Creates a new graph into the zone
144 // Creates a new graph into the zone
141 zoneWidget->createGraph(variables, index);
145 zoneWidget->createGraph(variables, index);
142
146
143 return zoneWidget;
147 return zoneWidget;
144 }
148 }
145
149
146 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
150 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
147 {
151 {
148 auto zoneWidget
152 auto zoneWidget
149 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
153 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
150 this->insertZone(index, zoneWidget);
154 this->insertZone(index, zoneWidget);
151
155
152 return zoneWidget;
156 return zoneWidget;
153 }
157 }
154
158
155 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
159 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
156 {
160 {
157 if (visitor) {
161 if (visitor) {
158 visitor->visitEnter(this);
162 visitor->visitEnter(this);
159
163
160 // Apply visitor to zone children: widgets different from zones are not visited (no action)
164 // Apply visitor to zone children: widgets different from zones are not visited (no action)
161 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
165 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
162 zoneWidget.accept(visitor);
166 zoneWidget.accept(visitor);
163 });
167 });
164
168
165 visitor->visitLeave(this);
169 visitor->visitLeave(this);
166 }
170 }
167 else {
171 else {
168 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
172 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
169 }
173 }
170 }
174 }
171
175
172 bool VisualizationTabWidget::canDrop(const Variable &variable) const
176 bool VisualizationTabWidget::canDrop(const Variable &variable) const
173 {
177 {
174 // A tab can always accomodate a variable
178 // A tab can always accomodate a variable
175 Q_UNUSED(variable);
179 Q_UNUSED(variable);
176 return true;
180 return true;
177 }
181 }
178
182
179 bool VisualizationTabWidget::contains(const Variable &variable) const
183 bool VisualizationTabWidget::contains(const Variable &variable) const
180 {
184 {
181 Q_UNUSED(variable);
185 Q_UNUSED(variable);
182 return false;
186 return false;
183 }
187 }
184
188
185 QString VisualizationTabWidget::name() const
189 QString VisualizationTabWidget::name() const
186 {
190 {
187 return impl->m_Name;
191 return impl->m_Name;
188 }
192 }
189
193
190 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
194 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
191 {
195 {
192 // Closes zones in the tab
196 // Closes zones in the tab
193 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
197 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
194
198
195 QWidget::closeEvent(event);
199 QWidget::closeEvent(event);
196 }
200 }
197
201
198 QLayout &VisualizationTabWidget::tabLayout() const noexcept
202 QLayout &VisualizationTabWidget::tabLayout() const noexcept
199 {
203 {
200 return *ui->dragDropContainer->layout();
204 return *ui->dragDropContainer->layout();
201 }
205 }
202
206
203 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
207 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
204 {
208 {
205 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
209 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
206 impl->dropGraph(index, this);
210 impl->dropGraph(index, this);
207 }
211 }
208 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
212 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
209 impl->dropZone(index, this);
213 impl->dropZone(index, this);
210 }
214 }
211 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
215 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
212 auto variables = sqpApp->variableController().variablesForMimeData(
216 auto variables = sqpApp->variableController().variablesForMimeData(
213 mimeData->data(MIME_TYPE_VARIABLE_LIST));
217 mimeData->data(MIME_TYPE_VARIABLE_LIST));
214 impl->dropVariables(variables, index, this);
218 impl->dropVariables(variables, index, this);
215 }
219 }
216 else {
220 else {
217 qCWarning(LOG_VisualizationZoneWidget())
221 qCWarning(LOG_VisualizationZoneWidget())
218 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
222 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
219 }
223 }
220 }
224 }
221
225
222 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
226 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
223 int index, VisualizationTabWidget *tabWidget)
227 int index, VisualizationTabWidget *tabWidget)
224 {
228 {
225 auto &helper = sqpApp->dragDropGuiController();
229 auto &helper = sqpApp->dragDropGuiController();
226
230
227 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
231 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
228 if (!graphWidget) {
232 if (!graphWidget) {
229 qCWarning(LOG_VisualizationZoneWidget())
233 qCWarning(LOG_VisualizationZoneWidget())
230 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
234 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
231 "found or invalid.");
235 "found or invalid.");
232 Q_ASSERT(false);
236 Q_ASSERT(false);
233 return;
237 return;
234 }
238 }
235
239
236 auto parentDragDropContainer
240 auto parentDragDropContainer
237 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
241 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
238 if (!parentDragDropContainer) {
242 if (!parentDragDropContainer) {
239 qCWarning(LOG_VisualizationZoneWidget())
243 qCWarning(LOG_VisualizationZoneWidget())
240 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
244 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
241 "the dropped graph is not found.");
245 "the dropped graph is not found.");
242 Q_ASSERT(false);
246 Q_ASSERT(false);
243 return;
247 return;
244 }
248 }
245
249
246 auto nbGraph = parentDragDropContainer->countDragWidget();
250 auto nbGraph = parentDragDropContainer->countDragWidget();
247
251
248 const auto &variables = graphWidget->variables();
252 const auto &variables = graphWidget->variables();
249
253
250 if (!variables.isEmpty()) {
254 if (!variables.isEmpty()) {
251 // Abort the requests for the variables (if any)
255 // Abort the requests for the variables (if any)
252 // Commented, because it's not sure if it's needed or not
256 // Commented, because it's not sure if it's needed or not
253 // for (const auto& var : variables)
257 // for (const auto& var : variables)
254 //{
258 //{
255 // sqpApp->variableController().onAbortProgressRequested(var);
259 // sqpApp->variableController().onAbortProgressRequested(var);
256 //}
260 //}
257
261
258 if (nbGraph == 1) {
262 if (nbGraph == 1) {
259 // This is the only graph in the previous zone, close the zone
263 // This is the only graph in the previous zone, close the zone
260 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
264 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
261 }
265 }
262 else {
266 else {
263 // Close the graph
267 // Close the graph
264 helper.delayedCloseWidget(graphWidget);
268 helper.delayedCloseWidget(graphWidget);
265 }
269 }
266
270
267 auto zoneWidget = tabWidget->createZone(variables, index);
271 auto zoneWidget = tabWidget->createZone(variables, index);
268 auto firstGraph = zoneWidget->firstGraph();
272 auto firstGraph = zoneWidget->firstGraph();
269 if (firstGraph) {
273 if (firstGraph) {
270 firstGraph->addSelectionZones(graphWidget->selectionZoneRanges());
274 firstGraph->addSelectionZones(graphWidget->selectionZoneRanges());
271 }
275 }
272 else {
276 else {
273 qCWarning(LOG_VisualizationZoneWidget())
277 qCWarning(LOG_VisualizationZoneWidget())
274 << tr("VisualizationTabWidget::dropGraph, no graph added in the widget.");
278 << tr("VisualizationTabWidget::dropGraph, no graph added in the widget.");
275 Q_ASSERT(false);
279 Q_ASSERT(false);
276 }
280 }
277 }
281 }
278 else {
282 else {
279 // The graph is empty, create an empty zone and move the graph inside
283 // The graph is empty, create an empty zone and move the graph inside
280
284
281 auto parentZoneWidget = graphWidget->parentZoneWidget();
285 auto parentZoneWidget = graphWidget->parentZoneWidget();
282
286
283 parentDragDropContainer->layout()->removeWidget(graphWidget);
287 parentDragDropContainer->layout()->removeWidget(graphWidget);
284
288
285 auto zoneWidget = tabWidget->createEmptyZone(index);
289 auto zoneWidget = tabWidget->createEmptyZone(index);
286 zoneWidget->addGraph(graphWidget);
290 zoneWidget->addGraph(graphWidget);
287
291
288 // Close the old zone if it was the only graph inside
292 // Close the old zone if it was the only graph inside
289 if (nbGraph == 1) {
293 if (nbGraph == 1) {
290 helper.delayedCloseWidget(parentZoneWidget);
294 helper.delayedCloseWidget(parentZoneWidget);
291 }
295 }
292 }
296 }
293 }
297 }
294
298
295 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
299 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
296 int index, VisualizationTabWidget *tabWidget)
300 int index, VisualizationTabWidget *tabWidget)
297 {
301 {
298 auto &helper = sqpApp->dragDropGuiController();
302 auto &helper = sqpApp->dragDropGuiController();
299
303
300 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
304 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
301 if (!zoneWidget) {
305 if (!zoneWidget) {
302 qCWarning(LOG_VisualizationZoneWidget())
306 qCWarning(LOG_VisualizationZoneWidget())
303 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
307 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
304 "found or invalid.");
308 "found or invalid.");
305 Q_ASSERT(false);
309 Q_ASSERT(false);
306 return;
310 return;
307 }
311 }
308
312
309 auto parentDragDropContainer
313 auto parentDragDropContainer
310 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
314 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
311 if (!parentDragDropContainer) {
315 if (!parentDragDropContainer) {
312 qCWarning(LOG_VisualizationZoneWidget())
316 qCWarning(LOG_VisualizationZoneWidget())
313 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
317 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
314 "the dropped zone is not found.");
318 "the dropped zone is not found.");
315 Q_ASSERT(false);
319 Q_ASSERT(false);
316 return;
320 return;
317 }
321 }
318
322
319 // Simple move of the zone, no variable operation associated
323 // Simple move of the zone, no variable operation associated
320 parentDragDropContainer->layout()->removeWidget(zoneWidget);
324 parentDragDropContainer->layout()->removeWidget(zoneWidget);
321 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
325 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
322 }
326 }
323
327
324 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
328 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
325 const QList<std::shared_ptr<Variable> > &variables, int index,
329 const QList<std::shared_ptr<Variable> > &variables, int index,
326 VisualizationTabWidget *tabWidget)
330 VisualizationTabWidget *tabWidget)
327 {
331 {
328 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
332 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
329 // compatible variable here
333 // compatible variable here
330 if (variables.count() > 1) {
334 if (variables.count() > 1) {
331 qCWarning(LOG_VisualizationZoneWidget())
335 qCWarning(LOG_VisualizationZoneWidget())
332 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
336 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
333 "aborted.");
337 "aborted.");
334 return;
338 return;
335 }
339 }
336
340
337 tabWidget->createZone(variables, index);
341 tabWidget->createZone(variables, index);
338 }
342 }
@@ -1,587 +1,590
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/SqpRange.h>
12 #include <Data/SqpRange.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14 #include <Variable/Variable.h>
14 #include <Variable/Variable.h>
15 #include <Variable/VariableController.h>
15 #include <Variable/VariableController.h>
16
16
17 #include <Visualization/operations/FindVariableOperation.h>
17 #include <Visualization/operations/FindVariableOperation.h>
18
18
19 #include <DragAndDrop/DragDropGuiController.h>
19 #include <DragAndDrop/DragDropGuiController.h>
20 #include <QUuid>
20 #include <QUuid>
21 #include <SqpApplication.h>
21 #include <SqpApplication.h>
22 #include <cmath>
22 #include <cmath>
23
23
24 #include <QLayout>
24 #include <QLayout>
25
25
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27
27
28 namespace {
28 namespace {
29
29
30
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
32 /// the zone
33 QString defaultGraphName(const QLayout &layout)
34 {
35 auto count = 0;
36 for (auto i = 0; i < layout.count(); ++i) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
38 count++;
39 }
40 }
41
42 return QObject::tr("Graph %1").arg(count + 1);
43 }
44
45 /**
30 /**
46 * Applies a function to all graphs of the zone represented by its layout
31 * Applies a function to all graphs of the zone represented by its layout
47 * @param layout the layout that contains graphs
32 * @param layout the layout that contains graphs
48 * @param fun the function to apply to each graph
33 * @param fun the function to apply to each graph
49 */
34 */
50 template <typename Fun>
35 template <typename Fun>
51 void processGraphs(QLayout &layout, Fun fun)
36 void processGraphs(QLayout &layout, Fun fun)
52 {
37 {
53 for (auto i = 0; i < layout.count(); ++i) {
38 for (auto i = 0; i < layout.count(); ++i) {
54 if (auto item = layout.itemAt(i)) {
39 if (auto item = layout.itemAt(i)) {
55 if (auto visualizationGraphWidget
40 if (auto visualizationGraphWidget
56 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
41 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
57 fun(*visualizationGraphWidget);
42 fun(*visualizationGraphWidget);
58 }
43 }
59 }
44 }
60 }
45 }
61 }
46 }
62
47
48 /// Generates a default name for a new graph, according to the number of graphs already displayed in
49 /// the zone
50 QString defaultGraphName(QLayout &layout)
51 {
52 QSet<QString> existingNames;
53 processGraphs(
54 layout, [&existingNames](auto &graphWidget) { existingNames.insert(graphWidget.name()); });
55
56 int zoneNum = 1;
57 QString name;
58 do {
59 name = QObject::tr("Graph ").append(QString::number(zoneNum));
60 ++zoneNum;
61 } while (existingNames.contains(name));
62
63 return name;
64 }
65
63 } // namespace
66 } // namespace
64
67
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
68 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
66
69
67 explicit VisualizationZoneWidgetPrivate()
70 explicit VisualizationZoneWidgetPrivate()
68 : m_SynchronisationGroupId{QUuid::createUuid()},
71 : m_SynchronisationGroupId{QUuid::createUuid()},
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
72 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
70 {
73 {
71 }
74 }
72 QUuid m_SynchronisationGroupId;
75 QUuid m_SynchronisationGroupId;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
76 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
74
77
75 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
78 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
76 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
79 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
77 VisualizationZoneWidget *zoneWidget);
80 VisualizationZoneWidget *zoneWidget);
78 };
81 };
79
82
80 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
83 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
81 : VisualizationDragWidget{parent},
84 : VisualizationDragWidget{parent},
82 ui{new Ui::VisualizationZoneWidget},
85 ui{new Ui::VisualizationZoneWidget},
83 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
86 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
84 {
87 {
85 ui->setupUi(this);
88 ui->setupUi(this);
86
89
87 ui->zoneNameLabel->setText(name);
90 ui->zoneNameLabel->setText(name);
88
91
89 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
92 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
90 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
93 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
91 VisualizationDragDropContainer::DropBehavior::Inserted);
94 VisualizationDragDropContainer::DropBehavior::Inserted);
92 ui->dragDropContainer->setMimeType(
95 ui->dragDropContainer->setMimeType(
93 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
96 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
94 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
97 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
95 VisualizationDragDropContainer::DropBehavior::Merged);
98 VisualizationDragDropContainer::DropBehavior::Merged);
96 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
99 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
97 VisualizationDragDropContainer::DropBehavior::Forbidden);
100 VisualizationDragDropContainer::DropBehavior::Forbidden);
98 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
101 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
99 VisualizationDragDropContainer::DropBehavior::Forbidden);
102 VisualizationDragDropContainer::DropBehavior::Forbidden);
100 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
103 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
101 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
104 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
102 ui->dragDropContainer);
105 ui->dragDropContainer);
103 });
106 });
104
107
105 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
108 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
106 if (!mimeData) {
109 if (!mimeData) {
107 return false;
110 return false;
108 }
111 }
109
112
110 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
113 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
111 auto variables = sqpApp->variableController().variablesForMimeData(
114 auto variables = sqpApp->variableController().variablesForMimeData(
112 mimeData->data(MIME_TYPE_VARIABLE_LIST));
115 mimeData->data(MIME_TYPE_VARIABLE_LIST));
113
116
114 if (variables.count() != 1) {
117 if (variables.count() != 1) {
115 return false;
118 return false;
116 }
119 }
117 auto variable = variables.first();
120 auto variable = variables.first();
118
121
119 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
122 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
120 return graphWidget->canDrop(*variable);
123 return graphWidget->canDrop(*variable);
121 }
124 }
122 }
125 }
123
126
124 return true;
127 return true;
125 };
128 };
126 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
129 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
127
130
128 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
131 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
129 &VisualizationZoneWidget::dropMimeData);
132 &VisualizationZoneWidget::dropMimeData);
130 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
133 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
131 &VisualizationZoneWidget::dropMimeDataOnGraph);
134 &VisualizationZoneWidget::dropMimeDataOnGraph);
132
135
133 // 'Close' options : widget is deleted when closed
136 // 'Close' options : widget is deleted when closed
134 setAttribute(Qt::WA_DeleteOnClose);
137 setAttribute(Qt::WA_DeleteOnClose);
135 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
138 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
136 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
139 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
137
140
138 // Synchronisation id
141 // Synchronisation id
139 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
142 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
140 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
143 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
141 }
144 }
142
145
143 VisualizationZoneWidget::~VisualizationZoneWidget()
146 VisualizationZoneWidget::~VisualizationZoneWidget()
144 {
147 {
145 delete ui;
148 delete ui;
146 }
149 }
147
150
148 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
151 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
149 {
152 {
150 // Synchronize new graph with others in the zone
153 // Synchronize new graph with others in the zone
151 impl->m_Synchronizer->addGraph(*graphWidget);
154 impl->m_Synchronizer->addGraph(*graphWidget);
152
155
153 ui->dragDropContainer->addDragWidget(graphWidget);
156 ui->dragDropContainer->addDragWidget(graphWidget);
154 }
157 }
155
158
156 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
159 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
157 {
160 {
158 // Synchronize new graph with others in the zone
161 // Synchronize new graph with others in the zone
159 impl->m_Synchronizer->addGraph(*graphWidget);
162 impl->m_Synchronizer->addGraph(*graphWidget);
160
163
161 ui->dragDropContainer->insertDragWidget(index, graphWidget);
164 ui->dragDropContainer->insertDragWidget(index, graphWidget);
162 }
165 }
163
166
164 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
167 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
165 {
168 {
166 return createGraph(variable, -1);
169 return createGraph(variable, -1);
167 }
170 }
168
171
169 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
172 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
170 int index)
173 int index)
171 {
174 {
172 auto graphWidget
175 auto graphWidget
173 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
176 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
174
177
175
178
176 // Set graph properties
179 // Set graph properties
177 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
180 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
178 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
181 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
179
182
180
183
181 // Lambda to synchronize zone widget
184 // Lambda to synchronize zone widget
182 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
185 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
183 const SqpRange &oldGraphRange) {
186 const SqpRange &oldGraphRange) {
184
187
185 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
188 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
186 auto frameLayout = ui->dragDropContainer->layout();
189 auto frameLayout = ui->dragDropContainer->layout();
187 for (auto i = 0; i < frameLayout->count(); ++i) {
190 for (auto i = 0; i < frameLayout->count(); ++i) {
188 auto graphChild
191 auto graphChild
189 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
192 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
190 if (graphChild && (graphChild != graphWidget)) {
193 if (graphChild && (graphChild != graphWidget)) {
191
194
192 auto graphChildRange = graphChild->graphRange();
195 auto graphChildRange = graphChild->graphRange();
193 switch (zoomType) {
196 switch (zoomType) {
194 case AcquisitionZoomType::ZoomIn: {
197 case AcquisitionZoomType::ZoomIn: {
195 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
198 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
196 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
199 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
197 graphChildRange.m_TStart += deltaLeft;
200 graphChildRange.m_TStart += deltaLeft;
198 graphChildRange.m_TEnd -= deltaRight;
201 graphChildRange.m_TEnd -= deltaRight;
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
200 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
203 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
201 << deltaLeft;
204 << deltaLeft;
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
205 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
203 << deltaRight;
206 << deltaRight;
204 qCDebug(LOG_VisualizationZoneWidget())
207 qCDebug(LOG_VisualizationZoneWidget())
205 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
208 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
206
209
207 break;
210 break;
208 }
211 }
209
212
210 case AcquisitionZoomType::ZoomOut: {
213 case AcquisitionZoomType::ZoomOut: {
211 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
214 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
212 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
215 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
213 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
216 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
214 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
217 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
215 << deltaLeft;
218 << deltaLeft;
216 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
219 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
217 << deltaRight;
220 << deltaRight;
218 qCDebug(LOG_VisualizationZoneWidget())
221 qCDebug(LOG_VisualizationZoneWidget())
219 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
222 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
220 graphChildRange.m_TStart -= deltaLeft;
223 graphChildRange.m_TStart -= deltaLeft;
221 graphChildRange.m_TEnd += deltaRight;
224 graphChildRange.m_TEnd += deltaRight;
222 break;
225 break;
223 }
226 }
224 case AcquisitionZoomType::PanRight: {
227 case AcquisitionZoomType::PanRight: {
225 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
228 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
226 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
229 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
227 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
230 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
228 graphChildRange.m_TStart += deltaLeft;
231 graphChildRange.m_TStart += deltaLeft;
229 graphChildRange.m_TEnd += deltaRight;
232 graphChildRange.m_TEnd += deltaRight;
230 qCDebug(LOG_VisualizationZoneWidget())
233 qCDebug(LOG_VisualizationZoneWidget())
231 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
234 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
232 break;
235 break;
233 }
236 }
234 case AcquisitionZoomType::PanLeft: {
237 case AcquisitionZoomType::PanLeft: {
235 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
238 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
236 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
239 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
237 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
240 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
238 graphChildRange.m_TStart -= deltaLeft;
241 graphChildRange.m_TStart -= deltaLeft;
239 graphChildRange.m_TEnd -= deltaRight;
242 graphChildRange.m_TEnd -= deltaRight;
240 break;
243 break;
241 }
244 }
242 case AcquisitionZoomType::Unknown: {
245 case AcquisitionZoomType::Unknown: {
243 qCDebug(LOG_VisualizationZoneWidget())
246 qCDebug(LOG_VisualizationZoneWidget())
244 << tr("Impossible to synchronize: zoom type unknown");
247 << tr("Impossible to synchronize: zoom type unknown");
245 break;
248 break;
246 }
249 }
247 default:
250 default:
248 qCCritical(LOG_VisualizationZoneWidget())
251 qCCritical(LOG_VisualizationZoneWidget())
249 << tr("Impossible to synchronize: zoom type not take into account");
252 << tr("Impossible to synchronize: zoom type not take into account");
250 // No action
253 // No action
251 break;
254 break;
252 }
255 }
253 graphChild->enableAcquisition(false);
256 graphChild->enableAcquisition(false);
254 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
257 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
255 << graphChild->graphRange();
258 << graphChild->graphRange();
256 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
259 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
257 << graphChildRange;
260 << graphChildRange;
258 qCDebug(LOG_VisualizationZoneWidget())
261 qCDebug(LOG_VisualizationZoneWidget())
259 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
262 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
260 graphChild->setGraphRange(graphChildRange);
263 graphChild->setGraphRange(graphChildRange);
261 graphChild->enableAcquisition(true);
264 graphChild->enableAcquisition(true);
262 }
265 }
263 }
266 }
264 };
267 };
265
268
266 // connection for synchronization
269 // connection for synchronization
267 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
270 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
268 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
271 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
269 &VisualizationZoneWidget::onVariableAdded);
272 &VisualizationZoneWidget::onVariableAdded);
270 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
273 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
271 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
274 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
272
275
273 auto range = SqpRange{};
276 auto range = SqpRange{};
274 if (auto firstGraph = this->firstGraph()) {
277 if (auto firstGraph = this->firstGraph()) {
275 // Case of a new graph in a existant zone
278 // Case of a new graph in a existant zone
276 range = firstGraph->graphRange();
279 range = firstGraph->graphRange();
277 }
280 }
278 else {
281 else {
279 // Case of a new graph as the first of the zone
282 // Case of a new graph as the first of the zone
280 range = variable->range();
283 range = variable->range();
281 }
284 }
282
285
283 this->insertGraph(index, graphWidget);
286 this->insertGraph(index, graphWidget);
284
287
285 graphWidget->addVariable(variable, range);
288 graphWidget->addVariable(variable, range);
286 graphWidget->setYRange(variable);
289 graphWidget->setYRange(variable);
287
290
288 return graphWidget;
291 return graphWidget;
289 }
292 }
290
293
291 VisualizationGraphWidget *
294 VisualizationGraphWidget *
292 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
295 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
293 {
296 {
294 if (variables.isEmpty()) {
297 if (variables.isEmpty()) {
295 return nullptr;
298 return nullptr;
296 }
299 }
297
300
298 auto graphWidget = createGraph(variables.first(), index);
301 auto graphWidget = createGraph(variables.first(), index);
299 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
302 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
300 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
303 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
301 }
304 }
302
305
303 return graphWidget;
306 return graphWidget;
304 }
307 }
305
308
306 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
309 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
307 {
310 {
308 VisualizationGraphWidget *firstGraph = nullptr;
311 VisualizationGraphWidget *firstGraph = nullptr;
309 auto layout = ui->dragDropContainer->layout();
312 auto layout = ui->dragDropContainer->layout();
310 if (layout->count() > 0) {
313 if (layout->count() > 0) {
311 if (auto visualizationGraphWidget
314 if (auto visualizationGraphWidget
312 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
315 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
313 firstGraph = visualizationGraphWidget;
316 firstGraph = visualizationGraphWidget;
314 }
317 }
315 }
318 }
316
319
317 return firstGraph;
320 return firstGraph;
318 }
321 }
319
322
320 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
323 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
321 {
324 {
322 if (visitor) {
325 if (visitor) {
323 visitor->visitEnter(this);
326 visitor->visitEnter(this);
324
327
325 // Apply visitor to graph children: widgets different from graphs are not visited (no
328 // Apply visitor to graph children: widgets different from graphs are not visited (no
326 // action)
329 // action)
327 processGraphs(
330 processGraphs(
328 *ui->dragDropContainer->layout(),
331 *ui->dragDropContainer->layout(),
329 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
332 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
330
333
331 visitor->visitLeave(this);
334 visitor->visitLeave(this);
332 }
335 }
333 else {
336 else {
334 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
337 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
335 }
338 }
336 }
339 }
337
340
338 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
341 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
339 {
342 {
340 // A tab can always accomodate a variable
343 // A tab can always accomodate a variable
341 Q_UNUSED(variable);
344 Q_UNUSED(variable);
342 return true;
345 return true;
343 }
346 }
344
347
345 bool VisualizationZoneWidget::contains(const Variable &variable) const
348 bool VisualizationZoneWidget::contains(const Variable &variable) const
346 {
349 {
347 Q_UNUSED(variable);
350 Q_UNUSED(variable);
348 return false;
351 return false;
349 }
352 }
350
353
351 QString VisualizationZoneWidget::name() const
354 QString VisualizationZoneWidget::name() const
352 {
355 {
353 return ui->zoneNameLabel->text();
356 return ui->zoneNameLabel->text();
354 }
357 }
355
358
356 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
359 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
357 {
360 {
358 Q_UNUSED(position);
361 Q_UNUSED(position);
359
362
360 auto mimeData = new QMimeData;
363 auto mimeData = new QMimeData;
361 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
364 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
362
365
363 if (auto firstGraph = this->firstGraph()) {
366 if (auto firstGraph = this->firstGraph()) {
364 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
367 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
365 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
368 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
366 }
369 }
367
370
368 return mimeData;
371 return mimeData;
369 }
372 }
370
373
371 bool VisualizationZoneWidget::isDragAllowed() const
374 bool VisualizationZoneWidget::isDragAllowed() const
372 {
375 {
373 return true;
376 return true;
374 }
377 }
375
378
376 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
379 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
377 const QPointF &plotPosition,
380 const QPointF &plotPosition,
378 VisualizationGraphWidget *graphWidget)
381 VisualizationGraphWidget *graphWidget)
379 {
382 {
380 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
383 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
381 VisualizationGraphWidget &processedGraph) {
384 VisualizationGraphWidget &processedGraph) {
382
385
383 switch (sqpApp->plotsCursorMode()) {
386 switch (sqpApp->plotsCursorMode()) {
384 case SqpApplication::PlotsCursorMode::Vertical:
387 case SqpApplication::PlotsCursorMode::Vertical:
385 processedGraph.removeHorizontalCursor();
388 processedGraph.removeHorizontalCursor();
386 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
389 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
387 break;
390 break;
388 case SqpApplication::PlotsCursorMode::Temporal:
391 case SqpApplication::PlotsCursorMode::Temporal:
389 processedGraph.addVerticalCursor(plotPosition.x());
392 processedGraph.addVerticalCursor(plotPosition.x());
390 processedGraph.removeHorizontalCursor();
393 processedGraph.removeHorizontalCursor();
391 break;
394 break;
392 case SqpApplication::PlotsCursorMode::Horizontal:
395 case SqpApplication::PlotsCursorMode::Horizontal:
393 processedGraph.removeVerticalCursor();
396 processedGraph.removeVerticalCursor();
394 if (&processedGraph == graphWidget) {
397 if (&processedGraph == graphWidget) {
395 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
398 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
396 }
399 }
397 else {
400 else {
398 processedGraph.removeHorizontalCursor();
401 processedGraph.removeHorizontalCursor();
399 }
402 }
400 break;
403 break;
401 case SqpApplication::PlotsCursorMode::Cross:
404 case SqpApplication::PlotsCursorMode::Cross:
402 if (&processedGraph == graphWidget) {
405 if (&processedGraph == graphWidget) {
403 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
406 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
404 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
407 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
405 }
408 }
406 else {
409 else {
407 processedGraph.removeHorizontalCursor();
410 processedGraph.removeHorizontalCursor();
408 processedGraph.removeVerticalCursor();
411 processedGraph.removeVerticalCursor();
409 }
412 }
410 break;
413 break;
411 case SqpApplication::PlotsCursorMode::NoCursor:
414 case SqpApplication::PlotsCursorMode::NoCursor:
412 processedGraph.removeHorizontalCursor();
415 processedGraph.removeHorizontalCursor();
413 processedGraph.removeVerticalCursor();
416 processedGraph.removeVerticalCursor();
414 break;
417 break;
415 }
418 }
416
419
417
420
418 });
421 });
419 }
422 }
420
423
421 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
424 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
422 {
425 {
423 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
426 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
424 processedGraph.removeHorizontalCursor();
427 processedGraph.removeHorizontalCursor();
425 processedGraph.removeVerticalCursor();
428 processedGraph.removeVerticalCursor();
426 });
429 });
427 }
430 }
428
431
429 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
432 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
430 {
433 {
431 // Closes graphs in the zone
434 // Closes graphs in the zone
432 processGraphs(*ui->dragDropContainer->layout(),
435 processGraphs(*ui->dragDropContainer->layout(),
433 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
436 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
434
437
435 // Delete synchronization group from variable controller
438 // Delete synchronization group from variable controller
436 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
439 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
437 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
440 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
438
441
439 QWidget::closeEvent(event);
442 QWidget::closeEvent(event);
440 }
443 }
441
444
442 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
445 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
443 {
446 {
444 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
447 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
445 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
448 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
446 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
449 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
447 }
450 }
448
451
449 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
452 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
450 {
453 {
451 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
454 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
452 Q_ARG(std::shared_ptr<Variable>, variable),
455 Q_ARG(std::shared_ptr<Variable>, variable),
453 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
456 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
454 }
457 }
455
458
456 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
459 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
457 {
460 {
458 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
461 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
459 impl->dropGraph(index, this);
462 impl->dropGraph(index, this);
460 }
463 }
461 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
464 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
462 auto variables = sqpApp->variableController().variablesForMimeData(
465 auto variables = sqpApp->variableController().variablesForMimeData(
463 mimeData->data(MIME_TYPE_VARIABLE_LIST));
466 mimeData->data(MIME_TYPE_VARIABLE_LIST));
464 impl->dropVariables(variables, index, this);
467 impl->dropVariables(variables, index, this);
465 }
468 }
466 else {
469 else {
467 qCWarning(LOG_VisualizationZoneWidget())
470 qCWarning(LOG_VisualizationZoneWidget())
468 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
471 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
469 }
472 }
470 }
473 }
471
474
472 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
475 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
473 const QMimeData *mimeData)
476 const QMimeData *mimeData)
474 {
477 {
475 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
478 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
476 if (!graphWidget) {
479 if (!graphWidget) {
477 qCWarning(LOG_VisualizationZoneWidget())
480 qCWarning(LOG_VisualizationZoneWidget())
478 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
481 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
479 "drop aborted");
482 "drop aborted");
480 Q_ASSERT(false);
483 Q_ASSERT(false);
481 return;
484 return;
482 }
485 }
483
486
484 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
487 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
485 auto variables = sqpApp->variableController().variablesForMimeData(
488 auto variables = sqpApp->variableController().variablesForMimeData(
486 mimeData->data(MIME_TYPE_VARIABLE_LIST));
489 mimeData->data(MIME_TYPE_VARIABLE_LIST));
487 for (const auto &var : variables) {
490 for (const auto &var : variables) {
488 graphWidget->addVariable(var, graphWidget->graphRange());
491 graphWidget->addVariable(var, graphWidget->graphRange());
489 }
492 }
490 }
493 }
491 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
494 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
492 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
495 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
493 graphWidget->setGraphRange(range);
496 graphWidget->setGraphRange(range);
494 }
497 }
495 else {
498 else {
496 qCWarning(LOG_VisualizationZoneWidget())
499 qCWarning(LOG_VisualizationZoneWidget())
497 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
500 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
498 }
501 }
499 }
502 }
500
503
501 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
504 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
502 int index, VisualizationZoneWidget *zoneWidget)
505 int index, VisualizationZoneWidget *zoneWidget)
503 {
506 {
504 auto &helper = sqpApp->dragDropGuiController();
507 auto &helper = sqpApp->dragDropGuiController();
505
508
506 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
509 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
507 if (!graphWidget) {
510 if (!graphWidget) {
508 qCWarning(LOG_VisualizationZoneWidget())
511 qCWarning(LOG_VisualizationZoneWidget())
509 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
512 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
510 "found or invalid.");
513 "found or invalid.");
511 Q_ASSERT(false);
514 Q_ASSERT(false);
512 return;
515 return;
513 }
516 }
514
517
515 auto parentDragDropContainer
518 auto parentDragDropContainer
516 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
519 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
517 if (!parentDragDropContainer) {
520 if (!parentDragDropContainer) {
518 qCWarning(LOG_VisualizationZoneWidget())
521 qCWarning(LOG_VisualizationZoneWidget())
519 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
522 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
520 "the dropped graph is not found.");
523 "the dropped graph is not found.");
521 Q_ASSERT(false);
524 Q_ASSERT(false);
522 return;
525 return;
523 }
526 }
524
527
525 const auto &variables = graphWidget->variables();
528 const auto &variables = graphWidget->variables();
526
529
527 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
530 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
528 // The drop didn't occur in the same zone
531 // The drop didn't occur in the same zone
529
532
530 // Abort the requests for the variables (if any)
533 // Abort the requests for the variables (if any)
531 // Commented, because it's not sure if it's needed or not
534 // Commented, because it's not sure if it's needed or not
532 // for (const auto& var : variables)
535 // for (const auto& var : variables)
533 //{
536 //{
534 // sqpApp->variableController().onAbortProgressRequested(var);
537 // sqpApp->variableController().onAbortProgressRequested(var);
535 //}
538 //}
536
539
537 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
540 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
538 auto nbGraph = parentDragDropContainer->countDragWidget();
541 auto nbGraph = parentDragDropContainer->countDragWidget();
539 if (nbGraph == 1) {
542 if (nbGraph == 1) {
540 // This is the only graph in the previous zone, close the zone
543 // This is the only graph in the previous zone, close the zone
541 helper.delayedCloseWidget(previousParentZoneWidget);
544 helper.delayedCloseWidget(previousParentZoneWidget);
542 }
545 }
543 else {
546 else {
544 // Close the graph
547 // Close the graph
545 helper.delayedCloseWidget(graphWidget);
548 helper.delayedCloseWidget(graphWidget);
546 }
549 }
547
550
548 // Creates the new graph in the zone
551 // Creates the new graph in the zone
549 auto newGraphWidget = zoneWidget->createGraph(variables, index);
552 auto newGraphWidget = zoneWidget->createGraph(variables, index);
550 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
553 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
551 }
554 }
552 else {
555 else {
553 // The drop occurred in the same zone or the graph is empty
556 // The drop occurred in the same zone or the graph is empty
554 // Simple move of the graph, no variable operation associated
557 // Simple move of the graph, no variable operation associated
555 parentDragDropContainer->layout()->removeWidget(graphWidget);
558 parentDragDropContainer->layout()->removeWidget(graphWidget);
556
559
557 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
560 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
558 // The graph is empty and dropped in a different zone.
561 // The graph is empty and dropped in a different zone.
559 // Take the range of the first graph in the zone (if existing).
562 // Take the range of the first graph in the zone (if existing).
560 auto layout = zoneWidget->ui->dragDropContainer->layout();
563 auto layout = zoneWidget->ui->dragDropContainer->layout();
561 if (layout->count() > 0) {
564 if (layout->count() > 0) {
562 if (auto visualizationGraphWidget
565 if (auto visualizationGraphWidget
563 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
566 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
564 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
567 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
565 }
568 }
566 }
569 }
567 }
570 }
568
571
569 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
572 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
570 }
573 }
571 }
574 }
572
575
573 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
576 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
574 const QList<std::shared_ptr<Variable> > &variables, int index,
577 const QList<std::shared_ptr<Variable> > &variables, int index,
575 VisualizationZoneWidget *zoneWidget)
578 VisualizationZoneWidget *zoneWidget)
576 {
579 {
577 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
580 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
578 // compatible variable here
581 // compatible variable here
579 if (variables.count() > 1) {
582 if (variables.count() > 1) {
580 qCWarning(LOG_VisualizationZoneWidget())
583 qCWarning(LOG_VisualizationZoneWidget())
581 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
584 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
582 "aborted.");
585 "aborted.");
583 return;
586 return;
584 }
587 }
585
588
586 zoneWidget->createGraph(variables, index);
589 zoneWidget->createGraph(variables, index);
587 }
590 }
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved

Status change > Approved

You need to be logged in to leave comments. Login now