##// END OF EJS Templates
perrinel -
r223:10a45fa60519 merge
parent child
Show More
@@ -1,166 +1,165
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/GraphPlottablesFactory.h"
2 #include "Visualization/GraphPlottablesFactory.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "ui_VisualizationGraphWidget.h"
4 #include "ui_VisualizationGraphWidget.h"
5
5
6 #include <Data/ArrayData.h>
6 #include <Data/ArrayData.h>
7 #include <Data/IDataSeries.h>
7 #include <Data/IDataSeries.h>
8 #include <SqpApplication.h>
8 #include <SqpApplication.h>
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
11
11
12 #include <unordered_map>
12 #include <unordered_map>
13
13
14 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
14 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
15
15
16 namespace {
16 namespace {
17
17
18 /// Key pressed to enable zoom on horizontal axis
18 /// Key pressed to enable zoom on horizontal axis
19 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
19 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
20
20
21 /// Key pressed to enable zoom on vertical axis
21 /// Key pressed to enable zoom on vertical axis
22 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
22 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
23
23
24 } // namespace
24 } // namespace
25
25
26 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
26 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
27
27
28 // 1 variable -> n qcpplot
28 // 1 variable -> n qcpplot
29 std::unordered_multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *>
29 std::unordered_multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *>
30 m_VariableToPlotMultiMap;
30 m_VariableToPlotMultiMap;
31 };
31 };
32
32
33 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
33 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
34 : QWidget{parent},
34 : QWidget{parent},
35 ui{new Ui::VisualizationGraphWidget},
35 ui{new Ui::VisualizationGraphWidget},
36 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
36 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
37 {
37 {
38 ui->setupUi(this);
38 ui->setupUi(this);
39
39
40 // qcpplot title
40 // qcpplot title
41 ui->widget->plotLayout()->insertRow(0);
41 ui->widget->plotLayout()->insertRow(0);
42 ui->widget->plotLayout()->addElement(0, 0, new QCPTextElement{ui->widget, name});
42 ui->widget->plotLayout()->addElement(0, 0, new QCPTextElement{ui->widget, name});
43
43
44 // Set qcpplot properties :
44 // Set qcpplot properties :
45 // - Drag (on x-axis) and zoom are enabled
45 // - Drag (on x-axis) and zoom are enabled
46 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
46 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
47 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
47 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
48 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
48 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
49 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
49 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
50 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
50 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
51 &QCPAxis::rangeChanged),
51 &QCPAxis::rangeChanged),
52 this, &VisualizationGraphWidget::onRangeChanged);
52 this, &VisualizationGraphWidget::onRangeChanged);
53 }
53 }
54
54
55
55
56 VisualizationGraphWidget::~VisualizationGraphWidget()
56 VisualizationGraphWidget::~VisualizationGraphWidget()
57 {
57 {
58 delete ui;
58 delete ui;
59 }
59 }
60
60
61 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
61 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
62 {
62 {
63 // Uses delegate to create the qcpplot components according to the variable
63 // Uses delegate to create the qcpplot components according to the variable
64 auto createdPlottables = GraphPlottablesFactory::create(variable, *ui->widget);
64 auto createdPlottables = GraphPlottablesFactory::create(variable, *ui->widget);
65
65
66 for (auto createdPlottable : qAsConst(createdPlottables)) {
66 for (auto createdPlottable : qAsConst(createdPlottables)) {
67 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
67 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
68 }
68 }
69
69
70 connect(variable.get(), &Variable::dataCacheUpdated, this,
70 connect(variable.get(), SIGNAL(dataCacheUpdated()), this, SLOT(onDataCacheVariableUpdated()));
71 &VisualizationGraphWidget::onDataCacheVariableUpdated);
72 }
71 }
73
72
74 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
73 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
75 {
74 {
76 if (visitor) {
75 if (visitor) {
77 visitor->visit(this);
76 visitor->visit(this);
78 }
77 }
79 else {
78 else {
80 qCCritical(LOG_VisualizationGraphWidget())
79 qCCritical(LOG_VisualizationGraphWidget())
81 << tr("Can't visit widget : the visitor is null");
80 << tr("Can't visit widget : the visitor is null");
82 }
81 }
83 }
82 }
84
83
85 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
84 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
86 {
85 {
87 /// @todo : for the moment, a graph can always accomodate a variable
86 /// @todo : for the moment, a graph can always accomodate a variable
88 Q_UNUSED(variable);
87 Q_UNUSED(variable);
89 return true;
88 return true;
90 }
89 }
91
90
92 void VisualizationGraphWidget::close()
91 void VisualizationGraphWidget::close()
93 {
92 {
94 // The main view cannot be directly closed.
93 // The main view cannot be directly closed.
95 return;
94 return;
96 }
95 }
97
96
98 QString VisualizationGraphWidget::name() const
97 QString VisualizationGraphWidget::name() const
99 {
98 {
100 if (auto title = dynamic_cast<QCPTextElement *>(ui->widget->plotLayout()->elementAt(0))) {
99 if (auto title = dynamic_cast<QCPTextElement *>(ui->widget->plotLayout()->elementAt(0))) {
101 return title->text();
100 return title->text();
102 }
101 }
103 else {
102 else {
104 return QString{};
103 return QString{};
105 }
104 }
106 }
105 }
107
106
108 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
107 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
109 {
108 {
110
109
111 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged");
110 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged");
112
111
113 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
112 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
114 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
113 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
115 auto variable = it->first;
114 auto variable = it->first;
116 auto tolerance = 0.1 * (t2.upper - t2.lower);
115 auto tolerance = 0.1 * (t2.upper - t2.lower);
117 auto dateTime = SqpDateTime{t2.lower - tolerance, t2.upper + tolerance};
116 auto dateTime = SqpDateTime{t2.lower - tolerance, t2.upper + tolerance};
118
117
119 qCInfo(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
118 qCInfo(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
120 << variable->dataSeries()->xAxisData()->size();
119 << variable->dataSeries()->xAxisData()->size();
121 if (!variable->contains(dateTime)) {
120 if (!variable->contains(dateTime)) {
122 sqpApp->variableController().requestDataLoading(variable, dateTime);
121 sqpApp->variableController().requestDataLoading(variable, dateTime);
123 }
122 }
124 }
123 }
125 }
124 }
126
125
127 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
126 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
128 {
127 {
129 auto zoomOrientations = QFlags<Qt::Orientation>{};
128 auto zoomOrientations = QFlags<Qt::Orientation>{};
130
129
131 // Lambda that enables a zoom orientation if the key modifier related to this orientation has
130 // Lambda that enables a zoom orientation if the key modifier related to this orientation has
132 // been pressed
131 // been pressed
133 auto enableOrientation
132 auto enableOrientation
134 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
133 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
135 auto orientationEnabled = event->modifiers().testFlag(modifier);
134 auto orientationEnabled = event->modifiers().testFlag(modifier);
136 zoomOrientations.setFlag(orientation, orientationEnabled);
135 zoomOrientations.setFlag(orientation, orientationEnabled);
137 };
136 };
138 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
137 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
139 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
138 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
140
139
141 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
140 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
142 }
141 }
143
142
144 void VisualizationGraphWidget::onDataCacheVariableUpdated()
143 void VisualizationGraphWidget::onDataCacheVariableUpdated()
145 {
144 {
146 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
145 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
147 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
146 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
148 auto variable = it->first;
147 auto variable = it->first;
149 GraphPlottablesFactory::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
148 GraphPlottablesFactory::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
150 variable->dataSeries(), variable->dateTime());
149 variable->dataSeries(), variable->dateTime());
151 }
150 }
152 }
151 }
153
152
154 void VisualizationGraphWidget::updateDisplay(std::shared_ptr<Variable> variable)
153 void VisualizationGraphWidget::updateDisplay(std::shared_ptr<Variable> variable)
155 {
154 {
156 auto abstractPlotableItPair = impl->m_VariableToPlotMultiMap.equal_range(variable);
155 auto abstractPlotableItPair = impl->m_VariableToPlotMultiMap.equal_range(variable);
157
156
158 auto abstractPlotableVect = QVector<QCPAbstractPlottable *>{};
157 auto abstractPlotableVect = QVector<QCPAbstractPlottable *>{};
159
158
160 for (auto it = abstractPlotableItPair.first; it != abstractPlotableItPair.second; ++it) {
159 for (auto it = abstractPlotableItPair.first; it != abstractPlotableItPair.second; ++it) {
161 abstractPlotableVect.push_back(it->second);
160 abstractPlotableVect.push_back(it->second);
162 }
161 }
163
162
164 GraphPlottablesFactory::updateData(abstractPlotableVect, variable->dataSeries(),
163 GraphPlottablesFactory::updateData(abstractPlotableVect, variable->dataSeries(),
165 variable->dateTime());
164 variable->dateTime());
166 }
165 }
@@ -1,71 +1,71
1 #include "CosinusProvider.h"
1 #include "CosinusProvider.h"
2
2
3 #include <Data/DataProviderParameters.h>
3 #include <Data/DataProviderParameters.h>
4 #include <Data/ScalarSeries.h>
4 #include <Data/ScalarSeries.h>
5
5
6 #include <cmath>
6 #include <cmath>
7
7
8 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
8 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
9
9
10 std::unique_ptr<IDataSeries>
10 std::unique_ptr<IDataSeries>
11 CosinusProvider::retrieveData(const DataProviderParameters &parameters) const
11 CosinusProvider::retrieveData(const DataProviderParameters &parameters) const
12 {
12 {
13 auto dateTime = parameters.m_Time;
13 auto dateTime = parameters.m_Time;
14
14
15 // Gets the timerange from the parameters
15 // Gets the timerange from the parameters
16 auto start = dateTime.m_TStart;
16 auto start = dateTime.m_TStart;
17 auto end = dateTime.m_TEnd;
17 auto end = dateTime.m_TEnd;
18
18
19 // We assure that timerange is valid
19 // We assure that timerange is valid
20 if (end < start) {
20 if (end < start) {
21 std::swap(start, end);
21 std::swap(start, end);
22 }
22 }
23
23
24 // Generates scalar series containing cosinus values (one value per second)
24 // Generates scalar series containing cosinus values (one value per second)
25 auto scalarSeries
25 auto scalarSeries
26 = std::make_unique<ScalarSeries>(end - start, Unit{QStringLiteral("t"), true}, Unit{});
26 = std::make_unique<ScalarSeries>(end - start, Unit{QStringLiteral("t"), true}, Unit{});
27
27
28 auto dataIndex = 0;
28 auto dataIndex = 0;
29 for (auto time = start; time < end; ++time, ++dataIndex) {
29 for (auto time = start; time < end; ++time, ++dataIndex) {
30 scalarSeries->setData(dataIndex, time, std::cos(time));
30 scalarSeries->setData(dataIndex, time, std::cos(time));
31 }
31 }
32
32
33 return scalarSeries;
33 return scalarSeries;
34 }
34 }
35
35
36 void CosinusProvider::requestDataLoading(const QVector<SqpDateTime> &dateTimeList)
36 void CosinusProvider::requestDataLoading(const QVector<SqpDateTime> &dateTimeList)
37 {
37 {
38 // NOTE: Try to use multithread if possible
38 // NOTE: Try to use multithread if possible
39 foreach (const auto &dateTime, dateTimeList) {
39 foreach (const auto &dateTime, dateTimeList) {
40
40
41 auto scalarSeries = this->retrieveDataSeries(dateTime);
41 auto scalarSeries = this->retrieveDataSeries(dateTime);
42
42
43 emit dataProvided(scalarSeries, dateTime);
43 emit dataProvided(scalarSeries, dateTime);
44 }
44 }
45 }
45 }
46
46
47
47
48 std::shared_ptr<IDataSeries> retrieveDataSeries(const SqpDateTime &dateTime)
48 std::shared_ptr<IDataSeries> CosinusProvider::retrieveDataSeries(const SqpDateTime &dateTime)
49 {
49 {
50
50
51 // Gets the timerange from the parameters
51 // Gets the timerange from the parameters
52 auto start = dateTime.m_TStart;
52 auto start = dateTime.m_TStart;
53 auto end = dateTime.m_TEnd;
53 auto end = dateTime.m_TEnd;
54
54
55 // We assure that timerange is valid
55 // We assure that timerange is valid
56 if (end < start) {
56 if (end < start) {
57 std::swap(start, end);
57 std::swap(start, end);
58 }
58 }
59
59
60 // Generates scalar series containing cosinus values (one value per second)
60 // Generates scalar series containing cosinus values (one value per second)
61 auto scalarSeries
61 auto scalarSeries
62 = std::make_shared<ScalarSeries>(end - start, Unit{QStringLiteral("t"), true}, Unit{});
62 = std::make_shared<ScalarSeries>(end - start, Unit{QStringLiteral("t"), true}, Unit{});
63
63
64 auto dataIndex = 0;
64 auto dataIndex = 0;
65 for (auto time = start; time < end; ++time, ++dataIndex) {
65 for (auto time = start; time < end; ++time, ++dataIndex) {
66 scalarSeries->setData(dataIndex, time, std::cos(time));
66 scalarSeries->setData(dataIndex, time, std::cos(time));
67 }
67 }
68
68
69
69
70 return scalarSeries;
70 return scalarSeries;
71 }
71 }
General Comments 0
You need to be logged in to leave comments. Login now