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