##// END OF EJS Templates
The cache is now updated only if date requested has been successfully...
perrinel -
r293:fc4b2122dbde
parent child
Show More
@@ -1,44 +1,44
1 #ifndef SCIQLOP_SQPDATETIME_H
1 #ifndef SCIQLOP_SQPDATETIME_H
2 #define SCIQLOP_SQPDATETIME_H
2 #define SCIQLOP_SQPDATETIME_H
3
3
4 #include <QObject>
4 #include <QObject>
5
5
6 #include <QDateTime>
6 #include <QDateTime>
7 #include <QDebug>
7 #include <QDebug>
8
8
9 #include <Common/MetaTypes.h>
9 #include <Common/MetaTypes.h>
10
10
11 /**
11 /**
12 * @brief The SqpDateTime struct holds the information of time parameters
12 * @brief The SqpDateTime struct holds the information of time parameters
13 */
13 */
14 struct SqpDateTime {
14 struct SqpDateTime {
15 /// Start time
15 /// Start time
16 double m_TStart;
16 double m_TStart;
17 /// End time
17 /// End time
18 double m_TEnd;
18 double m_TEnd;
19
19
20 bool contains(const SqpDateTime &dateTime)
20 bool contains(const SqpDateTime &dateTime) const noexcept
21 {
21 {
22 return (m_TStart <= dateTime.m_TStart && m_TEnd >= dateTime.m_TEnd);
22 return (m_TStart <= dateTime.m_TStart && m_TEnd >= dateTime.m_TEnd);
23 }
23 }
24
24
25 bool intersect(const SqpDateTime &dateTime)
25 bool intersect(const SqpDateTime &dateTime) const noexcept
26 {
26 {
27 return (m_TEnd >= dateTime.m_TStart && m_TStart <= dateTime.m_TEnd);
27 return (m_TEnd >= dateTime.m_TStart && m_TStart <= dateTime.m_TEnd);
28 }
28 }
29 };
29 };
30
30
31 inline QDebug operator<<(QDebug d, SqpDateTime obj)
31 inline QDebug operator<<(QDebug d, SqpDateTime obj)
32 {
32 {
33 auto tendDateTimeStart = QDateTime::fromMSecsSinceEpoch(obj.m_TStart * 1000);
33 auto tendDateTimeStart = QDateTime::fromMSecsSinceEpoch(obj.m_TStart * 1000);
34 auto tendDateTimeEnd = QDateTime::fromMSecsSinceEpoch(obj.m_TEnd * 1000);
34 auto tendDateTimeEnd = QDateTime::fromMSecsSinceEpoch(obj.m_TEnd * 1000);
35
35
36 // QDebug << "ts: " << tendDateTimeStart << " te: " << tendDateTimeEnd;
36 // QDebug << "ts: " << tendDateTimeStart << " te: " << tendDateTimeEnd;
37 d << "ts: " << tendDateTimeStart << " te: " << tendDateTimeEnd;
37 d << "ts: " << tendDateTimeStart << " te: " << tendDateTimeEnd;
38 return d;
38 return d;
39 }
39 }
40
40
41 // Required for using shared_ptr in signals/slots
41 // Required for using shared_ptr in signals/slots
42 SCIQLOP_REGISTER_META_TYPE(SQPDATETIME_REGISTRY, SqpDateTime)
42 SCIQLOP_REGISTER_META_TYPE(SQPDATETIME_REGISTRY, SqpDateTime)
43
43
44 #endif // SCIQLOP_SQPDATETIME_H
44 #endif // SCIQLOP_SQPDATETIME_H
@@ -1,54 +1,55
1 #ifndef SCIQLOP_VARIABLE_H
1 #ifndef SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
3
3
4 #include <Data/SqpDateTime.h>
4 #include <Data/SqpDateTime.h>
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QObject>
7 #include <QObject>
8
8
9 #include <Common/MetaTypes.h>
9 #include <Common/MetaTypes.h>
10 #include <Common/spimpl.h>
10 #include <Common/spimpl.h>
11
11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
13
13
14 class IDataSeries;
14 class IDataSeries;
15 class QString;
15 class QString;
16
16
17 /**
17 /**
18 * @brief The Variable class represents a variable in SciQlop.
18 * @brief The Variable class represents a variable in SciQlop.
19 */
19 */
20 class Variable : public QObject {
20 class Variable : public QObject {
21
21
22 Q_OBJECT
22 Q_OBJECT
23
23
24 public:
24 public:
25 explicit Variable(const QString &name, const QString &unit, const QString &mission,
25 explicit Variable(const QString &name, const QString &unit, const QString &mission,
26 const SqpDateTime &dateTime);
26 const SqpDateTime &dateTime);
27
27
28 QString name() const noexcept;
28 QString name() const noexcept;
29 QString mission() const noexcept;
29 QString mission() const noexcept;
30 QString unit() const noexcept;
30 QString unit() const noexcept;
31 SqpDateTime dateTime() const noexcept;
31 SqpDateTime dateTime() const noexcept;
32 void setDateTime(const SqpDateTime &dateTime) noexcept;
32 void setDateTime(const SqpDateTime &dateTime) noexcept;
33
33
34 /// @return the data of the variable, nullptr if there is no data
34 /// @return the data of the variable, nullptr if there is no data
35 IDataSeries *dataSeries() const noexcept;
35 IDataSeries *dataSeries() const noexcept;
36
36
37 bool contains(const SqpDateTime &dateTime);
37 bool contains(const SqpDateTime &dateTime) const noexcept;
38 bool intersect(const SqpDateTime &dateTime);
38 bool intersect(const SqpDateTime &dateTime) const noexcept;
39 bool isInside(const SqpDateTime &dateTime) const noexcept;
39
40
40 public slots:
41 public slots:
41 void setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
42 void setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
42
43
43 signals:
44 signals:
44 void updated();
45 void updated();
45
46
46 private:
47 private:
47 class VariablePrivate;
48 class VariablePrivate;
48 spimpl::unique_impl_ptr<VariablePrivate> impl;
49 spimpl::unique_impl_ptr<VariablePrivate> impl;
49 };
50 };
50
51
51 // Required for using shared_ptr in signals/slots
52 // Required for using shared_ptr in signals/slots
52 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
53 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
53
54
54 #endif // SCIQLOP_VARIABLE_H
55 #endif // SCIQLOP_VARIABLE_H
@@ -1,89 +1,94
1 #include "Variable/Variable.h"
1 #include "Variable/Variable.h"
2
2
3 #include <Data/IDataSeries.h>
3 #include <Data/IDataSeries.h>
4 #include <Data/SqpDateTime.h>
4 #include <Data/SqpDateTime.h>
5
5
6 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
6 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
7
7
8 struct Variable::VariablePrivate {
8 struct Variable::VariablePrivate {
9 explicit VariablePrivate(const QString &name, const QString &unit, const QString &mission,
9 explicit VariablePrivate(const QString &name, const QString &unit, const QString &mission,
10 const SqpDateTime &dateTime)
10 const SqpDateTime &dateTime)
11 : m_Name{name},
11 : m_Name{name},
12 m_Unit{unit},
12 m_Unit{unit},
13 m_Mission{mission},
13 m_Mission{mission},
14 m_DateTime{dateTime},
14 m_DateTime{dateTime},
15 m_DataSeries{nullptr}
15 m_DataSeries{nullptr}
16 {
16 {
17 }
17 }
18
18
19 QString m_Name;
19 QString m_Name;
20 QString m_Unit;
20 QString m_Unit;
21 QString m_Mission;
21 QString m_Mission;
22
22
23 SqpDateTime m_DateTime; // The dateTime available in the view and loaded. not the cache.
23 SqpDateTime m_DateTime; // The dateTime available in the view and loaded. not the cache.
24 std::unique_ptr<IDataSeries> m_DataSeries;
24 std::unique_ptr<IDataSeries> m_DataSeries;
25 };
25 };
26
26
27 Variable::Variable(const QString &name, const QString &unit, const QString &mission,
27 Variable::Variable(const QString &name, const QString &unit, const QString &mission,
28 const SqpDateTime &dateTime)
28 const SqpDateTime &dateTime)
29 : impl{spimpl::make_unique_impl<VariablePrivate>(name, unit, mission, dateTime)}
29 : impl{spimpl::make_unique_impl<VariablePrivate>(name, unit, mission, dateTime)}
30 {
30 {
31 }
31 }
32
32
33 QString Variable::name() const noexcept
33 QString Variable::name() const noexcept
34 {
34 {
35 return impl->m_Name;
35 return impl->m_Name;
36 }
36 }
37
37
38 QString Variable::mission() const noexcept
38 QString Variable::mission() const noexcept
39 {
39 {
40 return impl->m_Mission;
40 return impl->m_Mission;
41 }
41 }
42
42
43 QString Variable::unit() const noexcept
43 QString Variable::unit() const noexcept
44 {
44 {
45 return impl->m_Unit;
45 return impl->m_Unit;
46 }
46 }
47
47
48 SqpDateTime Variable::dateTime() const noexcept
48 SqpDateTime Variable::dateTime() const noexcept
49 {
49 {
50 return impl->m_DateTime;
50 return impl->m_DateTime;
51 }
51 }
52
52
53 void Variable::setDateTime(const SqpDateTime &dateTime) noexcept
53 void Variable::setDateTime(const SqpDateTime &dateTime) noexcept
54 {
54 {
55 impl->m_DateTime = dateTime;
55 impl->m_DateTime = dateTime;
56 }
56 }
57
57
58 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
58 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
59 {
59 {
60 if (!dataSeries) {
60 if (!dataSeries) {
61 /// @todo ALX : log
61 /// @todo ALX : log
62 return;
62 return;
63 }
63 }
64
64
65 // Inits the data series of the variable
65 // Inits the data series of the variable
66 if (!impl->m_DataSeries) {
66 if (!impl->m_DataSeries) {
67 impl->m_DataSeries = dataSeries->clone();
67 impl->m_DataSeries = dataSeries->clone();
68 }
68 }
69 else {
69 else {
70 impl->m_DataSeries->merge(dataSeries.get());
70 impl->m_DataSeries->merge(dataSeries.get());
71
71
72 emit updated();
72 emit updated();
73 }
73 }
74 }
74 }
75
75
76 IDataSeries *Variable::dataSeries() const noexcept
76 IDataSeries *Variable::dataSeries() const noexcept
77 {
77 {
78 return impl->m_DataSeries.get();
78 return impl->m_DataSeries.get();
79 }
79 }
80
80
81 bool Variable::contains(const SqpDateTime &dateTime)
81 bool Variable::contains(const SqpDateTime &dateTime) const noexcept
82 {
82 {
83 return impl->m_DateTime.contains(dateTime);
83 return impl->m_DateTime.contains(dateTime);
84 }
84 }
85
85
86 bool Variable::intersect(const SqpDateTime &dateTime)
86 bool Variable::intersect(const SqpDateTime &dateTime) const noexcept
87 {
87 {
88 return impl->m_DateTime.intersect(dateTime);
88 return impl->m_DateTime.intersect(dateTime);
89 }
89 }
90
91 bool Variable::isInside(const SqpDateTime &dateTime) const noexcept
92 {
93 return dateTime.contains(SqpDateTime{impl->m_DateTime.m_TStart, impl->m_DateTime.m_TEnd});
94 }
@@ -1,175 +1,181
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableCacheController.h>
2 #include <Variable/VariableCacheController.h>
3 #include <Variable/VariableController.h>
3 #include <Variable/VariableController.h>
4 #include <Variable/VariableModel.h>
4 #include <Variable/VariableModel.h>
5
5
6 #include <Data/DataProviderParameters.h>
6 #include <Data/DataProviderParameters.h>
7 #include <Data/IDataProvider.h>
7 #include <Data/IDataProvider.h>
8 #include <Data/IDataSeries.h>
8 #include <Data/IDataSeries.h>
9 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
10
10
11 #include <QDateTime>
11 #include <QDateTime>
12 #include <QMutex>
12 #include <QMutex>
13 #include <QThread>
13 #include <QThread>
14 #include <QtCore/QItemSelectionModel>
14 #include <QtCore/QItemSelectionModel>
15
15
16 #include <unordered_map>
16 #include <unordered_map>
17
17
18 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
18 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
19
19
20 namespace {
20 namespace {
21
21
22 /// @todo Generates default dataseries, according to the provider passed in parameter. This method
22 /// @todo Generates default dataseries, according to the provider passed in parameter. This method
23 /// will be deleted when the timerange is recovered from SciQlop
23 /// will be deleted when the timerange is recovered from SciQlop
24 std::shared_ptr<IDataSeries> generateDefaultDataSeries(const IDataProvider &provider,
24 std::shared_ptr<IDataSeries> generateDefaultDataSeries(const IDataProvider &provider,
25 const SqpDateTime &dateTime) noexcept
25 const SqpDateTime &dateTime) noexcept
26 {
26 {
27 auto parameters = DataProviderParameters{dateTime};
27 auto parameters = DataProviderParameters{dateTime};
28
28
29 return provider.retrieveData(parameters);
29 return provider.retrieveData(parameters);
30 }
30 }
31
31
32 } // namespace
32 } // namespace
33
33
34 struct VariableController::VariableControllerPrivate {
34 struct VariableController::VariableControllerPrivate {
35 explicit VariableControllerPrivate(VariableController *parent)
35 explicit VariableControllerPrivate(VariableController *parent)
36 : m_WorkingMutex{},
36 : m_WorkingMutex{},
37 m_VariableModel{new VariableModel{parent}},
37 m_VariableModel{new VariableModel{parent}},
38 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
38 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
39 m_VariableCacheController{std::make_unique<VariableCacheController>()}
39 m_VariableCacheController{std::make_unique<VariableCacheController>()}
40 {
40 {
41 }
41 }
42
42
43 QMutex m_WorkingMutex;
43 QMutex m_WorkingMutex;
44 /// Variable model. The VariableController has the ownership
44 /// Variable model. The VariableController has the ownership
45 VariableModel *m_VariableModel;
45 VariableModel *m_VariableModel;
46 QItemSelectionModel *m_VariableSelectionModel;
46 QItemSelectionModel *m_VariableSelectionModel;
47
47
48
48
49 TimeController *m_TimeController{nullptr};
49 TimeController *m_TimeController{nullptr};
50 std::unique_ptr<VariableCacheController> m_VariableCacheController;
50 std::unique_ptr<VariableCacheController> m_VariableCacheController;
51
51
52 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
52 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
53 m_VariableToProviderMap;
53 m_VariableToProviderMap;
54 };
54 };
55
55
56 VariableController::VariableController(QObject *parent)
56 VariableController::VariableController(QObject *parent)
57 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
57 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
58 {
58 {
59 qCDebug(LOG_VariableController()) << tr("VariableController construction")
59 qCDebug(LOG_VariableController()) << tr("VariableController construction")
60 << QThread::currentThread();
60 << QThread::currentThread();
61 }
61 }
62
62
63 VariableController::~VariableController()
63 VariableController::~VariableController()
64 {
64 {
65 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
65 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
66 << QThread::currentThread();
66 << QThread::currentThread();
67 this->waitForFinish();
67 this->waitForFinish();
68 }
68 }
69
69
70 VariableModel *VariableController::variableModel() noexcept
70 VariableModel *VariableController::variableModel() noexcept
71 {
71 {
72 return impl->m_VariableModel;
72 return impl->m_VariableModel;
73 }
73 }
74
74
75 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
75 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
76 {
76 {
77 return impl->m_VariableSelectionModel;
77 return impl->m_VariableSelectionModel;
78 }
78 }
79
79
80 void VariableController::setTimeController(TimeController *timeController) noexcept
80 void VariableController::setTimeController(TimeController *timeController) noexcept
81 {
81 {
82 impl->m_TimeController = timeController;
82 impl->m_TimeController = timeController;
83 }
83 }
84
84
85 void VariableController::createVariable(const QString &name,
85 void VariableController::createVariable(const QString &name,
86 std::shared_ptr<IDataProvider> provider) noexcept
86 std::shared_ptr<IDataProvider> provider) noexcept
87 {
87 {
88
88
89 if (!impl->m_TimeController) {
89 if (!impl->m_TimeController) {
90 qCCritical(LOG_VariableController())
90 qCCritical(LOG_VariableController())
91 << tr("Impossible to create variable: The time controller is null");
91 << tr("Impossible to create variable: The time controller is null");
92 return;
92 return;
93 }
93 }
94
94
95
95
96 /// @todo : for the moment :
96 /// @todo : for the moment :
97 /// - the provider is only used to retrieve data from the variable for its initialization, but
97 /// - the provider is only used to retrieve data from the variable for its initialization, but
98 /// it will be retained later
98 /// it will be retained later
99 /// - default data are generated for the variable, without taking into account the timerange set
99 /// - default data are generated for the variable, without taking into account the timerange set
100 /// in sciqlop
100 /// in sciqlop
101 auto dateTime = impl->m_TimeController->dateTime();
101 auto dateTime = impl->m_TimeController->dateTime();
102 if (auto newVariable = impl->m_VariableModel->createVariable(
102 if (auto newVariable = impl->m_VariableModel->createVariable(
103 name, dateTime, generateDefaultDataSeries(*provider, dateTime))) {
103 name, dateTime, generateDefaultDataSeries(*provider, dateTime))) {
104
104
105 // store the provider
105 // store the provider
106 impl->m_VariableToProviderMap[newVariable] = provider;
106 impl->m_VariableToProviderMap[newVariable] = provider;
107 connect(provider.get(), &IDataProvider::dataProvided, newVariable.get(),
107
108 &Variable::setDataSeries);
108 auto addDateTimeAcquired
109 = [this, newVariable](auto dataSeriesAcquired, auto dateTimeToPutInCache) {
110
111 impl->m_VariableCacheController->addDateTime(newVariable, dateTimeToPutInCache);
112 newVariable->setDataSeries(dataSeriesAcquired);
113
114 };
115
116 connect(provider.get(), &IDataProvider::dataProvided, addDateTimeAcquired);
109
117
110
118
111 // store in cache
119 // store in cache
112 impl->m_VariableCacheController->addDateTime(newVariable, dateTime);
120 impl->m_VariableCacheController->addDateTime(newVariable, dateTime);
113
121
114 // notify the creation
122 // notify the creation
115 emit variableCreated(newVariable);
123 emit variableCreated(newVariable);
116 }
124 }
117 }
125 }
118
126
119 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
127 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
120 {
128 {
121 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
129 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
122
130
123 for (const auto &selectedRow : qAsConst(selectedRows)) {
131 for (const auto &selectedRow : qAsConst(selectedRows)) {
124 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
132 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
125 selectedVariable->setDateTime(dateTime);
133 selectedVariable->setDateTime(dateTime);
126 this->onRequestDataLoading(selectedVariable, dateTime);
134 this->onRequestDataLoading(selectedVariable, dateTime);
127 }
135 }
128 }
136 }
129 }
137 }
130
138
131
139
132 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
140 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
133 const SqpDateTime &dateTime)
141 const SqpDateTime &dateTime)
134 {
142 {
135 // we want to load data of the variable for the dateTime.
143 // we want to load data of the variable for the dateTime.
136 // First we check if the cache contains some of them.
144 // First we check if the cache contains some of them.
137 // For the other, we ask the provider to give them.
145 // For the other, we ask the provider to give them.
138 if (variable) {
146 if (variable) {
139
147
140 auto dateTimeListNotInCache
148 auto dateTimeListNotInCache
141 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
149 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
142
150
143 if (!dateTimeListNotInCache.empty()) {
151 if (!dateTimeListNotInCache.empty()) {
144 // Ask the provider for each data on the dateTimeListNotInCache
152 // Ask the provider for each data on the dateTimeListNotInCache
145 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
153 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
146 std::move(dateTimeListNotInCache));
154 std::move(dateTimeListNotInCache));
147 // store in cache
148 impl->m_VariableCacheController->addDateTime(variable, dateTime);
149 }
155 }
150 else {
156 else {
151 emit variable->updated();
157 emit variable->updated();
152 }
158 }
153 }
159 }
154 else {
160 else {
155 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
161 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
156 }
162 }
157 }
163 }
158
164
159
165
160 void VariableController::initialize()
166 void VariableController::initialize()
161 {
167 {
162 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
168 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
163 impl->m_WorkingMutex.lock();
169 impl->m_WorkingMutex.lock();
164 qCDebug(LOG_VariableController()) << tr("VariableController init END");
170 qCDebug(LOG_VariableController()) << tr("VariableController init END");
165 }
171 }
166
172
167 void VariableController::finalize()
173 void VariableController::finalize()
168 {
174 {
169 impl->m_WorkingMutex.unlock();
175 impl->m_WorkingMutex.unlock();
170 }
176 }
171
177
172 void VariableController::waitForFinish()
178 void VariableController::waitForFinish()
173 {
179 {
174 QMutexLocker locker{&impl->m_WorkingMutex};
180 QMutexLocker locker{&impl->m_WorkingMutex};
175 }
181 }
@@ -1,157 +1,155
1 #include "Visualization/VisualizationGraphHelper.h"
1 #include "Visualization/VisualizationGraphHelper.h"
2 #include "Visualization/qcustomplot.h"
2 #include "Visualization/qcustomplot.h"
3
3
4 #include <Data/ScalarSeries.h>
4 #include <Data/ScalarSeries.h>
5
5
6 #include <Variable/Variable.h>
6 #include <Variable/Variable.h>
7
7
8 #include <QElapsedTimer>
8 #include <QElapsedTimer>
9
9
10 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
10 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
11
11
12 namespace {
12 namespace {
13
13
14 /// Format for datetimes on a axis
14 /// Format for datetimes on a axis
15 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
15 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
16
16
17 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
17 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
18 /// non-time data
18 /// non-time data
19 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
19 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
20 {
20 {
21 if (isTimeAxis) {
21 if (isTimeAxis) {
22 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
22 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
23 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
23 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
24
24
25 return dateTicker;
25 return dateTicker;
26 }
26 }
27 else {
27 else {
28 // default ticker
28 // default ticker
29 return QSharedPointer<QCPAxisTicker>::create();
29 return QSharedPointer<QCPAxisTicker>::create();
30 }
30 }
31 }
31 }
32
32
33 void updateScalarData(QCPAbstractPlottable *component, ScalarSeries &scalarSeries,
33 void updateScalarData(QCPAbstractPlottable *component, ScalarSeries &scalarSeries,
34 const SqpDateTime &dateTime)
34 const SqpDateTime &dateTime)
35 {
35 {
36 QElapsedTimer timer;
36 QElapsedTimer timer;
37 timer.start();
37 timer.start();
38 if (auto qcpGraph = dynamic_cast<QCPGraph *>(component)) {
38 if (auto qcpGraph = dynamic_cast<QCPGraph *>(component)) {
39 // Clean the graph
39 // Clean the graph
40 // NAIVE approch
40 // NAIVE approch
41 const auto &xData = scalarSeries.xAxisData()->data();
41 const auto &xData = scalarSeries.xAxisData()->data();
42 const auto &valuesData = scalarSeries.valuesData()->data();
42 const auto &valuesData = scalarSeries.valuesData()->data();
43 const auto count = xData.count();
43 const auto count = xData.count();
44 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points in cache" << xData.count();
44 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points in cache" << xData.count();
45
46 auto xValue = QVector<double>(count);
45 auto xValue = QVector<double>(count);
47 auto vValue = QVector<double>(count);
46 auto vValue = QVector<double>(count);
48
47
49 int n = 0;
48 int n = 0;
50 for (auto i = 0; i < count; ++i) {
49 for (auto i = 0; i < count; ++i) {
51 const auto x = xData[i];
50 const auto x = xData[i];
52 if (x >= dateTime.m_TStart && x <= dateTime.m_TEnd) {
51 if (x >= dateTime.m_TStart && x <= dateTime.m_TEnd) {
53 xValue[n] = x;
52 xValue[n] = x;
54 vValue[n] = valuesData[i];
53 vValue[n] = valuesData[i];
55 ++n;
54 ++n;
56 }
55 }
57 }
56 }
58
57
59 xValue.resize(n);
58 xValue.resize(n);
60 vValue.resize(n);
59 vValue.resize(n);
61
60
62 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points displayed"
61 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points displayed"
63 << xValue.count();
62 << xValue.count();
64
63
65 qcpGraph->setData(xValue, vValue);
64 qcpGraph->setData(xValue, vValue);
66
65
67 // Display all data
66 // Display all data
68 // component->parentPlot()->xAxis->setRange(dateTime.m_TStart, dateTime.m_TEnd);
69 component->rescaleAxes();
67 component->rescaleAxes();
70 component->parentPlot()->replot();
68 component->parentPlot()->replot();
71 }
69 }
72 else {
70 else {
73 /// @todo DEBUG
71 /// @todo DEBUG
74 }
72 }
75 }
73 }
76
74
77 QCPAbstractPlottable *createScalarSeriesComponent(ScalarSeries &scalarSeries, QCustomPlot &plot,
75 QCPAbstractPlottable *createScalarSeriesComponent(ScalarSeries &scalarSeries, QCustomPlot &plot,
78 const SqpDateTime &dateTime)
76 const SqpDateTime &dateTime)
79 {
77 {
80 auto component = plot.addGraph();
78 auto component = plot.addGraph();
81
79
82 if (component) {
80 if (component) {
83 // // Graph data
81 // // Graph data
84 component->setData(scalarSeries.xAxisData()->data(), scalarSeries.valuesData()->data(),
82 component->setData(scalarSeries.xAxisData()->data(), scalarSeries.valuesData()->data(),
85 true);
83 true);
86
84
87 updateScalarData(component, scalarSeries, dateTime);
85 updateScalarData(component, scalarSeries, dateTime);
88
86
89 // Axes properties
87 // Axes properties
90 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
88 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
91 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
89 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
92
90
93 auto setAxisProperties = [](auto axis, const auto &unit) {
91 auto setAxisProperties = [](auto axis, const auto &unit) {
94 // label (unit name)
92 // label (unit name)
95 axis->setLabel(unit.m_Name);
93 axis->setLabel(unit.m_Name);
96
94
97 // ticker (depending on the type of unit)
95 // ticker (depending on the type of unit)
98 axis->setTicker(axisTicker(unit.m_TimeUnit));
96 axis->setTicker(axisTicker(unit.m_TimeUnit));
99 };
97 };
100 setAxisProperties(plot.xAxis, scalarSeries.xAxisUnit());
98 setAxisProperties(plot.xAxis, scalarSeries.xAxisUnit());
101 setAxisProperties(plot.yAxis, scalarSeries.valuesUnit());
99 setAxisProperties(plot.yAxis, scalarSeries.valuesUnit());
102
100
103 // Display all data
101 // Display all data
104 component->rescaleAxes();
102 component->rescaleAxes();
105 plot.replot();
103 plot.replot();
106 }
104 }
107 else {
105 else {
108 qCDebug(LOG_VisualizationGraphHelper())
106 qCDebug(LOG_VisualizationGraphHelper())
109 << QObject::tr("Can't create graph for the scalar series");
107 << QObject::tr("Can't create graph for the scalar series");
110 }
108 }
111
109
112 return component;
110 return component;
113 }
111 }
114
112
115 } // namespace
113 } // namespace
116
114
117 QVector<QCPAbstractPlottable *> VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
115 QVector<QCPAbstractPlottable *> VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
118 QCustomPlot &plot) noexcept
116 QCustomPlot &plot) noexcept
119 {
117 {
120 auto result = QVector<QCPAbstractPlottable *>{};
118 auto result = QVector<QCPAbstractPlottable *>{};
121
119
122 if (variable) {
120 if (variable) {
123 // Gets the data series of the variable to call the creation of the right components
121 // Gets the data series of the variable to call the creation of the right components
124 // according to its type
122 // according to its type
125 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(variable->dataSeries())) {
123 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(variable->dataSeries())) {
126 result.append(createScalarSeriesComponent(*scalarSeries, plot, variable->dateTime()));
124 result.append(createScalarSeriesComponent(*scalarSeries, plot, variable->dateTime()));
127 }
125 }
128 else {
126 else {
129 qCDebug(LOG_VisualizationGraphHelper())
127 qCDebug(LOG_VisualizationGraphHelper())
130 << QObject::tr("Can't create graph plottables : unmanaged data series type");
128 << QObject::tr("Can't create graph plottables : unmanaged data series type");
131 }
129 }
132 }
130 }
133 else {
131 else {
134 qCDebug(LOG_VisualizationGraphHelper())
132 qCDebug(LOG_VisualizationGraphHelper())
135 << QObject::tr("Can't create graph plottables : the variable is null");
133 << QObject::tr("Can't create graph plottables : the variable is null");
136 }
134 }
137
135
138 return result;
136 return result;
139 }
137 }
140
138
141 void VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *> plotableVect,
139 void VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *> plotableVect,
142 IDataSeries *dataSeries, const SqpDateTime &dateTime)
140 IDataSeries *dataSeries, const SqpDateTime &dateTime)
143 {
141 {
144 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(dataSeries)) {
142 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(dataSeries)) {
145 if (plotableVect.size() == 1) {
143 if (plotableVect.size() == 1) {
146 updateScalarData(plotableVect.at(0), *scalarSeries, dateTime);
144 updateScalarData(plotableVect.at(0), *scalarSeries, dateTime);
147 }
145 }
148 else {
146 else {
149 qCCritical(LOG_VisualizationGraphHelper()) << QObject::tr(
147 qCCritical(LOG_VisualizationGraphHelper()) << QObject::tr(
150 "Can't update Data of a scalarSeries because there is not only one component "
148 "Can't update Data of a scalarSeries because there is not only one component "
151 "associated");
149 "associated");
152 }
150 }
153 }
151 }
154 else {
152 else {
155 /// @todo DEBUG
153 /// @todo DEBUG
156 }
154 }
157 }
155 }
@@ -1,263 +1,273
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 "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::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
29 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
30 };
30 };
31
31
32 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
32 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
33 : QWidget{parent},
33 : QWidget{parent},
34 ui{new Ui::VisualizationGraphWidget},
34 ui{new Ui::VisualizationGraphWidget},
35 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
35 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
36 {
36 {
37 ui->setupUi(this);
37 ui->setupUi(this);
38
38
39 ui->graphNameLabel->setText(name);
39 ui->graphNameLabel->setText(name);
40
40
41 // 'Close' options : widget is deleted when closed
41 // 'Close' options : widget is deleted when closed
42 setAttribute(Qt::WA_DeleteOnClose);
42 setAttribute(Qt::WA_DeleteOnClose);
43 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
43 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
44 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
44 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
45
45
46 // Set qcpplot properties :
46 // Set qcpplot properties :
47 // - Drag (on x-axis) and zoom are enabled
47 // - Drag (on x-axis) and zoom are enabled
48 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
48 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
49 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
49 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
50 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
50 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
51 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
51 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
52 connect(ui->widget->xAxis,
52 connect(ui->widget->xAxis,
53 static_cast<void (QCPAxis::*)(const QCPRange &)>(&QCPAxis::rangeChanged), this,
53 static_cast<void (QCPAxis::*)(const QCPRange &)>(&QCPAxis::rangeChanged), this,
54 &VisualizationGraphWidget::onRangeChanged);
54 &VisualizationGraphWidget::onRangeChanged);
55
55
56 // Activates menu when right clicking on the graph
56 // Activates menu when right clicking on the graph
57 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
57 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
58 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
58 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
59 &VisualizationGraphWidget::onGraphMenuRequested);
59 &VisualizationGraphWidget::onGraphMenuRequested);
60
60
61 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
61 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
62 &VariableController::onRequestDataLoading);
62 &VariableController::onRequestDataLoading);
63 }
63 }
64
64
65
65
66 VisualizationGraphWidget::~VisualizationGraphWidget()
66 VisualizationGraphWidget::~VisualizationGraphWidget()
67 {
67 {
68 delete ui;
68 delete ui;
69 }
69 }
70
70
71 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
71 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
72 {
72 {
73 // Uses delegate to create the qcpplot components according to the variable
73 // Uses delegate to create the qcpplot components according to the variable
74 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
74 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
75
75
76 for (auto createdPlottable : qAsConst(createdPlottables)) {
76 for (auto createdPlottable : qAsConst(createdPlottables)) {
77 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
77 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
78 }
78 }
79
79
80 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
80 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
81 }
81 }
82
82
83 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
83 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
84 {
84 {
85
85
86 // when adding a variable, we need to set its time range to the current graph range
86 // when adding a variable, we need to set its time range to the current graph range
87 auto grapheRange = ui->widget->xAxis->range();
87 auto grapheRange = ui->widget->xAxis->range();
88 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
88 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
89 variable->setDateTime(dateTime);
89 variable->setDateTime(dateTime);
90
90
91 auto variableDateTimeWithTolerance = dateTime;
91 auto variableDateTimeWithTolerance = dateTime;
92
92
93 // add 10% tolerance for each side
93 // add 10% tolerance for each side
94 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
94 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
95 variableDateTimeWithTolerance.m_TStart -= tolerance;
95 variableDateTimeWithTolerance.m_TStart -= tolerance;
96 variableDateTimeWithTolerance.m_TEnd += tolerance;
96 variableDateTimeWithTolerance.m_TEnd += tolerance;
97
97
98 // Uses delegate to create the qcpplot components according to the variable
98 // Uses delegate to create the qcpplot components according to the variable
99 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
99 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
100
100
101 for (auto createdPlottable : qAsConst(createdPlottables)) {
101 for (auto createdPlottable : qAsConst(createdPlottables)) {
102 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
102 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
103 }
103 }
104
104
105 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
105 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
106
106
107 // CHangement detected, we need to ask controller to request data loading
107 // CHangement detected, we need to ask controller to request data loading
108 emit requestDataLoading(variable, variableDateTimeWithTolerance);
108 emit requestDataLoading(variable, variableDateTimeWithTolerance);
109 }
109 }
110
110
111 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
111 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
112 {
112 {
113 // Each component associated to the variable :
113 // Each component associated to the variable :
114 // - is removed from qcpplot (which deletes it)
114 // - is removed from qcpplot (which deletes it)
115 // - is no longer referenced in the map
115 // - is no longer referenced in the map
116 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
116 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
117 for (auto it = componentsIt.first; it != componentsIt.second;) {
117 for (auto it = componentsIt.first; it != componentsIt.second;) {
118 ui->widget->removePlottable(it->second);
118 ui->widget->removePlottable(it->second);
119 it = impl->m_VariableToPlotMultiMap.erase(it);
119 it = impl->m_VariableToPlotMultiMap.erase(it);
120 }
120 }
121
121
122 // Updates graph
122 // Updates graph
123 ui->widget->replot();
123 ui->widget->replot();
124 }
124 }
125
125
126 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
126 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
127 {
127 {
128 if (visitor) {
128 if (visitor) {
129 visitor->visit(this);
129 visitor->visit(this);
130 }
130 }
131 else {
131 else {
132 qCCritical(LOG_VisualizationGraphWidget())
132 qCCritical(LOG_VisualizationGraphWidget())
133 << tr("Can't visit widget : the visitor is null");
133 << tr("Can't visit widget : the visitor is null");
134 }
134 }
135 }
135 }
136
136
137 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
137 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
138 {
138 {
139 /// @todo : for the moment, a graph can always accomodate a variable
139 /// @todo : for the moment, a graph can always accomodate a variable
140 Q_UNUSED(variable);
140 Q_UNUSED(variable);
141 return true;
141 return true;
142 }
142 }
143
143
144 QString VisualizationGraphWidget::name() const
144 QString VisualizationGraphWidget::name() const
145 {
145 {
146 return ui->graphNameLabel->text();
146 return ui->graphNameLabel->text();
147 }
147 }
148
148
149 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
149 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
150 {
150 {
151 QMenu graphMenu{};
151 QMenu graphMenu{};
152
152
153 // Iterates on variables (unique keys)
153 // Iterates on variables (unique keys)
154 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
154 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
155 end = impl->m_VariableToPlotMultiMap.cend();
155 end = impl->m_VariableToPlotMultiMap.cend();
156 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
156 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
157 // 'Remove variable' action
157 // 'Remove variable' action
158 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
158 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
159 [ this, var = it->first ]() { removeVariable(var); });
159 [ this, var = it->first ]() { removeVariable(var); });
160 }
160 }
161
161
162 if (!graphMenu.isEmpty()) {
162 if (!graphMenu.isEmpty()) {
163 graphMenu.exec(mapToGlobal(pos));
163 graphMenu.exec(mapToGlobal(pos));
164 }
164 }
165 }
165 }
166
166
167 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1)
167 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1)
168 {
168 {
169 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged");
169 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged");
170
170
171 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
171 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
172 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
172 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
173
173
174 auto variable = it->first;
174 auto variable = it->first;
175 auto dateTime = SqpDateTime{t1.lower, t1.upper};
175 auto dateTime = SqpDateTime{t1.lower, t1.upper};
176
176
177 if (!variable->contains(dateTime)) {
177 if (!variable->contains(dateTime)) {
178
178
179 auto variableDateTimeWithTolerance = dateTime;
179 auto variableDateTimeWithTolerance = dateTime;
180 if (variable->intersect(dateTime)) {
180 if (!variable->isInside(dateTime)) {
181 auto variableDateTime = variable->dateTime();
181 auto variableDateTime = variable->dateTime();
182 if (variableDateTime.m_TStart < dateTime.m_TStart) {
182 if (variableDateTime.m_TStart < dateTime.m_TStart) {
183 qCDebug(LOG_VisualizationGraphWidget()) << tr("TDetection pan to right:");
183
184
184 auto diffEndToKeepDelta = dateTime.m_TEnd - variableDateTime.m_TEnd;
185 auto diffEndToKeepDelta = dateTime.m_TEnd - variableDateTime.m_TEnd;
185 dateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
186 dateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
186 // Tolerance have to be added to the right
187 // Tolerance have to be added to the right
187 // add 10% tolerance for right (end) side
188 // add 10% tolerance for right (end) side
188 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
189 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
189 variableDateTimeWithTolerance.m_TEnd += tolerance;
190 variableDateTimeWithTolerance.m_TEnd += tolerance;
190 }
191 }
191 if (variableDateTime.m_TEnd > dateTime.m_TEnd) {
192 else if (variableDateTime.m_TEnd > dateTime.m_TEnd) {
193 qCDebug(LOG_VisualizationGraphWidget()) << tr("Detection pan to left: ");
192 auto diffStartToKeepDelta = variableDateTime.m_TStart - dateTime.m_TStart;
194 auto diffStartToKeepDelta = variableDateTime.m_TStart - dateTime.m_TStart;
193 dateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
195 dateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
194 // Tolerance have to be added to the left
196 // Tolerance have to be added to the left
195 // add 10% tolerance for left (start) side
197 // add 10% tolerance for left (start) side
196 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
198 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
197 variableDateTimeWithTolerance.m_TStart -= tolerance;
199 variableDateTimeWithTolerance.m_TStart -= tolerance;
198 }
200 }
201 else {
202 qCWarning(LOG_VisualizationGraphWidget())
203 << tr("Detection anormal zoom detection: ");
204 }
199 }
205 }
200 else {
206 else {
207 qCDebug(LOG_VisualizationGraphWidget()) << tr("Detection zoom out: ");
201 // add 10% tolerance for each side
208 // add 10% tolerance for each side
202 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
209 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
203 variableDateTimeWithTolerance.m_TStart -= tolerance;
210 variableDateTimeWithTolerance.m_TStart -= tolerance;
204 variableDateTimeWithTolerance.m_TEnd += tolerance;
211 variableDateTimeWithTolerance.m_TEnd += tolerance;
205 }
212 }
206 variable->setDateTime(dateTime);
213 variable->setDateTime(dateTime);
207
214
208 // CHangement detected, we need to ask controller to request data loading
215 // CHangement detected, we need to ask controller to request data loading
209 emit requestDataLoading(variable, variableDateTimeWithTolerance);
216 emit requestDataLoading(variable, variableDateTimeWithTolerance);
210 }
217 }
218 else {
219 qCDebug(LOG_VisualizationGraphWidget()) << tr("Detection zoom in: ");
220 }
211 }
221 }
212 }
222 }
213
223
214 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
224 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
215 {
225 {
216 auto zoomOrientations = QFlags<Qt::Orientation>{};
226 auto zoomOrientations = QFlags<Qt::Orientation>{};
217
227
218 // Lambda that enables a zoom orientation if the key modifier related to this orientation
228 // Lambda that enables a zoom orientation if the key modifier related to this orientation
219 // has
229 // has
220 // been pressed
230 // been pressed
221 auto enableOrientation
231 auto enableOrientation
222 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
232 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
223 auto orientationEnabled = event->modifiers().testFlag(modifier);
233 auto orientationEnabled = event->modifiers().testFlag(modifier);
224 zoomOrientations.setFlag(orientation, orientationEnabled);
234 zoomOrientations.setFlag(orientation, orientationEnabled);
225 };
235 };
226 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
236 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
227 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
237 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
228
238
229 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
239 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
230 }
240 }
231
241
232 void VisualizationGraphWidget::onDataCacheVariableUpdated()
242 void VisualizationGraphWidget::onDataCacheVariableUpdated()
233 {
243 {
234 // NOTE:
244 // NOTE:
235 // We don't want to call the method for each component of a variable unitarily, but for
245 // We don't want to call the method for each component of a variable unitarily, but for
236 // all
246 // all
237 // its components at once (eg its three components in the case of a vector).
247 // its components at once (eg its three components in the case of a vector).
238
248
239 // The unordered_multimap does not do this easily, so the question is whether to:
249 // The unordered_multimap does not do this easily, so the question is whether to:
240 // - use an ordered_multimap and the algos of std to group the values by key
250 // - use an ordered_multimap and the algos of std to group the values by key
241 // - use a map (unique keys) and store as values directly the list of components
251 // - use a map (unique keys) and store as values directly the list of components
242
252
243 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
253 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
244 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
254 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
245 auto variable = it->first;
255 auto variable = it->first;
246 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
256 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
247 variable->dataSeries(), variable->dateTime());
257 variable->dataSeries(), variable->dateTime());
248 }
258 }
249 }
259 }
250
260
251 void VisualizationGraphWidget::updateDisplay(std::shared_ptr<Variable> variable)
261 void VisualizationGraphWidget::updateDisplay(std::shared_ptr<Variable> variable)
252 {
262 {
253 auto abstractPlotableItPair = impl->m_VariableToPlotMultiMap.equal_range(variable);
263 auto abstractPlotableItPair = impl->m_VariableToPlotMultiMap.equal_range(variable);
254
264
255 auto abstractPlotableVect = QVector<QCPAbstractPlottable *>{};
265 auto abstractPlotableVect = QVector<QCPAbstractPlottable *>{};
256
266
257 for (auto it = abstractPlotableItPair.first; it != abstractPlotableItPair.second; ++it) {
267 for (auto it = abstractPlotableItPair.first; it != abstractPlotableItPair.second; ++it) {
258 abstractPlotableVect.push_back(it->second);
268 abstractPlotableVect.push_back(it->second);
259 }
269 }
260
270
261 VisualizationGraphHelper::updateData(abstractPlotableVect, variable->dataSeries(),
271 VisualizationGraphHelper::updateData(abstractPlotableVect, variable->dataSeries(),
262 variable->dateTime());
272 variable->dateTime());
263 }
273 }
General Comments 2
Under Review
author

Pull request updated. Auto status change to "Under Review"

Changed commits:
  * 3 added
  * 0 removed

Changed files:
  * M core/include/Data/SqpDateTime.h
  * M core/include/Variable/Variable.h
  * M core/include/Variable/VariableModel.h
  * M core/src/Variable/Variable.cpp
  * M core/src/Variable/VariableCacheController.cpp
  * M core/src/Variable/VariableController.cpp
  * M core/src/Variable/VariableModel.cpp
  * M gui/include/Visualization/VisualizationGraphWidget.h
  * M gui/src/Visualization/VisualizationGraphHelper.cpp
  * M gui/src/Visualization/VisualizationGraphWidget.cpp
  * M gui/src/Visualization/operations/GenerateVariableMenuOperation.cpp
  * R COPYING
  * R app/src/MainWindow.cpp
  * R app/ui/MainWindow.ui
  * R cmake/sciqlop_package_qt.cmake
  * R core/include/Common/MetaTypes.h
  * R core/include/Data/ArrayData.h
  * R core/include/Data/DataProviderParameters.h
  * R core/include/Data/DataSeries.h
  * R core/include/Data/IDataProvider.h
  * R core/include/Data/IDataSeries.h
  * R core/include/Data/ScalarSeries.h
  * R core/include/DataSource/DataSourceItemAction.h
  * R core/include/Plugin/PluginManager.h
  * R core/include/Time/TimeController.h
  * R core/include/Variable/VariableCacheController.h
  * R core/include/Variable/VariableController.h
  * R core/include/Visualization/VisualizationController.h
  * R core/src/Data/ScalarSeries.cpp
  * R core/src/DataSource/DataSourceItemAction.cpp
  * R core/src/Plugin/PluginManager.cpp
  * R core/src/Time/TimeController.cpp
  * R core/src/Visualization/VisualizationController.cpp
  * R core/tests/Variable/TestVariableCacheController.cpp
  * R gui/include/DataSource/DataSourceTreeWidgetItem.h
  * R gui/include/DataSource/DataSourceWidget.h
  * R gui/include/SidePane/SqpSidePane.h
  * R gui/include/TimeWidget/TimeWidget.h
  * R gui/include/Variable/VariableInspectorWidget.h
  * R gui/include/Variable/VariableMenuHeaderWidget.h
  * R gui/include/Visualization/IVariableContainer.h
  * R gui/include/Visualization/IVisualizationWidget.h
  * R gui/include/Visualization/IVisualizationWidgetVisitor.h
  * R gui/include/Visualization/VisualizationGraphHelper.h
  * R gui/include/Visualization/VisualizationTabWidget.h
  * R gui/include/Visualization/VisualizationWidget.h
  * R gui/include/Visualization/VisualizationZoneWidget.h
  * R gui/include/Visualization/operations/GenerateVariableMenuOperation.h
  * R gui/include/Visualization/operations/MenuBuilder.h
  * R gui/include/Visualization/qcustomplot.h
  * R gui/resources/icones/delete.png
  * R gui/resources/icones/next.png
  * R gui/resources/icones/openInspector.png
  * R gui/resources/icones/previous.png
  * R gui/resources/icones/sciqlop2PNG_1024.png
  * R gui/resources/sqpguiresources.qrc
  * R gui/src/DataSource/DataSourceTreeWidgetItem.cpp
  * R gui/src/DataSource/DataSourceWidget.cpp
  * R gui/src/SidePane/SqpSidePane.cpp
  * R gui/src/TimeWidget/TimeWidget.cpp
  * R gui/src/Variable/VariableInspectorWidget.cpp
  * R gui/src/Variable/VariableMenuHeaderWidget.cpp
  * R gui/src/Visualization/VisualizationTabWidget.cpp
  * R gui/src/Visualization/VisualizationWidget.cpp
  * R gui/src/Visualization/VisualizationZoneWidget.cpp
  * R gui/src/Visualization/operations/MenuBuilder.cpp
  * R gui/src/Visualization/qcustomplot.cpp
  * R gui/ui/DataSource/DataSourceWidget.ui
  * R gui/ui/SidePane/SqpSidePane.ui
  * R gui/ui/TimeWidget/TimeWidget.ui
  * R gui/ui/Variable/VariableInspectorWidget.ui
  * R gui/ui/Variable/VariableMenuHeaderWidget.ui
  * R gui/ui/Visualization/VisualizationGraphWidget.ui
  * R gui/ui/Visualization/VisualizationTabWidget.ui
  * R gui/ui/Visualization/VisualizationWidget.ui
  * R gui/ui/Visualization/VisualizationZoneWidget.ui
  * R gui/vera-exclusions/exclusions.txt
  * R plugin/CMakeLists.txt
  * R plugin/cmake/Findsciqlop-plugin.cmake
  * R plugin/include/Plugin/IPlugin.h
  * R plugins/mockplugin/CMakeLists.txt
  * R plugins/mockplugin/cmake/Findsciqlop-mockplugin.cmake
  * R plugins/mockplugin/include/CosinusProvider.h
  * R plugins/mockplugin/include/MockPlugin.h
  * R plugins/mockplugin/resources/mockplugin.json
  * R plugins/mockplugin/src/CosinusProvider.cpp
  * R plugins/mockplugin/src/MockPlugin.cpp
  * R README.md
  * R app/CMakeLists.txt
  * R app/include/MainWindow.h
  * R app/src/Main.cpp
  * R app/vera-exclusions/exclusions.txt
  * R cmake/sciqlop.cmake
  * R cmake/sciqlop_applications.cmake
  * R cmake/sciqlop_package.cmake
  * R cmake/sciqlop_params.cmake
  * R core/CMakeLists.txt
  * R core/include/Common/spimpl.h
  * R core/include/DataSource/DataSourceController.h
  * R core/include/DataSource/DataSourceItem.h
  * R core/src/DataSource/DataSourceController.cpp
  * R core/src/DataSource/DataSourceItem.cpp
  * R core/tests/DataSource/TestDataSourceController.cpp
  * R core/vera-exclusions/exclusions.txt
  * R formatting/cmake/use_clangformat.cmake
  * R formatting/vera-exclusions/exclusions.txt
  * R gui/CMakeLists.txt
  * R gui/include/SqpApplication.h
  * R gui/src/SqpApplication.cpp
  * R LICENSE
  * R app/src/mainwindow.cpp
  * R app/src/mainwindow.ui
You need to be logged in to leave comments. Login now