##// END OF EJS Templates
Refactors VisualizationGraphWidget::setYRange()...
Alexandre Leroux -
r903:8f094eaa3c04
parent child
Show More
@@ -1,39 +1,41
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHHELPER_H
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHHELPER_H
2 #define SCIQLOP_VISUALIZATIONGRAPHHELPER_H
2 #define SCIQLOP_VISUALIZATIONGRAPHHELPER_H
3
3
4 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationDefs.h"
5
5
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QVector>
9 #include <QVector>
10
10
11 #include <memory>
11 #include <memory>
12
12
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphHelper)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphHelper)
14
14
15 class IDataSeries;
15 class IDataSeries;
16 class QCPAbstractPlottable;
16 class QCPAbstractPlottable;
17 class QCustomPlot;
17 class QCustomPlot;
18 class Variable;
18 class Variable;
19
19
20 /**
20 /**
21 * @brief The VisualizationGraphHelper class aims to create the QCustomPlot components relative to a
21 * @brief The VisualizationGraphHelper class aims to create the QCustomPlot components relative to a
22 * variable, depending on the data series of this variable
22 * variable, depending on the data series of this variable
23 */
23 */
24 struct VisualizationGraphHelper {
24 struct VisualizationGraphHelper {
25 /**
25 /**
26 * Creates (if possible) the QCustomPlot components relative to the variable passed in
26 * Creates (if possible) the QCustomPlot components relative to the variable passed in
27 * parameter, and adds these to the plot passed in parameter.
27 * parameter, and adds these to the plot passed in parameter.
28 * @param variable the variable for which to create the components
28 * @param variable the variable for which to create the components
29 * @param plot the plot in which to add the created components. It takes ownership of these
29 * @param plot the plot in which to add the created components. It takes ownership of these
30 * components.
30 * components.
31 * @return the list of the components created
31 * @return the list of the components created
32 */
32 */
33 static PlottablesMap create(std::shared_ptr<Variable> variable, QCustomPlot &plot) noexcept;
33 static PlottablesMap create(std::shared_ptr<Variable> variable, QCustomPlot &plot) noexcept;
34
34
35 static void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
35 static void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
36 const SqpRange &dateTime);
36 const SqpRange &dateTime);
37
38 static void setYAxisRange(std::shared_ptr<Variable> variable, QCustomPlot &plot) noexcept;
37 };
39 };
38
40
39 #endif // SCIQLOP_VISUALIZATIONGRAPHHELPER_H
41 #endif // SCIQLOP_VISUALIZATIONGRAPHHELPER_H
@@ -1,108 +1,109
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
6
6
7 #include <QLoggingCategory>
7 #include <QLoggingCategory>
8 #include <QWidget>
8 #include <QWidget>
9
9
10 #include <memory>
10 #include <memory>
11
11
12 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
15
15
16 class QCPRange;
16 class QCPRange;
17 class QCustomPlot;
17 class QCustomPlot;
18 class SqpRange;
18 class SqpRange;
19 class Variable;
19 class Variable;
20 class VisualizationZoneWidget;
20 class VisualizationZoneWidget;
21
21
22 namespace Ui {
22 namespace Ui {
23 class VisualizationGraphWidget;
23 class VisualizationGraphWidget;
24 } // namespace Ui
24 } // namespace Ui
25
25
26 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
26 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
27 Q_OBJECT
27 Q_OBJECT
28
28
29 friend class QCustomPlotSynchronizer;
29 friend class QCustomPlotSynchronizer;
30 friend class VisualizationGraphRenderingDelegate;
30 friend class VisualizationGraphRenderingDelegate;
31
31
32 public:
32 public:
33 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
33 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
34 virtual ~VisualizationGraphWidget();
34 virtual ~VisualizationGraphWidget();
35
35
36 VisualizationZoneWidget *parentZoneWidget() const noexcept;
36 VisualizationZoneWidget *parentZoneWidget() const noexcept;
37
37
38 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
38 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
39 void enableAcquisition(bool enable);
39 void enableAcquisition(bool enable);
40
40
41 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
41 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
42
42
43 /// Removes a variable from the graph
43 /// Removes a variable from the graph
44 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
44 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
45
45
46 /// Returns the list of all variables used in the graph
46 /// Returns the list of all variables used in the graph
47 QList<std::shared_ptr<Variable> > variables() const;
47 QList<std::shared_ptr<Variable> > variables() const;
48
48
49 void setYRange(const SqpRange &range);
49 /// Sets the y-axis range based on the data of a variable
50 void setYRange(std::shared_ptr<Variable> variable);
50 SqpRange graphRange() const noexcept;
51 SqpRange graphRange() const noexcept;
51 void setGraphRange(const SqpRange &range);
52 void setGraphRange(const SqpRange &range);
52
53
53 // IVisualizationWidget interface
54 // IVisualizationWidget interface
54 void accept(IVisualizationWidgetVisitor *visitor) override;
55 void accept(IVisualizationWidgetVisitor *visitor) override;
55 bool canDrop(const Variable &variable) const override;
56 bool canDrop(const Variable &variable) const override;
56 bool contains(const Variable &variable) const override;
57 bool contains(const Variable &variable) const override;
57 QString name() const override;
58 QString name() const override;
58
59
59 // VisualisationDragWidget
60 // VisualisationDragWidget
60 QMimeData *mimeData() const override;
61 QMimeData *mimeData() const override;
61 bool isDragAllowed() const override;
62 bool isDragAllowed() const override;
62 void highlightForMerge(bool highlighted) override;
63 void highlightForMerge(bool highlighted) override;
63
64
64 signals:
65 signals:
65 void synchronize(const SqpRange &range, const SqpRange &oldRange);
66 void synchronize(const SqpRange &range, const SqpRange &oldRange);
66 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
67 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
67 bool synchronise);
68 bool synchronise);
68
69
69 /// Signal emitted when the variable is about to be removed from the graph
70 /// Signal emitted when the variable is about to be removed from the graph
70 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
71 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
71 /// Signal emitted when the variable has been added to the graph
72 /// Signal emitted when the variable has been added to the graph
72 void variableAdded(std::shared_ptr<Variable> var);
73 void variableAdded(std::shared_ptr<Variable> var);
73
74
74 protected:
75 protected:
75 void closeEvent(QCloseEvent *event) override;
76 void closeEvent(QCloseEvent *event) override;
76 void enterEvent(QEvent *event) override;
77 void enterEvent(QEvent *event) override;
77 void leaveEvent(QEvent *event) override;
78 void leaveEvent(QEvent *event) override;
78
79
79 QCustomPlot &plot() noexcept;
80 QCustomPlot &plot() noexcept;
80
81
81 private:
82 private:
82 Ui::VisualizationGraphWidget *ui;
83 Ui::VisualizationGraphWidget *ui;
83
84
84 class VisualizationGraphWidgetPrivate;
85 class VisualizationGraphWidgetPrivate;
85 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
86 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
86
87
87 private slots:
88 private slots:
88 /// Slot called when right clicking on the graph (displays a menu)
89 /// Slot called when right clicking on the graph (displays a menu)
89 void onGraphMenuRequested(const QPoint &pos) noexcept;
90 void onGraphMenuRequested(const QPoint &pos) noexcept;
90
91
91 /// Rescale the X axe to range parameter
92 /// Rescale the X axe to range parameter
92 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
93 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
93
94
94 /// Slot called when a mouse move was made
95 /// Slot called when a mouse move was made
95 void onMouseMove(QMouseEvent *event) noexcept;
96 void onMouseMove(QMouseEvent *event) noexcept;
96 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
97 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
97 void onMouseWheel(QWheelEvent *event) noexcept;
98 void onMouseWheel(QWheelEvent *event) noexcept;
98 /// Slot called when a mouse press was made, to activate the calibration of a graph
99 /// Slot called when a mouse press was made, to activate the calibration of a graph
99 void onMousePress(QMouseEvent *event) noexcept;
100 void onMousePress(QMouseEvent *event) noexcept;
100 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
101 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
101 void onMouseRelease(QMouseEvent *event) noexcept;
102 void onMouseRelease(QMouseEvent *event) noexcept;
102
103
103 void onDataCacheVariableUpdated();
104 void onDataCacheVariableUpdated();
104
105
105 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
106 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
106 };
107 };
107
108
108 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
109 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,204 +1,247
1 #include "Visualization/VisualizationGraphHelper.h"
1 #include "Visualization/VisualizationGraphHelper.h"
2 #include "Visualization/qcustomplot.h"
2 #include "Visualization/qcustomplot.h"
3
3
4 #include <Common/ColorUtils.h>
4 #include <Common/ColorUtils.h>
5
5
6 #include <Data/ScalarSeries.h>
6 #include <Data/ScalarSeries.h>
7 #include <Data/VectorSeries.h>
7 #include <Data/VectorSeries.h>
8
8
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10
10
11 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
11 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
12
12
13 namespace {
13 namespace {
14
14
15 class SqpDataContainer : public QCPGraphDataContainer {
15 class SqpDataContainer : public QCPGraphDataContainer {
16 public:
16 public:
17 void appendGraphData(const QCPGraphData &data) { mData.append(data); }
17 void appendGraphData(const QCPGraphData &data) { mData.append(data); }
18 };
18 };
19
19
20 /**
20 /**
21 * Struct used to create plottables, depending on the type of the data series from which to create
21 * Struct used to create plottables, depending on the type of the data series from which to create
22 * them
22 * them
23 * @tparam T the data series' type
23 * @tparam T the data series' type
24 * @remarks Default implementation can't create plottables
24 * @remarks Default implementation can't create plottables
25 */
25 */
26 template <typename T, typename Enabled = void>
26 template <typename T, typename Enabled = void>
27 struct PlottablesCreator {
27 struct PlottablesCreator {
28 static PlottablesMap createPlottables(T &, QCustomPlot &)
28 static PlottablesMap createPlottables(T &, QCustomPlot &)
29 {
29 {
30 qCCritical(LOG_DataSeries())
30 qCCritical(LOG_DataSeries())
31 << QObject::tr("Can't create plottables: unmanaged data series type");
31 << QObject::tr("Can't create plottables: unmanaged data series type");
32 return {};
32 return {};
33 }
33 }
34 };
34 };
35
35
36 /**
36 /**
37 * Specialization of PlottablesCreator for scalars and vectors
37 * Specialization of PlottablesCreator for scalars and vectors
38 * @sa ScalarSeries
38 * @sa ScalarSeries
39 * @sa VectorSeries
39 * @sa VectorSeries
40 */
40 */
41 template <typename T>
41 template <typename T>
42 struct PlottablesCreator<T,
42 struct PlottablesCreator<T,
43 typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
43 typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
44 or std::is_base_of<VectorSeries, T>::value> > {
44 or std::is_base_of<VectorSeries, T>::value> > {
45 static PlottablesMap createPlottables(T &dataSeries, QCustomPlot &plot)
45 static PlottablesMap createPlottables(T &dataSeries, QCustomPlot &plot)
46 {
46 {
47 PlottablesMap result{};
47 PlottablesMap result{};
48
48
49 // Gets the number of components of the data series
49 // Gets the number of components of the data series
50 dataSeries.lockRead();
50 dataSeries.lockRead();
51 auto componentCount = dataSeries.valuesData()->componentCount();
51 auto componentCount = dataSeries.valuesData()->componentCount();
52 dataSeries.unlock();
52 dataSeries.unlock();
53
53
54 auto colors = ColorUtils::colors(Qt::blue, Qt::red, componentCount);
54 auto colors = ColorUtils::colors(Qt::blue, Qt::red, componentCount);
55
55
56 // For each component of the data series, creates a QCPGraph to add to the plot
56 // For each component of the data series, creates a QCPGraph to add to the plot
57 for (auto i = 0; i < componentCount; ++i) {
57 for (auto i = 0; i < componentCount; ++i) {
58 auto graph = plot.addGraph();
58 auto graph = plot.addGraph();
59 graph->setPen(QPen{colors.at(i)});
59 graph->setPen(QPen{colors.at(i)});
60
60
61 result.insert({i, graph});
61 result.insert({i, graph});
62 }
62 }
63
63
64 plot.replot();
64 plot.replot();
65
65
66 return result;
66 return result;
67 }
67 }
68 };
68 };
69
69
70 /**
70 /**
71 * Struct used to update plottables, depending on the type of the data series from which to update
71 * Struct used to update plottables, depending on the type of the data series from which to update
72 * them
72 * them
73 * @tparam T the data series' type
73 * @tparam T the data series' type
74 * @remarks Default implementation can't update plottables
74 * @remarks Default implementation can't update plottables
75 */
75 */
76 template <typename T, typename Enabled = void>
76 template <typename T, typename Enabled = void>
77 struct PlottablesUpdater {
77 struct PlottablesUpdater {
78 static void setPlotYAxisRange(T &, const SqpRange &, QCustomPlot &)
79 {
80 qCCritical(LOG_DataSeries())
81 << QObject::tr("Can't set plot y-axis range: unmanaged data series type");
82 }
83
78 static void updatePlottables(T &, PlottablesMap &, const SqpRange &, bool)
84 static void updatePlottables(T &, PlottablesMap &, const SqpRange &, bool)
79 {
85 {
80 qCCritical(LOG_DataSeries())
86 qCCritical(LOG_DataSeries())
81 << QObject::tr("Can't update plottables: unmanaged data series type");
87 << QObject::tr("Can't update plottables: unmanaged data series type");
82 }
88 }
83 };
89 };
84
90
85 /**
91 /**
86 * Specialization of PlottablesUpdater for scalars and vectors
92 * Specialization of PlottablesUpdater for scalars and vectors
87 * @sa ScalarSeries
93 * @sa ScalarSeries
88 * @sa VectorSeries
94 * @sa VectorSeries
89 */
95 */
90 template <typename T>
96 template <typename T>
91 struct PlottablesUpdater<T,
97 struct PlottablesUpdater<T,
92 typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
98 typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
93 or std::is_base_of<VectorSeries, T>::value> > {
99 or std::is_base_of<VectorSeries, T>::value> > {
100 static void setPlotYAxisRange(T &dataSeries, const SqpRange &xAxisRange, QCustomPlot &plot)
101 {
102 auto minValue = 0., maxValue = 0.;
103
104 dataSeries.lockRead();
105 auto valuesBounds = dataSeries.valuesBounds(xAxisRange.m_TStart, xAxisRange.m_TEnd);
106 auto end = dataSeries.cend();
107 if (valuesBounds.first != end && valuesBounds.second != end) {
108 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
109
110 minValue = rangeValue(valuesBounds.first->minValue());
111 maxValue = rangeValue(valuesBounds.second->maxValue());
112 }
113 dataSeries.unlock();
114
115 plot.yAxis->setRange(QCPRange{minValue, maxValue});
116 }
117
94 static void updatePlottables(T &dataSeries, PlottablesMap &plottables, const SqpRange &range,
118 static void updatePlottables(T &dataSeries, PlottablesMap &plottables, const SqpRange &range,
95 bool rescaleAxes)
119 bool rescaleAxes)
96 {
120 {
97
121
98 // For each plottable to update, resets its data
122 // For each plottable to update, resets its data
99 std::map<int, QSharedPointer<SqpDataContainer> > dataContainers{};
123 std::map<int, QSharedPointer<SqpDataContainer> > dataContainers{};
100 for (const auto &plottable : plottables) {
124 for (const auto &plottable : plottables) {
101 if (auto graph = dynamic_cast<QCPGraph *>(plottable.second)) {
125 if (auto graph = dynamic_cast<QCPGraph *>(plottable.second)) {
102 auto dataContainer = QSharedPointer<SqpDataContainer>::create();
126 auto dataContainer = QSharedPointer<SqpDataContainer>::create();
103 graph->setData(dataContainer);
127 graph->setData(dataContainer);
104
128
105 dataContainers.insert({plottable.first, dataContainer});
129 dataContainers.insert({plottable.first, dataContainer});
106 }
130 }
107 }
131 }
108 dataSeries.lockRead();
132 dataSeries.lockRead();
109
133
110 // - Gets the data of the series included in the current range
134 // - Gets the data of the series included in the current range
111 // - Updates each plottable by adding, for each data item, a point that takes x-axis data
135 // - Updates each plottable by adding, for each data item, a point that takes x-axis data
112 // and value data. The correct value is retrieved according to the index of the component
136 // and value data. The correct value is retrieved according to the index of the component
113 auto subDataIts = dataSeries.xAxisRange(range.m_TStart, range.m_TEnd);
137 auto subDataIts = dataSeries.xAxisRange(range.m_TStart, range.m_TEnd);
114 for (auto it = subDataIts.first; it != subDataIts.second; ++it) {
138 for (auto it = subDataIts.first; it != subDataIts.second; ++it) {
115 for (const auto &dataContainer : dataContainers) {
139 for (const auto &dataContainer : dataContainers) {
116 auto componentIndex = dataContainer.first;
140 auto componentIndex = dataContainer.first;
117 dataContainer.second->appendGraphData(
141 dataContainer.second->appendGraphData(
118 QCPGraphData(it->x(), it->value(componentIndex)));
142 QCPGraphData(it->x(), it->value(componentIndex)));
119 }
143 }
120 }
144 }
121
145
122 dataSeries.unlock();
146 dataSeries.unlock();
123
147
124 if (!plottables.empty()) {
148 if (!plottables.empty()) {
125 auto plot = plottables.begin()->second->parentPlot();
149 auto plot = plottables.begin()->second->parentPlot();
126
150
127 if (rescaleAxes) {
151 if (rescaleAxes) {
128 plot->rescaleAxes();
152 plot->rescaleAxes();
129 }
153 }
130
154
131 plot->replot();
155 plot->replot();
132 }
156 }
133 }
157 }
134 };
158 };
135
159
136 /**
160 /**
137 * Helper used to create/update plottables
161 * Helper used to create/update plottables
138 */
162 */
139 struct IPlottablesHelper {
163 struct IPlottablesHelper {
140 virtual ~IPlottablesHelper() noexcept = default;
164 virtual ~IPlottablesHelper() noexcept = default;
141 virtual PlottablesMap create(QCustomPlot &plot) const = 0;
165 virtual PlottablesMap create(QCustomPlot &plot) const = 0;
166 virtual void setYAxisRange(const SqpRange &xAxisRange, QCustomPlot &plot) const = 0;
142 virtual void update(PlottablesMap &plottables, const SqpRange &range,
167 virtual void update(PlottablesMap &plottables, const SqpRange &range,
143 bool rescaleAxes = false) const = 0;
168 bool rescaleAxes = false) const = 0;
144 };
169 };
145
170
146 /**
171 /**
147 * Default implementation of IPlottablesHelper, which takes data series to create/update plottables
172 * Default implementation of IPlottablesHelper, which takes data series to create/update plottables
148 * @tparam T the data series' type
173 * @tparam T the data series' type
149 */
174 */
150 template <typename T>
175 template <typename T>
151 struct PlottablesHelper : public IPlottablesHelper {
176 struct PlottablesHelper : public IPlottablesHelper {
152 explicit PlottablesHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
177 explicit PlottablesHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
153
178
154 PlottablesMap create(QCustomPlot &plot) const override
179 PlottablesMap create(QCustomPlot &plot) const override
155 {
180 {
156 return PlottablesCreator<T>::createPlottables(m_DataSeries, plot);
181 return PlottablesCreator<T>::createPlottables(m_DataSeries, plot);
157 }
182 }
158
183
159 void update(PlottablesMap &plottables, const SqpRange &range, bool rescaleAxes) const override
184 void update(PlottablesMap &plottables, const SqpRange &range, bool rescaleAxes) const override
160 {
185 {
161 PlottablesUpdater<T>::updatePlottables(m_DataSeries, plottables, range, rescaleAxes);
186 PlottablesUpdater<T>::updatePlottables(m_DataSeries, plottables, range, rescaleAxes);
162 }
187 }
163
188
189 void setYAxisRange(const SqpRange &xAxisRange, QCustomPlot &plot) const override
190 {
191 return PlottablesUpdater<T>::setPlotYAxisRange(m_DataSeries, xAxisRange, plot);
192 }
193
164 T &m_DataSeries;
194 T &m_DataSeries;
165 };
195 };
166
196
167 /// Creates IPlottablesHelper according to a data series
197 /// Creates IPlottablesHelper according to a data series
168 std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<IDataSeries> dataSeries) noexcept
198 std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<IDataSeries> dataSeries) noexcept
169 {
199 {
170 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
200 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
171 return std::make_unique<PlottablesHelper<ScalarSeries> >(*scalarSeries);
201 return std::make_unique<PlottablesHelper<ScalarSeries> >(*scalarSeries);
172 }
202 }
173 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
203 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
174 return std::make_unique<PlottablesHelper<VectorSeries> >(*vectorSeries);
204 return std::make_unique<PlottablesHelper<VectorSeries> >(*vectorSeries);
175 }
205 }
176 else {
206 else {
177 return std::make_unique<PlottablesHelper<IDataSeries> >(*dataSeries);
207 return std::make_unique<PlottablesHelper<IDataSeries> >(*dataSeries);
178 }
208 }
179 }
209 }
180
210
181 } // namespace
211 } // namespace
182
212
183 PlottablesMap VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
213 PlottablesMap VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
184 QCustomPlot &plot) noexcept
214 QCustomPlot &plot) noexcept
185 {
215 {
186 if (variable) {
216 if (variable) {
187 auto helper = createHelper(variable->dataSeries());
217 auto helper = createHelper(variable->dataSeries());
188 auto plottables = helper->create(plot);
218 auto plottables = helper->create(plot);
189 return plottables;
219 return plottables;
190 }
220 }
191 else {
221 else {
192 qCDebug(LOG_VisualizationGraphHelper())
222 qCDebug(LOG_VisualizationGraphHelper())
193 << QObject::tr("Can't create graph plottables : the variable is null");
223 << QObject::tr("Can't create graph plottables : the variable is null");
194 return PlottablesMap{};
224 return PlottablesMap{};
195 }
225 }
196 }
226 }
197
227
228 void VisualizationGraphHelper::setYAxisRange(std::shared_ptr<Variable> variable,
229 QCustomPlot &plot) noexcept
230 {
231 if (variable) {
232 auto helper = createHelper(variable->dataSeries());
233 helper->setYAxisRange(variable->range(), plot);
234 }
235 else {
236 qCDebug(LOG_VisualizationGraphHelper())
237 << QObject::tr("Can't set y-axis range of plot: the variable is null");
238 }
239 }
240
198 void VisualizationGraphHelper::updateData(PlottablesMap &plottables,
241 void VisualizationGraphHelper::updateData(PlottablesMap &plottables,
199 std::shared_ptr<IDataSeries> dataSeries,
242 std::shared_ptr<IDataSeries> dataSeries,
200 const SqpRange &dateTime)
243 const SqpRange &dateTime)
201 {
244 {
202 auto helper = createHelper(dataSeries);
245 auto helper = createHelper(dataSeries);
203 helper->update(plottables, dateTime);
246 helper->update(plottables, dateTime);
204 }
247 }
@@ -1,401 +1,406
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationDefs.h"
3 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationGraphHelper.h"
4 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
8
8
9 #include <Common/MimeTypesDef.h>
9 #include <Common/MimeTypesDef.h>
10 #include <Data/ArrayData.h>
10 #include <Data/ArrayData.h>
11 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
12 #include <DragAndDrop/DragDropHelper.h>
12 #include <DragAndDrop/DragDropHelper.h>
13 #include <Settings/SqpSettingsDefs.h>
13 #include <Settings/SqpSettingsDefs.h>
14 #include <SqpApplication.h>
14 #include <SqpApplication.h>
15 #include <Time/TimeController.h>
15 #include <Time/TimeController.h>
16 #include <Variable/Variable.h>
16 #include <Variable/Variable.h>
17 #include <Variable/VariableController.h>
17 #include <Variable/VariableController.h>
18
18
19 #include <unordered_map>
19 #include <unordered_map>
20
20
21 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
21 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
22
22
23 namespace {
23 namespace {
24
24
25 /// Key pressed to enable zoom on horizontal axis
25 /// Key pressed to enable zoom on horizontal axis
26 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
26 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
27
27
28 /// Key pressed to enable zoom on vertical axis
28 /// Key pressed to enable zoom on vertical axis
29 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
29 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
30
30
31 } // namespace
31 } // namespace
32
32
33 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
33 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
34
34
35 explicit VisualizationGraphWidgetPrivate(const QString &name)
35 explicit VisualizationGraphWidgetPrivate(const QString &name)
36 : m_Name{name},
36 : m_Name{name},
37 m_DoAcquisition{true},
37 m_DoAcquisition{true},
38 m_IsCalibration{false},
38 m_IsCalibration{false},
39 m_RenderingDelegate{nullptr}
39 m_RenderingDelegate{nullptr}
40 {
40 {
41 }
41 }
42
42
43 QString m_Name;
43 QString m_Name;
44 // 1 variable -> n qcpplot
44 // 1 variable -> n qcpplot
45 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
45 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
46 bool m_DoAcquisition;
46 bool m_DoAcquisition;
47 bool m_IsCalibration;
47 bool m_IsCalibration;
48 QCPItemTracer *m_TextTracer;
48 QCPItemTracer *m_TextTracer;
49 /// Delegate used to attach rendering features to the plot
49 /// Delegate used to attach rendering features to the plot
50 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
50 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
51 };
51 };
52
52
53 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
53 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
54 : VisualizationDragWidget{parent},
54 : VisualizationDragWidget{parent},
55 ui{new Ui::VisualizationGraphWidget},
55 ui{new Ui::VisualizationGraphWidget},
56 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
56 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
57 {
57 {
58 ui->setupUi(this);
58 ui->setupUi(this);
59
59
60 // 'Close' options : widget is deleted when closed
60 // 'Close' options : widget is deleted when closed
61 setAttribute(Qt::WA_DeleteOnClose);
61 setAttribute(Qt::WA_DeleteOnClose);
62
62
63 // Set qcpplot properties :
63 // Set qcpplot properties :
64 // - Drag (on x-axis) and zoom are enabled
64 // - Drag (on x-axis) and zoom are enabled
65 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
65 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
66 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
66 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
67 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
67 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
68
68
69 // The delegate must be initialized after the ui as it uses the plot
69 // The delegate must be initialized after the ui as it uses the plot
70 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
70 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
71
71
72 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
72 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
73 connect(ui->widget, &QCustomPlot::mouseRelease, this,
73 connect(ui->widget, &QCustomPlot::mouseRelease, this,
74 &VisualizationGraphWidget::onMouseRelease);
74 &VisualizationGraphWidget::onMouseRelease);
75 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
75 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
76 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
76 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
77 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
77 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
78 &QCPAxis::rangeChanged),
78 &QCPAxis::rangeChanged),
79 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
79 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
80
80
81 // Activates menu when right clicking on the graph
81 // Activates menu when right clicking on the graph
82 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
82 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
83 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
83 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
84 &VisualizationGraphWidget::onGraphMenuRequested);
84 &VisualizationGraphWidget::onGraphMenuRequested);
85
85
86 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
86 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
87 &VariableController::onRequestDataLoading);
87 &VariableController::onRequestDataLoading);
88
88
89 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
89 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
90 &VisualizationGraphWidget::onUpdateVarDisplaying);
90 &VisualizationGraphWidget::onUpdateVarDisplaying);
91 }
91 }
92
92
93
93
94 VisualizationGraphWidget::~VisualizationGraphWidget()
94 VisualizationGraphWidget::~VisualizationGraphWidget()
95 {
95 {
96 delete ui;
96 delete ui;
97 }
97 }
98
98
99 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
99 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
100 {
100 {
101 auto parent = parentWidget();
101 auto parent = parentWidget();
102 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
102 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
103 parent = parent->parentWidget();
103 parent = parent->parentWidget();
104 }
104 }
105
105
106 return qobject_cast<VisualizationZoneWidget *>(parent);
106 return qobject_cast<VisualizationZoneWidget *>(parent);
107 }
107 }
108
108
109 void VisualizationGraphWidget::enableAcquisition(bool enable)
109 void VisualizationGraphWidget::enableAcquisition(bool enable)
110 {
110 {
111 impl->m_DoAcquisition = enable;
111 impl->m_DoAcquisition = enable;
112 }
112 }
113
113
114 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
114 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
115 {
115 {
116 // Uses delegate to create the qcpplot components according to the variable
116 // Uses delegate to create the qcpplot components according to the variable
117 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
117 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
118 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
118 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
119
119
120 // Set axes properties according to the units of the data series
120 // Set axes properties according to the units of the data series
121 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
121 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
122 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
122 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
123 auto xAxisUnit = Unit{};
123 auto xAxisUnit = Unit{};
124 auto valuesUnit = Unit{};
124 auto valuesUnit = Unit{};
125
125
126 if (auto dataSeries = variable->dataSeries()) {
126 if (auto dataSeries = variable->dataSeries()) {
127 dataSeries->lockRead();
127 dataSeries->lockRead();
128 xAxisUnit = dataSeries->xAxisUnit();
128 xAxisUnit = dataSeries->xAxisUnit();
129 valuesUnit = dataSeries->valuesUnit();
129 valuesUnit = dataSeries->valuesUnit();
130 dataSeries->unlock();
130 dataSeries->unlock();
131 }
131 }
132 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
132 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
133
133
134 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
134 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
135
135
136 this->enableAcquisition(false);
136 this->enableAcquisition(false);
137 this->setGraphRange(range);
137 this->setGraphRange(range);
138 this->enableAcquisition(true);
138 this->enableAcquisition(true);
139
139
140 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
140 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
141
141
142 emit variableAdded(variable);
142 emit variableAdded(variable);
143 }
143 }
144
144
145 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
145 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
146 {
146 {
147 // Each component associated to the variable :
147 // Each component associated to the variable :
148 // - is removed from qcpplot (which deletes it)
148 // - is removed from qcpplot (which deletes it)
149 // - is no longer referenced in the map
149 // - is no longer referenced in the map
150 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
150 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
151 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
151 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
152 emit variableAboutToBeRemoved(variable);
152 emit variableAboutToBeRemoved(variable);
153
153
154 auto &plottablesMap = variableIt->second;
154 auto &plottablesMap = variableIt->second;
155
155
156 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
156 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
157 plottableIt != plottableEnd;) {
157 plottableIt != plottableEnd;) {
158 ui->widget->removePlottable(plottableIt->second);
158 ui->widget->removePlottable(plottableIt->second);
159 plottableIt = plottablesMap.erase(plottableIt);
159 plottableIt = plottablesMap.erase(plottableIt);
160 }
160 }
161
161
162 impl->m_VariableToPlotMultiMap.erase(variableIt);
162 impl->m_VariableToPlotMultiMap.erase(variableIt);
163 }
163 }
164
164
165 // Updates graph
165 // Updates graph
166 ui->widget->replot();
166 ui->widget->replot();
167 }
167 }
168
168
169 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
169 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
170 {
170 {
171 auto variables = QList<std::shared_ptr<Variable> >{};
171 auto variables = QList<std::shared_ptr<Variable> >{};
172 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
172 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
173 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
173 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
174 variables << it->first;
174 variables << it->first;
175 }
175 }
176
176
177 return variables;
177 return variables;
178 }
178 }
179
179
180 void VisualizationGraphWidget::setYRange(const SqpRange &range)
180 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
181 {
181 {
182 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
182 if (!variable) {
183 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
184 return;
185 }
186
187 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
183 }
188 }
184
189
185 SqpRange VisualizationGraphWidget::graphRange() const noexcept
190 SqpRange VisualizationGraphWidget::graphRange() const noexcept
186 {
191 {
187 auto graphRange = ui->widget->xAxis->range();
192 auto graphRange = ui->widget->xAxis->range();
188 return SqpRange{graphRange.lower, graphRange.upper};
193 return SqpRange{graphRange.lower, graphRange.upper};
189 }
194 }
190
195
191 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
196 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
192 {
197 {
193 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
198 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
194 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
199 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
195 ui->widget->replot();
200 ui->widget->replot();
196 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
201 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
197 }
202 }
198
203
199 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
204 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
200 {
205 {
201 if (visitor) {
206 if (visitor) {
202 visitor->visit(this);
207 visitor->visit(this);
203 }
208 }
204 else {
209 else {
205 qCCritical(LOG_VisualizationGraphWidget())
210 qCCritical(LOG_VisualizationGraphWidget())
206 << tr("Can't visit widget : the visitor is null");
211 << tr("Can't visit widget : the visitor is null");
207 }
212 }
208 }
213 }
209
214
210 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
215 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
211 {
216 {
212 /// @todo : for the moment, a graph can always accomodate a variable
217 /// @todo : for the moment, a graph can always accomodate a variable
213 Q_UNUSED(variable);
218 Q_UNUSED(variable);
214 return true;
219 return true;
215 }
220 }
216
221
217 bool VisualizationGraphWidget::contains(const Variable &variable) const
222 bool VisualizationGraphWidget::contains(const Variable &variable) const
218 {
223 {
219 // Finds the variable among the keys of the map
224 // Finds the variable among the keys of the map
220 auto variablePtr = &variable;
225 auto variablePtr = &variable;
221 auto findVariable
226 auto findVariable
222 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
227 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
223
228
224 auto end = impl->m_VariableToPlotMultiMap.cend();
229 auto end = impl->m_VariableToPlotMultiMap.cend();
225 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
230 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
226 return it != end;
231 return it != end;
227 }
232 }
228
233
229 QString VisualizationGraphWidget::name() const
234 QString VisualizationGraphWidget::name() const
230 {
235 {
231 return impl->m_Name;
236 return impl->m_Name;
232 }
237 }
233
238
234 QMimeData *VisualizationGraphWidget::mimeData() const
239 QMimeData *VisualizationGraphWidget::mimeData() const
235 {
240 {
236 auto mimeData = new QMimeData;
241 auto mimeData = new QMimeData;
237 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
242 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
238
243
239 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
244 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
240 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
245 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
241
246
242 return mimeData;
247 return mimeData;
243 }
248 }
244
249
245 bool VisualizationGraphWidget::isDragAllowed() const
250 bool VisualizationGraphWidget::isDragAllowed() const
246 {
251 {
247 return true;
252 return true;
248 }
253 }
249
254
250 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
255 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
251 {
256 {
252 if (highlighted) {
257 if (highlighted) {
253 plot().setBackground(QBrush(QColor("#BBD5EE")));
258 plot().setBackground(QBrush(QColor("#BBD5EE")));
254 }
259 }
255 else {
260 else {
256 plot().setBackground(QBrush(Qt::white));
261 plot().setBackground(QBrush(Qt::white));
257 }
262 }
258
263
259 plot().update();
264 plot().update();
260 }
265 }
261
266
262 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
267 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
263 {
268 {
264 Q_UNUSED(event);
269 Q_UNUSED(event);
265
270
266 // Prevents that all variables will be removed from graph when it will be closed
271 // Prevents that all variables will be removed from graph when it will be closed
267 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
272 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
268 emit variableAboutToBeRemoved(variableEntry.first);
273 emit variableAboutToBeRemoved(variableEntry.first);
269 }
274 }
270 }
275 }
271
276
272 void VisualizationGraphWidget::enterEvent(QEvent *event)
277 void VisualizationGraphWidget::enterEvent(QEvent *event)
273 {
278 {
274 Q_UNUSED(event);
279 Q_UNUSED(event);
275 impl->m_RenderingDelegate->showGraphOverlay(true);
280 impl->m_RenderingDelegate->showGraphOverlay(true);
276 }
281 }
277
282
278 void VisualizationGraphWidget::leaveEvent(QEvent *event)
283 void VisualizationGraphWidget::leaveEvent(QEvent *event)
279 {
284 {
280 Q_UNUSED(event);
285 Q_UNUSED(event);
281 impl->m_RenderingDelegate->showGraphOverlay(false);
286 impl->m_RenderingDelegate->showGraphOverlay(false);
282 }
287 }
283
288
284 QCustomPlot &VisualizationGraphWidget::plot() noexcept
289 QCustomPlot &VisualizationGraphWidget::plot() noexcept
285 {
290 {
286 return *ui->widget;
291 return *ui->widget;
287 }
292 }
288
293
289 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
294 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
290 {
295 {
291 QMenu graphMenu{};
296 QMenu graphMenu{};
292
297
293 // Iterates on variables (unique keys)
298 // Iterates on variables (unique keys)
294 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
299 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
295 end = impl->m_VariableToPlotMultiMap.cend();
300 end = impl->m_VariableToPlotMultiMap.cend();
296 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
301 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
297 // 'Remove variable' action
302 // 'Remove variable' action
298 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
303 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
299 [ this, var = it->first ]() { removeVariable(var); });
304 [ this, var = it->first ]() { removeVariable(var); });
300 }
305 }
301
306
302 if (!graphMenu.isEmpty()) {
307 if (!graphMenu.isEmpty()) {
303 graphMenu.exec(QCursor::pos());
308 graphMenu.exec(QCursor::pos());
304 }
309 }
305 }
310 }
306
311
307 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
312 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
308 {
313 {
309 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
314 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
310 << QThread::currentThread()->objectName() << "DoAcqui"
315 << QThread::currentThread()->objectName() << "DoAcqui"
311 << impl->m_DoAcquisition;
316 << impl->m_DoAcquisition;
312
317
313 auto graphRange = SqpRange{t1.lower, t1.upper};
318 auto graphRange = SqpRange{t1.lower, t1.upper};
314 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
319 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
315
320
316 if (impl->m_DoAcquisition) {
321 if (impl->m_DoAcquisition) {
317 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
322 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
318
323
319 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
324 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
320 end = impl->m_VariableToPlotMultiMap.end();
325 end = impl->m_VariableToPlotMultiMap.end();
321 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
326 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
322 variableUnderGraphVector.push_back(it->first);
327 variableUnderGraphVector.push_back(it->first);
323 }
328 }
324 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
329 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
325 !impl->m_IsCalibration);
330 !impl->m_IsCalibration);
326
331
327 if (!impl->m_IsCalibration) {
332 if (!impl->m_IsCalibration) {
328 qCDebug(LOG_VisualizationGraphWidget())
333 qCDebug(LOG_VisualizationGraphWidget())
329 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
334 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
330 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
335 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
331 emit synchronize(graphRange, oldGraphRange);
336 emit synchronize(graphRange, oldGraphRange);
332 }
337 }
333 }
338 }
334 }
339 }
335
340
336 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
341 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
337 {
342 {
338 // Handles plot rendering when mouse is moving
343 // Handles plot rendering when mouse is moving
339 impl->m_RenderingDelegate->onMouseMove(event);
344 impl->m_RenderingDelegate->onMouseMove(event);
340
345
341 VisualizationDragWidget::mouseMoveEvent(event);
346 VisualizationDragWidget::mouseMoveEvent(event);
342 }
347 }
343
348
344 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
349 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
345 {
350 {
346 auto zoomOrientations = QFlags<Qt::Orientation>{};
351 auto zoomOrientations = QFlags<Qt::Orientation>{};
347
352
348 // Lambda that enables a zoom orientation if the key modifier related to this orientation
353 // Lambda that enables a zoom orientation if the key modifier related to this orientation
349 // has
354 // has
350 // been pressed
355 // been pressed
351 auto enableOrientation
356 auto enableOrientation
352 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
357 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
353 auto orientationEnabled = event->modifiers().testFlag(modifier);
358 auto orientationEnabled = event->modifiers().testFlag(modifier);
354 zoomOrientations.setFlag(orientation, orientationEnabled);
359 zoomOrientations.setFlag(orientation, orientationEnabled);
355 };
360 };
356 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
361 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
357 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
362 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
358
363
359 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
364 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
360 }
365 }
361
366
362 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
367 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
363 {
368 {
364 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
369 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
365
370
366 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
371 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
367
372
368 VisualizationDragWidget::mousePressEvent(event);
373 VisualizationDragWidget::mousePressEvent(event);
369 }
374 }
370
375
371 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
376 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
372 {
377 {
373 impl->m_IsCalibration = false;
378 impl->m_IsCalibration = false;
374 }
379 }
375
380
376 void VisualizationGraphWidget::onDataCacheVariableUpdated()
381 void VisualizationGraphWidget::onDataCacheVariableUpdated()
377 {
382 {
378 auto graphRange = ui->widget->xAxis->range();
383 auto graphRange = ui->widget->xAxis->range();
379 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
384 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
380
385
381 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
386 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
382 auto variable = variableEntry.first;
387 auto variable = variableEntry.first;
383 qCDebug(LOG_VisualizationGraphWidget())
388 qCDebug(LOG_VisualizationGraphWidget())
384 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
389 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
385 qCDebug(LOG_VisualizationGraphWidget())
390 qCDebug(LOG_VisualizationGraphWidget())
386 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
391 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
387 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
392 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
388 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
393 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
389 variable->range());
394 variable->range());
390 }
395 }
391 }
396 }
392 }
397 }
393
398
394 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
399 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
395 const SqpRange &range)
400 const SqpRange &range)
396 {
401 {
397 auto it = impl->m_VariableToPlotMultiMap.find(variable);
402 auto it = impl->m_VariableToPlotMultiMap.find(variable);
398 if (it != impl->m_VariableToPlotMultiMap.end()) {
403 if (it != impl->m_VariableToPlotMultiMap.end()) {
399 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
404 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
400 }
405 }
401 }
406 }
@@ -1,516 +1,500
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/DragDropHelper.h>
19 #include <DragAndDrop/DragDropHelper.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
30
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
32 /// the zone
32 /// the zone
33 QString defaultGraphName(const QLayout &layout)
33 QString defaultGraphName(const QLayout &layout)
34 {
34 {
35 auto count = 0;
35 auto count = 0;
36 for (auto i = 0; i < layout.count(); ++i) {
36 for (auto i = 0; i < layout.count(); ++i) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
38 count++;
38 count++;
39 }
39 }
40 }
40 }
41
41
42 return QObject::tr("Graph %1").arg(count + 1);
42 return QObject::tr("Graph %1").arg(count + 1);
43 }
43 }
44
44
45 /**
45 /**
46 * Applies a function to all graphs of the zone represented by its layout
46 * Applies a function to all graphs of the zone represented by its layout
47 * @param layout the layout that contains graphs
47 * @param layout the layout that contains graphs
48 * @param fun the function to apply to each graph
48 * @param fun the function to apply to each graph
49 */
49 */
50 template <typename Fun>
50 template <typename Fun>
51 void processGraphs(QLayout &layout, Fun fun)
51 void processGraphs(QLayout &layout, Fun fun)
52 {
52 {
53 for (auto i = 0; i < layout.count(); ++i) {
53 for (auto i = 0; i < layout.count(); ++i) {
54 if (auto item = layout.itemAt(i)) {
54 if (auto item = layout.itemAt(i)) {
55 if (auto visualizationGraphWidget
55 if (auto visualizationGraphWidget
56 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
56 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
57 fun(*visualizationGraphWidget);
57 fun(*visualizationGraphWidget);
58 }
58 }
59 }
59 }
60 }
60 }
61 }
61 }
62
62
63 } // namespace
63 } // namespace
64
64
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
66
66
67 explicit VisualizationZoneWidgetPrivate()
67 explicit VisualizationZoneWidgetPrivate()
68 : m_SynchronisationGroupId{QUuid::createUuid()},
68 : m_SynchronisationGroupId{QUuid::createUuid()},
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
70 {
70 {
71 }
71 }
72 QUuid m_SynchronisationGroupId;
72 QUuid m_SynchronisationGroupId;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
74
74
75 // Returns the first graph in the zone or nullptr if there is no graph inside
75 // Returns the first graph in the zone or nullptr if there is no graph inside
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
77 {
77 {
78 VisualizationGraphWidget *firstGraph = nullptr;
78 VisualizationGraphWidget *firstGraph = nullptr;
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
80 if (layout->count() > 0) {
80 if (layout->count() > 0) {
81 if (auto visualizationGraphWidget
81 if (auto visualizationGraphWidget
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
83 firstGraph = visualizationGraphWidget;
83 firstGraph = visualizationGraphWidget;
84 }
84 }
85 }
85 }
86
86
87 return firstGraph;
87 return firstGraph;
88 }
88 }
89
89
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
92 VisualizationZoneWidget *zoneWidget);
92 VisualizationZoneWidget *zoneWidget);
93 };
93 };
94
94
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
96 : VisualizationDragWidget{parent},
96 : VisualizationDragWidget{parent},
97 ui{new Ui::VisualizationZoneWidget},
97 ui{new Ui::VisualizationZoneWidget},
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
99 {
99 {
100 ui->setupUi(this);
100 ui->setupUi(this);
101
101
102 ui->zoneNameLabel->setText(name);
102 ui->zoneNameLabel->setText(name);
103
103
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
105 ui->dragDropContainer->addAcceptedMimeType(
105 ui->dragDropContainer->addAcceptedMimeType(
106 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
106 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
107 ui->dragDropContainer->addAcceptedMimeType(
107 ui->dragDropContainer->addAcceptedMimeType(
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
109 ui->dragDropContainer->addAcceptedMimeType(
109 ui->dragDropContainer->addAcceptedMimeType(
110 MIME_TYPE_TIME_RANGE, VisualizationDragDropContainer::DropBehavior::Merged);
110 MIME_TYPE_TIME_RANGE, VisualizationDragDropContainer::DropBehavior::Merged);
111 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
111 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
112 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
112 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
113 ui->dragDropContainer);
113 ui->dragDropContainer);
114 });
114 });
115
115
116 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
116 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
117 &VisualizationZoneWidget::dropMimeData);
117 &VisualizationZoneWidget::dropMimeData);
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
119 &VisualizationZoneWidget::dropMimeDataOnGraph);
119 &VisualizationZoneWidget::dropMimeDataOnGraph);
120
120
121 // 'Close' options : widget is deleted when closed
121 // 'Close' options : widget is deleted when closed
122 setAttribute(Qt::WA_DeleteOnClose);
122 setAttribute(Qt::WA_DeleteOnClose);
123 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
123 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
124 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
124 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
125
125
126 // Synchronisation id
126 // Synchronisation id
127 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
127 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
128 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
128 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
129 }
129 }
130
130
131 VisualizationZoneWidget::~VisualizationZoneWidget()
131 VisualizationZoneWidget::~VisualizationZoneWidget()
132 {
132 {
133 delete ui;
133 delete ui;
134 }
134 }
135
135
136 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
136 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
137 {
137 {
138 // Synchronize new graph with others in the zone
138 // Synchronize new graph with others in the zone
139 impl->m_Synchronizer->addGraph(*graphWidget);
139 impl->m_Synchronizer->addGraph(*graphWidget);
140
140
141 ui->dragDropContainer->addDragWidget(graphWidget);
141 ui->dragDropContainer->addDragWidget(graphWidget);
142 }
142 }
143
143
144 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
144 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
145 {
145 {
146 // Synchronize new graph with others in the zone
146 // Synchronize new graph with others in the zone
147 impl->m_Synchronizer->addGraph(*graphWidget);
147 impl->m_Synchronizer->addGraph(*graphWidget);
148
148
149 ui->dragDropContainer->insertDragWidget(index, graphWidget);
149 ui->dragDropContainer->insertDragWidget(index, graphWidget);
150 }
150 }
151
151
152 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
152 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
153 {
153 {
154 return createGraph(variable, -1);
154 return createGraph(variable, -1);
155 }
155 }
156
156
157 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
157 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
158 int index)
158 int index)
159 {
159 {
160 auto graphWidget
160 auto graphWidget
161 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
161 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
162
162
163
163
164 // Set graph properties
164 // Set graph properties
165 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
165 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
166 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
166 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
167
167
168
168
169 // Lambda to synchronize zone widget
169 // Lambda to synchronize zone widget
170 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
170 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
171 const SqpRange &oldGraphRange) {
171 const SqpRange &oldGraphRange) {
172
172
173 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
173 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
174 auto frameLayout = ui->dragDropContainer->layout();
174 auto frameLayout = ui->dragDropContainer->layout();
175 for (auto i = 0; i < frameLayout->count(); ++i) {
175 for (auto i = 0; i < frameLayout->count(); ++i) {
176 auto graphChild
176 auto graphChild
177 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
177 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
178 if (graphChild && (graphChild != graphWidget)) {
178 if (graphChild && (graphChild != graphWidget)) {
179
179
180 auto graphChildRange = graphChild->graphRange();
180 auto graphChildRange = graphChild->graphRange();
181 switch (zoomType) {
181 switch (zoomType) {
182 case AcquisitionZoomType::ZoomIn: {
182 case AcquisitionZoomType::ZoomIn: {
183 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
183 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
184 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
184 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
185 graphChildRange.m_TStart += deltaLeft;
185 graphChildRange.m_TStart += deltaLeft;
186 graphChildRange.m_TEnd -= deltaRight;
186 graphChildRange.m_TEnd -= deltaRight;
187 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
187 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
188 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
188 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
189 << deltaLeft;
189 << deltaLeft;
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
191 << deltaRight;
191 << deltaRight;
192 qCDebug(LOG_VisualizationZoneWidget())
192 qCDebug(LOG_VisualizationZoneWidget())
193 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
193 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
194
194
195 break;
195 break;
196 }
196 }
197
197
198 case AcquisitionZoomType::ZoomOut: {
198 case AcquisitionZoomType::ZoomOut: {
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
200 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
200 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
201 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
201 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
203 << deltaLeft;
203 << deltaLeft;
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
205 << deltaRight;
205 << deltaRight;
206 qCDebug(LOG_VisualizationZoneWidget())
206 qCDebug(LOG_VisualizationZoneWidget())
207 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
207 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
208 graphChildRange.m_TStart -= deltaLeft;
208 graphChildRange.m_TStart -= deltaLeft;
209 graphChildRange.m_TEnd += deltaRight;
209 graphChildRange.m_TEnd += deltaRight;
210 break;
210 break;
211 }
211 }
212 case AcquisitionZoomType::PanRight: {
212 case AcquisitionZoomType::PanRight: {
213 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
213 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
214 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
214 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
215 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
215 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
216 graphChildRange.m_TStart += deltaLeft;
216 graphChildRange.m_TStart += deltaLeft;
217 graphChildRange.m_TEnd += deltaRight;
217 graphChildRange.m_TEnd += deltaRight;
218 qCDebug(LOG_VisualizationZoneWidget())
218 qCDebug(LOG_VisualizationZoneWidget())
219 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
219 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
220 break;
220 break;
221 }
221 }
222 case AcquisitionZoomType::PanLeft: {
222 case AcquisitionZoomType::PanLeft: {
223 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
223 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
224 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
224 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
225 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
225 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
226 graphChildRange.m_TStart -= deltaLeft;
226 graphChildRange.m_TStart -= deltaLeft;
227 graphChildRange.m_TEnd -= deltaRight;
227 graphChildRange.m_TEnd -= deltaRight;
228 break;
228 break;
229 }
229 }
230 case AcquisitionZoomType::Unknown: {
230 case AcquisitionZoomType::Unknown: {
231 qCDebug(LOG_VisualizationZoneWidget())
231 qCDebug(LOG_VisualizationZoneWidget())
232 << tr("Impossible to synchronize: zoom type unknown");
232 << tr("Impossible to synchronize: zoom type unknown");
233 break;
233 break;
234 }
234 }
235 default:
235 default:
236 qCCritical(LOG_VisualizationZoneWidget())
236 qCCritical(LOG_VisualizationZoneWidget())
237 << tr("Impossible to synchronize: zoom type not take into account");
237 << tr("Impossible to synchronize: zoom type not take into account");
238 // No action
238 // No action
239 break;
239 break;
240 }
240 }
241 graphChild->enableAcquisition(false);
241 graphChild->enableAcquisition(false);
242 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
242 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
243 << graphChild->graphRange();
243 << graphChild->graphRange();
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
245 << graphChildRange;
245 << graphChildRange;
246 qCDebug(LOG_VisualizationZoneWidget())
246 qCDebug(LOG_VisualizationZoneWidget())
247 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
247 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
248 graphChild->setGraphRange(graphChildRange);
248 graphChild->setGraphRange(graphChildRange);
249 graphChild->enableAcquisition(true);
249 graphChild->enableAcquisition(true);
250 }
250 }
251 }
251 }
252 };
252 };
253
253
254 // connection for synchronization
254 // connection for synchronization
255 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
255 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
256 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
256 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
257 &VisualizationZoneWidget::onVariableAdded);
257 &VisualizationZoneWidget::onVariableAdded);
258 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
258 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
259 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
259 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
260
260
261 auto range = SqpRange{};
261 auto range = SqpRange{};
262 if (auto firstGraph = impl->firstGraph(this)) {
262 if (auto firstGraph = impl->firstGraph(this)) {
263 // Case of a new graph in a existant zone
263 // Case of a new graph in a existant zone
264 range = firstGraph->graphRange();
264 range = firstGraph->graphRange();
265 }
265 }
266 else {
266 else {
267 // Case of a new graph as the first of the zone
267 // Case of a new graph as the first of the zone
268 range = variable->range();
268 range = variable->range();
269 }
269 }
270
270
271 this->insertGraph(index, graphWidget);
271 this->insertGraph(index, graphWidget);
272
272
273 graphWidget->addVariable(variable, range);
273 graphWidget->addVariable(variable, range);
274
274 graphWidget->setYRange(variable);
275 // get y using variable range
276 if (auto dataSeries = variable->dataSeries()) {
277 dataSeries->lockRead();
278 auto valuesBounds
279 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
280 auto end = dataSeries->cend();
281 if (valuesBounds.first != end && valuesBounds.second != end) {
282 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
283
284 auto minValue = rangeValue(valuesBounds.first->minValue());
285 auto maxValue = rangeValue(valuesBounds.second->maxValue());
286
287 graphWidget->setYRange(SqpRange{minValue, maxValue});
288 }
289 dataSeries->unlock();
290 }
291
275
292 return graphWidget;
276 return graphWidget;
293 }
277 }
294
278
295 VisualizationGraphWidget *
279 VisualizationGraphWidget *
296 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
280 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
297 {
281 {
298 if (variables.isEmpty()) {
282 if (variables.isEmpty()) {
299 return nullptr;
283 return nullptr;
300 }
284 }
301
285
302 auto graphWidget = createGraph(variables.first(), index);
286 auto graphWidget = createGraph(variables.first(), index);
303 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
287 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
304 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
288 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
305 }
289 }
306
290
307 return graphWidget;
291 return graphWidget;
308 }
292 }
309
293
310 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
294 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
311 {
295 {
312 if (visitor) {
296 if (visitor) {
313 visitor->visitEnter(this);
297 visitor->visitEnter(this);
314
298
315 // Apply visitor to graph children: widgets different from graphs are not visited (no
299 // Apply visitor to graph children: widgets different from graphs are not visited (no
316 // action)
300 // action)
317 processGraphs(
301 processGraphs(
318 *ui->dragDropContainer->layout(),
302 *ui->dragDropContainer->layout(),
319 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
303 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
320
304
321 visitor->visitLeave(this);
305 visitor->visitLeave(this);
322 }
306 }
323 else {
307 else {
324 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
308 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
325 }
309 }
326 }
310 }
327
311
328 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
312 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
329 {
313 {
330 // A tab can always accomodate a variable
314 // A tab can always accomodate a variable
331 Q_UNUSED(variable);
315 Q_UNUSED(variable);
332 return true;
316 return true;
333 }
317 }
334
318
335 bool VisualizationZoneWidget::contains(const Variable &variable) const
319 bool VisualizationZoneWidget::contains(const Variable &variable) const
336 {
320 {
337 Q_UNUSED(variable);
321 Q_UNUSED(variable);
338 return false;
322 return false;
339 }
323 }
340
324
341 QString VisualizationZoneWidget::name() const
325 QString VisualizationZoneWidget::name() const
342 {
326 {
343 return ui->zoneNameLabel->text();
327 return ui->zoneNameLabel->text();
344 }
328 }
345
329
346 QMimeData *VisualizationZoneWidget::mimeData() const
330 QMimeData *VisualizationZoneWidget::mimeData() const
347 {
331 {
348 auto mimeData = new QMimeData;
332 auto mimeData = new QMimeData;
349 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
333 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
350
334
351 return mimeData;
335 return mimeData;
352 }
336 }
353
337
354 bool VisualizationZoneWidget::isDragAllowed() const
338 bool VisualizationZoneWidget::isDragAllowed() const
355 {
339 {
356 return true;
340 return true;
357 }
341 }
358
342
359 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
343 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
360 {
344 {
361 // Closes graphs in the zone
345 // Closes graphs in the zone
362 processGraphs(*ui->dragDropContainer->layout(),
346 processGraphs(*ui->dragDropContainer->layout(),
363 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
347 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
364
348
365 // Delete synchronization group from variable controller
349 // Delete synchronization group from variable controller
366 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
350 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
367 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
351 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
368
352
369 QWidget::closeEvent(event);
353 QWidget::closeEvent(event);
370 }
354 }
371
355
372 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
356 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
373 {
357 {
374 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
358 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
375 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
359 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
376 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
360 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
377 }
361 }
378
362
379 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
363 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
380 {
364 {
381 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
365 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
382 Q_ARG(std::shared_ptr<Variable>, variable),
366 Q_ARG(std::shared_ptr<Variable>, variable),
383 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
367 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
384 }
368 }
385
369
386 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
370 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
387 {
371 {
388 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
372 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
389 impl->dropGraph(index, this);
373 impl->dropGraph(index, this);
390 }
374 }
391 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
375 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
392 auto variables = sqpApp->variableController().variablesForMimeData(
376 auto variables = sqpApp->variableController().variablesForMimeData(
393 mimeData->data(MIME_TYPE_VARIABLE_LIST));
377 mimeData->data(MIME_TYPE_VARIABLE_LIST));
394 impl->dropVariables(variables, index, this);
378 impl->dropVariables(variables, index, this);
395 }
379 }
396 else {
380 else {
397 qCWarning(LOG_VisualizationZoneWidget())
381 qCWarning(LOG_VisualizationZoneWidget())
398 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
382 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
399 }
383 }
400 }
384 }
401
385
402 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
386 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
403 const QMimeData *mimeData)
387 const QMimeData *mimeData)
404 {
388 {
405 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
389 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
406 if (!graphWidget) {
390 if (!graphWidget) {
407 qCWarning(LOG_VisualizationZoneWidget())
391 qCWarning(LOG_VisualizationZoneWidget())
408 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
392 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
409 "drop aborted");
393 "drop aborted");
410 Q_ASSERT(false);
394 Q_ASSERT(false);
411 return;
395 return;
412 }
396 }
413
397
414 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
398 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
415 auto variables = sqpApp->variableController().variablesForMimeData(
399 auto variables = sqpApp->variableController().variablesForMimeData(
416 mimeData->data(MIME_TYPE_VARIABLE_LIST));
400 mimeData->data(MIME_TYPE_VARIABLE_LIST));
417 for (const auto &var : variables) {
401 for (const auto &var : variables) {
418 graphWidget->addVariable(var, graphWidget->graphRange());
402 graphWidget->addVariable(var, graphWidget->graphRange());
419 }
403 }
420 }
404 }
421 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
405 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
422 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
406 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
423 graphWidget->setGraphRange(range);
407 graphWidget->setGraphRange(range);
424 }
408 }
425 else {
409 else {
426 qCWarning(LOG_VisualizationZoneWidget())
410 qCWarning(LOG_VisualizationZoneWidget())
427 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
411 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
428 }
412 }
429 }
413 }
430
414
431 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
415 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
432 int index, VisualizationZoneWidget *zoneWidget)
416 int index, VisualizationZoneWidget *zoneWidget)
433 {
417 {
434 auto &helper = sqpApp->dragDropHelper();
418 auto &helper = sqpApp->dragDropHelper();
435
419
436 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
420 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
437 if (!graphWidget) {
421 if (!graphWidget) {
438 qCWarning(LOG_VisualizationZoneWidget())
422 qCWarning(LOG_VisualizationZoneWidget())
439 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
423 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
440 "found or invalid.");
424 "found or invalid.");
441 Q_ASSERT(false);
425 Q_ASSERT(false);
442 return;
426 return;
443 }
427 }
444
428
445 auto parentDragDropContainer
429 auto parentDragDropContainer
446 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
430 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
447 if (!parentDragDropContainer) {
431 if (!parentDragDropContainer) {
448 qCWarning(LOG_VisualizationZoneWidget())
432 qCWarning(LOG_VisualizationZoneWidget())
449 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
433 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
450 "the dropped graph is not found.");
434 "the dropped graph is not found.");
451 Q_ASSERT(false);
435 Q_ASSERT(false);
452 return;
436 return;
453 }
437 }
454
438
455 const auto &variables = graphWidget->variables();
439 const auto &variables = graphWidget->variables();
456
440
457 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
441 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
458 // The drop didn't occur in the same zone
442 // The drop didn't occur in the same zone
459
443
460 // Abort the requests for the variables (if any)
444 // Abort the requests for the variables (if any)
461 // Commented, because it's not sure if it's needed or not
445 // Commented, because it's not sure if it's needed or not
462 // for (const auto& var : variables)
446 // for (const auto& var : variables)
463 //{
447 //{
464 // sqpApp->variableController().onAbortProgressRequested(var);
448 // sqpApp->variableController().onAbortProgressRequested(var);
465 //}
449 //}
466
450
467 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
451 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
468 auto nbGraph = parentDragDropContainer->countDragWidget();
452 auto nbGraph = parentDragDropContainer->countDragWidget();
469 if (nbGraph == 1) {
453 if (nbGraph == 1) {
470 // This is the only graph in the previous zone, close the zone
454 // This is the only graph in the previous zone, close the zone
471 previousParentZoneWidget->close();
455 previousParentZoneWidget->close();
472 }
456 }
473 else {
457 else {
474 // Close the graph
458 // Close the graph
475 graphWidget->close();
459 graphWidget->close();
476 }
460 }
477
461
478 // Creates the new graph in the zone
462 // Creates the new graph in the zone
479 zoneWidget->createGraph(variables, index);
463 zoneWidget->createGraph(variables, index);
480 }
464 }
481 else {
465 else {
482 // The drop occurred in the same zone or the graph is empty
466 // The drop occurred in the same zone or the graph is empty
483 // Simple move of the graph, no variable operation associated
467 // Simple move of the graph, no variable operation associated
484 parentDragDropContainer->layout()->removeWidget(graphWidget);
468 parentDragDropContainer->layout()->removeWidget(graphWidget);
485
469
486 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
470 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
487 // The graph is empty and dropped in a different zone.
471 // The graph is empty and dropped in a different zone.
488 // Take the range of the first graph in the zone (if existing).
472 // Take the range of the first graph in the zone (if existing).
489 auto layout = zoneWidget->ui->dragDropContainer->layout();
473 auto layout = zoneWidget->ui->dragDropContainer->layout();
490 if (layout->count() > 0) {
474 if (layout->count() > 0) {
491 if (auto visualizationGraphWidget
475 if (auto visualizationGraphWidget
492 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
476 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
493 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
477 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
494 }
478 }
495 }
479 }
496 }
480 }
497
481
498 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
482 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
499 }
483 }
500 }
484 }
501
485
502 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
486 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
503 const QList<std::shared_ptr<Variable> > &variables, int index,
487 const QList<std::shared_ptr<Variable> > &variables, int index,
504 VisualizationZoneWidget *zoneWidget)
488 VisualizationZoneWidget *zoneWidget)
505 {
489 {
506 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
490 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
507 // compatible variable here
491 // compatible variable here
508 if (variables.count() > 1) {
492 if (variables.count() > 1) {
509 qCWarning(LOG_VisualizationZoneWidget())
493 qCWarning(LOG_VisualizationZoneWidget())
510 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
494 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
511 "aborted.");
495 "aborted.");
512 return;
496 return;
513 }
497 }
514
498
515 zoneWidget->createGraph(variables, index);
499 zoneWidget->createGraph(variables, index);
516 }
500 }
General Comments 0
You need to be logged in to leave comments. Login now