##// END OF EJS Templates
Integrates the drag&drop classes into the existing visualization classes.
trabillard -
r839:5f082699d3e8
parent child
Show More
@@ -1,97 +1,107
1 1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
5 6
6 7 #include <QLoggingCategory>
7 8 #include <QWidget>
8 9
9 10 #include <memory>
10 11
11 12 #include <Common/spimpl.h>
12 13
13 14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14 15
15 16 class QCPRange;
16 17 class QCustomPlot;
17 18 class SqpRange;
18 19 class Variable;
20 class VisualizationZoneWidget;
19 21
20 22 namespace Ui {
21 23 class VisualizationGraphWidget;
22 24 } // namespace Ui
23 25
24 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
26 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
25 27 Q_OBJECT
26 28
27 29 friend class QCustomPlotSynchronizer;
28 30 friend class VisualizationGraphRenderingDelegate;
29 31
30 32 public:
31 33 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
32 34 virtual ~VisualizationGraphWidget();
33 35
36 VisualizationZoneWidget* parentZoneWidget() const noexcept;
37
34 38 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
35 39 void enableAcquisition(bool enable);
36 40
37 41 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
38 42
39 43 /// Removes a variable from the graph
40 44 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
41 45
46 /// Returns the list of all variables used in the graph
47 QList<std::shared_ptr<Variable>> variables() const;
48
42 49 void setYRange(const SqpRange &range);
43 50 SqpRange graphRange() const noexcept;
44 51 void setGraphRange(const SqpRange &range);
45 52
46 53 // IVisualizationWidget interface
47 54 void accept(IVisualizationWidgetVisitor *visitor) override;
48 55 bool canDrop(const Variable &variable) const override;
49 56 bool contains(const Variable &variable) const override;
50 57 QString name() const override;
51 58
59 // VisualisationDragWidget
60 QMimeData* mimeData() const override;
61 bool isDragAllowed() const override;
52 62
53 63 signals:
54 64 void synchronize(const SqpRange &range, const SqpRange &oldRange);
55 65 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
56 66 bool synchronise);
57 67
58 68 /// Signal emitted when the variable is about to be removed from the graph
59 69 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
60 70 /// Signal emitted when the variable has been added to the graph
61 71 void variableAdded(std::shared_ptr<Variable> var);
62 72
63 73 protected:
64 74 void closeEvent(QCloseEvent *event) override;
65 75 void enterEvent(QEvent *event) override;
66 76 void leaveEvent(QEvent *event) override;
67 77
68 78 QCustomPlot &plot() noexcept;
69 79
70 80 private:
71 81 Ui::VisualizationGraphWidget *ui;
72 82
73 83 class VisualizationGraphWidgetPrivate;
74 84 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
75 85
76 86 private slots:
77 87 /// Slot called when right clicking on the graph (displays a menu)
78 88 void onGraphMenuRequested(const QPoint &pos) noexcept;
79 89
80 90 /// Rescale the X axe to range parameter
81 91 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
82 92
83 93 /// Slot called when a mouse move was made
84 94 void onMouseMove(QMouseEvent *event) noexcept;
85 95 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
86 96 void onMouseWheel(QWheelEvent *event) noexcept;
87 97 /// Slot called when a mouse press was made, to activate the calibration of a graph
88 98 void onMousePress(QMouseEvent *event) noexcept;
89 99 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
90 100 void onMouseRelease(QMouseEvent *event) noexcept;
91 101
92 102 void onDataCacheVariableUpdated();
93 103
94 104 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
95 105 };
96 106
97 107 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,57 +1,72
1 1 #ifndef SCIQLOP_VISUALIZATIONTABWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONTABWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5
6 6 #include <Common/spimpl.h>
7 7
8 8 #include <QLoggingCategory>
9 9 #include <QWidget>
10 #include <QMimeData>
10 11
11 12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget)
12 13
13 14 class Variable;
14 15 class VisualizationZoneWidget;
15 16
16 17 namespace Ui {
17 18 class VisualizationTabWidget;
18 19 } // namespace Ui
19 20
20 21 class VisualizationTabWidget : public QWidget, public IVisualizationWidget {
21 22 Q_OBJECT
22 23
23 24 public:
24 25 explicit VisualizationTabWidget(const QString &name = {}, QWidget *parent = 0);
25 26 virtual ~VisualizationTabWidget();
26 27
27 28 /// Add a zone widget
28 29 void addZone(VisualizationZoneWidget *zoneWidget);
29 30
31 void insertZone(int index, VisualizationZoneWidget *zoneWidget);
32
30 33 /**
31 34 * Creates a zone using a variable. The variable will be displayed in a new graph of the new
32 * zone.
35 * zone. The zone is added at the end.
33 36 * @param variable the variable for which to create the zone
34 37 * @return the pointer to the created zone
35 38 */
36 39 VisualizationZoneWidget *createZone(std::shared_ptr<Variable> variable);
37 40
41 /**
42 * Creates a zone using a list of variables. The variables will be displayed in a new graph of the new
43 * zone. The zone is inserted at the specified index.
44 * @param variables the variables for which to create the zone
45 * @param index The index where the zone should be inserted in the layout
46 * @return the pointer to the created zone
47 */
48 VisualizationZoneWidget *createZone(const QList<std::shared_ptr<Variable>>& variables, int index);
49
38 50 // IVisualizationWidget interface
39 51 void accept(IVisualizationWidgetVisitor *visitor) override;
40 52 bool canDrop(const Variable &variable) const override;
41 53 bool contains(const Variable &variable) const override;
42 54 QString name() const override;
43 55
44 56 protected:
45 57 void closeEvent(QCloseEvent *event) override;
46 58
47 59 private:
48 60 /// @return the layout of tab in which zones are added
49 61 QLayout &tabLayout() const noexcept;
50 62
51 63 Ui::VisualizationTabWidget *ui;
52 64
53 65 class VisualizationTabWidgetPrivate;
54 66 spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl;
67
68 private slots:
69 void dropMimeData(int index, const QMimeData *mimeData);
55 70 };
56 71
57 72 #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H
@@ -1,60 +1,89
1 1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
5 6
6 7 #include <QLoggingCategory>
7 8 #include <QWidget>
8 9
9 10 #include <memory>
10 11
11 12 #include <Common/spimpl.h>
12 13
13 14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
14 15
15 16 namespace Ui {
16 17 class VisualizationZoneWidget;
17 18 } // Ui
18 19
19 20 class Variable;
20 21 class VisualizationGraphWidget;
21 22
22 class VisualizationZoneWidget : public QWidget, public IVisualizationWidget {
23 class VisualizationZoneWidget : public VisualizationDragWidget, public IVisualizationWidget {
23 24 Q_OBJECT
24 25
25 26 public:
26 27 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
27 28 virtual ~VisualizationZoneWidget();
28 29
29 /// Add a graph widget
30 /// Adds a graph widget
30 31 void addGraph(VisualizationGraphWidget *graphWidget);
31 32
33 /// Inserts a graph widget
34 void insertGraph(int index, VisualizationGraphWidget *graphWidget);
35
32 36 /**
33 37 * Creates a graph using a variable. The variable will be displayed in the new graph.
38 * The graph is added at the end.
34 39 * @param variable the variable for which to create the graph
35 40 * @return the pointer to the created graph
36 41 */
37 42 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
38 43
44 /**
45 * Creates a graph using a variable. The variable will be displayed in the new graph.
46 * The graph is inserted at the specified index.
47 * @param variable the variable for which to create the graph
48 * @param index The index where the graph should be inserted in the layout
49 * @return the pointer to the created graph
50 */
51 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable, int index);
52
53 /**
54 * Creates a graph using a list of variables. The variables will be displayed in the new graph.
55 * The graph is inserted at the specified index.
56 * @param variables List of variables to be added to the graph
57 * @param index The index where the graph should be inserted in the layout
58 * @return the pointer to the created graph
59 */
60 VisualizationGraphWidget *createGraph(const QList<std::shared_ptr<Variable>> variables, int index);
61
39 62 // IVisualizationWidget interface
40 63 void accept(IVisualizationWidgetVisitor *visitor) override;
41 64 bool canDrop(const Variable &variable) const override;
42 65 bool contains(const Variable &variable) const override;
43 66 QString name() const override;
44 67
68 // VisualisationDragWidget
69 QMimeData* mimeData() const override;
70 bool isDragAllowed() const override;
71
45 72 protected:
46 73 void closeEvent(QCloseEvent *event) override;
47 74
48 75 private:
49 76 Ui::VisualizationZoneWidget *ui;
50 77
51 78 class VisualizationZoneWidgetPrivate;
52 79 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
53 80
54 81 private slots:
55 82 void onVariableAdded(std::shared_ptr<Variable> variable);
56 83 /// Slot called when a variable is about to be removed from a graph contained in the zone
57 84 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
85
86 void dropMimeData(int index, const QMimeData* mimeData);
58 87 };
59 88
60 89 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -1,342 +1,385
1 1 #include "Visualization/VisualizationGraphWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "Visualization/VisualizationDefs.h"
4 4 #include "Visualization/VisualizationGraphHelper.h"
5 5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 7 #include "ui_VisualizationGraphWidget.h"
7 8
8 9 #include <Data/ArrayData.h>
9 10 #include <Data/IDataSeries.h>
10 11 #include <Settings/SqpSettingsDefs.h>
11 12 #include <SqpApplication.h>
13 #include <DragDropHelper.h>
12 14 #include <Variable/Variable.h>
13 15 #include <Variable/VariableController.h>
14 16
15 17 #include <unordered_map>
16 18
17 19 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
18 20
19 21 namespace {
20 22
21 23 /// Key pressed to enable zoom on horizontal axis
22 24 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
23 25
24 26 /// Key pressed to enable zoom on vertical axis
25 27 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
26 28
27 29 } // namespace
28 30
29 31 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
30 32
31 33 explicit VisualizationGraphWidgetPrivate(const QString &name)
32 34 : m_Name{name},
33 35 m_DoAcquisition{true},
34 36 m_IsCalibration{false},
35 37 m_RenderingDelegate{nullptr}
36 38 {
37 39 }
38 40
39 41 QString m_Name;
40 42 // 1 variable -> n qcpplot
41 43 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
42 44 bool m_DoAcquisition;
43 45 bool m_IsCalibration;
44 46 QCPItemTracer *m_TextTracer;
45 47 /// Delegate used to attach rendering features to the plot
46 48 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
47 49 };
48 50
49 51 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
50 : QWidget{parent},
52 : VisualizationDragWidget{parent},
51 53 ui{new Ui::VisualizationGraphWidget},
52 54 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
53 55 {
54 56 ui->setupUi(this);
55 57
56 58 // 'Close' options : widget is deleted when closed
57 59 setAttribute(Qt::WA_DeleteOnClose);
58 60
59 61 // Set qcpplot properties :
60 62 // - Drag (on x-axis) and zoom are enabled
61 63 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
62 64 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
63 65 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
64 66
65 67 // The delegate must be initialized after the ui as it uses the plot
66 68 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
67 69
68 70 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
69 71 connect(ui->widget, &QCustomPlot::mouseRelease, this,
70 72 &VisualizationGraphWidget::onMouseRelease);
71 73 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
72 74 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
73 75 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
74 76 &QCPAxis::rangeChanged),
75 77 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
76 78
77 79 // Activates menu when right clicking on the graph
78 80 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
79 81 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
80 82 &VisualizationGraphWidget::onGraphMenuRequested);
81 83
82 84 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
83 85 &VariableController::onRequestDataLoading);
84 86
85 87 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
86 88 &VisualizationGraphWidget::onUpdateVarDisplaying);
87 89 }
88 90
89 91
90 92 VisualizationGraphWidget::~VisualizationGraphWidget()
91 93 {
92 94 delete ui;
93 95 }
94 96
97 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
98 {
99 auto parent = parentWidget();
100 do
101 {
102 parent = parent->parentWidget();
103 } while (parent != nullptr && !qobject_cast<VisualizationZoneWidget*>(parent));
104
105 return qobject_cast<VisualizationZoneWidget*>(parent);
106 }
107
95 108 void VisualizationGraphWidget::enableAcquisition(bool enable)
96 109 {
97 110 impl->m_DoAcquisition = enable;
98 111 }
99 112
100 113 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
101 114 {
102 115 // Uses delegate to create the qcpplot components according to the variable
103 116 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
104 117 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
105 118
106 119 // Set axes properties according to the units of the data series
107 120 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
108 121 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
109 122 auto xAxisUnit = Unit{};
110 123 auto valuesUnit = Unit{};
111 124
112 125 if (auto dataSeries = variable->dataSeries()) {
113 126 dataSeries->lockRead();
114 127 xAxisUnit = dataSeries->xAxisUnit();
115 128 valuesUnit = dataSeries->valuesUnit();
116 129 dataSeries->unlock();
117 130 }
118 131 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
119 132
120 133 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
121 134
122 135 this->enableAcquisition(false);
123 136 this->setGraphRange(range);
124 137 this->enableAcquisition(true);
125 138
126 139 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
127 140
128 141 emit variableAdded(variable);
129 142 }
130 143
131 144 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
132 145 {
133 146 // Each component associated to the variable :
134 147 // - is removed from qcpplot (which deletes it)
135 148 // - is no longer referenced in the map
136 149 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
137 150 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
138 151 emit variableAboutToBeRemoved(variable);
139 152
140 153 auto &plottablesMap = variableIt->second;
141 154
142 155 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
143 156 plottableIt != plottableEnd;) {
144 157 ui->widget->removePlottable(plottableIt->second);
145 158 plottableIt = plottablesMap.erase(plottableIt);
146 159 }
147 160
148 161 impl->m_VariableToPlotMultiMap.erase(variableIt);
149 162 }
150 163
151 164 // Updates graph
152 165 ui->widget->replot();
153 166 }
154 167
168 QList<std::shared_ptr<Variable>> VisualizationGraphWidget::variables() const
169 {
170 auto variables = QList<std::shared_ptr<Variable>>{};
171 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap); it != std::cend(impl->m_VariableToPlotMultiMap); ++it)
172 {
173 variables << it->first;
174 }
175
176 return variables;
177 }
178
155 179 void VisualizationGraphWidget::setYRange(const SqpRange &range)
156 180 {
157 181 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
158 182 }
159 183
160 184 SqpRange VisualizationGraphWidget::graphRange() const noexcept
161 185 {
162 186 auto graphRange = ui->widget->xAxis->range();
163 187 return SqpRange{graphRange.lower, graphRange.upper};
164 188 }
165 189
166 190 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
167 191 {
168 192 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
169 193 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
170 194 ui->widget->replot();
171 195 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
172 196 }
173 197
174 198 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
175 199 {
176 200 if (visitor) {
177 201 visitor->visit(this);
178 202 }
179 203 else {
180 204 qCCritical(LOG_VisualizationGraphWidget())
181 205 << tr("Can't visit widget : the visitor is null");
182 206 }
183 207 }
184 208
185 209 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
186 210 {
187 211 /// @todo : for the moment, a graph can always accomodate a variable
188 212 Q_UNUSED(variable);
189 213 return true;
190 214 }
191 215
192 216 bool VisualizationGraphWidget::contains(const Variable &variable) const
193 217 {
194 218 // Finds the variable among the keys of the map
195 219 auto variablePtr = &variable;
196 220 auto findVariable
197 221 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
198 222
199 223 auto end = impl->m_VariableToPlotMultiMap.cend();
200 224 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
201 225 return it != end;
202 226 }
203 227
204 228 QString VisualizationGraphWidget::name() const
205 229 {
206 230 return impl->m_Name;
207 231 }
208 232
233 QMimeData *VisualizationGraphWidget::mimeData() const
234 {
235 auto *mimeData = new QMimeData;
236 mimeData->setData(DragDropHelper::MIME_TYPE_GRAPH, QByteArray());
237
238 return mimeData;
239 }
240
241 bool VisualizationGraphWidget::isDragAllowed() const
242 {
243 return true;
244 }
245
209 246 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
210 247 {
211 248 Q_UNUSED(event);
212 249
213 250 // Prevents that all variables will be removed from graph when it will be closed
214 251 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
215 252 emit variableAboutToBeRemoved(variableEntry.first);
216 253 }
217 254 }
218 255
219 256 void VisualizationGraphWidget::enterEvent(QEvent *event)
220 257 {
221 258 Q_UNUSED(event);
222 259 impl->m_RenderingDelegate->showGraphOverlay(true);
223 260 }
224 261
225 262 void VisualizationGraphWidget::leaveEvent(QEvent *event)
226 263 {
227 264 Q_UNUSED(event);
228 265 impl->m_RenderingDelegate->showGraphOverlay(false);
229 266 }
230 267
231 268 QCustomPlot &VisualizationGraphWidget::plot() noexcept
232 269 {
233 270 return *ui->widget;
234 271 }
235 272
236 273 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
237 274 {
238 275 QMenu graphMenu{};
239 276
240 277 // Iterates on variables (unique keys)
241 278 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
242 279 end = impl->m_VariableToPlotMultiMap.cend();
243 280 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
244 281 // 'Remove variable' action
245 282 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
246 283 [ this, var = it->first ]() { removeVariable(var); });
247 284 }
248 285
249 286 if (!graphMenu.isEmpty()) {
250 287 graphMenu.exec(QCursor::pos());
251 288 }
252 289 }
253 290
254 291 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
255 292 {
256 293 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
257 294 << QThread::currentThread()->objectName() << "DoAcqui"
258 295 << impl->m_DoAcquisition;
259 296
260 297 auto graphRange = SqpRange{t1.lower, t1.upper};
261 298 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
262 299
263 300 if (impl->m_DoAcquisition) {
264 301 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
265 302
266 303 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
267 304 end = impl->m_VariableToPlotMultiMap.end();
268 305 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
269 306 variableUnderGraphVector.push_back(it->first);
270 307 }
271 308 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
272 309 !impl->m_IsCalibration);
273 310
274 311 if (!impl->m_IsCalibration) {
275 312 qCDebug(LOG_VisualizationGraphWidget())
276 313 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
277 314 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
278 315 emit synchronize(graphRange, oldGraphRange);
279 316 }
280 317 }
281 318 }
282 319
283 320 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
284 321 {
285 322 // Handles plot rendering when mouse is moving
286 323 impl->m_RenderingDelegate->onMouseMove(event);
324
325 VisualizationDragWidget::mouseMoveEvent(event);
287 326 }
288 327
289 328 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
290 329 {
291 330 auto zoomOrientations = QFlags<Qt::Orientation>{};
292 331
293 332 // Lambda that enables a zoom orientation if the key modifier related to this orientation
294 333 // has
295 334 // been pressed
296 335 auto enableOrientation
297 336 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
298 337 auto orientationEnabled = event->modifiers().testFlag(modifier);
299 338 zoomOrientations.setFlag(orientation, orientationEnabled);
300 339 };
301 340 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
302 341 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
303 342
304 343 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
305 344 }
306 345
307 346 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
308 347 {
309 348 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
349
350 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
351
352 VisualizationDragWidget::mousePressEvent(event);
310 353 }
311 354
312 355 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
313 356 {
314 357 impl->m_IsCalibration = false;
315 358 }
316 359
317 360 void VisualizationGraphWidget::onDataCacheVariableUpdated()
318 361 {
319 362 auto graphRange = ui->widget->xAxis->range();
320 363 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
321 364
322 365 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
323 366 auto variable = variableEntry.first;
324 367 qCDebug(LOG_VisualizationGraphWidget())
325 368 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
326 369 qCDebug(LOG_VisualizationGraphWidget())
327 370 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
328 371 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
329 372 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
330 373 variable->range());
331 374 }
332 375 }
333 376 }
334 377
335 378 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
336 379 const SqpRange &range)
337 380 {
338 381 auto it = impl->m_VariableToPlotMultiMap.find(variable);
339 382 if (it != impl->m_VariableToPlotMultiMap.end()) {
340 383 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
341 384 }
342 385 }
@@ -1,129 +1,181
1 1 #include "Visualization/VisualizationTabWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "ui_VisualizationTabWidget.h"
4 4
5 5 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationGraphWidget.h"
7
8 #include "SqpApplication.h"
9 #include "DragDropHelper.h"
6 10
7 11 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
8 12
9 13 namespace {
10 14
11 15 /// Generates a default name for a new zone, according to the number of zones already displayed in
12 16 /// the tab
13 17 QString defaultZoneName(const QLayout &layout)
14 18 {
15 19 auto count = 0;
16 20 for (auto i = 0; i < layout.count(); ++i) {
17 21 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
18 22 count++;
19 23 }
20 24 }
21 25
22 26 return QObject::tr("Zone %1").arg(count + 1);
23 27 }
24 28
25 29 /**
26 30 * Applies a function to all zones of the tab represented by its layout
27 31 * @param layout the layout that contains zones
28 32 * @param fun the function to apply to each zone
29 33 */
30 34 template <typename Fun>
31 35 void processZones(QLayout &layout, Fun fun)
32 36 {
33 37 for (auto i = 0; i < layout.count(); ++i) {
34 38 if (auto item = layout.itemAt(i)) {
35 39 if (auto visualizationZoneWidget
36 40 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
37 41 fun(*visualizationZoneWidget);
38 42 }
39 43 }
40 44 }
41 45 }
42 46
43 47 } // namespace
44 48
45 49 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
46 50 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
47 51
48 52 QString m_Name;
49 53 };
50 54
51 55 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
52 56 : QWidget{parent},
53 57 ui{new Ui::VisualizationTabWidget},
54 58 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
55 59 {
56 60 ui->setupUi(this);
57 61
62 ui->dragDropContainer->setAcceptedMimeTypes({DragDropHelper::MIME_TYPE_GRAPH, DragDropHelper::MIME_TYPE_ZONE});
63 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this, &VisualizationTabWidget::dropMimeData);
64
58 65 // Widget is deleted when closed
59 66 setAttribute(Qt::WA_DeleteOnClose);
60 67 }
61 68
62 69 VisualizationTabWidget::~VisualizationTabWidget()
63 70 {
64 71 delete ui;
65 72 }
66 73
67 74 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
68 75 {
69 tabLayout().addWidget(zoneWidget);
76 ui->dragDropContainer->addDragWidget(zoneWidget);
77 }
78
79 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
80 {
81 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
70 82 }
71 83
72 84 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
73 85 {
74 auto zoneWidget = new VisualizationZoneWidget{defaultZoneName(tabLayout()), this};
75 this->addZone(zoneWidget);
86 return createZone({variable}, -1);
87 }
88
89 VisualizationZoneWidget *VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
90 {
91 auto zoneWidget = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
92 this->insertZone(index, zoneWidget);
76 93
77 94 // Creates a new graph into the zone
78 zoneWidget->createGraph(variable);
95 zoneWidget->createGraph(variables, index);
79 96
80 97 return zoneWidget;
81 98 }
82 99
83 100 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
84 101 {
85 102 if (visitor) {
86 103 visitor->visitEnter(this);
87 104
88 105 // Apply visitor to zone children: widgets different from zones are not visited (no action)
89 106 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
90 107 zoneWidget.accept(visitor);
91 108 });
92 109
93 110 visitor->visitLeave(this);
94 111 }
95 112 else {
96 113 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
97 114 }
98 115 }
99 116
100 117 bool VisualizationTabWidget::canDrop(const Variable &variable) const
101 118 {
102 119 // A tab can always accomodate a variable
103 120 Q_UNUSED(variable);
104 121 return true;
105 122 }
106 123
107 124 bool VisualizationTabWidget::contains(const Variable &variable) const
108 125 {
109 126 Q_UNUSED(variable);
110 127 return false;
111 128 }
112 129
113 130 QString VisualizationTabWidget::name() const
114 131 {
115 132 return impl->m_Name;
116 133 }
117 134
118 135 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
119 136 {
120 137 // Closes zones in the tab
121 138 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
122 139
123 140 QWidget::closeEvent(event);
124 141 }
125 142
126 143 QLayout &VisualizationTabWidget::tabLayout() const noexcept
127 144 {
128 return *ui->scrollAreaWidgetContents->layout();
145 return *ui->dragDropContainer->layout();
146 }
147
148 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
149 {
150 auto& helper = sqpApp->dragDropHelper();
151 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH))
152 {
153 auto graphWidget = static_cast<VisualizationGraphWidget*>(helper.getCurrentDragWidget());
154 auto parentDragDropContainer = qobject_cast<VisualizationDragDropContainer*>(graphWidget->parentWidget());
155 Q_ASSERT(parentDragDropContainer);
156
157 auto nbGraph = parentDragDropContainer->countDragWidget();
158 if (nbGraph == 1)
159 {
160 //This is the only graph in the previous zone, close the zone
161 graphWidget->parentZoneWidget()->close();
162 }
163 else
164 {
165 //Close the graph
166 graphWidget->close();
167 }
168
169 const auto& variables = graphWidget->variables();
170 createZone(variables, index);
171 }
172 else if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_ZONE))
173 {
174 //Simple move of the zone, no variable operation associated
175 auto zoneWidget = static_cast<VisualizationZoneWidget*>(helper.getCurrentDragWidget());
176 auto parentDragDropContainer = zoneWidget->parentWidget();
177 parentDragDropContainer->layout()->removeWidget(zoneWidget);
178
179 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
180 }
129 181 }
@@ -1,304 +1,394
1 1 #include "Visualization/VisualizationZoneWidget.h"
2 2
3 3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 4 #include "Visualization/QCustomPlotSynchronizer.h"
5 5 #include "Visualization/VisualizationGraphWidget.h"
6 6 #include "ui_VisualizationZoneWidget.h"
7 7
8 8 #include <Data/SqpRange.h>
9 9 #include <Variable/Variable.h>
10 10 #include <Variable/VariableController.h>
11 11
12 12 #include <QUuid>
13 13 #include <SqpApplication.h>
14 #include <DragDropHelper.h>
14 15 #include <cmath>
15 16
17 #include <QLayout>
18
16 19 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
17 20
18 21 namespace {
19 22
20 23 /// Minimum height for graph added in zones (in pixels)
21 24 const auto GRAPH_MINIMUM_HEIGHT = 300;
22 25
23 26 /// Generates a default name for a new graph, according to the number of graphs already displayed in
24 27 /// the zone
25 28 QString defaultGraphName(const QLayout &layout)
26 29 {
27 30 auto count = 0;
28 31 for (auto i = 0; i < layout.count(); ++i) {
29 32 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
30 33 count++;
31 34 }
32 35 }
33 36
34 37 return QObject::tr("Graph %1").arg(count + 1);
35 38 }
36 39
37 40 /**
38 41 * Applies a function to all graphs of the zone represented by its layout
39 42 * @param layout the layout that contains graphs
40 43 * @param fun the function to apply to each graph
41 44 */
42 45 template <typename Fun>
43 46 void processGraphs(QLayout &layout, Fun fun)
44 47 {
45 48 for (auto i = 0; i < layout.count(); ++i) {
46 49 if (auto item = layout.itemAt(i)) {
47 50 if (auto visualizationGraphWidget
48 51 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
49 52 fun(*visualizationGraphWidget);
50 53 }
51 54 }
52 55 }
53 56 }
54 57
55 58 } // namespace
56 59
57 60 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
58 61
59 62 explicit VisualizationZoneWidgetPrivate()
60 63 : m_SynchronisationGroupId{QUuid::createUuid()},
61 64 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
62 65 {
63 66 }
64 67 QUuid m_SynchronisationGroupId;
65 68 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
66 69 };
67 70
68 71 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
69 : QWidget{parent},
72 : VisualizationDragWidget{parent},
70 73 ui{new Ui::VisualizationZoneWidget},
71 74 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
72 75 {
73 76 ui->setupUi(this);
74 77
75 78 ui->zoneNameLabel->setText(name);
76 79
80 ui->dragDropContainer->setAcceptedMimeTypes({DragDropHelper::MIME_TYPE_GRAPH});
81 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this, &VisualizationZoneWidget::dropMimeData);
82
77 83 // 'Close' options : widget is deleted when closed
78 84 setAttribute(Qt::WA_DeleteOnClose);
79 85 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
80 86 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
81 87
82 88 // Synchronisation id
83 89 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
84 90 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
85 91 }
86 92
87 93 VisualizationZoneWidget::~VisualizationZoneWidget()
88 94 {
89 95 delete ui;
90 96 }
91 97
92 98 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
93 99 {
94 100 // Synchronize new graph with others in the zone
95 101 impl->m_Synchronizer->addGraph(*graphWidget);
96 102
97 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
103 ui->dragDropContainer->addDragWidget(graphWidget);
104 }
105
106 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
107 {
108 // Synchronize new graph with others in the zone
109 impl->m_Synchronizer->addGraph(*graphWidget);
110
111 ui->dragDropContainer->insertDragWidget(index, graphWidget);
98 112 }
99 113
100 114 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
101 115 {
116 return createGraph(variable, -1);
117 }
118
119 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable, int index)
120 {
102 121 auto graphWidget = new VisualizationGraphWidget{
103 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
122 defaultGraphName(*ui->dragDropContainer->layout()), this};
104 123
105 124
106 125 // Set graph properties
107 126 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
108 127 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
109 128
110 129
111 130 // Lambda to synchronize zone widget
112 131 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
113 132 const SqpRange &oldGraphRange) {
114 133
115 134 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
116 auto frameLayout = ui->visualizationZoneFrame->layout();
135 auto frameLayout = ui->dragDropContainer->layout();
117 136 for (auto i = 0; i < frameLayout->count(); ++i) {
118 137 auto graphChild
119 138 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
120 139 if (graphChild && (graphChild != graphWidget)) {
121 140
122 141 auto graphChildRange = graphChild->graphRange();
123 142 switch (zoomType) {
124 143 case AcquisitionZoomType::ZoomIn: {
125 144 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
126 145 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
127 146 graphChildRange.m_TStart += deltaLeft;
128 147 graphChildRange.m_TEnd -= deltaRight;
129 148 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
130 149 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
131 150 << deltaLeft;
132 151 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
133 152 << deltaRight;
134 153 qCDebug(LOG_VisualizationZoneWidget())
135 154 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
136 155
137 156 break;
138 157 }
139 158
140 159 case AcquisitionZoomType::ZoomOut: {
141 160 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
142 161 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
143 162 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
144 163 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
145 164 << deltaLeft;
146 165 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
147 166 << deltaRight;
148 167 qCDebug(LOG_VisualizationZoneWidget())
149 168 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
150 169 graphChildRange.m_TStart -= deltaLeft;
151 170 graphChildRange.m_TEnd += deltaRight;
152 171 break;
153 172 }
154 173 case AcquisitionZoomType::PanRight: {
155 174 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
156 175 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
157 176 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
158 177 graphChildRange.m_TStart += deltaLeft;
159 178 graphChildRange.m_TEnd += deltaRight;
160 179 qCDebug(LOG_VisualizationZoneWidget())
161 180 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
162 181 break;
163 182 }
164 183 case AcquisitionZoomType::PanLeft: {
165 184 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
166 185 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
167 186 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
168 187 graphChildRange.m_TStart -= deltaLeft;
169 188 graphChildRange.m_TEnd -= deltaRight;
170 189 break;
171 190 }
172 191 case AcquisitionZoomType::Unknown: {
173 192 qCDebug(LOG_VisualizationZoneWidget())
174 193 << tr("Impossible to synchronize: zoom type unknown");
175 194 break;
176 195 }
177 196 default:
178 197 qCCritical(LOG_VisualizationZoneWidget())
179 198 << tr("Impossible to synchronize: zoom type not take into account");
180 199 // No action
181 200 break;
182 201 }
183 202 graphChild->enableAcquisition(false);
184 203 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
185 204 << graphChild->graphRange();
186 205 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
187 206 << graphChildRange;
188 207 qCDebug(LOG_VisualizationZoneWidget())
189 208 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
190 209 graphChild->setGraphRange(graphChildRange);
191 210 graphChild->enableAcquisition(true);
192 211 }
193 212 }
194 213 };
195 214
196 215 // connection for synchronization
197 216 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
198 217 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
199 218 &VisualizationZoneWidget::onVariableAdded);
200 219 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
201 220 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
202 221
203 222 auto range = SqpRange{};
204 223
205 224 // Apply visitor to graph children
206 auto layout = ui->visualizationZoneFrame->layout();
225 auto layout = ui->dragDropContainer->layout();
207 226 if (layout->count() > 0) {
208 227 // Case of a new graph in a existant zone
209 228 if (auto visualizationGraphWidget
210 229 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
211 230 range = visualizationGraphWidget->graphRange();
212 231 }
213 232 }
214 233 else {
215 234 // Case of a new graph as the first of the zone
216 235 range = variable->range();
217 236 }
218 237
219 this->addGraph(graphWidget);
238 this->insertGraph(index, graphWidget);
220 239
221 240 graphWidget->addVariable(variable, range);
222 241
223 242 // get y using variable range
224 243 if (auto dataSeries = variable->dataSeries()) {
225 244 dataSeries->lockRead();
226 245 auto valuesBounds
227 246 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
228 247 auto end = dataSeries->cend();
229 248 if (valuesBounds.first != end && valuesBounds.second != end) {
230 249 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
231 250
232 251 auto minValue = rangeValue(valuesBounds.first->minValue());
233 252 auto maxValue = rangeValue(valuesBounds.second->maxValue());
234 253
235 254 graphWidget->setYRange(SqpRange{minValue, maxValue});
236 255 }
237 256 dataSeries->unlock();
238 257 }
239 258
240 259 return graphWidget;
241 260 }
242 261
262 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
263 {
264 if (variables.isEmpty())
265 return nullptr;
266
267 auto graphWidget = createGraph(variables.first(), index);
268 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt)
269 {
270 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
271 }
272
273 return graphWidget;
274 }
275
243 276 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
244 277 {
245 278 if (visitor) {
246 279 visitor->visitEnter(this);
247 280
248 281 // Apply visitor to graph children: widgets different from graphs are not visited (no
249 282 // action)
250 283 processGraphs(
251 *ui->visualizationZoneFrame->layout(),
284 *ui->dragDropContainer->layout(),
252 285 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
253 286
254 287 visitor->visitLeave(this);
255 288 }
256 289 else {
257 290 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
258 291 }
259 292 }
260 293
261 294 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
262 295 {
263 296 // A tab can always accomodate a variable
264 297 Q_UNUSED(variable);
265 298 return true;
266 299 }
267 300
268 301 bool VisualizationZoneWidget::contains(const Variable &variable) const
269 302 {
270 303 Q_UNUSED(variable);
271 304 return false;
272 305 }
273 306
274 307 QString VisualizationZoneWidget::name() const
275 308 {
276 309 return ui->zoneNameLabel->text();
277 310 }
278 311
312 QMimeData *VisualizationZoneWidget::mimeData() const
313 {
314 auto *mimeData = new QMimeData;
315 mimeData->setData(DragDropHelper::MIME_TYPE_ZONE, QByteArray());
316
317 return mimeData;
318 }
319
320 bool VisualizationZoneWidget::isDragAllowed() const
321 {
322 return true;
323 }
324
279 325 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
280 326 {
281 327 // Closes graphs in the zone
282 processGraphs(*ui->visualizationZoneFrame->layout(),
328 processGraphs(*ui->dragDropContainer->layout(),
283 329 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
284 330
285 331 // Delete synchronization group from variable controller
286 332 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
287 333 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
288 334
289 335 QWidget::closeEvent(event);
290 336 }
291 337
292 338 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
293 339 {
294 340 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
295 341 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
296 342 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
297 343 }
298 344
299 345 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
300 346 {
301 347 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
302 348 Q_ARG(std::shared_ptr<Variable>, variable),
303 349 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
304 350 }
351
352 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
353 {
354 auto& helper = sqpApp->dragDropHelper();
355 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH))
356 {
357 auto graphWidget = static_cast<VisualizationGraphWidget*>(helper.getCurrentDragWidget());
358 auto parentDragDropContainer = qobject_cast<VisualizationDragDropContainer*>(graphWidget->parentWidget());
359 Q_ASSERT(parentDragDropContainer);
360
361 const auto& variables = graphWidget->variables();
362
363 if (!variables.empty())
364 {
365 if (parentDragDropContainer != ui->dragDropContainer)
366 {
367 //The drop didn't occur in the same zone
368
369 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
370 auto nbGraph = parentDragDropContainer->countDragWidget();
371 if (nbGraph == 1)
372 {
373 //This is the only graph in the previous zone, close the zone
374 previousParentZoneWidget->close();
375 }
376 else
377 {
378 //Close the graph
379 graphWidget->close();
380 }
381
382 //Creates the new graph in the zone
383 createGraph(variables, index);
384 }
385 else
386 {
387 //The drop occurred in the same zone
388 //Simple move of the graph, no variable operation associated
389 parentDragDropContainer->layout()->removeWidget(graphWidget);
390 ui->dragDropContainer->insertDragWidget(index, graphWidget);
391 }
392 }
393 }
394 }
@@ -1,73 +1,84
1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2 <ui version="4.0">
3 3 <class>VisualizationTabWidget</class>
4 4 <widget class="QWidget" name="VisualizationTabWidget">
5 5 <property name="geometry">
6 6 <rect>
7 7 <x>0</x>
8 8 <y>0</y>
9 9 <width>400</width>
10 10 <height>300</height>
11 11 </rect>
12 12 </property>
13 13 <property name="windowTitle">
14 14 <string>Form</string>
15 15 </property>
16 16 <layout class="QVBoxLayout" name="verticalLayout">
17 17 <property name="leftMargin">
18 18 <number>0</number>
19 19 </property>
20 20 <property name="topMargin">
21 21 <number>0</number>
22 22 </property>
23 23 <property name="rightMargin">
24 24 <number>0</number>
25 25 </property>
26 26 <property name="bottomMargin">
27 27 <number>0</number>
28 28 </property>
29 29 <item>
30 30 <widget class="QScrollArea" name="scrollArea">
31 31 <property name="frameShape">
32 32 <enum>QFrame::NoFrame</enum>
33 33 </property>
34 34 <property name="frameShadow">
35 35 <enum>QFrame::Sunken</enum>
36 36 </property>
37 37 <property name="widgetResizable">
38 38 <bool>true</bool>
39 39 </property>
40 40 <widget class="QWidget" name="scrollAreaWidgetContents">
41 41 <property name="geometry">
42 42 <rect>
43 43 <x>0</x>
44 44 <y>0</y>
45 45 <width>400</width>
46 46 <height>300</height>
47 47 </rect>
48 48 </property>
49 49 <layout class="QVBoxLayout" name="verticalLayout_3">
50 50 <property name="spacing">
51 51 <number>3</number>
52 52 </property>
53 53 <property name="leftMargin">
54 54 <number>0</number>
55 55 </property>
56 56 <property name="topMargin">
57 57 <number>0</number>
58 58 </property>
59 59 <property name="rightMargin">
60 60 <number>0</number>
61 61 </property>
62 62 <property name="bottomMargin">
63 63 <number>0</number>
64 64 </property>
65 <item>
66 <widget class="VisualizationDragDropContainer" name="dragDropContainer" native="true"/>
67 </item>
65 68 </layout>
66 69 </widget>
67 70 </widget>
68 71 </item>
69 72 </layout>
70 73 </widget>
74 <customwidgets>
75 <customwidget>
76 <class>VisualizationDragDropContainer</class>
77 <extends>QWidget</extends>
78 <header>Visualization/VisualizationDragDropContainer.h</header>
79 <container>1</container>
80 </customwidget>
81 </customwidgets>
71 82 <resources/>
72 83 <connections/>
73 84 </ui>
@@ -1,117 +1,128
1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2 <ui version="4.0">
3 3 <class>VisualizationZoneWidget</class>
4 4 <widget class="QWidget" name="VisualizationZoneWidget">
5 5 <property name="geometry">
6 6 <rect>
7 7 <x>0</x>
8 8 <y>0</y>
9 9 <width>400</width>
10 10 <height>300</height>
11 11 </rect>
12 12 </property>
13 13 <property name="windowTitle">
14 14 <string>Form</string>
15 15 </property>
16 16 <layout class="QVBoxLayout" name="verticalLayout_2">
17 17 <property name="spacing">
18 18 <number>0</number>
19 19 </property>
20 20 <property name="leftMargin">
21 21 <number>0</number>
22 22 </property>
23 23 <property name="topMargin">
24 24 <number>0</number>
25 25 </property>
26 26 <property name="rightMargin">
27 27 <number>0</number>
28 28 </property>
29 29 <property name="bottomMargin">
30 30 <number>0</number>
31 31 </property>
32 32 <item>
33 33 <widget class="QWidget" name="infobar" native="true">
34 34 <property name="sizePolicy">
35 35 <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
36 36 <horstretch>0</horstretch>
37 37 <verstretch>0</verstretch>
38 38 </sizepolicy>
39 39 </property>
40 40 <layout class="QHBoxLayout" name="horizontalLayout">
41 41 <property name="spacing">
42 42 <number>0</number>
43 43 </property>
44 44 <property name="leftMargin">
45 45 <number>0</number>
46 46 </property>
47 47 <property name="topMargin">
48 48 <number>0</number>
49 49 </property>
50 50 <property name="rightMargin">
51 51 <number>0</number>
52 52 </property>
53 53 <property name="bottomMargin">
54 54 <number>0</number>
55 55 </property>
56 56 <item>
57 57 <widget class="QLabel" name="zoneNameLabel">
58 58 <property name="styleSheet">
59 59 <string notr="true">color: rgb(127, 127, 127);
60 60 </string>
61 61 </property>
62 62 <property name="text">
63 63 <string>TextLabel</string>
64 64 </property>
65 65 </widget>
66 66 </item>
67 67 <item>
68 68 <widget class="QToolButton" name="closeButton">
69 69 <property name="styleSheet">
70 70 <string notr="true">background-color: transparent;</string>
71 71 </property>
72 72 <property name="text">
73 73 <string>Close</string>
74 74 </property>
75 75 </widget>
76 76 </item>
77 77 </layout>
78 78 </widget>
79 79 </item>
80 80 <item>
81 81 <widget class="QFrame" name="visualizationZoneFrame">
82 82 <property name="sizePolicy">
83 83 <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
84 84 <horstretch>0</horstretch>
85 85 <verstretch>0</verstretch>
86 86 </sizepolicy>
87 87 </property>
88 88 <property name="frameShape">
89 89 <enum>QFrame::Box</enum>
90 90 </property>
91 91 <property name="frameShadow">
92 92 <enum>QFrame::Raised</enum>
93 93 </property>
94 94 <property name="lineWidth">
95 95 <number>1</number>
96 96 </property>
97 97 <layout class="QVBoxLayout" name="verticalLayout">
98 98 <property name="leftMargin">
99 99 <number>0</number>
100 100 </property>
101 101 <property name="topMargin">
102 102 <number>0</number>
103 103 </property>
104 104 <property name="rightMargin">
105 105 <number>0</number>
106 106 </property>
107 107 <property name="bottomMargin">
108 108 <number>0</number>
109 109 </property>
110 <item>
111 <widget class="VisualizationDragDropContainer" name="dragDropContainer" native="true"/>
112 </item>
110 113 </layout>
111 114 </widget>
112 115 </item>
113 116 </layout>
114 117 </widget>
118 <customwidgets>
119 <customwidget>
120 <class>VisualizationDragDropContainer</class>
121 <extends>QWidget</extends>
122 <header>Visualization/VisualizationDragDropContainer.h</header>
123 <container>1</container>
124 </customwidget>
125 </customwidgets>
115 126 <resources/>
116 127 <connections/>
117 128 </ui>
General Comments 0
You need to be logged in to leave comments. Login now