@@ -1,8 +1,9 | |||||
1 | #ifndef SCIQLOP_ARRAYDATA_H |
|
1 | #ifndef SCIQLOP_ARRAYDATA_H | |
2 | #define SCIQLOP_ARRAYDATA_H |
|
2 | #define SCIQLOP_ARRAYDATA_H | |
3 |
|
3 | |||
|
4 | #include <QReadLocker> | |||
|
5 | #include <QReadWriteLock> | |||
4 | #include <QVector> |
|
6 | #include <QVector> | |
5 |
|
||||
6 | /** |
|
7 | /** | |
7 | * @brief The ArrayData class represents a dataset for a data series. |
|
8 | * @brief The ArrayData class represents a dataset for a data series. | |
8 | * |
|
9 | * | |
@@ -22,10 +23,22 public: | |||||
22 | template <int D = Dim, typename = std::enable_if_t<D == 1> > |
|
23 | template <int D = Dim, typename = std::enable_if_t<D == 1> > | |
23 | explicit ArrayData(int nbColumns) : m_Data{1, QVector<double>{}} |
|
24 | explicit ArrayData(int nbColumns) : m_Data{1, QVector<double>{}} | |
24 | { |
|
25 | { | |
|
26 | QWriteLocker locker(&m_Lock); | |||
25 | m_Data[0].resize(nbColumns); |
|
27 | m_Data[0].resize(nbColumns); | |
26 | } |
|
28 | } | |
27 |
|
29 | |||
28 | /** |
|
30 | /** | |
|
31 | * Ctor for a unidimensional ArrayData | |||
|
32 | * @param nbColumns the number of values the ArrayData will hold | |||
|
33 | */ | |||
|
34 | explicit ArrayData(const ArrayData &other) | |||
|
35 | { | |||
|
36 | QReadLocker otherLocker(&other.m_Lock); | |||
|
37 | QWriteLocker locker(&m_Lock); | |||
|
38 | m_Data = other.m_Data; | |||
|
39 | } | |||
|
40 | ||||
|
41 | /** | |||
29 | * Sets a data at a specified index. The index has to be valid to be effective |
|
42 | * Sets a data at a specified index. The index has to be valid to be effective | |
30 | * @param index the index to which the data will be set |
|
43 | * @param index the index to which the data will be set | |
31 | * @param data the data to set |
|
44 | * @param data the data to set | |
@@ -34,6 +47,7 public: | |||||
34 | template <int D = Dim, typename = std::enable_if_t<D == 1> > |
|
47 | template <int D = Dim, typename = std::enable_if_t<D == 1> > | |
35 | void setData(int index, double data) noexcept |
|
48 | void setData(int index, double data) noexcept | |
36 | { |
|
49 | { | |
|
50 | QWriteLocker locker(&m_Lock); | |||
37 | if (index >= 0 && index < m_Data.at(0).size()) { |
|
51 | if (index >= 0 && index < m_Data.at(0).size()) { | |
38 | m_Data[0].replace(index, data); |
|
52 | m_Data[0].replace(index, data); | |
39 | } |
|
53 | } | |
@@ -44,8 +58,9 public: | |||||
44 | * @remarks this method is only available for a unidimensional ArrayData |
|
58 | * @remarks this method is only available for a unidimensional ArrayData | |
45 | */ |
|
59 | */ | |
46 | template <int D = Dim, typename = std::enable_if_t<D == 1> > |
|
60 | template <int D = Dim, typename = std::enable_if_t<D == 1> > | |
47 |
|
|
61 | QVector<double> data() const noexcept | |
48 | { |
|
62 | { | |
|
63 | QReadLocker locker(&m_Lock); | |||
49 | return m_Data[0]; |
|
64 | return m_Data[0]; | |
50 | } |
|
65 | } | |
51 |
|
66 | |||
@@ -54,8 +69,9 public: | |||||
54 | * @remarks this method is only available for a unidimensional ArrayData |
|
69 | * @remarks this method is only available for a unidimensional ArrayData | |
55 | */ |
|
70 | */ | |
56 | template <int D = Dim, typename = std::enable_if_t<D == 1> > |
|
71 | template <int D = Dim, typename = std::enable_if_t<D == 1> > | |
57 |
|
|
72 | QVector<double> data(double tStart, double tEnd) const noexcept | |
58 | { |
|
73 | { | |
|
74 | QReadLocker locker(&m_Lock); | |||
59 | return m_Data.at(tStart); |
|
75 | return m_Data.at(tStart); | |
60 | } |
|
76 | } | |
61 |
|
77 | |||
@@ -63,20 +79,30 public: | |||||
63 | template <int D = Dim, typename = std::enable_if_t<D == 1> > |
|
79 | template <int D = Dim, typename = std::enable_if_t<D == 1> > | |
64 | void merge(const ArrayData<1> &arrayData) |
|
80 | void merge(const ArrayData<1> &arrayData) | |
65 | { |
|
81 | { | |
|
82 | QWriteLocker locker(&m_Lock); | |||
66 | if (!m_Data.empty()) { |
|
83 | if (!m_Data.empty()) { | |
|
84 | QReadLocker otherLocker(&arrayData.m_Lock); | |||
67 | m_Data[0] += arrayData.data(); |
|
85 | m_Data[0] += arrayData.data(); | |
68 | } |
|
86 | } | |
69 | } |
|
87 | } | |
70 |
|
88 | |||
71 | template <int D = Dim, typename = std::enable_if_t<D == 1> > |
|
89 | template <int D = Dim, typename = std::enable_if_t<D == 1> > | |
72 | int size() |
|
90 | int size() const | |
73 | { |
|
91 | { | |
|
92 | QReadLocker locker(&m_Lock); | |||
74 | return m_Data[0].size(); |
|
93 | return m_Data[0].size(); | |
75 | } |
|
94 | } | |
76 |
|
95 | |||
|
96 | void clear() | |||
|
97 | { | |||
|
98 | QWriteLocker locker(&m_Lock); | |||
|
99 | m_Data.clear(); | |||
|
100 | } | |||
|
101 | ||||
77 |
|
102 | |||
78 | private: |
|
103 | private: | |
79 | QVector<QVector<double> > m_Data; |
|
104 | QVector<QVector<double> > m_Data; | |
|
105 | mutable QReadWriteLock m_Lock; | |||
80 | }; |
|
106 | }; | |
81 |
|
107 | |||
82 | #endif // SCIQLOP_ARRAYDATA_H |
|
108 | #endif // SCIQLOP_ARRAYDATA_H |
@@ -6,9 +6,10 | |||||
6 |
|
6 | |||
7 | #include <QLoggingCategory> |
|
7 | #include <QLoggingCategory> | |
8 |
|
8 | |||
|
9 | #include <QReadLocker> | |||
|
10 | #include <QReadWriteLock> | |||
9 | #include <memory> |
|
11 | #include <memory> | |
10 |
|
12 | |||
11 |
|
||||
12 | Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeries) |
|
13 | Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeries) | |
13 | Q_LOGGING_CATEGORY(LOG_DataSeries, "DataSeries") |
|
14 | Q_LOGGING_CATEGORY(LOG_DataSeries, "DataSeries") | |
14 |
|
15 | |||
@@ -38,12 +39,19 public: | |||||
38 | /// @sa IDataSeries::valuesUnit() |
|
39 | /// @sa IDataSeries::valuesUnit() | |
39 | Unit valuesUnit() const override { return m_ValuesUnit; } |
|
40 | Unit valuesUnit() const override { return m_ValuesUnit; } | |
40 |
|
41 | |||
|
42 | void clear() | |||
|
43 | { | |||
|
44 | m_XAxisData->clear(); | |||
|
45 | m_ValuesData->clear(); | |||
|
46 | } | |||
|
47 | ||||
41 | /// @sa IDataSeries::merge() |
|
48 | /// @sa IDataSeries::merge() | |
42 | void merge(IDataSeries *dataSeries) override |
|
49 | void merge(IDataSeries *dataSeries) override | |
43 | { |
|
50 | { | |
44 | if (auto dimDataSeries = dynamic_cast<DataSeries<Dim> *>(dataSeries)) { |
|
51 | if (auto dimDataSeries = dynamic_cast<DataSeries<Dim> *>(dataSeries)) { | |
45 | m_XAxisData->merge(*dimDataSeries->xAxisData()); |
|
52 | m_XAxisData->merge(*dimDataSeries->xAxisData()); | |
46 | m_ValuesData->merge(*dimDataSeries->valuesData()); |
|
53 | m_ValuesData->merge(*dimDataSeries->valuesData()); | |
|
54 | dimDataSeries->clear(); | |||
47 | } |
|
55 | } | |
48 | else { |
|
56 | else { | |
49 | qCWarning(LOG_DataSeries()) |
|
57 | qCWarning(LOG_DataSeries()) | |
@@ -51,6 +59,10 public: | |||||
51 | } |
|
59 | } | |
52 | } |
|
60 | } | |
53 |
|
61 | |||
|
62 | virtual void lockRead() { m_Lock.lockForRead(); } | |||
|
63 | virtual void lockWrite() { m_Lock.lockForWrite(); } | |||
|
64 | virtual void unlock() { m_Lock.unlock(); } | |||
|
65 | ||||
54 | protected: |
|
66 | protected: | |
55 | /// Protected ctor (DataSeries is abstract) |
|
67 | /// Protected ctor (DataSeries is abstract) | |
56 | explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit, |
|
68 | explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit, | |
@@ -88,6 +100,8 private: | |||||
88 | Unit m_XAxisUnit; |
|
100 | Unit m_XAxisUnit; | |
89 | std::shared_ptr<ArrayData<Dim> > m_ValuesData; |
|
101 | std::shared_ptr<ArrayData<Dim> > m_ValuesData; | |
90 | Unit m_ValuesUnit; |
|
102 | Unit m_ValuesUnit; | |
|
103 | ||||
|
104 | QReadWriteLock m_Lock; | |||
91 | }; |
|
105 | }; | |
92 |
|
106 | |||
93 | #endif // SCIQLOP_DATASERIES_H |
|
107 | #endif // SCIQLOP_DATASERIES_H |
@@ -51,6 +51,10 public: | |||||
51 | virtual void merge(IDataSeries *dataSeries) = 0; |
|
51 | virtual void merge(IDataSeries *dataSeries) = 0; | |
52 |
|
52 | |||
53 | virtual std::unique_ptr<IDataSeries> clone() const = 0; |
|
53 | virtual std::unique_ptr<IDataSeries> clone() const = 0; | |
|
54 | ||||
|
55 | virtual void lockRead() = 0; | |||
|
56 | virtual void lockWrite() = 0; | |||
|
57 | virtual void unlock() = 0; | |||
54 | }; |
|
58 | }; | |
55 |
|
59 | |||
56 | // Required for using shared_ptr in signals/slots |
|
60 | // Required for using shared_ptr in signals/slots |
@@ -27,14 +27,14 public: | |||||
27 | DataSourceController::DataSourceController(QObject *parent) |
|
27 | DataSourceController::DataSourceController(QObject *parent) | |
28 | : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()} |
|
28 | : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()} | |
29 | { |
|
29 | { | |
30 |
qCDebug(LOG_DataSourceController()) |
|
30 | qCDebug(LOG_DataSourceController()) | |
31 | << QThread::currentThread(); |
|
31 | << tr("DataSourceController construction") << QThread::currentThread(); | |
32 | } |
|
32 | } | |
33 |
|
33 | |||
34 | DataSourceController::~DataSourceController() |
|
34 | DataSourceController::~DataSourceController() | |
35 | { |
|
35 | { | |
36 |
qCDebug(LOG_DataSourceController()) |
|
36 | qCDebug(LOG_DataSourceController()) | |
37 | << QThread::currentThread(); |
|
37 | << tr("DataSourceController destruction") << QThread::currentThread(); | |
38 | this->waitForFinish(); |
|
38 | this->waitForFinish(); | |
39 | } |
|
39 | } | |
40 |
|
40 | |||
@@ -97,8 +97,8 void DataSourceController::loadProductItem(const QUuid &dataSourceUid, | |||||
97 |
|
97 | |||
98 | void DataSourceController::initialize() |
|
98 | void DataSourceController::initialize() | |
99 | { |
|
99 | { | |
100 |
qCDebug(LOG_DataSourceController()) |
|
100 | qCDebug(LOG_DataSourceController()) | |
101 | << QThread::currentThread(); |
|
101 | << tr("DataSourceController init") << QThread::currentThread(); | |
102 | impl->m_WorkingMutex.lock(); |
|
102 | impl->m_WorkingMutex.lock(); | |
103 | qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END"); |
|
103 | qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END"); | |
104 | } |
|
104 | } |
@@ -3,6 +3,9 | |||||
3 | #include <Data/IDataSeries.h> |
|
3 | #include <Data/IDataSeries.h> | |
4 | #include <Data/SqpDateTime.h> |
|
4 | #include <Data/SqpDateTime.h> | |
5 |
|
5 | |||
|
6 | #include <QReadWriteLock> | |||
|
7 | #include <QThread> | |||
|
8 | ||||
6 | Q_LOGGING_CATEGORY(LOG_Variable, "Variable") |
|
9 | Q_LOGGING_CATEGORY(LOG_Variable, "Variable") | |
7 |
|
10 | |||
8 | struct Variable::VariablePrivate { |
|
11 | struct Variable::VariablePrivate { | |
@@ -57,6 +60,7 void Variable::setDateTime(const SqpDateTime &dateTime) noexcept | |||||
57 |
|
60 | |||
58 | void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept |
|
61 | void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept | |
59 | { |
|
62 | { | |
|
63 | qCInfo(LOG_Variable()) << "Variable::setDataSeries" << QThread::currentThread()->objectName(); | |||
60 | if (!dataSeries) { |
|
64 | if (!dataSeries) { | |
61 | /// @todo ALX : log |
|
65 | /// @todo ALX : log | |
62 | return; |
|
66 | return; | |
@@ -67,8 +71,11 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept | |||||
67 | impl->m_DataSeries = dataSeries->clone(); |
|
71 | impl->m_DataSeries = dataSeries->clone(); | |
68 | } |
|
72 | } | |
69 | else { |
|
73 | else { | |
|
74 | dataSeries->lockWrite(); | |||
|
75 | impl->m_DataSeries->lockWrite(); | |||
70 | impl->m_DataSeries->merge(dataSeries.get()); |
|
76 | impl->m_DataSeries->merge(dataSeries.get()); | |
71 |
|
77 | impl->m_DataSeries->unlock(); | ||
|
78 | dataSeries->unlock(); | |||
72 | emit updated(); |
|
79 | emit updated(); | |
73 | } |
|
80 | } | |
74 | } |
|
81 | } |
@@ -3,6 +3,7 | |||||
3 | #include "Variable/Variable.h" |
|
3 | #include "Variable/Variable.h" | |
4 | #include <unordered_map> |
|
4 | #include <unordered_map> | |
5 |
|
5 | |||
|
6 | #include <QThread> | |||
6 | Q_LOGGING_CATEGORY(LOG_VariableCacheController, "VariableCacheController") |
|
7 | Q_LOGGING_CATEGORY(LOG_VariableCacheController, "VariableCacheController") | |
7 |
|
8 | |||
8 | struct VariableCacheController::VariableCacheControllerPrivate { |
|
9 | struct VariableCacheController::VariableCacheControllerPrivate { | |
@@ -32,6 +33,8 VariableCacheController::VariableCacheController(QObject *parent) | |||||
32 | void VariableCacheController::addDateTime(std::shared_ptr<Variable> variable, |
|
33 | void VariableCacheController::addDateTime(std::shared_ptr<Variable> variable, | |
33 | const SqpDateTime &dateTime) |
|
34 | const SqpDateTime &dateTime) | |
34 | { |
|
35 | { | |
|
36 | qCInfo(LOG_VariableCacheController()) | |||
|
37 | << "VariableCacheController::addDateTime" << QThread::currentThread()->objectName(); | |||
35 | if (variable) { |
|
38 | if (variable) { | |
36 | auto findVariableIte = impl->m_VariableToSqpDateTimeListMap.find(variable); |
|
39 | auto findVariableIte = impl->m_VariableToSqpDateTimeListMap.find(variable); | |
37 | if (findVariableIte == impl->m_VariableToSqpDateTimeListMap.end()) { |
|
40 | if (findVariableIte == impl->m_VariableToSqpDateTimeListMap.end()) { | |
@@ -81,6 +84,9 QVector<SqpDateTime> | |||||
81 | VariableCacheController::provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable, |
|
84 | VariableCacheController::provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable, | |
82 | const SqpDateTime &dateTime) |
|
85 | const SqpDateTime &dateTime) | |
83 | { |
|
86 | { | |
|
87 | qCInfo(LOG_VariableCacheController()) | |||
|
88 | << "VariableCacheController::provideNotInCacheDateTimeList" | |||
|
89 | << QThread::currentThread()->objectName(); | |||
84 | auto notInCache = QVector<SqpDateTime>{}; |
|
90 | auto notInCache = QVector<SqpDateTime>{}; | |
85 |
|
91 | |||
86 | // This algorithm is recursif. The idea is to localise the start time then the end time in the |
|
92 | // This algorithm is recursif. The idea is to localise the start time then the end time in the | |
@@ -101,6 +107,8 VariableCacheController::provideNotInCacheDateTimeList(std::shared_ptr<Variable> | |||||
101 | QVector<SqpDateTime> |
|
107 | QVector<SqpDateTime> | |
102 | VariableCacheController::dateCacheList(std::shared_ptr<Variable> variable) const noexcept |
|
108 | VariableCacheController::dateCacheList(std::shared_ptr<Variable> variable) const noexcept | |
103 | { |
|
109 | { | |
|
110 | qCInfo(LOG_VariableCacheController()) | |||
|
111 | << "VariableCacheController::dateCacheList" << QThread::currentThread()->objectName(); | |||
104 | try { |
|
112 | try { | |
105 | return impl->m_VariableToSqpDateTimeListMap.at(variable); |
|
113 | return impl->m_VariableToSqpDateTimeListMap.at(variable); | |
106 | } |
|
114 | } | |
@@ -210,8 +218,8 void VariableCacheController::displayCache(std::shared_ptr<Variable> variable) c | |||||
210 | { |
|
218 | { | |
211 | auto variableDateTimeList = impl->m_VariableToSqpDateTimeListMap.find(variable); |
|
219 | auto variableDateTimeList = impl->m_VariableToSqpDateTimeListMap.find(variable); | |
212 | if (variableDateTimeList != impl->m_VariableToSqpDateTimeListMap.end()) { |
|
220 | if (variableDateTimeList != impl->m_VariableToSqpDateTimeListMap.end()) { | |
213 |
qCInfo(LOG_VariableCacheController()) |
|
221 | qCInfo(LOG_VariableCacheController()) | |
214 | << variableDateTimeList->second; |
|
222 | << tr("VariableCacheController::displayCache") << variableDateTimeList->second; | |
215 | } |
|
223 | } | |
216 | else { |
|
224 | else { | |
217 | qCWarning(LOG_VariableCacheController()) |
|
225 | qCWarning(LOG_VariableCacheController()) |
@@ -56,14 +56,14 struct VariableController::VariableControllerPrivate { | |||||
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()) |
|
59 | qCDebug(LOG_VariableController()) | |
60 | << QThread::currentThread(); |
|
60 | << tr("VariableController construction") << QThread::currentThread(); | |
61 | } |
|
61 | } | |
62 |
|
62 | |||
63 | VariableController::~VariableController() |
|
63 | VariableController::~VariableController() | |
64 | { |
|
64 | { | |
65 |
qCDebug(LOG_VariableController()) |
|
65 | qCDebug(LOG_VariableController()) | |
66 | << QThread::currentThread(); |
|
66 | << tr("VariableController destruction") << QThread::currentThread(); | |
67 | this->waitForFinish(); |
|
67 | this->waitForFinish(); | |
68 | } |
|
68 | } | |
69 |
|
69 | |||
@@ -152,6 +152,8 void VariableController::createVariable(const QString &name, | |||||
152 |
|
152 | |||
153 | void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime) |
|
153 | void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime) | |
154 | { |
|
154 | { | |
|
155 | qCDebug(LOG_VariableController()) | |||
|
156 | << "VariableController::onDateTimeOnSelection" << QThread::currentThread()->objectName(); | |||
155 | auto selectedRows = impl->m_VariableSelectionModel->selectedRows(); |
|
157 | auto selectedRows = impl->m_VariableSelectionModel->selectedRows(); | |
156 |
|
158 | |||
157 | for (const auto &selectedRow : qAsConst(selectedRows)) { |
|
159 | for (const auto &selectedRow : qAsConst(selectedRows)) { | |
@@ -166,6 +168,8 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime) | |||||
166 | void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable, |
|
168 | void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable, | |
167 | const SqpDateTime &dateTime) |
|
169 | const SqpDateTime &dateTime) | |
168 | { |
|
170 | { | |
|
171 | qCDebug(LOG_VariableController()) | |||
|
172 | << "VariableController::onRequestDataLoading" << QThread::currentThread()->objectName(); | |||
169 | // we want to load data of the variable for the dateTime. |
|
173 | // we want to load data of the variable for the dateTime. | |
170 | // First we check if the cache contains some of them. |
|
174 | // First we check if the cache contains some of them. | |
171 | // For the other, we ask the provider to give them. |
|
175 | // For the other, we ask the provider to give them. |
@@ -18,6 +18,14 public: | |||||
18 | m_VariableController{std::make_unique<VariableController>()}, |
|
18 | m_VariableController{std::make_unique<VariableController>()}, | |
19 | m_VisualizationController{std::make_unique<VisualizationController>()} |
|
19 | m_VisualizationController{std::make_unique<VisualizationController>()} | |
20 | { |
|
20 | { | |
|
21 | QThread::currentThread()->setObjectName("MainThread"); | |||
|
22 | m_DataSourceController->moveToThread(&m_DataSourceControllerThread); | |||
|
23 | m_DataSourceControllerThread.setObjectName("DataSourceControllerThread"); | |||
|
24 | m_VariableController->moveToThread(&m_VariableControllerThread); | |||
|
25 | m_VariableControllerThread.setObjectName("VariableControllerThread"); | |||
|
26 | m_VisualizationController->moveToThread(&m_VisualizationControllerThread); | |||
|
27 | m_VisualizationControllerThread.setObjectName("VisualizationControllerThread"); | |||
|
28 | ||||
21 | // /////////////////////////////// // |
|
29 | // /////////////////////////////// // | |
22 | // Connections between controllers // |
|
30 | // Connections between controllers // | |
23 | // /////////////////////////////// // |
|
31 | // /////////////////////////////// // | |
@@ -34,9 +42,6 public: | |||||
34 | m_VisualizationController.get(), |
|
42 | m_VisualizationController.get(), | |
35 | SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection); |
|
43 | SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection); | |
36 |
|
44 | |||
37 | m_DataSourceController->moveToThread(&m_DataSourceControllerThread); |
|
|||
38 | m_VariableController->moveToThread(&m_VariableControllerThread); |
|
|||
39 | m_VisualizationController->moveToThread(&m_VisualizationControllerThread); |
|
|||
40 |
|
45 | |||
41 | // Additionnal init |
|
46 | // Additionnal init | |
42 | m_VariableController->setTimeController(m_TimeController.get()); |
|
47 | m_VariableController->setTimeController(m_TimeController.get()); |
@@ -5,12 +5,16 | |||||
5 |
|
5 | |||
6 | #include <Variable/Variable.h> |
|
6 | #include <Variable/Variable.h> | |
7 |
|
7 | |||
8 | #include <QElapsedTimer> |
|
|||
9 |
|
||||
10 | Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper") |
|
8 | Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper") | |
11 |
|
9 | |||
12 | namespace { |
|
10 | namespace { | |
13 |
|
11 | |||
|
12 | class SqpDataContainer : public QCPGraphDataContainer { | |||
|
13 | public: | |||
|
14 | void sqpAdd(const QCPGraphData &data) { mData.append(data); } | |||
|
15 | }; | |||
|
16 | ||||
|
17 | ||||
14 | /// Format for datetimes on a axis |
|
18 | /// Format for datetimes on a axis | |
15 | const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss"); |
|
19 | const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss"); | |
16 |
|
20 | |||
@@ -33,35 +37,36 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis) | |||||
33 | void updateScalarData(QCPAbstractPlottable *component, ScalarSeries &scalarSeries, |
|
37 | void updateScalarData(QCPAbstractPlottable *component, ScalarSeries &scalarSeries, | |
34 | const SqpDateTime &dateTime) |
|
38 | const SqpDateTime &dateTime) | |
35 | { |
|
39 | { | |
36 | QElapsedTimer timer; |
|
40 | qCInfo(LOG_VisualizationGraphHelper()) | |
37 | timer.start(); |
|
41 | << "TORM: updateScalarData" << QThread::currentThread()->objectName(); | |
38 | if (auto qcpGraph = dynamic_cast<QCPGraph *>(component)) { |
|
42 | if (auto qcpGraph = dynamic_cast<QCPGraph *>(component)) { | |
39 | // Clean the graph |
|
43 | // Clean the graph | |
40 | // NAIVE approch |
|
44 | // NAIVE approch | |
41 | const auto &xData = scalarSeries.xAxisData()->data(); |
|
45 | scalarSeries.lockRead(); | |
42 | const auto &valuesData = scalarSeries.valuesData()->data(); |
|
46 | { | |
43 | const auto count = xData.count(); |
|
47 | const auto xData = scalarSeries.xAxisData()->data(); | |
44 | qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points in cache" << xData.count(); |
|
48 | const auto valuesData = scalarSeries.valuesData()->data(); | |
45 | auto xValue = QVector<double>(count); |
|
49 | const auto count = xData.count(); | |
46 | auto vValue = QVector<double>(count); |
|
50 | qCInfo(LOG_VisualizationGraphHelper()) | |
47 |
|
51 | << "TORM: Current points in cache" << xData.count(); | ||
48 | int n = 0; |
|
52 | ||
49 | for (auto i = 0; i < count; ++i) { |
|
53 | auto dataContainer = qcpGraph->data(); | |
50 | const auto x = xData[i]; |
|
54 | dataContainer->clear(); | |
51 | if (x >= dateTime.m_TStart && x <= dateTime.m_TEnd) { |
|
55 | auto sqpDataContainer = QSharedPointer<SqpDataContainer>::create(); | |
52 | xValue[n] = x; |
|
56 | qcpGraph->setData(sqpDataContainer); | |
53 | vValue[n] = valuesData[i]; |
|
57 | ||
54 | ++n; |
|
58 | for (auto i = 0; i < count; ++i) { | |
|
59 | const auto x = xData[i]; | |||
|
60 | if (x >= dateTime.m_TStart && x <= dateTime.m_TEnd) { | |||
|
61 | sqpDataContainer->sqpAdd(QCPGraphData(x, valuesData[i])); | |||
|
62 | } | |||
55 | } |
|
63 | } | |
|
64 | sqpDataContainer->sort(); | |||
|
65 | qCInfo(LOG_VisualizationGraphHelper()) | |||
|
66 | << "TORM: Current points displayed" << sqpDataContainer->size(); | |||
56 | } |
|
67 | } | |
|
68 | scalarSeries.unlock(); | |||
57 |
|
69 | |||
58 | xValue.resize(n); |
|
|||
59 | vValue.resize(n); |
|
|||
60 |
|
||||
61 | qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points displayed" |
|
|||
62 | << xValue.count(); |
|
|||
63 |
|
||||
64 | qcpGraph->setData(xValue, vValue); |
|
|||
65 |
|
70 | |||
66 | // Display all data |
|
71 | // Display all data | |
67 | component->rescaleAxes(); |
|
72 | component->rescaleAxes(); |
@@ -79,7 +79,6 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable) | |||||
79 |
|
79 | |||
80 | connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated())); |
|
80 | connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated())); | |
81 | } |
|
81 | } | |
82 |
|
||||
83 | void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable) |
|
82 | void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable) | |
84 | { |
|
83 | { | |
85 |
|
84 | |||
@@ -178,7 +177,8 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept | |||||
178 |
|
177 | |||
179 | void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1) |
|
178 | void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1) | |
180 | { |
|
179 | { | |
181 |
qCDebug(LOG_VisualizationGraphWidget()) |
|
180 | qCDebug(LOG_VisualizationGraphWidget()) | |
|
181 | << tr("VisualizationGraphWidget::onRangeChanged") << QThread::currentThread()->objectName(); | |||
182 |
|
182 | |||
183 | for (auto it = impl->m_VariableToPlotMultiMap.cbegin(); |
|
183 | for (auto it = impl->m_VariableToPlotMultiMap.cbegin(); | |
184 | it != impl->m_VariableToPlotMultiMap.cend(); ++it) { |
|
184 | it != impl->m_VariableToPlotMultiMap.cend(); ++it) { |
@@ -1049,8 +1049,9 QCPLayer::~QCPLayer() | |||||
1049 | mChildren.last()->setLayer(0); // removes itself from mChildren via removeChild() |
|
1049 | mChildren.last()->setLayer(0); // removes itself from mChildren via removeChild() | |
1050 |
|
1050 | |||
1051 | if (mParentPlot->currentLayer() == this) |
|
1051 | if (mParentPlot->currentLayer() == this) | |
1052 | qDebug() << Q_FUNC_INFO << "The parent plot's mCurrentLayer will be a dangling pointer. " |
|
1052 | qDebug() << Q_FUNC_INFO | |
1053 | "Should have been set to a valid layer or 0 beforehand."; |
|
1053 | << "The parent plot's mCurrentLayer will be a dangling pointer. " | |
|
1054 | "Should have been set to a valid layer or 0 beforehand."; | |||
1054 | } |
|
1055 | } | |
1055 |
|
1056 | |||
1056 | /*! |
|
1057 | /*! | |
@@ -1574,10 +1575,7 void QCPLayerable::applyAntialiasingHint(QCPPainter *painter, bool localAntialia | |||||
1574 |
|
1575 | |||
1575 | \see initializeParentPlot |
|
1576 | \see initializeParentPlot | |
1576 | */ |
|
1577 | */ | |
1577 | void QCPLayerable::parentPlotInitialized(QCustomPlot *parentPlot) |
|
1578 | void QCPLayerable::parentPlotInitialized(QCustomPlot *parentPlot){Q_UNUSED(parentPlot)} | |
1578 | { |
|
|||
1579 | Q_UNUSED(parentPlot) |
|
|||
1580 | } |
|
|||
1581 |
|
1579 | |||
1582 | /*! \internal |
|
1580 | /*! \internal | |
1583 |
|
1581 | |||
@@ -8485,8 +8483,9 void QCPAxis::scaleRange(double factor, double center) | |||||
8485 | mRange = newRange.sanitizedForLogScale(); |
|
8483 | mRange = newRange.sanitizedForLogScale(); | |
8486 | } |
|
8484 | } | |
8487 | else |
|
8485 | else | |
8488 | qDebug() << Q_FUNC_INFO << "Center of scaling operation doesn't lie in same " |
|
8486 | qDebug() << Q_FUNC_INFO | |
8489 | "logarithmic sign domain as range:" |
|
8487 | << "Center of scaling operation doesn't lie in same " | |
|
8488 | "logarithmic sign domain as range:" | |||
8490 | << center; |
|
8489 | << center; | |
8491 | } |
|
8490 | } | |
8492 | emit rangeChanged(mRange); |
|
8491 | emit rangeChanged(mRange); | |
@@ -9257,14 +9256,16 void QCPAxisPainterPrivate::draw(QCPPainter *painter) | |||||
9257 | painter->setBrush(QBrush(basePen.color())); |
|
9256 | painter->setBrush(QBrush(basePen.color())); | |
9258 | QCPVector2D baseLineVector(baseLine.dx(), baseLine.dy()); |
|
9257 | QCPVector2D baseLineVector(baseLine.dx(), baseLine.dy()); | |
9259 | if (lowerEnding.style() != QCPLineEnding::esNone) |
|
9258 | if (lowerEnding.style() != QCPLineEnding::esNone) | |
9260 |
lowerEnding.draw(painter, |
|
9259 | lowerEnding.draw(painter, | |
9261 | - baseLineVector.normalized() * lowerEnding.realLength() |
|
9260 | QCPVector2D(baseLine.p1()) | |
9262 | * (lowerEnding.inverted() ? -1 : 1), |
|
9261 | - baseLineVector.normalized() * lowerEnding.realLength() | |
|
9262 | * (lowerEnding.inverted() ? -1 : 1), | |||
9263 | -baseLineVector); |
|
9263 | -baseLineVector); | |
9264 | if (upperEnding.style() != QCPLineEnding::esNone) |
|
9264 | if (upperEnding.style() != QCPLineEnding::esNone) | |
9265 |
upperEnding.draw(painter, |
|
9265 | upperEnding.draw(painter, | |
9266 | + baseLineVector.normalized() * upperEnding.realLength() |
|
9266 | QCPVector2D(baseLine.p2()) | |
9267 | * (upperEnding.inverted() ? -1 : 1), |
|
9267 | + baseLineVector.normalized() * upperEnding.realLength() | |
|
9268 | * (upperEnding.inverted() ? -1 : 1), | |||
9268 | baseLineVector); |
|
9269 | baseLineVector); | |
9269 | painter->setAntialiasing(antialiasingBackup); |
|
9270 | painter->setAntialiasing(antialiasingBackup); | |
9270 |
|
9271 | |||
@@ -9570,14 +9571,16 void QCPAxisPainterPrivate::placeTickLabel(QCPPainter *painter, double position, | |||||
9570 | bool labelClippedByBorder = false; |
|
9571 | bool labelClippedByBorder = false; | |
9571 | if (tickLabelSide == QCPAxis::lsOutside) { |
|
9572 | if (tickLabelSide == QCPAxis::lsOutside) { | |
9572 | if (QCPAxis::orientation(type) == Qt::Horizontal) |
|
9573 | if (QCPAxis::orientation(type) == Qt::Horizontal) | |
9573 |
labelClippedByBorder = finalPosition.x() |
|
9574 | labelClippedByBorder = finalPosition.x() | |
9574 |
|
|
9575 | + (labelData.rotatedTotalBounds.width() | |
|
9576 | + labelData.rotatedTotalBounds.left()) | |||
9575 | > viewportRect.right() |
|
9577 | > viewportRect.right() | |
9576 | || finalPosition.x() + labelData.rotatedTotalBounds.left() |
|
9578 | || finalPosition.x() + labelData.rotatedTotalBounds.left() | |
9577 | < viewportRect.left(); |
|
9579 | < viewportRect.left(); | |
9578 | else |
|
9580 | else | |
9579 |
labelClippedByBorder = finalPosition.y() |
|
9581 | labelClippedByBorder = finalPosition.y() | |
9580 |
|
|
9582 | + (labelData.rotatedTotalBounds.height() | |
|
9583 | + labelData.rotatedTotalBounds.top()) | |||
9581 | > viewportRect.bottom() |
|
9584 | > viewportRect.bottom() | |
9582 | || finalPosition.y() + labelData.rotatedTotalBounds.top() |
|
9585 | || finalPosition.y() + labelData.rotatedTotalBounds.top() | |
9583 | < viewportRect.top(); |
|
9586 | < viewportRect.top(); | |
@@ -12528,8 +12531,9 double QCPAbstractItem::rectDistance(const QRectF &rect, const QPointF &pos, boo | |||||
12528 | */ |
|
12531 | */ | |
12529 | QPointF QCPAbstractItem::anchorPixelPosition(int anchorId) const |
|
12532 | QPointF QCPAbstractItem::anchorPixelPosition(int anchorId) const | |
12530 | { |
|
12533 | { | |
12531 | qDebug() << Q_FUNC_INFO << "called on item which shouldn't have any anchors (this method not " |
|
12534 | qDebug() << Q_FUNC_INFO | |
12532 | "reimplemented). anchorId" |
|
12535 | << "called on item which shouldn't have any anchors (this method not " | |
|
12536 | "reimplemented). anchorId" | |||
12533 | << anchorId; |
|
12537 | << anchorId; | |
12534 | return QPointF(); |
|
12538 | return QPointF(); | |
12535 | } |
|
12539 | } | |
@@ -13455,9 +13459,10 void QCustomPlot::setOpenGl(bool enabled, int multisampling) | |||||
13455 | setupPaintBuffers(); |
|
13459 | setupPaintBuffers(); | |
13456 | #else |
|
13460 | #else | |
13457 | Q_UNUSED(enabled) |
|
13461 | Q_UNUSED(enabled) | |
13458 | qDebug() << Q_FUNC_INFO << "QCustomPlot can't use OpenGL because QCUSTOMPLOT_USE_OPENGL was " |
|
13462 | qDebug() << Q_FUNC_INFO | |
13459 | "not defined during compilation (add 'DEFINES += " |
|
13463 | << "QCustomPlot can't use OpenGL because QCUSTOMPLOT_USE_OPENGL was " | |
13460 | "QCUSTOMPLOT_USE_OPENGL' to your qmake .pro file)"; |
|
13464 | "not defined during compilation (add 'DEFINES += " | |
|
13465 | "QCUSTOMPLOT_USE_OPENGL' to your qmake .pro file)"; | |||
13461 | #endif |
|
13466 | #endif | |
13462 | } |
|
13467 | } | |
13463 |
|
13468 | |||
@@ -13814,8 +13819,9 QCPGraph *QCustomPlot::addGraph(QCPAxis *keyAxis, QCPAxis *valueAxis) | |||||
13814 | if (!valueAxis) |
|
13819 | if (!valueAxis) | |
13815 | valueAxis = yAxis; |
|
13820 | valueAxis = yAxis; | |
13816 | if (!keyAxis || !valueAxis) { |
|
13821 | if (!keyAxis || !valueAxis) { | |
13817 | qDebug() << Q_FUNC_INFO << "can't use default QCustomPlot xAxis or yAxis, because at least " |
|
13822 | qDebug() << Q_FUNC_INFO | |
13818 | "one is invalid (has been deleted)"; |
|
13823 | << "can't use default QCustomPlot xAxis or yAxis, because at least " | |
|
13824 | "one is invalid (has been deleted)"; | |||
13819 | return 0; |
|
13825 | return 0; | |
13820 | } |
|
13826 | } | |
13821 | if (keyAxis->parentPlot() != this || valueAxis->parentPlot() != this) { |
|
13827 | if (keyAxis->parentPlot() != this || valueAxis->parentPlot() != this) { | |
@@ -15237,8 +15243,9 QCPAbstractPaintBuffer *QCustomPlot::createPaintBuffer() | |||||
15237 | return new QCPPaintBufferGlPbuffer(viewport().size(), mBufferDevicePixelRatio, |
|
15243 | return new QCPPaintBufferGlPbuffer(viewport().size(), mBufferDevicePixelRatio, | |
15238 | mOpenGlMultisamples); |
|
15244 | mOpenGlMultisamples); | |
15239 | #else |
|
15245 | #else | |
15240 | qDebug() << Q_FUNC_INFO << "OpenGL enabled even though no support for it compiled in, this " |
|
15246 | qDebug() << Q_FUNC_INFO | |
15241 | "shouldn't have happened. Falling back to pixmap paint buffer."; |
|
15247 | << "OpenGL enabled even though no support for it compiled in, this " | |
|
15248 | "shouldn't have happened. Falling back to pixmap paint buffer."; | |||
15242 | return new QCPPaintBufferPixmap(viewport().size(), mBufferDevicePixelRatio); |
|
15249 | return new QCPPaintBufferPixmap(viewport().size(), mBufferDevicePixelRatio); | |
15243 | #endif |
|
15250 | #endif | |
15244 | } |
|
15251 | } | |
@@ -16469,8 +16476,9 void QCPColorGradient::updateColorBuffer() | |||||
16469 | hue -= 1.0; |
|
16476 | hue -= 1.0; | |
16470 | if (useAlpha) { |
|
16477 | if (useAlpha) { | |
16471 | const QRgb rgb |
|
16478 | const QRgb rgb | |
16472 |
= QColor::fromHsvF(hue, |
|
16479 | = QColor::fromHsvF(hue, | |
16473 |
|
|
16480 | (1 - t) * lowHsv.saturationF() | |
|
16481 | + t * highHsv.saturationF(), | |||
16474 | (1 - t) * lowHsv.valueF() + t * highHsv.valueF()) |
|
16482 | (1 - t) * lowHsv.valueF() + t * highHsv.valueF()) | |
16475 | .rgb(); |
|
16483 | .rgb(); | |
16476 | const float alpha = (1 - t) * lowHsv.alphaF() + t * highHsv.alphaF(); |
|
16484 | const float alpha = (1 - t) * lowHsv.alphaF() + t * highHsv.alphaF(); | |
@@ -16479,8 +16487,9 void QCPColorGradient::updateColorBuffer() | |||||
16479 | } |
|
16487 | } | |
16480 | else { |
|
16488 | else { | |
16481 | mColorBuffer[i] |
|
16489 | mColorBuffer[i] | |
16482 |
= QColor::fromHsvF(hue, |
|
16490 | = QColor::fromHsvF(hue, | |
16483 |
|
|
16491 | (1 - t) * lowHsv.saturationF() | |
|
16492 | + t * highHsv.saturationF(), | |||
16484 | (1 - t) * lowHsv.valueF() + t * highHsv.valueF()) |
|
16493 | (1 - t) * lowHsv.valueF() + t * highHsv.valueF()) | |
16485 | .rgb(); |
|
16494 | .rgb(); | |
16486 | } |
|
16495 | } | |
@@ -18570,7 +18579,7 void QCPLegend::setIconSize(const QSize &size) | |||||
18570 | } |
|
18579 | } | |
18571 |
|
18580 | |||
18572 | /*! \overload |
|
18581 | /*! \overload | |
18573 | */ |
|
18582 | */ | |
18574 | void QCPLegend::setIconSize(int width, int height) |
|
18583 | void QCPLegend::setIconSize(int width, int height) | |
18575 | { |
|
18584 | { | |
18576 | mIconSize.setWidth(width); |
|
18585 | mIconSize.setWidth(width); |
@@ -6,6 +6,7 | |||||
6 | #include <cmath> |
|
6 | #include <cmath> | |
7 |
|
7 | |||
8 | #include <QDateTime> |
|
8 | #include <QDateTime> | |
|
9 | #include <QThread> | |||
9 |
|
10 | |||
10 | Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider") |
|
11 | Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider") | |
11 |
|
12 | |||
@@ -39,6 +40,8 CosinusProvider::retrieveData(const DataProviderParameters ¶meters) const | |||||
39 |
|
40 | |||
40 | void CosinusProvider::requestDataLoading(const QVector<SqpDateTime> &dateTimeList) |
|
41 | void CosinusProvider::requestDataLoading(const QVector<SqpDateTime> &dateTimeList) | |
41 | { |
|
42 | { | |
|
43 | qCInfo(LOG_CosinusProvider()) << "CosinusProvider::requestDataLoading" | |||
|
44 | << QThread::currentThread()->objectName(); | |||
42 | // NOTE: Try to use multithread if possible |
|
45 | // NOTE: Try to use multithread if possible | |
43 | for (const auto &dateTime : dateTimeList) { |
|
46 | for (const auto &dateTime : dateTimeList) { | |
44 | auto scalarSeries = this->retrieveData(DataProviderParameters{dateTime}); |
|
47 | auto scalarSeries = this->retrieveData(DataProviderParameters{dateTime}); |
General Comments 0
You need to be logged in to leave comments.
Login now