##// END OF EJS Templates
Merge branch 'feature/GraphFixes' into develop
Alexandre Leroux -
r679:c3be9e8d665b merge
parent child
Show More
@@ -0,0 +1,42
1 #ifndef SCIQLOP_FINDVARIABLEOPERATION_H
2 #define SCIQLOP_FINDVARIABLEOPERATION_H
3
4 #include "Visualization/IVisualizationWidgetVisitor.h"
5
6 #include <Common/spimpl.h>
7
8 #include <set>
9
10 class IVisualizationWidget;
11 class Variable;
12
13 /**
14 * @brief The FindVariableOperation class defines an operation that traverses all of visualization
15 * widgets to determine which ones contain the variable passed as parameter. The result of the
16 * operation is the list of widgets that contain the variable.
17 */
18 class FindVariableOperation : public IVisualizationWidgetVisitor {
19 public:
20 /**
21 * Ctor
22 * @param variable the variable to find
23 */
24 explicit FindVariableOperation(std::shared_ptr<Variable> variable);
25
26 void visitEnter(VisualizationWidget *widget) override final;
27 void visitLeave(VisualizationWidget *widget) override final;
28 void visitEnter(VisualizationTabWidget *tabWidget) override final;
29 void visitLeave(VisualizationTabWidget *tabWidget) override final;
30 void visitEnter(VisualizationZoneWidget *zoneWidget) override final;
31 void visitLeave(VisualizationZoneWidget *zoneWidget) override final;
32 void visit(VisualizationGraphWidget *graphWidget) override final;
33
34 /// @return the widgets that contain the variable
35 std::set<IVisualizationWidget *> result() const noexcept;
36
37 private:
38 class FindVariableOperationPrivate;
39 spimpl::unique_impl_ptr<FindVariableOperationPrivate> impl;
40 };
41
42 #endif // SCIQLOP_FINDVARIABLEOPERATION_H
@@ -0,0 +1,72
1 #include "Visualization/operations/FindVariableOperation.h"
2
3 #include "Visualization/VisualizationGraphWidget.h"
4 #include "Visualization/VisualizationTabWidget.h"
5 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7
8 #include <Variable/Variable.h>
9
10 struct FindVariableOperation::FindVariableOperationPrivate {
11 explicit FindVariableOperationPrivate(std::shared_ptr<Variable> variable) : m_Variable{variable}
12 {
13 }
14
15 void visit(IVisualizationWidget *widget)
16 {
17 if (m_Variable && widget && widget->contains(*m_Variable)) {
18 m_Containers.insert(widget);
19 }
20 }
21
22 std::shared_ptr<Variable> m_Variable; ///< Variable to find
23 std::set<IVisualizationWidget *> m_Containers; ///< Containers found for the variable
24 };
25
26 FindVariableOperation::FindVariableOperation(std::shared_ptr<Variable> variable)
27 : impl{spimpl::make_unique_impl<FindVariableOperationPrivate>(variable)}
28 {
29 }
30
31 void FindVariableOperation::visitEnter(VisualizationWidget *widget)
32 {
33 impl->visit(widget);
34 }
35
36 void FindVariableOperation::visitLeave(VisualizationWidget *widget)
37 {
38 // Does nothing
39 Q_UNUSED(widget);
40 }
41
42 void FindVariableOperation::visitEnter(VisualizationTabWidget *tabWidget)
43 {
44 impl->visit(tabWidget);
45 }
46
47 void FindVariableOperation::visitLeave(VisualizationTabWidget *tabWidget)
48 {
49 // Does nothing
50 Q_UNUSED(tabWidget);
51 }
52
53 void FindVariableOperation::visitEnter(VisualizationZoneWidget *zoneWidget)
54 {
55 impl->visit(zoneWidget);
56 }
57
58 void FindVariableOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
59 {
60 // Does nothing
61 Q_UNUSED(zoneWidget);
62 }
63
64 void FindVariableOperation::visit(VisualizationGraphWidget *graphWidget)
65 {
66 impl->visit(graphWidget);
67 }
68
69 std::set<IVisualizationWidget *> FindVariableOperation::result() const noexcept
70 {
71 return impl->m_Containers;
72 }
@@ -111,11 +111,15 public slots:
111 111 /// Cancel the current request for the variable
112 112 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
113 113
114 /// synchronization group methods
114 // synchronization group methods
115 115 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
116 116 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
117 117 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
118 118
119 /// Desynchronizes the variable of the group whose identifier is passed in parameter
120 /// @remarks the method does nothing if the variable is not part of the group
121 void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
122
119 123 void initialize();
120 124 void finalize();
121 125
@@ -389,6 +389,36 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
389 389 }
390 390 }
391 391
392 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
393 QUuid synchronizationGroupId)
394 {
395 // Gets variable id
396 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
397 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
398 qCCritical(LOG_VariableController())
399 << tr("Can't desynchronize variable %1: variable identifier not found")
400 .arg(variable->name());
401 return;
402 }
403
404 // Gets synchronization group
405 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
406 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
407 qCCritical(LOG_VariableController())
408 << tr("Can't desynchronize variable %1: unknown synchronization group")
409 .arg(variable->name());
410 return;
411 }
412
413 auto variableId = variableIt->second;
414
415 // Removes variable from synchronization group
416 auto synchronizationGroup = groupIt->second;
417 synchronizationGroup->removeVariableId(variableId);
418
419 // Removes link between variable and synchronization group
420 impl->m_VariableIdGroupIdMap.erase(variableId);
421 }
392 422
393 423 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
394 424 const SqpRange &range, const SqpRange &oldRange,
@@ -56,9 +56,13 signals:
56 56 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
57 57 const SqpRange &oldRange, bool synchronise);
58 58
59 /// Signal emitted when the variable is about to be removed from the graph
60 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
61 /// Signal emitted when the variable has been added to the graph
59 62 void variableAdded(std::shared_ptr<Variable> var);
60 63
61 64 protected:
65 void closeEvent(QCloseEvent *event) override;
62 66 void enterEvent(QEvent *event) override;
63 67 void leaveEvent(QEvent *event) override;
64 68
@@ -41,6 +41,9 public:
41 41 bool contains(const Variable &variable) const override;
42 42 QString name() const override;
43 43
44 protected:
45 void closeEvent(QCloseEvent *event) override;
46
44 47 private:
45 48 /// @return the layout of tab in which zones are added
46 49 QLayout &tabLayout() const noexcept;
@@ -44,6 +44,9 public slots:
44 44
45 45 void onRangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range) noexcept;
46 46
47 protected:
48 void closeEvent(QCloseEvent *event) override;
49
47 50 private:
48 51 Ui::VisualizationWidget *ui;
49 52 };
@@ -42,6 +42,9 public:
42 42 bool contains(const Variable &variable) const override;
43 43 QString name() const override;
44 44
45 protected:
46 void closeEvent(QCloseEvent *event) override;
47
45 48 private:
46 49 Ui::VisualizationZoneWidget *ui;
47 50
@@ -50,6 +53,8 private:
50 53
51 54 private slots:
52 55 void onVariableAdded(std::shared_ptr<Variable> variable);
56 /// Slot called when a variable is about to be removed from a graph contained in the zone
57 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
53 58 };
54 59
55 60 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -7,7 +7,10
7 7
8 8 #include <QLoggingCategory>
9 9
10 #include <set>
11
10 12 class QMenu;
13 class IVisualizationWidget;
11 14 class Variable;
12 15
13 16 Q_DECLARE_LOGGING_CATEGORY(LOG_GenerateVariableMenuOperation)
@@ -23,8 +26,11 public:
23 26 * Ctor
24 27 * @param menu the menu to which to attach the generated menu
25 28 * @param variable the variable for which to generate the menu
29 * @param variableContainers the containers that already contain the variable for which to
30 * generate the menu
26 31 */
27 explicit GenerateVariableMenuOperation(QMenu *menu, std::shared_ptr<Variable> variable);
32 explicit GenerateVariableMenuOperation(QMenu *menu, std::shared_ptr<Variable> variable,
33 std::set<IVisualizationWidget *> variableContainers);
28 34
29 35 void visitEnter(VisualizationWidget *widget) override final;
30 36 void visitLeave(VisualizationWidget *widget) override final;
@@ -54,6 +54,7 gui_sources = [
54 54 'src/Visualization/VisualizationZoneWidget.cpp',
55 55 'src/Visualization/qcustomplot.cpp',
56 56 'src/Visualization/QCustomPlotSynchronizer.cpp',
57 'src/Visualization/operations/FindVariableOperation.cpp',
57 58 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
58 59 'src/Visualization/operations/MenuBuilder.cpp',
59 60 'src/Visualization/operations/RemoveVariableOperation.cpp',
@@ -138,6 +138,8 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable
138 138 // - is no longer referenced in the map
139 139 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
140 140 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
141 emit variableAboutToBeRemoved(variable);
142
141 143 auto &plottablesMap = variableIt->second;
142 144
143 145 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
@@ -218,6 +220,16 QString VisualizationGraphWidget::name() const
218 220 return impl->m_Name;
219 221 }
220 222
223 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
224 {
225 Q_UNUSED(event);
226
227 // Prevents that all variables will be removed from graph when it will be closed
228 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
229 emit variableAboutToBeRemoved(variableEntry.first);
230 }
231 }
232
221 233 void VisualizationGraphWidget::enterEvent(QEvent *event)
222 234 {
223 235 Q_UNUSED(event);
@@ -22,6 +22,24 QString defaultZoneName(const QLayout &layout)
22 22 return QObject::tr("Zone %1").arg(count + 1);
23 23 }
24 24
25 /**
26 * Applies a function to all zones of the tab represented by its layout
27 * @param layout the layout that contains zones
28 * @param fun the function to apply to each zone
29 */
30 template <typename Fun>
31 void processZones(QLayout &layout, Fun fun)
32 {
33 for (auto i = 0; i < layout.count(); ++i) {
34 if (auto item = layout.itemAt(i)) {
35 if (auto visualizationZoneWidget
36 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
37 fun(*visualizationZoneWidget);
38 }
39 }
40 }
41 }
42
25 43 } // namespace
26 44
27 45 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
@@ -67,17 +85,10 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
67 85 if (visitor) {
68 86 visitor->visitEnter(this);
69 87
70 // Apply visitor to zone children
71 auto &layout = tabLayout();
72 for (auto i = 0; i < layout.count(); ++i) {
73 if (auto item = layout.itemAt(i)) {
74 // Widgets different from zones are not visited (no action)
75 if (auto visualizationZoneWidget
76 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
77 visualizationZoneWidget->accept(visitor);
78 }
79 }
80 }
88 // Apply visitor to zone children: widgets different from zones are not visited (no action)
89 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
90 zoneWidget.accept(visitor);
91 });
81 92
82 93 visitor->visitLeave(this);
83 94 }
@@ -104,6 +115,14 QString VisualizationTabWidget::name() const
104 115 return impl->m_Name;
105 116 }
106 117
118 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
119 {
120 // Closes zones in the tab
121 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
122
123 QWidget::closeEvent(event);
124 }
125
107 126 QLayout &VisualizationTabWidget::tabLayout() const noexcept
108 127 {
109 128 return *ui->scrollAreaWidgetContents->layout();
@@ -3,6 +3,7
3 3 #include "Visualization/VisualizationGraphWidget.h"
4 4 #include "Visualization/VisualizationTabWidget.h"
5 5 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/operations/FindVariableOperation.h"
6 7 #include "Visualization/operations/GenerateVariableMenuOperation.h"
7 8 #include "Visualization/operations/RemoveVariableOperation.h"
8 9 #include "Visualization/operations/RescaleAxeOperation.h"
@@ -120,8 +121,14 void VisualizationWidget::attachVariableMenu(
120 121 // Menu is generated only if there is a single variable
121 122 if (variables.size() == 1) {
122 123 if (auto variable = variables.first()) {
124 // Gets the containers of the variable
125 FindVariableOperation findVariableOperation{variable};
126 accept(&findVariableOperation);
127 auto variableContainers = findVariableOperation.result();
128
123 129 // Generates the actions that make it possible to visualize the variable
124 auto generateVariableMenuOperation = GenerateVariableMenuOperation{menu, variable};
130 GenerateVariableMenuOperation generateVariableMenuOperation{
131 menu, variable, std::move(variableContainers)};
125 132 accept(&generateVariableMenuOperation);
126 133 }
127 134 else {
@@ -150,3 +157,16 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
150 157 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
151 158 accept(&rescaleVariableOperation);
152 159 }
160
161 void VisualizationWidget::closeEvent(QCloseEvent *event)
162 {
163 // Closes tabs in the widget
164 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
165 if (auto visualizationTabWidget
166 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
167 visualizationTabWidget->close();
168 }
169 }
170
171 QWidget::closeEvent(event);
172 }
@@ -34,6 +34,24 QString defaultGraphName(const QLayout &layout)
34 34 return QObject::tr("Graph %1").arg(count + 1);
35 35 }
36 36
37 /**
38 * Applies a function to all graphs of the zone represented by its layout
39 * @param layout the layout that contains graphs
40 * @param fun the function to apply to each graph
41 */
42 template <typename Fun>
43 void processGraphs(QLayout &layout, Fun fun)
44 {
45 for (auto i = 0; i < layout.count(); ++i) {
46 if (auto item = layout.itemAt(i)) {
47 if (auto visualizationGraphWidget
48 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
49 fun(*visualizationGraphWidget);
50 }
51 }
52 }
53 }
54
37 55 } // namespace
38 56
39 57 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
@@ -177,6 +195,8 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<V
177 195 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
178 196 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
179 197 &VisualizationZoneWidget::onVariableAdded);
198 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
199 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
180 200
181 201 auto range = SqpRange{};
182 202
@@ -223,17 +243,11 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
223 243 if (visitor) {
224 244 visitor->visitEnter(this);
225 245
226 // Apply visitor to graph children
227 auto layout = ui->visualizationZoneFrame->layout();
228 for (auto i = 0; i < layout->count(); ++i) {
229 if (auto item = layout->itemAt(i)) {
230 // Widgets different from graphs are not visited (no action)
231 if (auto visualizationGraphWidget
232 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
233 visualizationGraphWidget->accept(visitor);
234 }
235 }
236 }
246 // Apply visitor to graph children: widgets different from graphs are not visited (no
247 // action)
248 processGraphs(
249 *ui->visualizationZoneFrame->layout(),
250 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
237 251
238 252 visitor->visitLeave(this);
239 253 }
@@ -260,9 +274,29 QString VisualizationZoneWidget::name() const
260 274 return ui->zoneNameLabel->text();
261 275 }
262 276
277 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
278 {
279 // Closes graphs in the zone
280 processGraphs(*ui->visualizationZoneFrame->layout(),
281 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
282
283 // Delete synchronization group from variable controller
284 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
285 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
286
287 QWidget::closeEvent(event);
288 }
289
263 290 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
264 291 {
265 292 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
266 293 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
267 294 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
268 295 }
296
297 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
298 {
299 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
300 Q_ARG(std::shared_ptr<Variable>, variable),
301 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
302 }
@@ -13,8 +13,13
13 13 Q_LOGGING_CATEGORY(LOG_GenerateVariableMenuOperation, "GenerateVariableMenuOperation")
14 14
15 15 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
16 explicit GenerateVariableMenuOperationPrivate(QMenu *menu, std::shared_ptr<Variable> variable)
17 : m_Variable{variable}, m_PlotMenuBuilder{menu}, m_UnplotMenuBuilder{menu}
16 explicit GenerateVariableMenuOperationPrivate(
17 QMenu *menu, std::shared_ptr<Variable> variable,
18 std::set<IVisualizationWidget *> variableContainers)
19 : m_Variable{variable},
20 m_PlotMenuBuilder{menu},
21 m_UnplotMenuBuilder{menu},
22 m_VariableContainers{std::move(variableContainers)}
18 23 {
19 24 }
20 25
@@ -47,7 +52,7 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
47 52 void visitNodeLeavePlot(const IVisualizationWidget &container, const QString &actionName,
48 53 ActionFun actionFunction)
49 54 {
50 if (m_Variable && container.canDrop(*m_Variable)) {
55 if (isValidContainer(container)) {
51 56 m_PlotMenuBuilder.addSeparator();
52 57 m_PlotMenuBuilder.addAction(actionName, actionFunction);
53 58 }
@@ -66,28 +71,39 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
66 71 void visitLeafPlot(const IVisualizationWidget &container, const QString &actionName,
67 72 ActionFun actionFunction)
68 73 {
69 if (m_Variable && container.canDrop(*m_Variable)) {
74 if (isValidContainer(container)) {
70 75 m_PlotMenuBuilder.addAction(actionName, actionFunction);
71 76 }
72 77 }
73 78
74 79 template <typename ActionFun>
75 void visitLeafUnplot(const IVisualizationWidget &container, const QString &actionName,
80 void visitLeafUnplot(IVisualizationWidget *container, const QString &actionName,
76 81 ActionFun actionFunction)
77 82 {
78 if (m_Variable && container.contains(*m_Variable)) {
83 // If the container contains the variable, we generate 'unplot' action
84 if (m_VariableContainers.count(container) == 1) {
79 85 m_UnplotMenuBuilder.addAction(actionName, actionFunction);
80 86 }
81 87 }
82 88
89 bool isValidContainer(const IVisualizationWidget &container) const noexcept
90 {
91 // A container is valid if it can contain the variable and if the variable is not already
92 // contained in another container
93 return m_Variable && m_VariableContainers.size() == 0 && container.canDrop(*m_Variable);
94 }
95
83 96 std::shared_ptr<Variable> m_Variable;
97 std::set<IVisualizationWidget *> m_VariableContainers;
84 98 MenuBuilder m_PlotMenuBuilder; ///< Builder for the 'Plot' menu
85 99 MenuBuilder m_UnplotMenuBuilder; ///< Builder for the 'Unplot' menu
86 100 };
87 101
88 GenerateVariableMenuOperation::GenerateVariableMenuOperation(QMenu *menu,
89 std::shared_ptr<Variable> variable)
90 : impl{spimpl::make_unique_impl<GenerateVariableMenuOperationPrivate>(menu, variable)}
102 GenerateVariableMenuOperation::GenerateVariableMenuOperation(
103 QMenu *menu, std::shared_ptr<Variable> variable,
104 std::set<IVisualizationWidget *> variableContainers)
105 : impl{spimpl::make_unique_impl<GenerateVariableMenuOperationPrivate>(
106 menu, variable, std::move(variableContainers))}
91 107 {
92 108 }
93 109
@@ -155,7 +171,6 void GenerateVariableMenuOperation::visitEnter(VisualizationZoneWidget *zoneWidg
155 171
156 172 void GenerateVariableMenuOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
157 173 {
158 qCCritical(LOG_GenerateVariableMenuOperation(), "Open in a new graph DETECTED !!");
159 174 if (zoneWidget) {
160 175 // 'Plot' menu
161 176 impl->visitNodeLeavePlot(
@@ -187,7 +202,7 void GenerateVariableMenuOperation::visit(VisualizationGraphWidget *graphWidget)
187 202 });
188 203
189 204 // 'Unplot' menu
190 impl->visitLeafUnplot(*graphWidget, QObject::tr("Remove from %1").arg(graphWidget->name()),
205 impl->visitLeafUnplot(graphWidget, QObject::tr("Remove from %1").arg(graphWidget->name()),
191 206 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
192 207 if (auto var = varW.lock()) {
193 208 graphWidget->removeVariable(var);
General Comments 0
You need to be logged in to leave comments. Login now