##// END OF EJS Templates
Creates method that will display a tooltip and a tracer with data point information after a while
Alexandre Leroux -
r443:0277630b5c10
parent child
Show More
@@ -1,18 +1,20
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
2 #define SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
2 #define SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5
5
6 class QCustomPlot;
6 class QCustomPlot;
7 class QMouseEvent;
7 class QMouseEvent;
8
8
9 class VisualizationGraphRenderingDelegate {
9 class VisualizationGraphRenderingDelegate {
10 public:
10 public:
11 explicit VisualizationGraphRenderingDelegate(QCustomPlot &plot);
11 explicit VisualizationGraphRenderingDelegate(QCustomPlot &plot);
12
12
13 void onMouseMove(QMouseEvent *event) noexcept;
14
13 private:
15 private:
14 class VisualizationGraphRenderingDelegatePrivate;
16 class VisualizationGraphRenderingDelegatePrivate;
15 spimpl::unique_impl_ptr<VisualizationGraphRenderingDelegatePrivate> impl;
17 spimpl::unique_impl_ptr<VisualizationGraphRenderingDelegatePrivate> impl;
16 };
18 };
17
19
18 #endif // SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
20 #endif // SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
@@ -1,82 +1,84
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
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QWidget>
7 #include <QWidget>
8
8
9 #include <memory>
9 #include <memory>
10
10
11 #include <Common/spimpl.h>
11 #include <Common/spimpl.h>
12
12
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14
14
15 class QCPRange;
15 class QCPRange;
16 class SqpDateTime;
16 class SqpDateTime;
17 class Variable;
17 class Variable;
18
18
19 /**
19 /**
20 * Possible types of zoom operation
20 * Possible types of zoom operation
21 */
21 */
22 enum class VisualizationGraphWidgetZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
22 enum class VisualizationGraphWidgetZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
23
23
24 namespace Ui {
24 namespace Ui {
25 class VisualizationGraphWidget;
25 class VisualizationGraphWidget;
26 } // namespace Ui
26 } // namespace Ui
27
27
28 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
28 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
29 Q_OBJECT
29 Q_OBJECT
30
30
31 public:
31 public:
32 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
32 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
33 virtual ~VisualizationGraphWidget();
33 virtual ~VisualizationGraphWidget();
34
34
35 void enableSynchronize(bool enable);
35 void enableSynchronize(bool enable);
36
36
37 void addVariable(std::shared_ptr<Variable> variable);
37 void addVariable(std::shared_ptr<Variable> variable);
38 void addVariableUsingGraph(std::shared_ptr<Variable> variable);
38 void addVariableUsingGraph(std::shared_ptr<Variable> variable);
39 /// Removes a variable from the graph
39 /// Removes a variable from the graph
40 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
40 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
41
41
42 void setRange(std::shared_ptr<Variable> variable, const SqpDateTime &range);
42 void setRange(std::shared_ptr<Variable> variable, const SqpDateTime &range);
43 SqpDateTime graphRange() const noexcept;
43 SqpDateTime graphRange() const noexcept;
44 void setGraphRange(const SqpDateTime &range);
44 void setGraphRange(const SqpDateTime &range);
45
45
46 // IVisualizationWidget interface
46 // IVisualizationWidget interface
47 void accept(IVisualizationWidgetVisitor *visitor) override;
47 void accept(IVisualizationWidgetVisitor *visitor) override;
48 bool canDrop(const Variable &variable) const override;
48 bool canDrop(const Variable &variable) const override;
49 bool contains(const Variable &variable) const override;
49 bool contains(const Variable &variable) const override;
50 QString name() const override;
50 QString name() const override;
51
51
52
52
53 signals:
53 signals:
54 void requestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
54 void requestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
55 void synchronize(const SqpDateTime &dateTime, const SqpDateTime &oldDateTime,
55 void synchronize(const SqpDateTime &dateTime, const SqpDateTime &oldDateTime,
56 VisualizationGraphWidgetZoomType zoomType);
56 VisualizationGraphWidgetZoomType zoomType);
57
57
58
58
59 private:
59 private:
60 Ui::VisualizationGraphWidget *ui;
60 Ui::VisualizationGraphWidget *ui;
61
61
62 class VisualizationGraphWidgetPrivate;
62 class VisualizationGraphWidgetPrivate;
63 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
63 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
64
64
65 private slots:
65 private slots:
66 /// Slot called when right clicking on the graph (displays a menu)
66 /// Slot called when right clicking on the graph (displays a menu)
67 void onGraphMenuRequested(const QPoint &pos) noexcept;
67 void onGraphMenuRequested(const QPoint &pos) noexcept;
68
68
69 /// Rescale the X axe to range parameter
69 /// Rescale the X axe to range parameter
70 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
70 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
71
71
72 /// Slot called when a mouse move was made
73 void onMouseMove(QMouseEvent *event) noexcept;
72 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
74 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
73 void onMouseWheel(QWheelEvent *event) noexcept;
75 void onMouseWheel(QWheelEvent *event) noexcept;
74 /// Slot called when a mouse press was made, to activate the calibration of a graph
76 /// Slot called when a mouse press was made, to activate the calibration of a graph
75 void onMousePress(QMouseEvent *event) noexcept;
77 void onMousePress(QMouseEvent *event) noexcept;
76 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
78 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
77 void onMouseRelease(QMouseEvent *event) noexcept;
79 void onMouseRelease(QMouseEvent *event) noexcept;
78
80
79 void onDataCacheVariableUpdated();
81 void onDataCacheVariableUpdated();
80 };
82 };
81
83
82 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
84 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,13 +1,17
1 #include "Visualization/VisualizationGraphRenderingDelegate.h"
1 #include "Visualization/VisualizationGraphRenderingDelegate.h"
2 #include "Visualization/qcustomplot.h"
2 #include "Visualization/qcustomplot.h"
3
3
4 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
4 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
5 explicit VisualizationGraphRenderingDelegatePrivate(QCustomPlot &plot) : m_Plot{plot} {}
5 explicit VisualizationGraphRenderingDelegatePrivate(QCustomPlot &plot) : m_Plot{plot} {}
6
6
7 QCustomPlot &m_Plot;
7 QCustomPlot &m_Plot;
8 };
8 };
9
9
10 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(QCustomPlot &plot)
10 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(QCustomPlot &plot)
11 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(plot)}
11 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(plot)}
12 {
12 {
13 }
13 }
14
15 void VisualizationGraphRenderingDelegate::onMouseMove(QMouseEvent *event) noexcept
16 {
17 }
@@ -1,420 +1,428
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationGraphHelper.h"
3 #include "Visualization/VisualizationGraphHelper.h"
4 #include "Visualization/VisualizationGraphRenderingDelegate.h"
4 #include "Visualization/VisualizationGraphRenderingDelegate.h"
5 #include "ui_VisualizationGraphWidget.h"
5 #include "ui_VisualizationGraphWidget.h"
6
6
7 #include <Data/ArrayData.h>
7 #include <Data/ArrayData.h>
8 #include <Data/IDataSeries.h>
8 #include <Data/IDataSeries.h>
9 #include <Settings/SqpSettingsDefs.h>
9 #include <Settings/SqpSettingsDefs.h>
10 #include <SqpApplication.h>
10 #include <SqpApplication.h>
11 #include <Variable/Variable.h>
11 #include <Variable/Variable.h>
12 #include <Variable/VariableController.h>
12 #include <Variable/VariableController.h>
13
13
14 #include <unordered_map>
14 #include <unordered_map>
15
15
16 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
16 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
17
17
18 namespace {
18 namespace {
19
19
20 /// Key pressed to enable zoom on horizontal axis
20 /// Key pressed to enable zoom on horizontal axis
21 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
21 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
22
22
23 /// Key pressed to enable zoom on vertical axis
23 /// Key pressed to enable zoom on vertical axis
24 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
24 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
25
25
26 /// Gets a tolerance value from application settings. If the setting can't be found, the default
26 /// Gets a tolerance value from application settings. If the setting can't be found, the default
27 /// value passed in parameter is returned
27 /// value passed in parameter is returned
28 double toleranceValue(const QString &key, double defaultValue) noexcept
28 double toleranceValue(const QString &key, double defaultValue) noexcept
29 {
29 {
30 return QSettings{}.value(key, defaultValue).toDouble();
30 return QSettings{}.value(key, defaultValue).toDouble();
31 }
31 }
32
32
33 } // namespace
33 } // namespace
34
34
35 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
35 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
36
36
37 explicit VisualizationGraphWidgetPrivate()
37 explicit VisualizationGraphWidgetPrivate()
38 : m_DoSynchronize{true}, m_IsCalibration{false}, m_RenderingDelegate{nullptr}
38 : m_DoSynchronize{true}, m_IsCalibration{false}, m_RenderingDelegate{nullptr}
39 {
39 {
40 }
40 }
41
41
42 // Return the operation when range changed
42 // Return the operation when range changed
43 VisualizationGraphWidgetZoomType getZoomType(const QCPRange &t1, const QCPRange &t2);
43 VisualizationGraphWidgetZoomType getZoomType(const QCPRange &t1, const QCPRange &t2);
44
44
45 // 1 variable -> n qcpplot
45 // 1 variable -> n qcpplot
46 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
46 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
47 bool m_DoSynchronize;
47 bool m_DoSynchronize;
48 bool m_IsCalibration;
48 bool m_IsCalibration;
49 QCPItemTracer *m_TextTracer;
49 QCPItemTracer *m_TextTracer;
50 /// Delegate used to attach rendering features to the plot
50 /// Delegate used to attach rendering features to the plot
51 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
51 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
52 };
52 };
53
53
54 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
54 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
55 : QWidget{parent},
55 : QWidget{parent},
56 ui{new Ui::VisualizationGraphWidget},
56 ui{new Ui::VisualizationGraphWidget},
57 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
57 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
58 {
58 {
59 ui->setupUi(this);
59 ui->setupUi(this);
60
60
61 // The delegate must be initialized after the ui as it uses the plot
61 // The delegate must be initialized after the ui as it uses the plot
62 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*ui->widget);
62 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*ui->widget);
63
63
64 ui->graphNameLabel->setText(name);
64 ui->graphNameLabel->setText(name);
65
65
66 // 'Close' options : widget is deleted when closed
66 // 'Close' options : widget is deleted when closed
67 setAttribute(Qt::WA_DeleteOnClose);
67 setAttribute(Qt::WA_DeleteOnClose);
68 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
68 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
69 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
69 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
70
70
71 // Set qcpplot properties :
71 // Set qcpplot properties :
72 // - Drag (on x-axis) and zoom are enabled
72 // - Drag (on x-axis) and zoom are enabled
73 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
73 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
74 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
74 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
75 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
75 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
76
76 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
77 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
77 connect(ui->widget, &QCustomPlot::mouseRelease, this,
78 connect(ui->widget, &QCustomPlot::mouseRelease, this,
78 &VisualizationGraphWidget::onMouseRelease);
79 &VisualizationGraphWidget::onMouseRelease);
80 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
79 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
81 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
80 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
82 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
81 &QCPAxis::rangeChanged),
83 &QCPAxis::rangeChanged),
82 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
84 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
83
85
84 // Activates menu when right clicking on the graph
86 // Activates menu when right clicking on the graph
85 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
87 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
86 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
88 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
87 &VisualizationGraphWidget::onGraphMenuRequested);
89 &VisualizationGraphWidget::onGraphMenuRequested);
88
90
89 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
91 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
90 &VariableController::onRequestDataLoading);
92 &VariableController::onRequestDataLoading);
91 }
93 }
92
94
93
95
94 VisualizationGraphWidget::~VisualizationGraphWidget()
96 VisualizationGraphWidget::~VisualizationGraphWidget()
95 {
97 {
96 delete ui;
98 delete ui;
97 }
99 }
98
100
99 void VisualizationGraphWidget::enableSynchronize(bool enable)
101 void VisualizationGraphWidget::enableSynchronize(bool enable)
100 {
102 {
101 impl->m_DoSynchronize = enable;
103 impl->m_DoSynchronize = enable;
102 }
104 }
103
105
104 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
106 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
105 {
107 {
106 // Uses delegate to create the qcpplot components according to the variable
108 // Uses delegate to create the qcpplot components according to the variable
107 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
109 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
108
110
109 for (auto createdPlottable : qAsConst(createdPlottables)) {
111 for (auto createdPlottable : qAsConst(createdPlottables)) {
110 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
112 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
111 }
113 }
112
114
113 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
115 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
114 }
116 }
115 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
117 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
116 {
118 {
117
119
118 // when adding a variable, we need to set its time range to the current graph range
120 // when adding a variable, we need to set its time range to the current graph range
119 auto grapheRange = ui->widget->xAxis->range();
121 auto grapheRange = ui->widget->xAxis->range();
120 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
122 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
121 variable->setDateTime(dateTime);
123 variable->setDateTime(dateTime);
122
124
123 auto variableDateTimeWithTolerance = dateTime;
125 auto variableDateTimeWithTolerance = dateTime;
124
126
125 // add tolerance for each side
127 // add tolerance for each side
126 auto toleranceFactor
128 auto toleranceFactor
127 = toleranceValue(GENERAL_TOLERANCE_AT_INIT_KEY, GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE);
129 = toleranceValue(GENERAL_TOLERANCE_AT_INIT_KEY, GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE);
128 auto tolerance = toleranceFactor * (dateTime.m_TEnd - dateTime.m_TStart);
130 auto tolerance = toleranceFactor * (dateTime.m_TEnd - dateTime.m_TStart);
129 variableDateTimeWithTolerance.m_TStart -= tolerance;
131 variableDateTimeWithTolerance.m_TStart -= tolerance;
130 variableDateTimeWithTolerance.m_TEnd += tolerance;
132 variableDateTimeWithTolerance.m_TEnd += tolerance;
131
133
132 // Uses delegate to create the qcpplot components according to the variable
134 // Uses delegate to create the qcpplot components according to the variable
133 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
135 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
134
136
135 for (auto createdPlottable : qAsConst(createdPlottables)) {
137 for (auto createdPlottable : qAsConst(createdPlottables)) {
136 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
138 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
137 }
139 }
138
140
139 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
141 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
140
142
141 // CHangement detected, we need to ask controller to request data loading
143 // CHangement detected, we need to ask controller to request data loading
142 emit requestDataLoading(variable, variableDateTimeWithTolerance);
144 emit requestDataLoading(variable, variableDateTimeWithTolerance);
143 }
145 }
144
146
145 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
147 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
146 {
148 {
147 // Each component associated to the variable :
149 // Each component associated to the variable :
148 // - is removed from qcpplot (which deletes it)
150 // - is removed from qcpplot (which deletes it)
149 // - is no longer referenced in the map
151 // - is no longer referenced in the map
150 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
152 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
151 for (auto it = componentsIt.first; it != componentsIt.second;) {
153 for (auto it = componentsIt.first; it != componentsIt.second;) {
152 ui->widget->removePlottable(it->second);
154 ui->widget->removePlottable(it->second);
153 it = impl->m_VariableToPlotMultiMap.erase(it);
155 it = impl->m_VariableToPlotMultiMap.erase(it);
154 }
156 }
155
157
156 // Updates graph
158 // Updates graph
157 ui->widget->replot();
159 ui->widget->replot();
158 }
160 }
159
161
160 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable,
162 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable,
161 const SqpDateTime &range)
163 const SqpDateTime &range)
162 {
164 {
163 // Note: in case of different axes that depends on variable, we could start with a code like
165 // Note: in case of different axes that depends on variable, we could start with a code like
164 // that:
166 // that:
165 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
167 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
166 // for (auto it = componentsIt.first; it != componentsIt.second;) {
168 // for (auto it = componentsIt.first; it != componentsIt.second;) {
167 // }
169 // }
168 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
170 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
169 ui->widget->replot();
171 ui->widget->replot();
170 }
172 }
171
173
172 SqpDateTime VisualizationGraphWidget::graphRange() const noexcept
174 SqpDateTime VisualizationGraphWidget::graphRange() const noexcept
173 {
175 {
174 auto grapheRange = ui->widget->xAxis->range();
176 auto grapheRange = ui->widget->xAxis->range();
175 return SqpDateTime{grapheRange.lower, grapheRange.upper};
177 return SqpDateTime{grapheRange.lower, grapheRange.upper};
176 }
178 }
177
179
178 void VisualizationGraphWidget::setGraphRange(const SqpDateTime &range)
180 void VisualizationGraphWidget::setGraphRange(const SqpDateTime &range)
179 {
181 {
180 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
182 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
181 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
183 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
182 ui->widget->replot();
184 ui->widget->replot();
183 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
185 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
184 }
186 }
185
187
186 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
188 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
187 {
189 {
188 if (visitor) {
190 if (visitor) {
189 visitor->visit(this);
191 visitor->visit(this);
190 }
192 }
191 else {
193 else {
192 qCCritical(LOG_VisualizationGraphWidget())
194 qCCritical(LOG_VisualizationGraphWidget())
193 << tr("Can't visit widget : the visitor is null");
195 << tr("Can't visit widget : the visitor is null");
194 }
196 }
195 }
197 }
196
198
197 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
199 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
198 {
200 {
199 /// @todo : for the moment, a graph can always accomodate a variable
201 /// @todo : for the moment, a graph can always accomodate a variable
200 Q_UNUSED(variable);
202 Q_UNUSED(variable);
201 return true;
203 return true;
202 }
204 }
203
205
204 bool VisualizationGraphWidget::contains(const Variable &variable) const
206 bool VisualizationGraphWidget::contains(const Variable &variable) const
205 {
207 {
206 // Finds the variable among the keys of the map
208 // Finds the variable among the keys of the map
207 auto variablePtr = &variable;
209 auto variablePtr = &variable;
208 auto findVariable
210 auto findVariable
209 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
211 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
210
212
211 auto end = impl->m_VariableToPlotMultiMap.cend();
213 auto end = impl->m_VariableToPlotMultiMap.cend();
212 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
214 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
213 return it != end;
215 return it != end;
214 }
216 }
215
217
216 QString VisualizationGraphWidget::name() const
218 QString VisualizationGraphWidget::name() const
217 {
219 {
218 return ui->graphNameLabel->text();
220 return ui->graphNameLabel->text();
219 }
221 }
220
222
221 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
223 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
222 {
224 {
223 QMenu graphMenu{};
225 QMenu graphMenu{};
224
226
225 // Iterates on variables (unique keys)
227 // Iterates on variables (unique keys)
226 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
228 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
227 end = impl->m_VariableToPlotMultiMap.cend();
229 end = impl->m_VariableToPlotMultiMap.cend();
228 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
230 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
229 // 'Remove variable' action
231 // 'Remove variable' action
230 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
232 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
231 [ this, var = it->first ]() { removeVariable(var); });
233 [ this, var = it->first ]() { removeVariable(var); });
232 }
234 }
233
235
234 if (!graphMenu.isEmpty()) {
236 if (!graphMenu.isEmpty()) {
235 graphMenu.exec(mapToGlobal(pos));
237 graphMenu.exec(mapToGlobal(pos));
236 }
238 }
237 }
239 }
238
240
239 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
241 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
240 {
242 {
241 qCInfo(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
243 qCInfo(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
242 << QThread::currentThread()->objectName();
244 << QThread::currentThread()->objectName();
243
245
244 auto dateTimeRange = SqpDateTime{t1.lower, t1.upper};
246 auto dateTimeRange = SqpDateTime{t1.lower, t1.upper};
245
247
246 auto zoomType = impl->getZoomType(t1, t2);
248 auto zoomType = impl->getZoomType(t1, t2);
247 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
249 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
248 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
250 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
249
251
250 auto variable = it->first;
252 auto variable = it->first;
251 auto currentDateTime = dateTimeRange;
253 auto currentDateTime = dateTimeRange;
252
254
253 auto toleranceFactor = toleranceValue(GENERAL_TOLERANCE_AT_UPDATE_KEY,
255 auto toleranceFactor = toleranceValue(GENERAL_TOLERANCE_AT_UPDATE_KEY,
254 GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE);
256 GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE);
255 auto tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
257 auto tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
256 auto variableDateTimeWithTolerance = currentDateTime;
258 auto variableDateTimeWithTolerance = currentDateTime;
257 variableDateTimeWithTolerance.m_TStart -= tolerance;
259 variableDateTimeWithTolerance.m_TStart -= tolerance;
258 variableDateTimeWithTolerance.m_TEnd += tolerance;
260 variableDateTimeWithTolerance.m_TEnd += tolerance;
259
261
260 qCDebug(LOG_VisualizationGraphWidget()) << "r" << currentDateTime;
262 qCDebug(LOG_VisualizationGraphWidget()) << "r" << currentDateTime;
261 qCDebug(LOG_VisualizationGraphWidget()) << "t" << variableDateTimeWithTolerance;
263 qCDebug(LOG_VisualizationGraphWidget()) << "t" << variableDateTimeWithTolerance;
262 qCDebug(LOG_VisualizationGraphWidget()) << "v" << variable->dateTime();
264 qCDebug(LOG_VisualizationGraphWidget()) << "v" << variable->dateTime();
263 // If new range with tol is upper than variable datetime parameters. we need to request new
265 // If new range with tol is upper than variable datetime parameters. we need to request new
264 // data
266 // data
265 if (!variable->contains(variableDateTimeWithTolerance)) {
267 if (!variable->contains(variableDateTimeWithTolerance)) {
266
268
267 auto variableDateTimeWithTolerance = currentDateTime;
269 auto variableDateTimeWithTolerance = currentDateTime;
268 if (!variable->isInside(currentDateTime)) {
270 if (!variable->isInside(currentDateTime)) {
269 auto variableDateTime = variable->dateTime();
271 auto variableDateTime = variable->dateTime();
270 if (variable->contains(variableDateTimeWithTolerance)) {
272 if (variable->contains(variableDateTimeWithTolerance)) {
271 qCDebug(LOG_VisualizationGraphWidget())
273 qCDebug(LOG_VisualizationGraphWidget())
272 << tr("TORM: Detection zoom in that need request:");
274 << tr("TORM: Detection zoom in that need request:");
273 // add tolerance for each side
275 // add tolerance for each side
274 tolerance
276 tolerance
275 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
277 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
276 variableDateTimeWithTolerance.m_TStart -= tolerance;
278 variableDateTimeWithTolerance.m_TStart -= tolerance;
277 variableDateTimeWithTolerance.m_TEnd += tolerance;
279 variableDateTimeWithTolerance.m_TEnd += tolerance;
278 }
280 }
279 else if (variableDateTime.m_TStart < currentDateTime.m_TStart) {
281 else if (variableDateTime.m_TStart < currentDateTime.m_TStart) {
280 qCInfo(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to right:");
282 qCInfo(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to right:");
281
283
282 auto diffEndToKeepDelta = currentDateTime.m_TEnd - variableDateTime.m_TEnd;
284 auto diffEndToKeepDelta = currentDateTime.m_TEnd - variableDateTime.m_TEnd;
283 currentDateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
285 currentDateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
284 // Tolerance have to be added to the right
286 // Tolerance have to be added to the right
285 // add tolerance for right (end) side
287 // add tolerance for right (end) side
286 tolerance
288 tolerance
287 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
289 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
288 variableDateTimeWithTolerance.m_TEnd += tolerance;
290 variableDateTimeWithTolerance.m_TEnd += tolerance;
289 }
291 }
290 else if (variableDateTime.m_TEnd > currentDateTime.m_TEnd) {
292 else if (variableDateTime.m_TEnd > currentDateTime.m_TEnd) {
291 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to left: ");
293 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to left: ");
292 auto diffStartToKeepDelta
294 auto diffStartToKeepDelta
293 = variableDateTime.m_TStart - currentDateTime.m_TStart;
295 = variableDateTime.m_TStart - currentDateTime.m_TStart;
294 currentDateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
296 currentDateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
295 // Tolerance have to be added to the left
297 // Tolerance have to be added to the left
296 // add tolerance for left (start) side
298 // add tolerance for left (start) side
297 tolerance
299 tolerance
298 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
300 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
299 variableDateTimeWithTolerance.m_TStart -= tolerance;
301 variableDateTimeWithTolerance.m_TStart -= tolerance;
300 }
302 }
301 else {
303 else {
302 qCCritical(LOG_VisualizationGraphWidget())
304 qCCritical(LOG_VisualizationGraphWidget())
303 << tr("Detection anormal zoom detection: ");
305 << tr("Detection anormal zoom detection: ");
304 }
306 }
305 }
307 }
306 else {
308 else {
307 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection zoom out: ");
309 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection zoom out: ");
308 // add tolerance for each side
310 // add tolerance for each side
309 tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
311 tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
310 variableDateTimeWithTolerance.m_TStart -= tolerance;
312 variableDateTimeWithTolerance.m_TStart -= tolerance;
311 variableDateTimeWithTolerance.m_TEnd += tolerance;
313 variableDateTimeWithTolerance.m_TEnd += tolerance;
312 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
314 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
313 }
315 }
314 if (!variable->contains(dateTimeRange)) {
316 if (!variable->contains(dateTimeRange)) {
315 qCDebug(LOG_VisualizationGraphWidget())
317 qCDebug(LOG_VisualizationGraphWidget())
316 << "TORM: Modif on variable datetime detected" << currentDateTime;
318 << "TORM: Modif on variable datetime detected" << currentDateTime;
317 variable->setDateTime(currentDateTime);
319 variable->setDateTime(currentDateTime);
318 }
320 }
319
321
320 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Request data detection: ");
322 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Request data detection: ");
321 // CHangement detected, we need to ask controller to request data loading
323 // CHangement detected, we need to ask controller to request data loading
322 emit requestDataLoading(variable, variableDateTimeWithTolerance);
324 emit requestDataLoading(variable, variableDateTimeWithTolerance);
323 }
325 }
324 else {
326 else {
325 qCInfo(LOG_VisualizationGraphWidget())
327 qCInfo(LOG_VisualizationGraphWidget())
326 << tr("TORM: Detection zoom in that doesn't need request: ");
328 << tr("TORM: Detection zoom in that doesn't need request: ");
327 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
329 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
328 }
330 }
329 }
331 }
330
332
331 if (impl->m_DoSynchronize && !impl->m_IsCalibration) {
333 if (impl->m_DoSynchronize && !impl->m_IsCalibration) {
332 auto oldDateTime = SqpDateTime{t2.lower, t2.upper};
334 auto oldDateTime = SqpDateTime{t2.lower, t2.upper};
333 qCDebug(LOG_VisualizationGraphWidget())
335 qCDebug(LOG_VisualizationGraphWidget())
334 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
336 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
335 << QThread::currentThread()->objectName();
337 << QThread::currentThread()->objectName();
336 emit synchronize(dateTimeRange, oldDateTime, zoomType);
338 emit synchronize(dateTimeRange, oldDateTime, zoomType);
337 }
339 }
338 }
340 }
339
341
342 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
343 {
344 // Handles plot rendering when mouse is moving
345 impl->m_RenderingDelegate->onMouseMove(event);
346 }
347
340 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
348 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
341 {
349 {
342 auto zoomOrientations = QFlags<Qt::Orientation>{};
350 auto zoomOrientations = QFlags<Qt::Orientation>{};
343
351
344 // Lambda that enables a zoom orientation if the key modifier related to this orientation
352 // Lambda that enables a zoom orientation if the key modifier related to this orientation
345 // has
353 // has
346 // been pressed
354 // been pressed
347 auto enableOrientation
355 auto enableOrientation
348 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
356 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
349 auto orientationEnabled = event->modifiers().testFlag(modifier);
357 auto orientationEnabled = event->modifiers().testFlag(modifier);
350 zoomOrientations.setFlag(orientation, orientationEnabled);
358 zoomOrientations.setFlag(orientation, orientationEnabled);
351 };
359 };
352 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
360 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
353 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
361 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
354
362
355 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
363 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
356 }
364 }
357
365
358 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
366 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
359 {
367 {
360 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
368 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
361 }
369 }
362
370
363 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
371 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
364 {
372 {
365 impl->m_IsCalibration = false;
373 impl->m_IsCalibration = false;
366 }
374 }
367
375
368 void VisualizationGraphWidget::onDataCacheVariableUpdated()
376 void VisualizationGraphWidget::onDataCacheVariableUpdated()
369 {
377 {
370 // NOTE:
378 // NOTE:
371 // We don't want to call the method for each component of a variable unitarily, but for
379 // We don't want to call the method for each component of a variable unitarily, but for
372 // all
380 // all
373 // its components at once (eg its three components in the case of a vector).
381 // its components at once (eg its three components in the case of a vector).
374
382
375 // The unordered_multimap does not do this easily, so the question is whether to:
383 // The unordered_multimap does not do this easily, so the question is whether to:
376 // - use an ordered_multimap and the algos of std to group the values by key
384 // - use an ordered_multimap and the algos of std to group the values by key
377 // - use a map (unique keys) and store as values directly the list of components
385 // - use a map (unique keys) and store as values directly the list of components
378
386
379 auto grapheRange = ui->widget->xAxis->range();
387 auto grapheRange = ui->widget->xAxis->range();
380 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
388 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
381
389
382 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
390 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
383 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
391 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
384 auto variable = it->first;
392 auto variable = it->first;
385 qCDebug(LOG_VisualizationGraphWidget())
393 qCDebug(LOG_VisualizationGraphWidget())
386 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S"
394 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S"
387 << variable->dateTime();
395 << variable->dateTime();
388 qCDebug(LOG_VisualizationGraphWidget())
396 qCDebug(LOG_VisualizationGraphWidget())
389 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
397 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
390 if (dateTime.contains(variable->dateTime()) || dateTime.intersect(variable->dateTime())) {
398 if (dateTime.contains(variable->dateTime()) || dateTime.intersect(variable->dateTime())) {
391
399
392 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
400 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
393 variable->dataSeries(), variable->dateTime());
401 variable->dataSeries(), variable->dateTime());
394 }
402 }
395 }
403 }
396 }
404 }
397
405
398 VisualizationGraphWidgetZoomType
406 VisualizationGraphWidgetZoomType
399 VisualizationGraphWidget::VisualizationGraphWidgetPrivate::getZoomType(const QCPRange &t1,
407 VisualizationGraphWidget::VisualizationGraphWidgetPrivate::getZoomType(const QCPRange &t1,
400 const QCPRange &t2)
408 const QCPRange &t2)
401 {
409 {
402 // t1.lower <= t2.lower && t2.upper <= t1.upper
410 // t1.lower <= t2.lower && t2.upper <= t1.upper
403 auto zoomType = VisualizationGraphWidgetZoomType::Unknown;
411 auto zoomType = VisualizationGraphWidgetZoomType::Unknown;
404 if (t1.lower <= t2.lower && t2.upper <= t1.upper) {
412 if (t1.lower <= t2.lower && t2.upper <= t1.upper) {
405 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
413 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
406 }
414 }
407 else if (t1.lower > t2.lower && t1.upper > t2.upper) {
415 else if (t1.lower > t2.lower && t1.upper > t2.upper) {
408 zoomType = VisualizationGraphWidgetZoomType::PanRight;
416 zoomType = VisualizationGraphWidgetZoomType::PanRight;
409 }
417 }
410 else if (t1.lower < t2.lower && t1.upper < t2.upper) {
418 else if (t1.lower < t2.lower && t1.upper < t2.upper) {
411 zoomType = VisualizationGraphWidgetZoomType::PanLeft;
419 zoomType = VisualizationGraphWidgetZoomType::PanLeft;
412 }
420 }
413 else if (t1.lower > t2.lower && t2.upper > t1.upper) {
421 else if (t1.lower > t2.lower && t2.upper > t1.upper) {
414 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
422 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
415 }
423 }
416 else {
424 else {
417 qCCritical(LOG_VisualizationGraphWidget()) << "getZoomType: Unknown type detected";
425 qCCritical(LOG_VisualizationGraphWidget()) << "getZoomType: Unknown type detected";
418 }
426 }
419 return zoomType;
427 return zoomType;
420 }
428 }
General Comments 0
You need to be logged in to leave comments. Login now