##// END OF EJS Templates
Merge branch 'feature/CloneVariable' into develop
Alexandre Leroux -
r658:ceac74ef218a merge
parent child
Show More
@@ -0,0 +1,35
1 #ifndef SCIQLOP_STRINGUTILS_H
2 #define SCIQLOP_STRINGUTILS_H
3
4 #include "CoreGlobal.h"
5
6 #include <vector>
7
8 class QString;
9
10 /**
11 * Utility class with methods for strings
12 */
13 struct SCIQLOP_CORE_EXPORT StringUtils {
14 /**
15 * Generates a unique name from a default name and a set of forbidden names.
16 *
17 * Generating the unique name is done by adding an index to the default name and stopping at the
18 * first index for which the generated name is not in the forbidden names.
19 *
20 * Examples (defaultName, forbiddenNames -> result):
21 * - "FGM", {"FGM"} -> "FGM1"
22 * - "FGM", {"ABC"} -> "FGM"
23 * - "FGM", {"FGM", "FGM1"} -> "FGM2"
24 * - "FGM", {"FGM", "FGM2"} -> "FGM1"
25 * - "", {"ABC"} -> "1"
26 *
27 * @param defaultName the default name
28 * @param forbiddenNames the set of forbidden names
29 * @return the unique name generated
30 */
31 static QString uniqueName(const QString &defaultName,
32 const std::vector<QString> &forbiddenNames) noexcept;
33 };
34
35 #endif // SCIQLOP_STRINGUTILS_H
@@ -0,0 +1,30
1 #include "Common/StringUtils.h"
2
3 #include <QRegExp>
4 #include <QString>
5
6 #include <set>
7
8 QString StringUtils::uniqueName(const QString &defaultName,
9 const std::vector<QString> &forbiddenNames) noexcept
10 {
11 // Gets the base of the unique name to generate, by removing trailing number (for example, base
12 // name of "FGM12" is "FGM")
13 auto baseName = defaultName;
14 baseName.remove(QRegExp{QStringLiteral("\\d*$")});
15
16 // Finds the unique name by adding an index to the base name and stops when the generated name
17 // isn't forbidden
18 QString newName{};
19 auto forbidden = true;
20 for (auto i = 0; forbidden; ++i) {
21 newName = (i == 0) ? baseName : baseName + QString::number(i);
22 forbidden = newName.isEmpty()
23 || std::any_of(forbiddenNames.cbegin(), forbiddenNames.cend(),
24 [&newName](const auto &name) {
25 return name.compare(newName, Qt::CaseInsensitive) == 0;
26 });
27 }
28
29 return newName;
30 }
@@ -0,0 +1,50
1 #include <Common/StringUtils.h>
2
3 #include <QObject>
4 #include <QtTest>
5
6 class TestStringUtils : public QObject {
7 Q_OBJECT
8
9 private slots:
10 void testUniqueName_data();
11 void testUniqueName();
12 };
13
14 void TestStringUtils::testUniqueName_data()
15 {
16 // ////////////// //
17 // Test structure //
18 // ////////////// //
19
20 QTest::addColumn<QString>("defaultName");
21 QTest::addColumn<std::vector<QString> >("forbiddenNames");
22 QTest::addColumn<QString>("expectedName");
23
24 // ////////// //
25 // Test cases //
26 // ////////// //
27
28 QTest::newRow("uniqueName") << "FGM" << std::vector<QString>{"FGM2"} << "FGM";
29 QTest::newRow("uniqueName2") << "FGM2" << std::vector<QString>{"FGM", "FGM1", "FGM2"} << "FGM3";
30 QTest::newRow("uniqueName3") << "FGM1" << std::vector<QString>{"FGM1"} << "FGM";
31 QTest::newRow("uniqueName4") << "FGM" << std::vector<QString>{"FGM"} << "FGM1";
32 QTest::newRow("uniqueName5") << "FGM" << std::vector<QString>{"FGM", "FGM1", "FGM3"} << "FGM2";
33 QTest::newRow("uniqueName6") << "FGM" << std::vector<QString>{"A", "B", "C"} << "FGM";
34 QTest::newRow("uniqueName7") << "FGM" << std::vector<QString>{"fGm", "FGm1", "Fgm2"} << "FGM3";
35 QTest::newRow("uniqueName8") << "" << std::vector<QString>{"A", "B", "C"} << "1";
36 QTest::newRow("uniqueName9") << "24" << std::vector<QString>{"A", "B", "C"} << "1";
37 }
38
39 void TestStringUtils::testUniqueName()
40 {
41 QFETCH(QString, defaultName);
42 QFETCH(std::vector<QString>, forbiddenNames);
43 QFETCH(QString, expectedName);
44
45 auto result = StringUtils::uniqueName(defaultName, forbiddenNames);
46 QCOMPARE(result, expectedName);
47 }
48
49 QTEST_MAIN(TestStringUtils)
50 #include "TestStringUtils.moc"
@@ -1,76 +1,77
1 #ifndef SCIQLOP_IDATAPROVIDER_H
1 #ifndef SCIQLOP_IDATAPROVIDER_H
2 #define SCIQLOP_IDATAPROVIDER_H
2 #define SCIQLOP_IDATAPROVIDER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <memory>
6 #include <memory>
7
7
8 #include <QObject>
8 #include <QObject>
9 #include <QUuid>
9 #include <QUuid>
10
10
11 #include <Common/MetaTypes.h>
11 #include <Common/MetaTypes.h>
12
12
13 #include <Data/SqpRange.h>
13 #include <Data/SqpRange.h>
14
14
15 #include <functional>
15 #include <functional>
16
16
17 class DataProviderParameters;
17 class DataProviderParameters;
18 class IDataSeries;
18 class IDataSeries;
19 class QNetworkReply;
19 class QNetworkReply;
20 class QNetworkRequest;
20 class QNetworkRequest;
21
21
22 /**
22 /**
23 * @brief The IDataProvider interface aims to declare a data provider.
23 * @brief The IDataProvider interface aims to declare a data provider.
24 *
24 *
25 * A data provider is an entity that generates data and returns it according to various parameters
25 * A data provider is an entity that generates data and returns it according to various parameters
26 * (time interval, product to retrieve the data, etc.)
26 * (time interval, product to retrieve the data, etc.)
27 *
27 *
28 * @sa IDataSeries
28 * @sa IDataSeries
29 */
29 */
30 class SCIQLOP_CORE_EXPORT IDataProvider : public QObject {
30 class SCIQLOP_CORE_EXPORT IDataProvider : public QObject {
31
31
32 Q_OBJECT
32 Q_OBJECT
33 public:
33 public:
34 virtual ~IDataProvider() noexcept = default;
34 virtual ~IDataProvider() noexcept = default;
35 virtual std::shared_ptr<IDataProvider> clone() const = 0;
35
36
36 /**
37 /**
37 * @brief requestDataLoading provide datas for the data identified by acqIdentifier and
38 * @brief requestDataLoading provide datas for the data identified by acqIdentifier and
38 * parameters
39 * parameters
39 */
40 */
40 virtual void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
41 virtual void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
41 = 0;
42 = 0;
42
43
43 /**
44 /**
44 * @brief requestDataAborting stop data loading of the data identified by acqIdentifier
45 * @brief requestDataAborting stop data loading of the data identified by acqIdentifier
45 */
46 */
46 virtual void requestDataAborting(QUuid acqIdentifier) = 0;
47 virtual void requestDataAborting(QUuid acqIdentifier) = 0;
47
48
48 signals:
49 signals:
49 /**
50 /**
50 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
51 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
51 * identified by acqIdentifier
52 * identified by acqIdentifier
52 */
53 */
53 void dataProvided(QUuid acqIdentifier, std::shared_ptr<IDataSeries> dateSeriesAcquired,
54 void dataProvided(QUuid acqIdentifier, std::shared_ptr<IDataSeries> dateSeriesAcquired,
54 const SqpRange &dataRangeAcquired);
55 const SqpRange &dataRangeAcquired);
55
56
56 /**
57 /**
57 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
58 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
58 * identified by identifier
59 * identified by identifier
59 */
60 */
60 void dataProvidedProgress(QUuid acqIdentifier, double progress);
61 void dataProvidedProgress(QUuid acqIdentifier, double progress);
61
62
62
63
63 /**
64 /**
64 * @brief requestConstructed send a request for the data identified by acqIdentifier
65 * @brief requestConstructed send a request for the data identified by acqIdentifier
65 * @callback is the methode call by the reply of the request when it is finished.
66 * @callback is the methode call by the reply of the request when it is finished.
66 */
67 */
67 void requestConstructed(const QNetworkRequest &request, QUuid acqIdentifier,
68 void requestConstructed(const QNetworkRequest &request, QUuid acqIdentifier,
68 std::function<void(QNetworkReply *, QUuid)> callback);
69 std::function<void(QNetworkReply *, QUuid)> callback);
69 };
70 };
70
71
71 // Required for using shared_ptr in signals/slots
72 // Required for using shared_ptr in signals/slots
72 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
73 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
73 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
74 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
74 std::function<void(QNetworkReply *, QUuid)>)
75 std::function<void(QNetworkReply *, QUuid)>)
75
76
76 #endif // SCIQLOP_IDATAPROVIDER_H
77 #endif // SCIQLOP_IDATAPROVIDER_H
@@ -1,75 +1,80
1 #ifndef SCIQLOP_VARIABLE_H
1 #ifndef SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/DataSeriesIterator.h>
6 #include <Data/DataSeriesIterator.h>
7 #include <Data/SqpRange.h>
7 #include <Data/SqpRange.h>
8
8
9 #include <QLoggingCategory>
9 #include <QLoggingCategory>
10 #include <QObject>
10 #include <QObject>
11
11
12 #include <Common/MetaTypes.h>
12 #include <Common/MetaTypes.h>
13 #include <Common/spimpl.h>
13 #include <Common/spimpl.h>
14
14
15 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
15 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
16
16
17 class IDataSeries;
17 class IDataSeries;
18 class QString;
18 class QString;
19
19
20 /**
20 /**
21 * @brief The Variable class represents a variable in SciQlop.
21 * @brief The Variable class represents a variable in SciQlop.
22 */
22 */
23 class SCIQLOP_CORE_EXPORT Variable : public QObject {
23 class SCIQLOP_CORE_EXPORT Variable : public QObject {
24
24
25 Q_OBJECT
25 Q_OBJECT
26
26
27 public:
27 public:
28 explicit Variable(const QString &name, const SqpRange &dateTime,
28 explicit Variable(const QString &name, const SqpRange &dateTime,
29 const QVariantHash &metadata = {});
29 const QVariantHash &metadata = {});
30
30
31 /// Copy ctor
32 explicit Variable(const Variable &other);
33
34 std::shared_ptr<Variable> clone() const;
35
31 QString name() const noexcept;
36 QString name() const noexcept;
32 void setName(const QString &name) noexcept;
37 void setName(const QString &name) noexcept;
33 SqpRange range() const noexcept;
38 SqpRange range() const noexcept;
34 void setRange(const SqpRange &range) noexcept;
39 void setRange(const SqpRange &range) noexcept;
35 SqpRange cacheRange() const noexcept;
40 SqpRange cacheRange() const noexcept;
36 void setCacheRange(const SqpRange &cacheRange) noexcept;
41 void setCacheRange(const SqpRange &cacheRange) noexcept;
37
42
38 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
43 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
39 /// series between the range of the variable. The real range is updated each time the variable
44 /// series between the range of the variable. The real range is updated each time the variable
40 /// range or the data series changed
45 /// range or the data series changed
41 /// @return the real range, invalid range if the data series is null or empty
46 /// @return the real range, invalid range if the data series is null or empty
42 /// @sa setDataSeries()
47 /// @sa setDataSeries()
43 /// @sa setRange()
48 /// @sa setRange()
44 SqpRange realRange() const noexcept;
49 SqpRange realRange() const noexcept;
45
50
46 /// @return the data of the variable, nullptr if there is no data
51 /// @return the data of the variable, nullptr if there is no data
47 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
52 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
48
53
49 QVariantHash metadata() const noexcept;
54 QVariantHash metadata() const noexcept;
50
55
51 bool contains(const SqpRange &range) const noexcept;
56 bool contains(const SqpRange &range) const noexcept;
52 bool intersect(const SqpRange &range) const noexcept;
57 bool intersect(const SqpRange &range) const noexcept;
53 bool isInside(const SqpRange &range) const noexcept;
58 bool isInside(const SqpRange &range) const noexcept;
54
59
55 bool cacheContains(const SqpRange &range) const noexcept;
60 bool cacheContains(const SqpRange &range) const noexcept;
56 bool cacheIntersect(const SqpRange &range) const noexcept;
61 bool cacheIntersect(const SqpRange &range) const noexcept;
57 bool cacheIsInside(const SqpRange &range) const noexcept;
62 bool cacheIsInside(const SqpRange &range) const noexcept;
58
63
59 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
64 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
60 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
65 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
61 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
66 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
62
67
63 signals:
68 signals:
64 void updated();
69 void updated();
65
70
66 private:
71 private:
67 class VariablePrivate;
72 class VariablePrivate;
68 spimpl::unique_impl_ptr<VariablePrivate> impl;
73 spimpl::unique_impl_ptr<VariablePrivate> impl;
69 };
74 };
70
75
71 // Required for using shared_ptr in signals/slots
76 // Required for using shared_ptr in signals/slots
72 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
77 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
73 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
78 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
74
79
75 #endif // SCIQLOP_VARIABLE_H
80 #endif // SCIQLOP_VARIABLE_H
@@ -1,122 +1,129
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/AcquisitionDataPacket.h>
6 #include <Data/AcquisitionDataPacket.h>
7 #include <Data/SqpRange.h>
7 #include <Data/SqpRange.h>
8
8
9 #include <QLoggingCategory>
9 #include <QLoggingCategory>
10 #include <QObject>
10 #include <QObject>
11 #include <QUuid>
11 #include <QUuid>
12
12
13 #include <Common/spimpl.h>
13 #include <Common/spimpl.h>
14
14
15 class IDataProvider;
15 class IDataProvider;
16 class QItemSelectionModel;
16 class QItemSelectionModel;
17 class TimeController;
17 class TimeController;
18 class Variable;
18 class Variable;
19 class VariableModel;
19 class VariableModel;
20
20
21 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
21 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
22
22
23
23
24 /**
24 /**
25 * Possible types of zoom operation
25 * Possible types of zoom operation
26 */
26 */
27 enum class AcquisitionZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
27 enum class AcquisitionZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
28
28
29
29
30 /**
30 /**
31 * @brief The VariableController class aims to handle the variables in SciQlop.
31 * @brief The VariableController class aims to handle the variables in SciQlop.
32 */
32 */
33 class SCIQLOP_CORE_EXPORT VariableController : public QObject {
33 class SCIQLOP_CORE_EXPORT VariableController : public QObject {
34 Q_OBJECT
34 Q_OBJECT
35 public:
35 public:
36 explicit VariableController(QObject *parent = 0);
36 explicit VariableController(QObject *parent = 0);
37 virtual ~VariableController();
37 virtual ~VariableController();
38
38
39 VariableModel *variableModel() noexcept;
39 VariableModel *variableModel() noexcept;
40 QItemSelectionModel *variableSelectionModel() noexcept;
40 QItemSelectionModel *variableSelectionModel() noexcept;
41
41
42 void setTimeController(TimeController *timeController) noexcept;
42 void setTimeController(TimeController *timeController) noexcept;
43
43
44 /**
44 /**
45 * Clones the variable passed in parameter and adds the duplicate to the controller
46 * @param variable the variable to duplicate
47 * @return the duplicate created, nullptr if the variable couldn't be created
48 */
49 std::shared_ptr<Variable> cloneVariable(std::shared_ptr<Variable> variable) noexcept;
50
51 /**
45 * Deletes from the controller the variable passed in parameter.
52 * Deletes from the controller the variable passed in parameter.
46 *
53 *
47 * Delete a variable includes:
54 * Delete a variable includes:
48 * - the deletion of the various references to the variable in SciQlop
55 * - the deletion of the various references to the variable in SciQlop
49 * - the deletion of the model variable
56 * - the deletion of the model variable
50 * - the deletion of the provider associated with the variable
57 * - the deletion of the provider associated with the variable
51 * - removing the cache associated with the variable
58 * - removing the cache associated with the variable
52 *
59 *
53 * @param variable the variable to delete from the controller.
60 * @param variable the variable to delete from the controller.
54 */
61 */
55 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
62 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
56
63
57 /**
64 /**
58 * Deletes from the controller the variables passed in parameter.
65 * Deletes from the controller the variables passed in parameter.
59 * @param variables the variables to delete from the controller.
66 * @param variables the variables to delete from the controller.
60 * @sa deleteVariable()
67 * @sa deleteVariable()
61 */
68 */
62 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
69 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
63
70
64 /**
71 /**
65 * @brief abort the variable retrieve data progression
72 * @brief abort the variable retrieve data progression
66 */
73 */
67 void abortProgress(std::shared_ptr<Variable> variable);
74 void abortProgress(std::shared_ptr<Variable> variable);
68
75
69 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
76 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
70 signals:
77 signals:
71 /// Signal emitted when a variable is about to be deleted from the controller
78 /// Signal emitted when a variable is about to be deleted from the controller
72 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
79 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
73
80
74 /// Signal emitted when a data acquisition is requested on a range for a variable
81 /// Signal emitted when a data acquisition is requested on a range for a variable
75 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
82 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
76
83
77 /// Signal emitted when a sub range of the cacheRange of the variable can be displayed
84 /// Signal emitted when a sub range of the cacheRange of the variable can be displayed
78 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
85 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
79
86
80 public slots:
87 public slots:
81 /// Request the data loading of the variable whithin range
88 /// Request the data loading of the variable whithin range
82 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
89 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
83 const SqpRange &oldRange, bool synchronise);
90 const SqpRange &oldRange, bool synchronise);
84 /**
91 /**
85 * Creates a new variable and adds it to the model
92 * Creates a new variable and adds it to the model
86 * @param name the name of the new variable
93 * @param name the name of the new variable
87 * @param metadata the metadata of the new variable
94 * @param metadata the metadata of the new variable
88 * @param provider the data provider for the new variable
95 * @param provider the data provider for the new variable
89 * @return the pointer to the new variable or nullptr if the creation failed
96 * @return the pointer to the new variable or nullptr if the creation failed
90 */
97 */
91 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
98 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
92 std::shared_ptr<IDataProvider> provider) noexcept;
99 std::shared_ptr<IDataProvider> provider) noexcept;
93
100
94 /// Update the temporal parameters of every selected variable to dateTime
101 /// Update the temporal parameters of every selected variable to dateTime
95 void onDateTimeOnSelection(const SqpRange &dateTime);
102 void onDateTimeOnSelection(const SqpRange &dateTime);
96
103
97
104
98 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
105 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
99 const SqpRange &cacheRangeRequested,
106 const SqpRange &cacheRangeRequested,
100 QVector<AcquisitionDataPacket> dataAcquired);
107 QVector<AcquisitionDataPacket> dataAcquired);
101
108
102 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
109 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
103
110
104 /// Cancel the current request for the variable
111 /// Cancel the current request for the variable
105 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
112 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
106
113
107 /// synchronization group methods
114 /// synchronization group methods
108 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
115 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
109 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
116 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
110 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
117 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
111
118
112 void initialize();
119 void initialize();
113 void finalize();
120 void finalize();
114
121
115 private:
122 private:
116 void waitForFinish();
123 void waitForFinish();
117
124
118 class VariableControllerPrivate;
125 class VariableControllerPrivate;
119 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
126 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
120 };
127 };
121
128
122 #endif // SCIQLOP_VARIABLECONTROLLER_H
129 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,81 +1,96
1 #ifndef SCIQLOP_VARIABLEMODEL_H
1 #ifndef SCIQLOP_VARIABLEMODEL_H
2 #define SCIQLOP_VARIABLEMODEL_H
2 #define SCIQLOP_VARIABLEMODEL_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 #include <QAbstractTableModel>
8 #include <QAbstractTableModel>
9 #include <QLoggingCategory>
9 #include <QLoggingCategory>
10
10
11 #include <Common/MetaTypes.h>
11 #include <Common/MetaTypes.h>
12 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
15
15
16 enum VariableRoles { ProgressRole = Qt::UserRole };
16 enum VariableRoles { ProgressRole = Qt::UserRole };
17
17
18
18
19 class IDataSeries;
19 class IDataSeries;
20 class Variable;
20 class Variable;
21
21
22 /**
22 /**
23 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
23 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
24 */
24 */
25 class SCIQLOP_CORE_EXPORT VariableModel : public QAbstractTableModel {
25 class SCIQLOP_CORE_EXPORT VariableModel : public QAbstractTableModel {
26 Q_OBJECT
26 Q_OBJECT
27 public:
27 public:
28 explicit VariableModel(QObject *parent = nullptr);
28 explicit VariableModel(QObject *parent = nullptr);
29
29
30 /**
30 /**
31 * Adds an existing variable in the model.
32 * @param variable the variable to add.
33 * @remarks the variable's name is modified to avoid name duplicates
34 * @remarks this method does nothing if the variable already exists in the model
35 */
36 void addVariable(std::shared_ptr<Variable> variable) noexcept;
37
38 /**
39 * Checks that a variable is contained in the model
40 * @param variable the variable to check
41 * @return true if the variable is in the model, false otherwise
42 */
43 bool containsVariable(std::shared_ptr<Variable> variable) const noexcept;
44
45 /**
31 * Creates a new variable in the model
46 * Creates a new variable in the model
32 * @param name the name of the new variable
47 * @param name the name of the new variable
33 * @param dateTime the dateTime of the new variable
48 * @param dateTime the dateTime of the new variable
34 * @param metadata the metadata associated to the new variable
49 * @param metadata the metadata associated to the new variable
35 * @return the pointer to the new variable
50 * @return the pointer to the new variable
36 */
51 */
37 std::shared_ptr<Variable> createVariable(const QString &name, const SqpRange &dateTime,
52 std::shared_ptr<Variable> createVariable(const QString &name, const SqpRange &dateTime,
38 const QVariantHash &metadata) noexcept;
53 const QVariantHash &metadata) noexcept;
39
54
40 /**
55 /**
41 * Deletes a variable from the model, if it exists
56 * Deletes a variable from the model, if it exists
42 * @param variable the variable to delete
57 * @param variable the variable to delete
43 */
58 */
44 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
59 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
45
60
46
61
47 std::shared_ptr<Variable> variable(int index) const;
62 std::shared_ptr<Variable> variable(int index) const;
48 std::vector<std::shared_ptr<Variable> > variables() const;
63 std::vector<std::shared_ptr<Variable> > variables() const;
49
64
50 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
65 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
51
66
52
67
53 // /////////////////////////// //
68 // /////////////////////////// //
54 // QAbstractTableModel methods //
69 // QAbstractTableModel methods //
55 // /////////////////////////// //
70 // /////////////////////////// //
56
71
57 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
72 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
58 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
73 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
59 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
74 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
60 virtual QVariant headerData(int section, Qt::Orientation orientation,
75 virtual QVariant headerData(int section, Qt::Orientation orientation,
61 int role = Qt::DisplayRole) const override;
76 int role = Qt::DisplayRole) const override;
62
77
63
78
64 void abortProgress(const QModelIndex &index);
79 void abortProgress(const QModelIndex &index);
65
80
66 signals:
81 signals:
67 void abortProgessRequested(std::shared_ptr<Variable> variable);
82 void abortProgessRequested(std::shared_ptr<Variable> variable);
68
83
69 private:
84 private:
70 class VariableModelPrivate;
85 class VariableModelPrivate;
71 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
86 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
72
87
73 private slots:
88 private slots:
74 /// Slot called when data of a variable has been updated
89 /// Slot called when data of a variable has been updated
75 void onVariableUpdated() noexcept;
90 void onVariableUpdated() noexcept;
76 };
91 };
77
92
78 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
93 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
79 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
94 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
80
95
81 #endif // SCIQLOP_VARIABLEMODEL_H
96 #endif // SCIQLOP_VARIABLEMODEL_H
@@ -1,62 +1,63
1
1
2 core_moc_headers = [
2 core_moc_headers = [
3 'include/Data/IDataProvider.h',
3 'include/Data/IDataProvider.h',
4 'include/DataSource/DataSourceController.h',
4 'include/DataSource/DataSourceController.h',
5 'include/DataSource/DataSourceItemAction.h',
5 'include/DataSource/DataSourceItemAction.h',
6 'include/Network/NetworkController.h',
6 'include/Network/NetworkController.h',
7 'include/Time/TimeController.h',
7 'include/Time/TimeController.h',
8 'include/Variable/Variable.h',
8 'include/Variable/Variable.h',
9 'include/Variable/VariableCacheController.h',
9 'include/Variable/VariableCacheController.h',
10 'include/Variable/VariableController.h',
10 'include/Variable/VariableController.h',
11 'include/Variable/VariableAcquisitionWorker.h',
11 'include/Variable/VariableAcquisitionWorker.h',
12 'include/Variable/VariableCacheStrategy.h',
12 'include/Variable/VariableCacheStrategy.h',
13 'include/Variable/VariableSynchronizationGroup.h',
13 'include/Variable/VariableSynchronizationGroup.h',
14 'include/Variable/VariableModel.h',
14 'include/Variable/VariableModel.h',
15 'include/Visualization/VisualizationController.h'
15 'include/Visualization/VisualizationController.h'
16 ]
16 ]
17
17
18
18
19 core_moc_files = qt5.preprocess(moc_headers : core_moc_headers)
19 core_moc_files = qt5.preprocess(moc_headers : core_moc_headers)
20
20
21 core_sources = [
21 core_sources = [
22 'src/Common/DateUtils.cpp',
22 'src/Common/DateUtils.cpp',
23 'src/Common/StringUtils.cpp',
23 'src/Data/ScalarSeries.cpp',
24 'src/Data/ScalarSeries.cpp',
24 'src/Data/DataSeriesIterator.cpp',
25 'src/Data/DataSeriesIterator.cpp',
25 'src/Data/ArrayDataIterator.cpp',
26 'src/Data/ArrayDataIterator.cpp',
26 'src/Data/VectorSeries.cpp',
27 'src/Data/VectorSeries.cpp',
27 'src/DataSource/DataSourceController.cpp',
28 'src/DataSource/DataSourceController.cpp',
28 'src/DataSource/DataSourceItem.cpp',
29 'src/DataSource/DataSourceItem.cpp',
29 'src/DataSource/DataSourceItemAction.cpp',
30 'src/DataSource/DataSourceItemAction.cpp',
30 'src/Network/NetworkController.cpp',
31 'src/Network/NetworkController.cpp',
31 'src/Plugin/PluginManager.cpp',
32 'src/Plugin/PluginManager.cpp',
32 'src/Settings/SqpSettingsDefs.cpp',
33 'src/Settings/SqpSettingsDefs.cpp',
33 'src/Time/TimeController.cpp',
34 'src/Time/TimeController.cpp',
34 'src/Variable/Variable.cpp',
35 'src/Variable/Variable.cpp',
35 'src/Variable/VariableCacheController.cpp',
36 'src/Variable/VariableCacheController.cpp',
36 'src/Variable/VariableController.cpp',
37 'src/Variable/VariableController.cpp',
37 'src/Variable/VariableAcquisitionWorker.cpp',
38 'src/Variable/VariableAcquisitionWorker.cpp',
38 'src/Variable/VariableCacheStrategy.cpp',
39 'src/Variable/VariableCacheStrategy.cpp',
39 'src/Variable/VariableSynchronizationGroup.cpp',
40 'src/Variable/VariableSynchronizationGroup.cpp',
40 'src/Variable/VariableModel.cpp',
41 'src/Variable/VariableModel.cpp',
41 'src/Visualization/VisualizationController.cpp'
42 'src/Visualization/VisualizationController.cpp'
42 ]
43 ]
43
44
44 core_inc = include_directories(['include', '../plugin/include'])
45 core_inc = include_directories(['include', '../plugin/include'])
45
46
46 sciqlop_core_lib = library('sciqlopcore',
47 sciqlop_core_lib = library('sciqlopcore',
47 core_sources,
48 core_sources,
48 core_moc_files,
49 core_moc_files,
49 cpp_args : '-DCORE_LIB',
50 cpp_args : '-DCORE_LIB',
50 include_directories : core_inc,
51 include_directories : core_inc,
51 dependencies : [qt5core, qt5network],
52 dependencies : [qt5core, qt5network],
52 install : true
53 install : true
53 )
54 )
54
55
55
56
56 sciqlop_core = declare_dependency(link_with : sciqlop_core_lib,
57 sciqlop_core = declare_dependency(link_with : sciqlop_core_lib,
57 include_directories : core_inc,
58 include_directories : core_inc,
58 dependencies : [qt5core, qt5network])
59 dependencies : [qt5core, qt5network])
59
60
60
61
61 subdir('tests')
62 subdir('tests')
62
63
@@ -1,277 +1,296
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/SqpRange.h>
4 #include <Data/SqpRange.h>
5
5
6 #include <QMutex>
6 #include <QMutex>
7 #include <QReadWriteLock>
7 #include <QReadWriteLock>
8 #include <QThread>
8 #include <QThread>
9
9
10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
11
11
12 struct Variable::VariablePrivate {
12 struct Variable::VariablePrivate {
13 explicit VariablePrivate(const QString &name, const SqpRange &dateTime,
13 explicit VariablePrivate(const QString &name, const SqpRange &dateTime,
14 const QVariantHash &metadata)
14 const QVariantHash &metadata)
15 : m_Name{name},
15 : m_Name{name},
16 m_Range{dateTime},
16 m_Range{dateTime},
17 m_Metadata{metadata},
17 m_Metadata{metadata},
18 m_DataSeries{nullptr},
18 m_DataSeries{nullptr},
19 m_RealRange{INVALID_RANGE}
19 m_RealRange{INVALID_RANGE}
20 {
20 {
21 }
21 }
22
22
23 VariablePrivate(const VariablePrivate &other)
24 : m_Name{other.m_Name},
25 m_Range{other.m_Range},
26 m_Metadata{other.m_Metadata},
27 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
28 m_RealRange{other.m_RealRange}
29 {
30 }
31
23 void lockRead() { m_Lock.lockForRead(); }
32 void lockRead() { m_Lock.lockForRead(); }
24 void lockWrite() { m_Lock.lockForWrite(); }
33 void lockWrite() { m_Lock.lockForWrite(); }
25 void unlock() { m_Lock.unlock(); }
34 void unlock() { m_Lock.unlock(); }
26
35
27 void purgeDataSeries()
36 void purgeDataSeries()
28 {
37 {
29 if (m_DataSeries) {
38 if (m_DataSeries) {
30 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
39 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
31 }
40 }
32 updateRealRange();
41 updateRealRange();
33 }
42 }
34
43
35 /// Updates real range according to current variable range and data series
44 /// Updates real range according to current variable range and data series
36 void updateRealRange()
45 void updateRealRange()
37 {
46 {
38 if (m_DataSeries) {
47 if (m_DataSeries) {
39 m_DataSeries->lockRead();
48 m_DataSeries->lockRead();
40 auto end = m_DataSeries->cend();
49 auto end = m_DataSeries->cend();
41 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
50 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
42 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
51 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
43
52
44 m_RealRange = (minXAxisIt != end && maxXAxisIt != end)
53 m_RealRange = (minXAxisIt != end && maxXAxisIt != end)
45 ? SqpRange{minXAxisIt->x(), maxXAxisIt->x()}
54 ? SqpRange{minXAxisIt->x(), maxXAxisIt->x()}
46 : INVALID_RANGE;
55 : INVALID_RANGE;
47 m_DataSeries->unlock();
56 m_DataSeries->unlock();
48 }
57 }
49 else {
58 else {
50 m_RealRange = INVALID_RANGE;
59 m_RealRange = INVALID_RANGE;
51 }
60 }
52 }
61 }
53
62
54 QString m_Name;
63 QString m_Name;
55
64
56 SqpRange m_Range;
65 SqpRange m_Range;
57 SqpRange m_CacheRange;
66 SqpRange m_CacheRange;
58 QVariantHash m_Metadata;
67 QVariantHash m_Metadata;
59 std::shared_ptr<IDataSeries> m_DataSeries;
68 std::shared_ptr<IDataSeries> m_DataSeries;
60 SqpRange m_RealRange;
69 SqpRange m_RealRange;
61
70
62 QReadWriteLock m_Lock;
71 QReadWriteLock m_Lock;
63 };
72 };
64
73
65 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
74 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
66 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
75 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
67 {
76 {
68 }
77 }
69
78
79 Variable::Variable(const Variable &other)
80 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)}
81 {
82 }
83
84 std::shared_ptr<Variable> Variable::clone() const
85 {
86 return std::make_shared<Variable>(*this);
87 }
88
70 QString Variable::name() const noexcept
89 QString Variable::name() const noexcept
71 {
90 {
72 impl->lockRead();
91 impl->lockRead();
73 auto name = impl->m_Name;
92 auto name = impl->m_Name;
74 impl->unlock();
93 impl->unlock();
75 return name;
94 return name;
76 }
95 }
77
96
78 void Variable::setName(const QString &name) noexcept
97 void Variable::setName(const QString &name) noexcept
79 {
98 {
80 impl->lockWrite();
99 impl->lockWrite();
81 impl->m_Name = name;
100 impl->m_Name = name;
82 impl->unlock();
101 impl->unlock();
83 }
102 }
84
103
85 SqpRange Variable::range() const noexcept
104 SqpRange Variable::range() const noexcept
86 {
105 {
87 impl->lockRead();
106 impl->lockRead();
88 auto range = impl->m_Range;
107 auto range = impl->m_Range;
89 impl->unlock();
108 impl->unlock();
90 return range;
109 return range;
91 }
110 }
92
111
93 void Variable::setRange(const SqpRange &range) noexcept
112 void Variable::setRange(const SqpRange &range) noexcept
94 {
113 {
95 impl->lockWrite();
114 impl->lockWrite();
96 impl->m_Range = range;
115 impl->m_Range = range;
97 impl->updateRealRange();
116 impl->updateRealRange();
98 impl->unlock();
117 impl->unlock();
99 }
118 }
100
119
101 SqpRange Variable::cacheRange() const noexcept
120 SqpRange Variable::cacheRange() const noexcept
102 {
121 {
103 impl->lockRead();
122 impl->lockRead();
104 auto cacheRange = impl->m_CacheRange;
123 auto cacheRange = impl->m_CacheRange;
105 impl->unlock();
124 impl->unlock();
106 return cacheRange;
125 return cacheRange;
107 }
126 }
108
127
109 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
128 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
110 {
129 {
111 impl->lockWrite();
130 impl->lockWrite();
112 if (cacheRange != impl->m_CacheRange) {
131 if (cacheRange != impl->m_CacheRange) {
113 impl->m_CacheRange = cacheRange;
132 impl->m_CacheRange = cacheRange;
114 impl->purgeDataSeries();
133 impl->purgeDataSeries();
115 }
134 }
116 impl->unlock();
135 impl->unlock();
117 }
136 }
118
137
119 SqpRange Variable::realRange() const noexcept
138 SqpRange Variable::realRange() const noexcept
120 {
139 {
121 return impl->m_RealRange;
140 return impl->m_RealRange;
122 }
141 }
123
142
124 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
143 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
125 {
144 {
126 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
145 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
127 << QThread::currentThread()->objectName();
146 << QThread::currentThread()->objectName();
128 if (!dataSeries) {
147 if (!dataSeries) {
129 /// @todo ALX : log
148 /// @todo ALX : log
130 return;
149 return;
131 }
150 }
132
151
133 // Add or merge the data
152 // Add or merge the data
134 impl->lockWrite();
153 impl->lockWrite();
135 if (!impl->m_DataSeries) {
154 if (!impl->m_DataSeries) {
136 impl->m_DataSeries = dataSeries->clone();
155 impl->m_DataSeries = dataSeries->clone();
137 }
156 }
138 else {
157 else {
139 impl->m_DataSeries->merge(dataSeries.get());
158 impl->m_DataSeries->merge(dataSeries.get());
140 }
159 }
141 impl->purgeDataSeries();
160 impl->purgeDataSeries();
142 impl->unlock();
161 impl->unlock();
143 }
162 }
144
163
145 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
164 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
146 {
165 {
147 impl->lockRead();
166 impl->lockRead();
148 auto dataSeries = impl->m_DataSeries;
167 auto dataSeries = impl->m_DataSeries;
149 impl->unlock();
168 impl->unlock();
150
169
151 return dataSeries;
170 return dataSeries;
152 }
171 }
153
172
154 QVariantHash Variable::metadata() const noexcept
173 QVariantHash Variable::metadata() const noexcept
155 {
174 {
156 impl->lockRead();
175 impl->lockRead();
157 auto metadata = impl->m_Metadata;
176 auto metadata = impl->m_Metadata;
158 impl->unlock();
177 impl->unlock();
159 return metadata;
178 return metadata;
160 }
179 }
161
180
162 bool Variable::contains(const SqpRange &range) const noexcept
181 bool Variable::contains(const SqpRange &range) const noexcept
163 {
182 {
164 impl->lockRead();
183 impl->lockRead();
165 auto res = impl->m_Range.contains(range);
184 auto res = impl->m_Range.contains(range);
166 impl->unlock();
185 impl->unlock();
167 return res;
186 return res;
168 }
187 }
169
188
170 bool Variable::intersect(const SqpRange &range) const noexcept
189 bool Variable::intersect(const SqpRange &range) const noexcept
171 {
190 {
172
191
173 impl->lockRead();
192 impl->lockRead();
174 auto res = impl->m_Range.intersect(range);
193 auto res = impl->m_Range.intersect(range);
175 impl->unlock();
194 impl->unlock();
176 return res;
195 return res;
177 }
196 }
178
197
179 bool Variable::isInside(const SqpRange &range) const noexcept
198 bool Variable::isInside(const SqpRange &range) const noexcept
180 {
199 {
181 impl->lockRead();
200 impl->lockRead();
182 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
201 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
183 impl->unlock();
202 impl->unlock();
184 return res;
203 return res;
185 }
204 }
186
205
187 bool Variable::cacheContains(const SqpRange &range) const noexcept
206 bool Variable::cacheContains(const SqpRange &range) const noexcept
188 {
207 {
189 impl->lockRead();
208 impl->lockRead();
190 auto res = impl->m_CacheRange.contains(range);
209 auto res = impl->m_CacheRange.contains(range);
191 impl->unlock();
210 impl->unlock();
192 return res;
211 return res;
193 }
212 }
194
213
195 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
214 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
196 {
215 {
197 impl->lockRead();
216 impl->lockRead();
198 auto res = impl->m_CacheRange.intersect(range);
217 auto res = impl->m_CacheRange.intersect(range);
199 impl->unlock();
218 impl->unlock();
200 return res;
219 return res;
201 }
220 }
202
221
203 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
222 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
204 {
223 {
205 impl->lockRead();
224 impl->lockRead();
206 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
225 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
207 impl->unlock();
226 impl->unlock();
208 return res;
227 return res;
209 }
228 }
210
229
211
230
212 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
231 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
213 {
232 {
214 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
233 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
215
234
216 auto notInCache = QVector<SqpRange>{};
235 auto notInCache = QVector<SqpRange>{};
217
236
218 if (!this->cacheContains(range)) {
237 if (!this->cacheContains(range)) {
219 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
238 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
220 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
239 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
221 notInCache << range;
240 notInCache << range;
222 }
241 }
223 else if (range.m_TStart < impl->m_CacheRange.m_TStart
242 else if (range.m_TStart < impl->m_CacheRange.m_TStart
224 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
243 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
225 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
244 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
226 }
245 }
227 else if (range.m_TStart < impl->m_CacheRange.m_TStart
246 else if (range.m_TStart < impl->m_CacheRange.m_TStart
228 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
247 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
229 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
248 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
230 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
249 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
231 }
250 }
232 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
251 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
233 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
252 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
234 }
253 }
235 else {
254 else {
236 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
255 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
237 << QThread::currentThread();
256 << QThread::currentThread();
238 }
257 }
239 }
258 }
240
259
241 return notInCache;
260 return notInCache;
242 }
261 }
243
262
244 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
263 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
245 {
264 {
246 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
265 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
247
266
248 auto inCache = QVector<SqpRange>{};
267 auto inCache = QVector<SqpRange>{};
249
268
250
269
251 if (this->intersect(range)) {
270 if (this->intersect(range)) {
252 if (range.m_TStart <= impl->m_CacheRange.m_TStart
271 if (range.m_TStart <= impl->m_CacheRange.m_TStart
253 && range.m_TEnd >= impl->m_CacheRange.m_TStart
272 && range.m_TEnd >= impl->m_CacheRange.m_TStart
254 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
273 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
255 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
274 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
256 }
275 }
257
276
258 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
277 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
259 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
278 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
260 inCache << range;
279 inCache << range;
261 }
280 }
262 else if (range.m_TStart > impl->m_CacheRange.m_TStart
281 else if (range.m_TStart > impl->m_CacheRange.m_TStart
263 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
282 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
264 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
283 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
265 }
284 }
266 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
285 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
267 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
286 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
268 inCache << impl->m_CacheRange;
287 inCache << impl->m_CacheRange;
269 }
288 }
270 else {
289 else {
271 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
290 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
272 << QThread::currentThread();
291 << QThread::currentThread();
273 }
292 }
274 }
293 }
275
294
276 return inCache;
295 return inCache;
277 }
296 }
@@ -1,743 +1,775
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableAcquisitionWorker.h>
2 #include <Variable/VariableAcquisitionWorker.h>
3 #include <Variable/VariableCacheStrategy.h>
3 #include <Variable/VariableCacheStrategy.h>
4 #include <Variable/VariableController.h>
4 #include <Variable/VariableController.h>
5 #include <Variable/VariableModel.h>
5 #include <Variable/VariableModel.h>
6 #include <Variable/VariableSynchronizationGroup.h>
6 #include <Variable/VariableSynchronizationGroup.h>
7
7
8 #include <Data/DataProviderParameters.h>
8 #include <Data/DataProviderParameters.h>
9 #include <Data/IDataProvider.h>
9 #include <Data/IDataProvider.h>
10 #include <Data/IDataSeries.h>
10 #include <Data/IDataSeries.h>
11 #include <Data/VariableRequest.h>
11 #include <Data/VariableRequest.h>
12 #include <Time/TimeController.h>
12 #include <Time/TimeController.h>
13
13
14 #include <QMutex>
14 #include <QMutex>
15 #include <QThread>
15 #include <QThread>
16 #include <QUuid>
16 #include <QUuid>
17 #include <QtCore/QItemSelectionModel>
17 #include <QtCore/QItemSelectionModel>
18
18
19 #include <deque>
19 #include <deque>
20 #include <set>
20 #include <set>
21 #include <unordered_map>
21 #include <unordered_map>
22
22
23 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
23 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
24
24
25 namespace {
25 namespace {
26
26
27 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
27 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
28 const SqpRange &oldGraphRange)
28 const SqpRange &oldGraphRange)
29 {
29 {
30 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
30 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
31
31
32 auto varRangeRequested = varRange;
32 auto varRangeRequested = varRange;
33 switch (zoomType) {
33 switch (zoomType) {
34 case AcquisitionZoomType::ZoomIn: {
34 case AcquisitionZoomType::ZoomIn: {
35 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
35 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
36 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
36 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
37 varRangeRequested.m_TStart += deltaLeft;
37 varRangeRequested.m_TStart += deltaLeft;
38 varRangeRequested.m_TEnd -= deltaRight;
38 varRangeRequested.m_TEnd -= deltaRight;
39 break;
39 break;
40 }
40 }
41
41
42 case AcquisitionZoomType::ZoomOut: {
42 case AcquisitionZoomType::ZoomOut: {
43 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
43 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
44 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
44 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
45 varRangeRequested.m_TStart -= deltaLeft;
45 varRangeRequested.m_TStart -= deltaLeft;
46 varRangeRequested.m_TEnd += deltaRight;
46 varRangeRequested.m_TEnd += deltaRight;
47 break;
47 break;
48 }
48 }
49 case AcquisitionZoomType::PanRight: {
49 case AcquisitionZoomType::PanRight: {
50 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
50 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
51 varRangeRequested.m_TStart += deltaRight;
51 varRangeRequested.m_TStart += deltaRight;
52 varRangeRequested.m_TEnd += deltaRight;
52 varRangeRequested.m_TEnd += deltaRight;
53 break;
53 break;
54 }
54 }
55 case AcquisitionZoomType::PanLeft: {
55 case AcquisitionZoomType::PanLeft: {
56 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
56 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
57 varRangeRequested.m_TStart -= deltaLeft;
57 varRangeRequested.m_TStart -= deltaLeft;
58 varRangeRequested.m_TEnd -= deltaLeft;
58 varRangeRequested.m_TEnd -= deltaLeft;
59 break;
59 break;
60 }
60 }
61 case AcquisitionZoomType::Unknown: {
61 case AcquisitionZoomType::Unknown: {
62 qCCritical(LOG_VariableController())
62 qCCritical(LOG_VariableController())
63 << VariableController::tr("Impossible to synchronize: zoom type unknown");
63 << VariableController::tr("Impossible to synchronize: zoom type unknown");
64 break;
64 break;
65 }
65 }
66 default:
66 default:
67 qCCritical(LOG_VariableController()) << VariableController::tr(
67 qCCritical(LOG_VariableController()) << VariableController::tr(
68 "Impossible to synchronize: zoom type not take into account");
68 "Impossible to synchronize: zoom type not take into account");
69 // No action
69 // No action
70 break;
70 break;
71 }
71 }
72
72
73 return varRangeRequested;
73 return varRangeRequested;
74 }
74 }
75 }
75 }
76
76
77 struct VariableController::VariableControllerPrivate {
77 struct VariableController::VariableControllerPrivate {
78 explicit VariableControllerPrivate(VariableController *parent)
78 explicit VariableControllerPrivate(VariableController *parent)
79 : m_WorkingMutex{},
79 : m_WorkingMutex{},
80 m_VariableModel{new VariableModel{parent}},
80 m_VariableModel{new VariableModel{parent}},
81 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
81 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
82 m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
82 m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
83 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
83 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
84 q{parent}
84 q{parent}
85 {
85 {
86
86
87 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
87 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
88 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
88 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
89 }
89 }
90
90
91
91
92 virtual ~VariableControllerPrivate()
92 virtual ~VariableControllerPrivate()
93 {
93 {
94 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
94 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
95 m_VariableAcquisitionWorkerThread.quit();
95 m_VariableAcquisitionWorkerThread.quit();
96 m_VariableAcquisitionWorkerThread.wait();
96 m_VariableAcquisitionWorkerThread.wait();
97 }
97 }
98
98
99
99
100 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
100 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
101 QUuid varRequestId);
101 QUuid varRequestId);
102
102
103 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
103 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
104 const SqpRange &dateTime);
104 const SqpRange &dateTime);
105
105
106 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
106 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
107 std::shared_ptr<IDataSeries>
107 std::shared_ptr<IDataSeries>
108 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
108 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
109
109
110 void registerProvider(std::shared_ptr<IDataProvider> provider);
110 void registerProvider(std::shared_ptr<IDataProvider> provider);
111
111
112 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
112 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
113 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
113 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
114 void updateVariableRequest(QUuid varRequestId);
114 void updateVariableRequest(QUuid varRequestId);
115 void cancelVariableRequest(QUuid varRequestId);
115 void cancelVariableRequest(QUuid varRequestId);
116
116
117 QMutex m_WorkingMutex;
117 QMutex m_WorkingMutex;
118 /// Variable model. The VariableController has the ownership
118 /// Variable model. The VariableController has the ownership
119 VariableModel *m_VariableModel;
119 VariableModel *m_VariableModel;
120 QItemSelectionModel *m_VariableSelectionModel;
120 QItemSelectionModel *m_VariableSelectionModel;
121
121
122
122
123 TimeController *m_TimeController{nullptr};
123 TimeController *m_TimeController{nullptr};
124 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
124 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
125 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
125 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
126 QThread m_VariableAcquisitionWorkerThread;
126 QThread m_VariableAcquisitionWorkerThread;
127
127
128 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
128 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
129 m_VariableToProviderMap;
129 m_VariableToProviderMap;
130 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
130 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
131 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
131 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
132 m_GroupIdToVariableSynchronizationGroupMap;
132 m_GroupIdToVariableSynchronizationGroupMap;
133 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
133 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
134 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
134 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
135
135
136 std::map<QUuid, std::map<QUuid, VariableRequest> > m_VarRequestIdToVarIdVarRequestMap;
136 std::map<QUuid, std::map<QUuid, VariableRequest> > m_VarRequestIdToVarIdVarRequestMap;
137
137
138 std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap;
138 std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap;
139
139
140
140
141 VariableController *q;
141 VariableController *q;
142 };
142 };
143
143
144
144
145 VariableController::VariableController(QObject *parent)
145 VariableController::VariableController(QObject *parent)
146 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
146 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
147 {
147 {
148 qCDebug(LOG_VariableController()) << tr("VariableController construction")
148 qCDebug(LOG_VariableController()) << tr("VariableController construction")
149 << QThread::currentThread();
149 << QThread::currentThread();
150
150
151 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
151 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
152 &VariableController::onAbortProgressRequested);
152 &VariableController::onAbortProgressRequested);
153
153
154 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
154 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
155 &VariableController::onDataProvided);
155 &VariableController::onDataProvided);
156 connect(impl->m_VariableAcquisitionWorker.get(),
156 connect(impl->m_VariableAcquisitionWorker.get(),
157 &VariableAcquisitionWorker::variableRequestInProgress, this,
157 &VariableAcquisitionWorker::variableRequestInProgress, this,
158 &VariableController::onVariableRetrieveDataInProgress);
158 &VariableController::onVariableRetrieveDataInProgress);
159
159
160 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
160 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
161 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
161 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
162 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
162 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
163 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
163 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
164
164
165
165
166 impl->m_VariableAcquisitionWorkerThread.start();
166 impl->m_VariableAcquisitionWorkerThread.start();
167 }
167 }
168
168
169 VariableController::~VariableController()
169 VariableController::~VariableController()
170 {
170 {
171 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
171 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
172 << QThread::currentThread();
172 << QThread::currentThread();
173 this->waitForFinish();
173 this->waitForFinish();
174 }
174 }
175
175
176 VariableModel *VariableController::variableModel() noexcept
176 VariableModel *VariableController::variableModel() noexcept
177 {
177 {
178 return impl->m_VariableModel;
178 return impl->m_VariableModel;
179 }
179 }
180
180
181 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
181 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
182 {
182 {
183 return impl->m_VariableSelectionModel;
183 return impl->m_VariableSelectionModel;
184 }
184 }
185
185
186 void VariableController::setTimeController(TimeController *timeController) noexcept
186 void VariableController::setTimeController(TimeController *timeController) noexcept
187 {
187 {
188 impl->m_TimeController = timeController;
188 impl->m_TimeController = timeController;
189 }
189 }
190
190
191 std::shared_ptr<Variable>
192 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
193 {
194 if (impl->m_VariableModel->containsVariable(variable)) {
195 // Clones variable
196 auto duplicate = variable->clone();
197
198 // Adds clone to model
199 impl->m_VariableModel->addVariable(duplicate);
200
201 // Generates clone identifier
202 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
203
204 // Registers provider
205 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
206 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
207
208 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
209 if (duplicateProvider) {
210 impl->registerProvider(duplicateProvider);
211 }
212
213 return duplicate;
214 }
215 else {
216 qCCritical(LOG_VariableController())
217 << tr("Can't create duplicate of variable %1: variable not registered in the model")
218 .arg(variable->name());
219 return nullptr;
220 }
221 }
222
191 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
223 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
192 {
224 {
193 if (!variable) {
225 if (!variable) {
194 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
226 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
195 return;
227 return;
196 }
228 }
197
229
198 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
230 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
199 // make some treatments before the deletion
231 // make some treatments before the deletion
200 emit variableAboutToBeDeleted(variable);
232 emit variableAboutToBeDeleted(variable);
201
233
202 // Deletes identifier
234 // Deletes identifier
203 impl->m_VariableToIdentifierMap.erase(variable);
235 impl->m_VariableToIdentifierMap.erase(variable);
204
236
205 // Deletes provider
237 // Deletes provider
206 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
238 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
207 qCDebug(LOG_VariableController())
239 qCDebug(LOG_VariableController())
208 << tr("Number of providers deleted for variable %1: %2")
240 << tr("Number of providers deleted for variable %1: %2")
209 .arg(variable->name(), QString::number(nbProvidersDeleted));
241 .arg(variable->name(), QString::number(nbProvidersDeleted));
210
242
211
243
212 // Deletes from model
244 // Deletes from model
213 impl->m_VariableModel->deleteVariable(variable);
245 impl->m_VariableModel->deleteVariable(variable);
214 }
246 }
215
247
216 void VariableController::deleteVariables(
248 void VariableController::deleteVariables(
217 const QVector<std::shared_ptr<Variable> > &variables) noexcept
249 const QVector<std::shared_ptr<Variable> > &variables) noexcept
218 {
250 {
219 for (auto variable : qAsConst(variables)) {
251 for (auto variable : qAsConst(variables)) {
220 deleteVariable(variable);
252 deleteVariable(variable);
221 }
253 }
222 }
254 }
223
255
224 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
256 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
225 {
257 {
226 }
258 }
227
259
228 std::shared_ptr<Variable>
260 std::shared_ptr<Variable>
229 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
261 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
230 std::shared_ptr<IDataProvider> provider) noexcept
262 std::shared_ptr<IDataProvider> provider) noexcept
231 {
263 {
232 if (!impl->m_TimeController) {
264 if (!impl->m_TimeController) {
233 qCCritical(LOG_VariableController())
265 qCCritical(LOG_VariableController())
234 << tr("Impossible to create variable: The time controller is null");
266 << tr("Impossible to create variable: The time controller is null");
235 return nullptr;
267 return nullptr;
236 }
268 }
237
269
238 auto range = impl->m_TimeController->dateTime();
270 auto range = impl->m_TimeController->dateTime();
239
271
240 if (auto newVariable = impl->m_VariableModel->createVariable(name, range, metadata)) {
272 if (auto newVariable = impl->m_VariableModel->createVariable(name, range, metadata)) {
241 auto identifier = QUuid::createUuid();
273 auto identifier = QUuid::createUuid();
242
274
243 // store the provider
275 // store the provider
244 impl->registerProvider(provider);
276 impl->registerProvider(provider);
245
277
246 // Associate the provider
278 // Associate the provider
247 impl->m_VariableToProviderMap[newVariable] = provider;
279 impl->m_VariableToProviderMap[newVariable] = provider;
248 impl->m_VariableToIdentifierMap[newVariable] = identifier;
280 impl->m_VariableToIdentifierMap[newVariable] = identifier;
249
281
250
282
251 auto varRequestId = QUuid::createUuid();
283 auto varRequestId = QUuid::createUuid();
252 qCInfo(LOG_VariableController()) << "processRequest for" << name << varRequestId;
284 qCInfo(LOG_VariableController()) << "processRequest for" << name << varRequestId;
253 impl->processRequest(newVariable, range, varRequestId);
285 impl->processRequest(newVariable, range, varRequestId);
254 impl->updateVariableRequest(varRequestId);
286 impl->updateVariableRequest(varRequestId);
255
287
256 return newVariable;
288 return newVariable;
257 }
289 }
258 }
290 }
259
291
260 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
292 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
261 {
293 {
262 // TODO check synchronisation and Rescale
294 // TODO check synchronisation and Rescale
263 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
295 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
264 << QThread::currentThread()->objectName();
296 << QThread::currentThread()->objectName();
265 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
297 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
266 auto varRequestId = QUuid::createUuid();
298 auto varRequestId = QUuid::createUuid();
267
299
268 for (const auto &selectedRow : qAsConst(selectedRows)) {
300 for (const auto &selectedRow : qAsConst(selectedRows)) {
269 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
301 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
270 selectedVariable->setRange(dateTime);
302 selectedVariable->setRange(dateTime);
271 impl->processRequest(selectedVariable, dateTime, varRequestId);
303 impl->processRequest(selectedVariable, dateTime, varRequestId);
272
304
273 // notify that rescale operation has to be done
305 // notify that rescale operation has to be done
274 emit rangeChanged(selectedVariable, dateTime);
306 emit rangeChanged(selectedVariable, dateTime);
275 }
307 }
276 }
308 }
277 impl->updateVariableRequest(varRequestId);
309 impl->updateVariableRequest(varRequestId);
278 }
310 }
279
311
280 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
312 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
281 const SqpRange &cacheRangeRequested,
313 const SqpRange &cacheRangeRequested,
282 QVector<AcquisitionDataPacket> dataAcquired)
314 QVector<AcquisitionDataPacket> dataAcquired)
283 {
315 {
284 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
316 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
285 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
317 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
286 if (!varRequestId.isNull()) {
318 if (!varRequestId.isNull()) {
287 impl->updateVariableRequest(varRequestId);
319 impl->updateVariableRequest(varRequestId);
288 }
320 }
289 }
321 }
290
322
291 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
323 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
292 {
324 {
293 if (auto var = impl->findVariable(identifier)) {
325 if (auto var = impl->findVariable(identifier)) {
294 impl->m_VariableModel->setDataProgress(var, progress);
326 impl->m_VariableModel->setDataProgress(var, progress);
295 }
327 }
296 else {
328 else {
297 qCCritical(LOG_VariableController())
329 qCCritical(LOG_VariableController())
298 << tr("Impossible to notify progression of a null variable");
330 << tr("Impossible to notify progression of a null variable");
299 }
331 }
300 }
332 }
301
333
302 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
334 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
303 {
335 {
304 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
336 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
305 << QThread::currentThread()->objectName();
337 << QThread::currentThread()->objectName();
306
338
307 auto it = impl->m_VariableToIdentifierMap.find(variable);
339 auto it = impl->m_VariableToIdentifierMap.find(variable);
308 if (it != impl->m_VariableToIdentifierMap.cend()) {
340 if (it != impl->m_VariableToIdentifierMap.cend()) {
309 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
341 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
310 }
342 }
311 else {
343 else {
312 qCWarning(LOG_VariableController())
344 qCWarning(LOG_VariableController())
313 << tr("Aborting progression of inexistant variable detected !!!")
345 << tr("Aborting progression of inexistant variable detected !!!")
314 << QThread::currentThread()->objectName();
346 << QThread::currentThread()->objectName();
315 }
347 }
316 }
348 }
317
349
318 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
350 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
319 {
351 {
320 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
352 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
321 << QThread::currentThread()->objectName()
353 << QThread::currentThread()->objectName()
322 << synchronizationGroupId;
354 << synchronizationGroupId;
323 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
355 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
324 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
356 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
325 std::make_pair(synchronizationGroupId, vSynchroGroup));
357 std::make_pair(synchronizationGroupId, vSynchroGroup));
326 }
358 }
327
359
328 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
360 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
329 {
361 {
330 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
362 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
331 }
363 }
332
364
333 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
365 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
334 QUuid synchronizationGroupId)
366 QUuid synchronizationGroupId)
335
367
336 {
368 {
337 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
369 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
338 << synchronizationGroupId;
370 << synchronizationGroupId;
339 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
371 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
340 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
372 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
341 auto groupIdToVSGIt
373 auto groupIdToVSGIt
342 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
374 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
343 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
375 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
344 impl->m_VariableIdGroupIdMap.insert(
376 impl->m_VariableIdGroupIdMap.insert(
345 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
377 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
346 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
378 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
347 }
379 }
348 else {
380 else {
349 qCCritical(LOG_VariableController())
381 qCCritical(LOG_VariableController())
350 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
382 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
351 << variable->name();
383 << variable->name();
352 }
384 }
353 }
385 }
354 else {
386 else {
355 qCCritical(LOG_VariableController())
387 qCCritical(LOG_VariableController())
356 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
388 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
357 }
389 }
358 }
390 }
359
391
360
392
361 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
393 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
362 const SqpRange &range, const SqpRange &oldRange,
394 const SqpRange &range, const SqpRange &oldRange,
363 bool synchronise)
395 bool synchronise)
364 {
396 {
365 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
397 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
366
398
367 // we want to load data of the variable for the dateTime.
399 // we want to load data of the variable for the dateTime.
368 // First we check if the cache contains some of them.
400 // First we check if the cache contains some of them.
369 // For the other, we ask the provider to give them.
401 // For the other, we ask the provider to give them.
370
402
371 auto varRequestId = QUuid::createUuid();
403 auto varRequestId = QUuid::createUuid();
372 qCInfo(LOG_VariableController()) << "VariableController::onRequestDataLoading"
404 qCInfo(LOG_VariableController()) << "VariableController::onRequestDataLoading"
373 << QThread::currentThread()->objectName() << varRequestId;
405 << QThread::currentThread()->objectName() << varRequestId;
374
406
375 for (const auto &var : variables) {
407 for (const auto &var : variables) {
376 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId;
408 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId;
377 impl->processRequest(var, range, varRequestId);
409 impl->processRequest(var, range, varRequestId);
378 }
410 }
379
411
380 if (synchronise) {
412 if (synchronise) {
381 // Get the group ids
413 // Get the group ids
382 qCDebug(LOG_VariableController())
414 qCDebug(LOG_VariableController())
383 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
415 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
384 auto groupIds = std::set<QUuid>{};
416 auto groupIds = std::set<QUuid>{};
385 auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{};
417 auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{};
386 for (const auto &var : variables) {
418 for (const auto &var : variables) {
387 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
419 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
388 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
420 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
389 auto vId = varToVarIdIt->second;
421 auto vId = varToVarIdIt->second;
390 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
422 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
391 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
423 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
392 auto gId = varIdToGroupIdIt->second;
424 auto gId = varIdToGroupIdIt->second;
393 groupIdToOldRangeMap.insert(std::make_pair(gId, var->range()));
425 groupIdToOldRangeMap.insert(std::make_pair(gId, var->range()));
394 if (groupIds.find(gId) == groupIds.cend()) {
426 if (groupIds.find(gId) == groupIds.cend()) {
395 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
427 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
396 groupIds.insert(gId);
428 groupIds.insert(gId);
397 }
429 }
398 }
430 }
399 }
431 }
400 }
432 }
401
433
402 // We assume here all group ids exist
434 // We assume here all group ids exist
403 for (const auto &gId : groupIds) {
435 for (const auto &gId : groupIds) {
404 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
436 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
405 auto vSyncIds = vSynchronizationGroup->getIds();
437 auto vSyncIds = vSynchronizationGroup->getIds();
406 qCDebug(LOG_VariableController()) << "Var in synchro group ";
438 qCDebug(LOG_VariableController()) << "Var in synchro group ";
407 for (auto vId : vSyncIds) {
439 for (auto vId : vSyncIds) {
408 auto var = impl->findVariable(vId);
440 auto var = impl->findVariable(vId);
409
441
410 // Don't process already processed var
442 // Don't process already processed var
411 if (!variables.contains(var)) {
443 if (!variables.contains(var)) {
412 if (var != nullptr) {
444 if (var != nullptr) {
413 qCDebug(LOG_VariableController()) << "processRequest synchro for"
445 qCDebug(LOG_VariableController()) << "processRequest synchro for"
414 << var->name();
446 << var->name();
415 auto vSyncRangeRequested = computeSynchroRangeRequested(
447 auto vSyncRangeRequested = computeSynchroRangeRequested(
416 var->range(), range, groupIdToOldRangeMap.at(gId));
448 var->range(), range, groupIdToOldRangeMap.at(gId));
417 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
449 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
418 impl->processRequest(var, vSyncRangeRequested, varRequestId);
450 impl->processRequest(var, vSyncRangeRequested, varRequestId);
419 }
451 }
420 else {
452 else {
421 qCCritical(LOG_VariableController())
453 qCCritical(LOG_VariableController())
422
454
423 << tr("Impossible to synchronize a null variable");
455 << tr("Impossible to synchronize a null variable");
424 }
456 }
425 }
457 }
426 }
458 }
427 }
459 }
428 }
460 }
429
461
430 impl->updateVariableRequest(varRequestId);
462 impl->updateVariableRequest(varRequestId);
431 }
463 }
432
464
433
465
434 void VariableController::initialize()
466 void VariableController::initialize()
435 {
467 {
436 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
468 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
437 impl->m_WorkingMutex.lock();
469 impl->m_WorkingMutex.lock();
438 qCDebug(LOG_VariableController()) << tr("VariableController init END");
470 qCDebug(LOG_VariableController()) << tr("VariableController init END");
439 }
471 }
440
472
441 void VariableController::finalize()
473 void VariableController::finalize()
442 {
474 {
443 impl->m_WorkingMutex.unlock();
475 impl->m_WorkingMutex.unlock();
444 }
476 }
445
477
446 void VariableController::waitForFinish()
478 void VariableController::waitForFinish()
447 {
479 {
448 QMutexLocker locker{&impl->m_WorkingMutex};
480 QMutexLocker locker{&impl->m_WorkingMutex};
449 }
481 }
450
482
451 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
483 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
452 {
484 {
453 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
485 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
454 auto zoomType = AcquisitionZoomType::Unknown;
486 auto zoomType = AcquisitionZoomType::Unknown;
455 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
487 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
456 zoomType = AcquisitionZoomType::ZoomOut;
488 zoomType = AcquisitionZoomType::ZoomOut;
457 }
489 }
458 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
490 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
459 zoomType = AcquisitionZoomType::PanRight;
491 zoomType = AcquisitionZoomType::PanRight;
460 }
492 }
461 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
493 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
462 zoomType = AcquisitionZoomType::PanLeft;
494 zoomType = AcquisitionZoomType::PanLeft;
463 }
495 }
464 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
496 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
465 zoomType = AcquisitionZoomType::ZoomIn;
497 zoomType = AcquisitionZoomType::ZoomIn;
466 }
498 }
467 else {
499 else {
468 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
500 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
469 }
501 }
470 return zoomType;
502 return zoomType;
471 }
503 }
472
504
473 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
505 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
474 const SqpRange &rangeRequested,
506 const SqpRange &rangeRequested,
475 QUuid varRequestId)
507 QUuid varRequestId)
476 {
508 {
477
509
478 // TODO: protect at
510 // TODO: protect at
479 auto varRequest = VariableRequest{};
511 auto varRequest = VariableRequest{};
480 auto varId = m_VariableToIdentifierMap.at(var);
512 auto varId = m_VariableToIdentifierMap.at(var);
481
513
482 auto varStrategyRangesRequested
514 auto varStrategyRangesRequested
483 = m_VariableCacheStrategy->computeStrategyRanges(var->range(), rangeRequested);
515 = m_VariableCacheStrategy->computeStrategyRanges(var->range(), rangeRequested);
484 auto notInCacheRangeList = var->provideNotInCacheRangeList(varStrategyRangesRequested.second);
516 auto notInCacheRangeList = var->provideNotInCacheRangeList(varStrategyRangesRequested.second);
485 auto inCacheRangeList = var->provideInCacheRangeList(varStrategyRangesRequested.second);
517 auto inCacheRangeList = var->provideInCacheRangeList(varStrategyRangesRequested.second);
486
518
487 if (!notInCacheRangeList.empty()) {
519 if (!notInCacheRangeList.empty()) {
488 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
520 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
489 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
521 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
490 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest RR ") << rangeRequested;
522 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest RR ") << rangeRequested;
491 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest R ")
523 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest R ")
492 << varStrategyRangesRequested.first;
524 << varStrategyRangesRequested.first;
493 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest CR ")
525 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest CR ")
494 << varStrategyRangesRequested.second;
526 << varStrategyRangesRequested.second;
495 // store VarRequest
527 // store VarRequest
496 storeVariableRequest(varId, varRequestId, varRequest);
528 storeVariableRequest(varId, varRequestId, varRequest);
497
529
498 auto varProvider = m_VariableToProviderMap.at(var);
530 auto varProvider = m_VariableToProviderMap.at(var);
499 if (varProvider != nullptr) {
531 if (varProvider != nullptr) {
500 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
532 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
501 varRequestId, varId, varStrategyRangesRequested.first,
533 varRequestId, varId, varStrategyRangesRequested.first,
502 varStrategyRangesRequested.second,
534 varStrategyRangesRequested.second,
503 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
535 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
504 varProvider);
536 varProvider);
505
537
506 if (!varRequestIdCanceled.isNull()) {
538 if (!varRequestIdCanceled.isNull()) {
507 qCInfo(LOG_VariableAcquisitionWorker()) << tr("varRequestIdCanceled: ")
539 qCInfo(LOG_VariableAcquisitionWorker()) << tr("varRequestIdCanceled: ")
508 << varRequestIdCanceled;
540 << varRequestIdCanceled;
509 cancelVariableRequest(varRequestIdCanceled);
541 cancelVariableRequest(varRequestIdCanceled);
510 }
542 }
511 }
543 }
512 else {
544 else {
513 qCCritical(LOG_VariableController())
545 qCCritical(LOG_VariableController())
514 << "Impossible to provide data with a null provider";
546 << "Impossible to provide data with a null provider";
515 }
547 }
516
548
517 if (!inCacheRangeList.empty()) {
549 if (!inCacheRangeList.empty()) {
518 emit q->updateVarDisplaying(var, inCacheRangeList.first());
550 emit q->updateVarDisplaying(var, inCacheRangeList.first());
519 }
551 }
520 }
552 }
521 else {
553 else {
522
554
523 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
555 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
524 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
556 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
525 // store VarRequest
557 // store VarRequest
526 storeVariableRequest(varId, varRequestId, varRequest);
558 storeVariableRequest(varId, varRequestId, varRequest);
527 acceptVariableRequest(varId,
559 acceptVariableRequest(varId,
528 var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
560 var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
529 }
561 }
530 }
562 }
531
563
532 std::shared_ptr<Variable>
564 std::shared_ptr<Variable>
533 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
565 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
534 {
566 {
535 std::shared_ptr<Variable> var;
567 std::shared_ptr<Variable> var;
536 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
568 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
537
569
538 auto end = m_VariableToIdentifierMap.cend();
570 auto end = m_VariableToIdentifierMap.cend();
539 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
571 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
540 if (it != end) {
572 if (it != end) {
541 var = it->first;
573 var = it->first;
542 }
574 }
543 else {
575 else {
544 qCCritical(LOG_VariableController())
576 qCCritical(LOG_VariableController())
545 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
577 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
546 }
578 }
547
579
548 return var;
580 return var;
549 }
581 }
550
582
551 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
583 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
552 const QVector<AcquisitionDataPacket> acqDataPacketVector)
584 const QVector<AcquisitionDataPacket> acqDataPacketVector)
553 {
585 {
554 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
586 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
555 << acqDataPacketVector.size();
587 << acqDataPacketVector.size();
556 std::shared_ptr<IDataSeries> dataSeries;
588 std::shared_ptr<IDataSeries> dataSeries;
557 if (!acqDataPacketVector.isEmpty()) {
589 if (!acqDataPacketVector.isEmpty()) {
558 dataSeries = acqDataPacketVector[0].m_DateSeries;
590 dataSeries = acqDataPacketVector[0].m_DateSeries;
559 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
591 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
560 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
592 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
561 }
593 }
562 }
594 }
563 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
595 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
564 << acqDataPacketVector.size();
596 << acqDataPacketVector.size();
565 return dataSeries;
597 return dataSeries;
566 }
598 }
567
599
568 void VariableController::VariableControllerPrivate::registerProvider(
600 void VariableController::VariableControllerPrivate::registerProvider(
569 std::shared_ptr<IDataProvider> provider)
601 std::shared_ptr<IDataProvider> provider)
570 {
602 {
571 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
603 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
572 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
604 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
573 << provider->objectName();
605 << provider->objectName();
574 m_ProviderSet.insert(provider);
606 m_ProviderSet.insert(provider);
575 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
607 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
576 &VariableAcquisitionWorker::onVariableDataAcquired);
608 &VariableAcquisitionWorker::onVariableDataAcquired);
577 connect(provider.get(), &IDataProvider::dataProvidedProgress,
609 connect(provider.get(), &IDataProvider::dataProvidedProgress,
578 m_VariableAcquisitionWorker.get(),
610 m_VariableAcquisitionWorker.get(),
579 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
611 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
580 }
612 }
581 else {
613 else {
582 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
614 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
583 }
615 }
584 }
616 }
585
617
586 void VariableController::VariableControllerPrivate::storeVariableRequest(
618 void VariableController::VariableControllerPrivate::storeVariableRequest(
587 QUuid varId, QUuid varRequestId, const VariableRequest &varRequest)
619 QUuid varId, QUuid varRequestId, const VariableRequest &varRequest)
588 {
620 {
589 // First request for the variable. we can create an entry for it
621 // First request for the variable. we can create an entry for it
590 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
622 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
591 if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) {
623 if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) {
592 auto varRequestIdQueue = std::deque<QUuid>{};
624 auto varRequestIdQueue = std::deque<QUuid>{};
593 qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE");
625 qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE");
594 varRequestIdQueue.push_back(varRequestId);
626 varRequestIdQueue.push_back(varRequestId);
595 m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue)));
627 m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue)));
596 }
628 }
597 else {
629 else {
598 qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE");
630 qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE");
599 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
631 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
600 varRequestIdQueue.push_back(varRequestId);
632 varRequestIdQueue.push_back(varRequestId);
601 }
633 }
602
634
603 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
635 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
604 if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) {
636 if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) {
605 auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{};
637 auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{};
606 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
638 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
607 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP");
639 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP");
608 m_VarRequestIdToVarIdVarRequestMap.insert(
640 m_VarRequestIdToVarIdVarRequestMap.insert(
609 std::make_pair(varRequestId, std::move(varIdToVarRequestMap)));
641 std::make_pair(varRequestId, std::move(varIdToVarRequestMap)));
610 }
642 }
611 else {
643 else {
612 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
644 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
613 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP");
645 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP");
614 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
646 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
615 }
647 }
616 }
648 }
617
649
618 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
650 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
619 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
651 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
620 {
652 {
621 QUuid varRequestId;
653 QUuid varRequestId;
622 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
654 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
623 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
655 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
624 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
656 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
625 varRequestId = varRequestIdQueue.front();
657 varRequestId = varRequestIdQueue.front();
626 auto varRequestIdToVarIdVarRequestMapIt
658 auto varRequestIdToVarIdVarRequestMapIt
627 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
659 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
628 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
660 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
629 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
661 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
630 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
662 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
631 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
663 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
632 qCDebug(LOG_VariableController()) << tr("acceptVariableRequest");
664 qCDebug(LOG_VariableController()) << tr("acceptVariableRequest");
633 auto &varRequest = varIdToVarRequestMapIt->second;
665 auto &varRequest = varIdToVarRequestMapIt->second;
634 varRequest.m_DataSeries = dataSeries;
666 varRequest.m_DataSeries = dataSeries;
635 varRequest.m_CanUpdate = true;
667 varRequest.m_CanUpdate = true;
636 }
668 }
637 else {
669 else {
638 qCDebug(LOG_VariableController())
670 qCDebug(LOG_VariableController())
639 << tr("Impossible to acceptVariableRequest of a unknown variable id attached "
671 << tr("Impossible to acceptVariableRequest of a unknown variable id attached "
640 "to a variableRequestId")
672 "to a variableRequestId")
641 << varRequestId << varId;
673 << varRequestId << varId;
642 }
674 }
643 }
675 }
644 else {
676 else {
645 qCCritical(LOG_VariableController())
677 qCCritical(LOG_VariableController())
646 << tr("Impossible to acceptVariableRequest of a unknown variableRequestId")
678 << tr("Impossible to acceptVariableRequest of a unknown variableRequestId")
647 << varRequestId;
679 << varRequestId;
648 }
680 }
649
681
650 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in QUEUE ?")
682 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in QUEUE ?")
651 << varRequestIdQueue.size();
683 << varRequestIdQueue.size();
652 varRequestIdQueue.pop_front();
684 varRequestIdQueue.pop_front();
653 qCDebug(LOG_VariableController()) << tr("2: erase REQUEST in QUEUE ?")
685 qCDebug(LOG_VariableController()) << tr("2: erase REQUEST in QUEUE ?")
654 << varRequestIdQueue.size();
686 << varRequestIdQueue.size();
655 if (varRequestIdQueue.empty()) {
687 if (varRequestIdQueue.empty()) {
656 m_VarIdToVarRequestIdQueueMap.erase(varId);
688 m_VarIdToVarRequestIdQueueMap.erase(varId);
657 }
689 }
658 }
690 }
659 else {
691 else {
660 qCCritical(LOG_VariableController())
692 qCCritical(LOG_VariableController())
661 << tr("Impossible to acceptVariableRequest of a unknown variable id") << varId;
693 << tr("Impossible to acceptVariableRequest of a unknown variable id") << varId;
662 }
694 }
663
695
664 return varRequestId;
696 return varRequestId;
665 }
697 }
666
698
667 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
699 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
668 {
700 {
669
701
670 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
702 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
671 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
703 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
672 bool processVariableUpdate = true;
704 bool processVariableUpdate = true;
673 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
705 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
674 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
706 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
675 (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) && processVariableUpdate;
707 (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) && processVariableUpdate;
676 ++varIdToVarRequestMapIt) {
708 ++varIdToVarRequestMapIt) {
677 processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate;
709 processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate;
678 qCDebug(LOG_VariableController()) << tr("updateVariableRequest")
710 qCDebug(LOG_VariableController()) << tr("updateVariableRequest")
679 << processVariableUpdate;
711 << processVariableUpdate;
680 }
712 }
681
713
682 if (processVariableUpdate) {
714 if (processVariableUpdate) {
683 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
715 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
684 varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) {
716 varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) {
685 if (auto var = findVariable(varIdToVarRequestMapIt->first)) {
717 if (auto var = findVariable(varIdToVarRequestMapIt->first)) {
686 auto &varRequest = varIdToVarRequestMapIt->second;
718 auto &varRequest = varIdToVarRequestMapIt->second;
687 var->setRange(varRequest.m_RangeRequested);
719 var->setRange(varRequest.m_RangeRequested);
688 var->setCacheRange(varRequest.m_CacheRangeRequested);
720 var->setCacheRange(varRequest.m_CacheRangeRequested);
689 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
721 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
690 << varRequest.m_RangeRequested;
722 << varRequest.m_RangeRequested;
691 qCDebug(LOG_VariableController()) << tr("2: onDataProvided")
723 qCDebug(LOG_VariableController()) << tr("2: onDataProvided")
692 << varRequest.m_CacheRangeRequested;
724 << varRequest.m_CacheRangeRequested;
693 var->mergeDataSeries(varRequest.m_DataSeries);
725 var->mergeDataSeries(varRequest.m_DataSeries);
694 qCDebug(LOG_VariableController()) << tr("3: onDataProvided")
726 qCDebug(LOG_VariableController()) << tr("3: onDataProvided")
695 << varRequest.m_DataSeries->range();
727 << varRequest.m_DataSeries->range();
696 qCDebug(LOG_VariableController()) << tr("4: onDataProvided");
728 qCDebug(LOG_VariableController()) << tr("4: onDataProvided");
697
729
698 /// @todo MPL: confirm
730 /// @todo MPL: confirm
699 // Variable update is notified only if there is no pending request for it
731 // Variable update is notified only if there is no pending request for it
700 if (m_VarIdToVarRequestIdQueueMap.count(varIdToVarRequestMapIt->first) == 0) {
732 if (m_VarIdToVarRequestIdQueueMap.count(varIdToVarRequestMapIt->first) == 0) {
701 emit var->updated();
733 emit var->updated();
702 }
734 }
703 }
735 }
704 else {
736 else {
705 qCCritical(LOG_VariableController())
737 qCCritical(LOG_VariableController())
706 << tr("Impossible to update data to a null variable");
738 << tr("Impossible to update data to a null variable");
707 }
739 }
708 }
740 }
709
741
710 // cleaning varRequestId
742 // cleaning varRequestId
711 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
743 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
712 << m_VarRequestIdToVarIdVarRequestMap.size();
744 << m_VarRequestIdToVarIdVarRequestMap.size();
713 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
745 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
714 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?")
746 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?")
715 << m_VarRequestIdToVarIdVarRequestMap.size();
747 << m_VarRequestIdToVarIdVarRequestMap.size();
716 }
748 }
717 }
749 }
718 else {
750 else {
719 qCCritical(LOG_VariableController())
751 qCCritical(LOG_VariableController())
720 << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId;
752 << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId;
721 }
753 }
722 }
754 }
723
755
724 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
756 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
725 {
757 {
726 // cleaning varRequestId
758 // cleaning varRequestId
727 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
759 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
728
760
729 for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin();
761 for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin();
730 varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.end();) {
762 varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.end();) {
731 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
763 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
732 varRequestIdQueue.erase(
764 varRequestIdQueue.erase(
733 std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId),
765 std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId),
734 varRequestIdQueue.end());
766 varRequestIdQueue.end());
735 if (varRequestIdQueue.empty()) {
767 if (varRequestIdQueue.empty()) {
736 varIdToVarRequestIdQueueMapIt
768 varIdToVarRequestIdQueueMapIt
737 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
769 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
738 }
770 }
739 else {
771 else {
740 ++varIdToVarRequestIdQueueMapIt;
772 ++varIdToVarRequestIdQueueMapIt;
741 }
773 }
742 }
774 }
743 }
775 }
@@ -1,265 +1,290
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableModel.h>
2 #include <Variable/VariableModel.h>
3
3
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5 #include <Common/StringUtils.h>
5
6
6 #include <Data/IDataSeries.h>
7 #include <Data/IDataSeries.h>
7
8
8 #include <QSize>
9 #include <QSize>
9 #include <unordered_map>
10 #include <unordered_map>
10
11
11 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
12 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
12
13
13 namespace {
14 namespace {
14
15
15 // Column indexes
16 // Column indexes
16 const auto NAME_COLUMN = 0;
17 const auto NAME_COLUMN = 0;
17 const auto TSTART_COLUMN = 1;
18 const auto TSTART_COLUMN = 1;
18 const auto TEND_COLUMN = 2;
19 const auto TEND_COLUMN = 2;
19 const auto UNIT_COLUMN = 3;
20 const auto UNIT_COLUMN = 3;
20 const auto MISSION_COLUMN = 4;
21 const auto MISSION_COLUMN = 4;
21 const auto PLUGIN_COLUMN = 5;
22 const auto PLUGIN_COLUMN = 5;
22 const auto NB_COLUMNS = 6;
23 const auto NB_COLUMNS = 6;
23
24
24 // Column properties
25 // Column properties
25 const auto DEFAULT_HEIGHT = 25;
26 const auto DEFAULT_HEIGHT = 25;
26 const auto DEFAULT_WIDTH = 100;
27 const auto DEFAULT_WIDTH = 100;
27
28
28 struct ColumnProperties {
29 struct ColumnProperties {
29 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
30 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
30 int height = DEFAULT_HEIGHT)
31 int height = DEFAULT_HEIGHT)
31 : m_Name{name}, m_Width{width}, m_Height{height}
32 : m_Name{name}, m_Width{width}, m_Height{height}
32 {
33 {
33 }
34 }
34
35
35 QString m_Name;
36 QString m_Name;
36 int m_Width;
37 int m_Width;
37 int m_Height;
38 int m_Height;
38 };
39 };
39
40
40 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
41 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
41 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
42 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
42 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {UNIT_COLUMN, {QObject::tr("Unit")}},
43 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {UNIT_COLUMN, {QObject::tr("Unit")}},
43 {MISSION_COLUMN, {QObject::tr("Mission")}}, {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
44 {MISSION_COLUMN, {QObject::tr("Mission")}}, {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
44
45
45 /// Format for datetimes
46 /// Format for datetimes
46 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
47 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
47
48
49 QString uniqueName(const QString &defaultName,
50 const std::vector<std::shared_ptr<Variable> > &variables)
51 {
52 auto forbiddenNames = std::vector<QString>(variables.size());
53 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
54 [](const auto &variable) { return variable->name(); });
55 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
56 Q_ASSERT(!uniqueName.isEmpty());
57
58 return uniqueName;
59 }
48
60
49 } // namespace
61 } // namespace
50
62
51 struct VariableModel::VariableModelPrivate {
63 struct VariableModel::VariableModelPrivate {
52 /// Variables created in SciQlop
64 /// Variables created in SciQlop
53 std::vector<std::shared_ptr<Variable> > m_Variables;
65 std::vector<std::shared_ptr<Variable> > m_Variables;
54 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
66 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
55
67
56 /// Return the row index of the variable. -1 if it's not found
68 /// Return the row index of the variable. -1 if it's not found
57 int indexOfVariable(Variable *variable) const noexcept;
69 int indexOfVariable(Variable *variable) const noexcept;
58 };
70 };
59
71
60 VariableModel::VariableModel(QObject *parent)
72 VariableModel::VariableModel(QObject *parent)
61 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
73 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
62 {
74 {
63 }
75 }
64
76
65 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
77 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
66 const SqpRange &dateTime,
67 const QVariantHash &metadata) noexcept
68 {
78 {
69 auto insertIndex = rowCount();
79 auto insertIndex = rowCount();
70 beginInsertRows({}, insertIndex, insertIndex);
80 beginInsertRows({}, insertIndex, insertIndex);
71
81
72 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
82 // Generates unique name for the variable
83 variable->setName(uniqueName(variable->name(), impl->m_Variables));
73
84
74 impl->m_Variables.push_back(variable);
85 impl->m_Variables.push_back(variable);
75 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
86 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
76
87
77 endInsertRows();
88 endInsertRows();
89 }
90
91 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
92 {
93 auto end = impl->m_Variables.cend();
94 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
95 }
96
97 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
98 const SqpRange &dateTime,
99 const QVariantHash &metadata) noexcept
100 {
101 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
102 addVariable(variable);
78
103
79 return variable;
104 return variable;
80 }
105 }
81
106
82 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
107 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
83 {
108 {
84 if (!variable) {
109 if (!variable) {
85 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
110 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
86 return;
111 return;
87 }
112 }
88
113
89 // Finds variable in the model
114 // Finds variable in the model
90 auto begin = impl->m_Variables.cbegin();
115 auto begin = impl->m_Variables.cbegin();
91 auto end = impl->m_Variables.cend();
116 auto end = impl->m_Variables.cend();
92 auto it = std::find(begin, end, variable);
117 auto it = std::find(begin, end, variable);
93 if (it != end) {
118 if (it != end) {
94 auto removeIndex = std::distance(begin, it);
119 auto removeIndex = std::distance(begin, it);
95
120
96 // Deletes variable
121 // Deletes variable
97 beginRemoveRows({}, removeIndex, removeIndex);
122 beginRemoveRows({}, removeIndex, removeIndex);
98 impl->m_Variables.erase(it);
123 impl->m_Variables.erase(it);
99 endRemoveRows();
124 endRemoveRows();
100 }
125 }
101 else {
126 else {
102 qCritical(LOG_VariableModel())
127 qCritical(LOG_VariableModel())
103 << tr("Can't delete variable %1 from the model: the variable is not in the model")
128 << tr("Can't delete variable %1 from the model: the variable is not in the model")
104 .arg(variable->name());
129 .arg(variable->name());
105 }
130 }
106
131
107 // Removes variable from progress map
132 // Removes variable from progress map
108 impl->m_VariableToProgress.erase(variable);
133 impl->m_VariableToProgress.erase(variable);
109 }
134 }
110
135
111
136
112 std::shared_ptr<Variable> VariableModel::variable(int index) const
137 std::shared_ptr<Variable> VariableModel::variable(int index) const
113 {
138 {
114 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
139 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
115 }
140 }
116
141
117 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
142 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
118 {
143 {
119 return impl->m_Variables;
144 return impl->m_Variables;
120 }
145 }
121
146
122 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
147 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
123 {
148 {
124 if (progress > 0.0) {
149 if (progress > 0.0) {
125 impl->m_VariableToProgress[variable] = progress;
150 impl->m_VariableToProgress[variable] = progress;
126 }
151 }
127 else {
152 else {
128 impl->m_VariableToProgress.erase(variable);
153 impl->m_VariableToProgress.erase(variable);
129 }
154 }
130 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
155 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
131
156
132 emit dataChanged(modelIndex, modelIndex);
157 emit dataChanged(modelIndex, modelIndex);
133 }
158 }
134
159
135 int VariableModel::columnCount(const QModelIndex &parent) const
160 int VariableModel::columnCount(const QModelIndex &parent) const
136 {
161 {
137 Q_UNUSED(parent);
162 Q_UNUSED(parent);
138
163
139 return NB_COLUMNS;
164 return NB_COLUMNS;
140 }
165 }
141
166
142 int VariableModel::rowCount(const QModelIndex &parent) const
167 int VariableModel::rowCount(const QModelIndex &parent) const
143 {
168 {
144 Q_UNUSED(parent);
169 Q_UNUSED(parent);
145
170
146 return impl->m_Variables.size();
171 return impl->m_Variables.size();
147 }
172 }
148
173
149 QVariant VariableModel::data(const QModelIndex &index, int role) const
174 QVariant VariableModel::data(const QModelIndex &index, int role) const
150 {
175 {
151 if (!index.isValid()) {
176 if (!index.isValid()) {
152 return QVariant{};
177 return QVariant{};
153 }
178 }
154
179
155 if (index.row() < 0 || index.row() >= rowCount()) {
180 if (index.row() < 0 || index.row() >= rowCount()) {
156 return QVariant{};
181 return QVariant{};
157 }
182 }
158
183
159 if (role == Qt::DisplayRole) {
184 if (role == Qt::DisplayRole) {
160 if (auto variable = impl->m_Variables.at(index.row()).get()) {
185 if (auto variable = impl->m_Variables.at(index.row()).get()) {
161 switch (index.column()) {
186 switch (index.column()) {
162 case NAME_COLUMN:
187 case NAME_COLUMN:
163 return variable->name();
188 return variable->name();
164 case TSTART_COLUMN: {
189 case TSTART_COLUMN: {
165 auto range = variable->realRange();
190 auto range = variable->realRange();
166 return range != INVALID_RANGE
191 return range != INVALID_RANGE
167 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
192 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
168 : QVariant{};
193 : QVariant{};
169 }
194 }
170 case TEND_COLUMN: {
195 case TEND_COLUMN: {
171 auto range = variable->realRange();
196 auto range = variable->realRange();
172 return range != INVALID_RANGE
197 return range != INVALID_RANGE
173 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
198 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
174 : QVariant{};
199 : QVariant{};
175 }
200 }
176 case UNIT_COLUMN:
201 case UNIT_COLUMN:
177 return variable->metadata().value(QStringLiteral("units"));
202 return variable->metadata().value(QStringLiteral("units"));
178 case MISSION_COLUMN:
203 case MISSION_COLUMN:
179 return variable->metadata().value(QStringLiteral("mission"));
204 return variable->metadata().value(QStringLiteral("mission"));
180 case PLUGIN_COLUMN:
205 case PLUGIN_COLUMN:
181 return variable->metadata().value(QStringLiteral("plugin"));
206 return variable->metadata().value(QStringLiteral("plugin"));
182 default:
207 default:
183 // No action
208 // No action
184 break;
209 break;
185 }
210 }
186
211
187 qWarning(LOG_VariableModel())
212 qWarning(LOG_VariableModel())
188 << tr("Can't get data (unknown column %1)").arg(index.column());
213 << tr("Can't get data (unknown column %1)").arg(index.column());
189 }
214 }
190 else {
215 else {
191 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
216 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
192 }
217 }
193 }
218 }
194 else if (role == VariableRoles::ProgressRole) {
219 else if (role == VariableRoles::ProgressRole) {
195 if (auto variable = impl->m_Variables.at(index.row())) {
220 if (auto variable = impl->m_Variables.at(index.row())) {
196
221
197 auto it = impl->m_VariableToProgress.find(variable);
222 auto it = impl->m_VariableToProgress.find(variable);
198 if (it != impl->m_VariableToProgress.cend()) {
223 if (it != impl->m_VariableToProgress.cend()) {
199 return it->second;
224 return it->second;
200 }
225 }
201 }
226 }
202 }
227 }
203
228
204 return QVariant{};
229 return QVariant{};
205 }
230 }
206
231
207 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
232 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
208 {
233 {
209 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
234 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
210 return QVariant{};
235 return QVariant{};
211 }
236 }
212
237
213 if (orientation == Qt::Horizontal) {
238 if (orientation == Qt::Horizontal) {
214 auto propertiesIt = COLUMN_PROPERTIES.find(section);
239 auto propertiesIt = COLUMN_PROPERTIES.find(section);
215 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
240 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
216 // Role is either DisplayRole or SizeHintRole
241 // Role is either DisplayRole or SizeHintRole
217 return (role == Qt::DisplayRole)
242 return (role == Qt::DisplayRole)
218 ? QVariant{propertiesIt->m_Name}
243 ? QVariant{propertiesIt->m_Name}
219 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
244 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
220 }
245 }
221 else {
246 else {
222 qWarning(LOG_VariableModel())
247 qWarning(LOG_VariableModel())
223 << tr("Can't get header data (unknown column %1)").arg(section);
248 << tr("Can't get header data (unknown column %1)").arg(section);
224 }
249 }
225 }
250 }
226
251
227 return QVariant{};
252 return QVariant{};
228 }
253 }
229
254
230 void VariableModel::abortProgress(const QModelIndex &index)
255 void VariableModel::abortProgress(const QModelIndex &index)
231 {
256 {
232 if (auto variable = impl->m_Variables.at(index.row())) {
257 if (auto variable = impl->m_Variables.at(index.row())) {
233 emit abortProgessRequested(variable);
258 emit abortProgessRequested(variable);
234 }
259 }
235 }
260 }
236
261
237 void VariableModel::onVariableUpdated() noexcept
262 void VariableModel::onVariableUpdated() noexcept
238 {
263 {
239 // Finds variable that has been updated in the model
264 // Finds variable that has been updated in the model
240 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
265 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
241 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
266 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
242
267
243 if (updatedVariableIndex > -1) {
268 if (updatedVariableIndex > -1) {
244 emit dataChanged(createIndex(updatedVariableIndex, 0),
269 emit dataChanged(createIndex(updatedVariableIndex, 0),
245 createIndex(updatedVariableIndex, columnCount() - 1));
270 createIndex(updatedVariableIndex, columnCount() - 1));
246 }
271 }
247 }
272 }
248 }
273 }
249
274
250 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
275 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
251 {
276 {
252 auto begin = std::cbegin(m_Variables);
277 auto begin = std::cbegin(m_Variables);
253 auto end = std::cend(m_Variables);
278 auto end = std::cend(m_Variables);
254 auto it
279 auto it
255 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
280 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
256
281
257 if (it != end) {
282 if (it != end) {
258 // Gets the index of the variable in the model: we assume here that views have the same
283 // Gets the index of the variable in the model: we assume here that views have the same
259 // order as the model
284 // order as the model
260 return std::distance(begin, it);
285 return std::distance(begin, it);
261 }
286 }
262 else {
287 else {
263 return -1;
288 return -1;
264 }
289 }
265 }
290 }
@@ -1,72 +1,74
1 #include <QObject>
1 #include <QObject>
2 #include <QtTest>
2 #include <QtTest>
3
3
4 #include <Data/IDataProvider.h>
4 #include <Data/IDataProvider.h>
5 #include <Time/TimeController.h>
5 #include <Time/TimeController.h>
6 #include <Variable/Variable.h>
6 #include <Variable/Variable.h>
7 #include <Variable/VariableController.h>
7 #include <Variable/VariableController.h>
8
8
9 #include <memory>
9 #include <memory>
10
10
11 namespace {
11 namespace {
12
12
13 /// Provider used for the tests
13 /// Provider used for the tests
14 class TestProvider : public IDataProvider {
14 class TestProvider : public IDataProvider {
15 std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); }
16
15 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
17 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
16 {
18 {
17 // Does nothing
19 // Does nothing
18 }
20 }
19
21
20 void requestDataAborting(QUuid acqIdentifier) override
22 void requestDataAborting(QUuid acqIdentifier) override
21 {
23 {
22 // Does nothing
24 // Does nothing
23 }
25 }
24 };
26 };
25
27
26 /// Generates a time controller for the tests
28 /// Generates a time controller for the tests
27 std::unique_ptr<TimeController> defaultTimeController()
29 std::unique_ptr<TimeController> defaultTimeController()
28 {
30 {
29 auto timeController = std::make_unique<TimeController>();
31 auto timeController = std::make_unique<TimeController>();
30
32
31 QDateTime start{QDate{2017, 01, 01}, QTime{0, 0, 0, 0}};
33 QDateTime start{QDate{2017, 01, 01}, QTime{0, 0, 0, 0}};
32 QDateTime end{QDate{2017, 01, 02}, QTime{0, 0, 0, 0}};
34 QDateTime end{QDate{2017, 01, 02}, QTime{0, 0, 0, 0}};
33 timeController->onTimeToUpdate(
35 timeController->onTimeToUpdate(
34 SqpRange{DateUtils::secondsSinceEpoch(start), DateUtils::secondsSinceEpoch(end)});
36 SqpRange{DateUtils::secondsSinceEpoch(start), DateUtils::secondsSinceEpoch(end)});
35
37
36 return timeController;
38 return timeController;
37 }
39 }
38
40
39 } // namespace
41 } // namespace
40
42
41 class TestVariableController : public QObject {
43 class TestVariableController : public QObject {
42 Q_OBJECT
44 Q_OBJECT
43
45
44 private slots:
46 private slots:
45 /// Test removes variable from controller
47 /// Test removes variable from controller
46 void testDeleteVariable();
48 void testDeleteVariable();
47 };
49 };
48
50
49 void TestVariableController::testDeleteVariable()
51 void TestVariableController::testDeleteVariable()
50 {
52 {
51 // Creates variable controller
53 // Creates variable controller
52 auto timeController = defaultTimeController();
54 auto timeController = defaultTimeController();
53 VariableController variableController{};
55 VariableController variableController{};
54 variableController.setTimeController(timeController.get());
56 variableController.setTimeController(timeController.get());
55
57
56 // Creates a variable from the controller
58 // Creates a variable from the controller
57 auto variable
59 auto variable
58 = variableController.createVariable("variable", {}, std::make_shared<TestProvider>());
60 = variableController.createVariable("variable", {}, std::make_shared<TestProvider>());
59
61
60 qDebug() << QString::number(variable.use_count());
62 qDebug() << QString::number(variable.use_count());
61
63
62 // Removes the variable from the controller
64 // Removes the variable from the controller
63 variableController.deleteVariable(variable);
65 variableController.deleteVariable(variable);
64
66
65 // Verifies that the variable has been deleted: this implies that the number of shared_ptr
67 // Verifies that the variable has been deleted: this implies that the number of shared_ptr
66 // objects referring to the variable is 1 (the reference of this scope). Otherwise, the deletion
68 // objects referring to the variable is 1 (the reference of this scope). Otherwise, the deletion
67 // is considered invalid since the variable is still referenced in the controller
69 // is considered invalid since the variable is still referenced in the controller
68 QVERIFY(variable.use_count() == 1);
70 QVERIFY(variable.use_count() == 1);
69 }
71 }
70
72
71 QTEST_MAIN(TestVariableController)
73 QTEST_MAIN(TestVariableController)
72 #include "TestVariableController.moc"
74 #include "TestVariableController.moc"
@@ -1,18 +1,19
1
1
2
2
3 tests = [
3 tests = [
4 [['Common/TestStringUtils.cpp'],'test_string_utils','StringUtils test'],
4 [['Data/TestDataSeries.cpp'],'test_data','DataSeries test'],
5 [['Data/TestDataSeries.cpp'],'test_data','DataSeries test'],
5 [['Data/TestOneDimArrayData.cpp'],'test_1d','One Dim Array test'],
6 [['Data/TestOneDimArrayData.cpp'],'test_1d','One Dim Array test'],
6 [['Data/TestTwoDimArrayData.cpp'],'test_2d','Two Dim Array test'],
7 [['Data/TestTwoDimArrayData.cpp'],'test_2d','Two Dim Array test'],
7 [['DataSource/TestDataSourceController.cpp'],'test_data_source','DataSourceController test'],
8 [['DataSource/TestDataSourceController.cpp'],'test_data_source','DataSourceController test'],
8 [['Variable/TestVariableCacheController.cpp'],'test_variable_cache','VariableCacheController test'],
9 [['Variable/TestVariableCacheController.cpp'],'test_variable_cache','VariableCacheController test'],
9 [['Variable/TestVariable.cpp'],'test_variable','Variable test']
10 [['Variable/TestVariable.cpp'],'test_variable','Variable test']
10 ]
11 ]
11
12
12 foreach unit_test : tests
13 foreach unit_test : tests
13 test_moc_files = qt5.preprocess(moc_sources : unit_test[0])
14 test_moc_files = qt5.preprocess(moc_sources : unit_test[0])
14 test_exe = executable(unit_test[1],unit_test[0] , test_moc_files,
15 test_exe = executable(unit_test[1],unit_test[0] , test_moc_files,
15 dependencies : [sciqlop_core, qt5test])
16 dependencies : [sciqlop_core, qt5test])
16 test(unit_test[2], test_exe, args: ['-teamcity', '-o', '@0@.teamcity.txt'.format(unit_test[1])])
17 test(unit_test[2], test_exe, args: ['-teamcity', '-o', '@0@.teamcity.txt'.format(unit_test[1])])
17 endforeach
18 endforeach
18
19
@@ -1,63 +1,63
1 #include "Variable/RenameVariableDialog.h"
1 #include "Variable/RenameVariableDialog.h"
2
2
3 #include <ui_RenameVariableDialog.h>
3 #include <ui_RenameVariableDialog.h>
4
4
5 RenameVariableDialog::RenameVariableDialog(const QString &defaultName,
5 RenameVariableDialog::RenameVariableDialog(const QString &defaultName,
6 const QVector<QString> &forbiddenNames, QWidget *parent)
6 const QVector<QString> &forbiddenNames, QWidget *parent)
7 : QDialog{parent},
7 : QDialog{parent},
8 ui{new Ui::RenameVariableDialog},
8 ui{new Ui::RenameVariableDialog},
9 m_DefaultName{defaultName},
9 m_DefaultName{defaultName},
10 m_ForbiddenNames{forbiddenNames}
10 m_ForbiddenNames{forbiddenNames}
11 {
11 {
12 ui->setupUi(this);
12 ui->setupUi(this);
13
13
14 connect(ui->nameLineEdit, &QLineEdit::textChanged, [this]() { ui->errorLabel->hide(); });
14 connect(ui->nameLineEdit, &QLineEdit::textChanged, [this]() { ui->errorLabel->hide(); });
15
15
16 ui->nameLineEdit->setText(defaultName);
16 ui->nameLineEdit->setText(defaultName);
17 ui->nameLineEdit->selectAll();
17 ui->nameLineEdit->selectAll();
18 ui->nameLineEdit->setFocus();
18 ui->nameLineEdit->setFocus();
19 }
19 }
20
20
21 RenameVariableDialog::~RenameVariableDialog() noexcept
21 RenameVariableDialog::~RenameVariableDialog() noexcept
22 {
22 {
23 delete ui;
23 delete ui;
24 }
24 }
25
25
26 QString RenameVariableDialog::name() const noexcept
26 QString RenameVariableDialog::name() const noexcept
27 {
27 {
28 return ui->nameLineEdit->text();
28 return ui->nameLineEdit->text().trimmed();
29 }
29 }
30
30
31 void RenameVariableDialog::accept()
31 void RenameVariableDialog::accept()
32 {
32 {
33 auto invalidateInput = [this](const auto &error) {
33 auto invalidateInput = [this](const auto &error) {
34 ui->nameLineEdit->selectAll();
34 ui->nameLineEdit->selectAll();
35 ui->nameLineEdit->setFocus();
35 ui->nameLineEdit->setFocus();
36 ui->errorLabel->setText(error);
36 ui->errorLabel->setText(error);
37 ui->errorLabel->show();
37 ui->errorLabel->show();
38 };
38 };
39
39
40 // Empty name
40 // Empty name
41 auto name = ui->nameLineEdit->text();
41 auto name = this->name();
42 if (name.isEmpty()) {
42 if (name.isEmpty()) {
43 invalidateInput(tr("A variable name must be specified"));
43 invalidateInput(tr("A variable name must be specified"));
44 return;
44 return;
45 }
45 }
46
46
47 // Same name when opening dialog
47 // Same name when opening dialog
48 if (name.compare(m_DefaultName, Qt::CaseInsensitive) == 0) {
48 if (name.compare(m_DefaultName, Qt::CaseInsensitive) == 0) {
49 reject();
49 reject();
50 return;
50 return;
51 }
51 }
52
52
53 // Forbidden name
53 // Forbidden name
54 auto isForbidden
54 auto isForbidden
55 = [&name](const auto &it) { return name.compare(it, Qt::CaseInsensitive) == 0; };
55 = [&name](const auto &it) { return name.compare(it, Qt::CaseInsensitive) == 0; };
56 if (std::any_of(m_ForbiddenNames.cbegin(), m_ForbiddenNames.cend(), isForbidden)) {
56 if (std::any_of(m_ForbiddenNames.cbegin(), m_ForbiddenNames.cend(), isForbidden)) {
57 invalidateInput(tr("'%1' is already used").arg(name));
57 invalidateInput(tr("'%1' is already used").arg(name));
58 return;
58 return;
59 }
59 }
60
60
61 // Valid name
61 // Valid name
62 QDialog::accept();
62 QDialog::accept();
63 }
63 }
@@ -1,222 +1,228
1 #include <Variable/RenameVariableDialog.h>
1 #include <Variable/RenameVariableDialog.h>
2 #include <Variable/Variable.h>
2 #include <Variable/Variable.h>
3 #include <Variable/VariableController.h>
3 #include <Variable/VariableController.h>
4 #include <Variable/VariableInspectorWidget.h>
4 #include <Variable/VariableInspectorWidget.h>
5 #include <Variable/VariableMenuHeaderWidget.h>
5 #include <Variable/VariableMenuHeaderWidget.h>
6 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
7
7
8 #include <ui_VariableInspectorWidget.h>
8 #include <ui_VariableInspectorWidget.h>
9
9
10 #include <QMouseEvent>
10 #include <QMouseEvent>
11 #include <QSortFilterProxyModel>
11 #include <QSortFilterProxyModel>
12 #include <QStyledItemDelegate>
12 #include <QStyledItemDelegate>
13 #include <QWidgetAction>
13 #include <QWidgetAction>
14
14
15 #include <SqpApplication.h>
15 #include <SqpApplication.h>
16
16
17 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
17 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
18
18
19
19
20 class QProgressBarItemDelegate : public QStyledItemDelegate {
20 class QProgressBarItemDelegate : public QStyledItemDelegate {
21
21
22 public:
22 public:
23 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
23 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
24
24
25 void paint(QPainter *painter, const QStyleOptionViewItem &option,
25 void paint(QPainter *painter, const QStyleOptionViewItem &option,
26 const QModelIndex &index) const
26 const QModelIndex &index) const
27 {
27 {
28 auto data = index.data(Qt::DisplayRole);
28 auto data = index.data(Qt::DisplayRole);
29 auto progressData = index.data(VariableRoles::ProgressRole);
29 auto progressData = index.data(VariableRoles::ProgressRole);
30 if (data.isValid() && progressData.isValid()) {
30 if (data.isValid() && progressData.isValid()) {
31 auto name = data.value<QString>();
31 auto name = data.value<QString>();
32 auto progress = progressData.value<double>();
32 auto progress = progressData.value<double>();
33 if (progress > 0) {
33 if (progress > 0) {
34 auto cancelButtonWidth = 20;
34 auto cancelButtonWidth = 20;
35 auto progressBarOption = QStyleOptionProgressBar{};
35 auto progressBarOption = QStyleOptionProgressBar{};
36 auto progressRect = option.rect;
36 auto progressRect = option.rect;
37 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
37 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
38 progressBarOption.rect = progressRect;
38 progressBarOption.rect = progressRect;
39 progressBarOption.minimum = 0;
39 progressBarOption.minimum = 0;
40 progressBarOption.maximum = 100;
40 progressBarOption.maximum = 100;
41 progressBarOption.progress = progress;
41 progressBarOption.progress = progress;
42 progressBarOption.text
42 progressBarOption.text
43 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
43 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
44 progressBarOption.textVisible = true;
44 progressBarOption.textVisible = true;
45 progressBarOption.textAlignment = Qt::AlignCenter;
45 progressBarOption.textAlignment = Qt::AlignCenter;
46
46
47
47
48 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
48 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
49 painter);
49 painter);
50
50
51 // Cancel button
51 // Cancel button
52 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
52 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
53 option.rect.height());
53 option.rect.height());
54 auto buttonOption = QStyleOptionButton{};
54 auto buttonOption = QStyleOptionButton{};
55 buttonOption.rect = buttonRect;
55 buttonOption.rect = buttonRect;
56 buttonOption.text = "X";
56 buttonOption.text = "X";
57
57
58 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
58 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
59 }
59 }
60 else {
60 else {
61 QStyledItemDelegate::paint(painter, option, index);
61 QStyledItemDelegate::paint(painter, option, index);
62 }
62 }
63 }
63 }
64 else {
64 else {
65 QStyledItemDelegate::paint(painter, option, index);
65 QStyledItemDelegate::paint(painter, option, index);
66 }
66 }
67 }
67 }
68
68
69 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
69 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
70 const QModelIndex &index)
70 const QModelIndex &index)
71 {
71 {
72 if (event->type() == QEvent::MouseButtonRelease) {
72 if (event->type() == QEvent::MouseButtonRelease) {
73 auto data = index.data(Qt::DisplayRole);
73 auto data = index.data(Qt::DisplayRole);
74 auto progressData = index.data(VariableRoles::ProgressRole);
74 auto progressData = index.data(VariableRoles::ProgressRole);
75 if (data.isValid() && progressData.isValid()) {
75 if (data.isValid() && progressData.isValid()) {
76 auto cancelButtonWidth = 20;
76 auto cancelButtonWidth = 20;
77 auto progressRect = option.rect;
77 auto progressRect = option.rect;
78 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
78 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
79 // Cancel button
79 // Cancel button
80 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
80 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
81 option.rect.height());
81 option.rect.height());
82
82
83 auto e = (QMouseEvent *)event;
83 auto e = (QMouseEvent *)event;
84 auto clickX = e->x();
84 auto clickX = e->x();
85 auto clickY = e->y();
85 auto clickY = e->y();
86
86
87 auto x = buttonRect.left(); // the X coordinate
87 auto x = buttonRect.left(); // the X coordinate
88 auto y = buttonRect.top(); // the Y coordinate
88 auto y = buttonRect.top(); // the Y coordinate
89 auto w = buttonRect.width(); // button width
89 auto w = buttonRect.width(); // button width
90 auto h = buttonRect.height(); // button height
90 auto h = buttonRect.height(); // button height
91
91
92 if (clickX > x && clickX < x + w) {
92 if (clickX > x && clickX < x + w) {
93 if (clickY > y && clickY < y + h) {
93 if (clickY > y && clickY < y + h) {
94 auto variableModel = sqpApp->variableController().variableModel();
94 auto variableModel = sqpApp->variableController().variableModel();
95 variableModel->abortProgress(index);
95 variableModel->abortProgress(index);
96 }
96 }
97 }
97 }
98 else {
98 else {
99 QStyledItemDelegate::editorEvent(event, model, option, index);
99 QStyledItemDelegate::editorEvent(event, model, option, index);
100 }
100 }
101 }
101 }
102 else {
102 else {
103 QStyledItemDelegate::editorEvent(event, model, option, index);
103 QStyledItemDelegate::editorEvent(event, model, option, index);
104 }
104 }
105 }
105 }
106 else {
106 else {
107 QStyledItemDelegate::editorEvent(event, model, option, index);
107 QStyledItemDelegate::editorEvent(event, model, option, index);
108 }
108 }
109 }
109 }
110 };
110 };
111
111
112 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
112 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
113 : QWidget{parent},
113 : QWidget{parent},
114 ui{new Ui::VariableInspectorWidget},
114 ui{new Ui::VariableInspectorWidget},
115 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
115 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
116 {
116 {
117 ui->setupUi(this);
117 ui->setupUi(this);
118
118
119 // Sets model for table
119 // Sets model for table
120 // auto sortFilterModel = new QSortFilterProxyModel{this};
120 // auto sortFilterModel = new QSortFilterProxyModel{this};
121 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
121 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
122
122
123 auto variableModel = sqpApp->variableController().variableModel();
123 auto variableModel = sqpApp->variableController().variableModel();
124 ui->tableView->setModel(variableModel);
124 ui->tableView->setModel(variableModel);
125
125
126 // Adds extra signal/slot between view and model, so the view can be updated instantly when
126 // Adds extra signal/slot between view and model, so the view can be updated instantly when
127 // there is a change of data in the model
127 // there is a change of data in the model
128 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
128 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
129 SLOT(refresh()));
129 SLOT(refresh()));
130
130
131 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
131 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
132 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
132 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
133
133
134 // Fixes column sizes
134 // Fixes column sizes
135 auto model = ui->tableView->model();
135 auto model = ui->tableView->model();
136 const auto count = model->columnCount();
136 const auto count = model->columnCount();
137 for (auto i = 0; i < count; ++i) {
137 for (auto i = 0; i < count; ++i) {
138 ui->tableView->setColumnWidth(
138 ui->tableView->setColumnWidth(
139 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
139 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
140 }
140 }
141
141
142 // Sets selection options
142 // Sets selection options
143 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
143 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
144 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
144 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
145
145
146 // Connection to show a menu when right clicking on the tree
146 // Connection to show a menu when right clicking on the tree
147 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
147 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
148 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
148 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
149 &VariableInspectorWidget::onTableMenuRequested);
149 &VariableInspectorWidget::onTableMenuRequested);
150 }
150 }
151
151
152 VariableInspectorWidget::~VariableInspectorWidget()
152 VariableInspectorWidget::~VariableInspectorWidget()
153 {
153 {
154 delete ui;
154 delete ui;
155 }
155 }
156
156
157 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
157 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
158 {
158 {
159 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
159 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
160
160
161 // Gets the model to retrieve the underlying selected variables
161 // Gets the model to retrieve the underlying selected variables
162 auto model = sqpApp->variableController().variableModel();
162 auto model = sqpApp->variableController().variableModel();
163 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
163 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
164 for (const auto &selectedRow : qAsConst(selectedRows)) {
164 for (const auto &selectedRow : qAsConst(selectedRows)) {
165 if (auto selectedVariable = model->variable(selectedRow.row())) {
165 if (auto selectedVariable = model->variable(selectedRow.row())) {
166 selectedVariables.push_back(selectedVariable);
166 selectedVariables.push_back(selectedVariable);
167 }
167 }
168 }
168 }
169
169
170 QMenu tableMenu{};
170 QMenu tableMenu{};
171
171
172 // Emits a signal so that potential receivers can populate the menu before displaying it
172 // Emits a signal so that potential receivers can populate the menu before displaying it
173 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
173 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
174
174
175 // Adds menu-specific actions
175 // Adds menu-specific actions
176 if (!selectedVariables.isEmpty()) {
176 if (!selectedVariables.isEmpty()) {
177 tableMenu.addSeparator();
177 tableMenu.addSeparator();
178
178
179 // 'Rename' action (only if one variable selected)
179 // 'Rename' and 'Duplicate' actions (only if one variable selected)
180 if (selectedVariables.size() == 1) {
180 if (selectedVariables.size() == 1) {
181 auto selectedVariable = selectedVariables.front();
181 auto selectedVariable = selectedVariables.front();
182
182
183 auto duplicateFun = [&selectedVariable]() {
184 sqpApp->variableController().cloneVariable(selectedVariable);
185 };
186
187 tableMenu.addAction(tr("Duplicate"), duplicateFun);
188
183 auto renameFun = [&selectedVariable, &model, this]() {
189 auto renameFun = [&selectedVariable, &model, this]() {
184 // Generates forbidden names (names associated to existing variables)
190 // Generates forbidden names (names associated to existing variables)
185 auto allVariables = model->variables();
191 auto allVariables = model->variables();
186 auto forbiddenNames = QVector<QString>(allVariables.size());
192 auto forbiddenNames = QVector<QString>(allVariables.size());
187 std::transform(allVariables.cbegin(), allVariables.cend(), forbiddenNames.begin(),
193 std::transform(allVariables.cbegin(), allVariables.cend(), forbiddenNames.begin(),
188 [](const auto &variable) { return variable->name(); });
194 [](const auto &variable) { return variable->name(); });
189
195
190 RenameVariableDialog dialog{selectedVariable->name(), forbiddenNames, this};
196 RenameVariableDialog dialog{selectedVariable->name(), forbiddenNames, this};
191 if (dialog.exec() == QDialog::Accepted) {
197 if (dialog.exec() == QDialog::Accepted) {
192 selectedVariable->setName(dialog.name());
198 selectedVariable->setName(dialog.name());
193 }
199 }
194 };
200 };
195
201
196 tableMenu.addAction(tr("Rename..."), renameFun);
202 tableMenu.addAction(tr("Rename..."), renameFun);
197 }
203 }
198
204
199 // 'Delete' action
205 // 'Delete' action
200 auto deleteFun = [&selectedVariables]() {
206 auto deleteFun = [&selectedVariables]() {
201 sqpApp->variableController().deleteVariables(selectedVariables);
207 sqpApp->variableController().deleteVariables(selectedVariables);
202 };
208 };
203
209
204 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
210 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
205 }
211 }
206
212
207 if (!tableMenu.isEmpty()) {
213 if (!tableMenu.isEmpty()) {
208 // Generates menu header (inserted before first action)
214 // Generates menu header (inserted before first action)
209 auto firstAction = tableMenu.actions().first();
215 auto firstAction = tableMenu.actions().first();
210 auto headerAction = new QWidgetAction{&tableMenu};
216 auto headerAction = new QWidgetAction{&tableMenu};
211 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
217 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
212 tableMenu.insertAction(firstAction, headerAction);
218 tableMenu.insertAction(firstAction, headerAction);
213
219
214 // Displays menu
220 // Displays menu
215 tableMenu.exec(QCursor::pos());
221 tableMenu.exec(QCursor::pos());
216 }
222 }
217 }
223 }
218
224
219 void VariableInspectorWidget::refresh() noexcept
225 void VariableInspectorWidget::refresh() noexcept
220 {
226 {
221 ui->tableView->viewport()->update();
227 ui->tableView->viewport()->update();
222 }
228 }
@@ -1,30 +1,31
1 #ifndef SCIQLOP_AMDAPROVIDER_H
1 #ifndef SCIQLOP_AMDAPROVIDER_H
2 #define SCIQLOP_AMDAPROVIDER_H
2 #define SCIQLOP_AMDAPROVIDER_H
3
3
4 #include "AmdaGlobal.h"
4 #include "AmdaGlobal.h"
5
5
6 #include <Data/IDataProvider.h>
6 #include <Data/IDataProvider.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9
9
10
10
11 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
11 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
12
12
13 class QNetworkReply;
13 class QNetworkReply;
14
14
15 /**
15 /**
16 * @brief The AmdaProvider class is an example of how a data provider can generate data
16 * @brief The AmdaProvider class is an example of how a data provider can generate data
17 */
17 */
18 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
18 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
19 public:
19 public:
20 explicit AmdaProvider();
20 explicit AmdaProvider();
21 std::shared_ptr<IDataProvider> clone() const override;
21
22
22 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override;
23 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override;
23
24
24 void requestDataAborting(QUuid acqIdentifier) override;
25 void requestDataAborting(QUuid acqIdentifier) override;
25
26
26 private:
27 private:
27 void retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data);
28 void retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data);
28 };
29 };
29
30
30 #endif // SCIQLOP_AMDAPROVIDER_H
31 #endif // SCIQLOP_AMDAPROVIDER_H
@@ -1,168 +1,174
1 #include "AmdaProvider.h"
1 #include "AmdaProvider.h"
2 #include "AmdaDefs.h"
2 #include "AmdaDefs.h"
3 #include "AmdaResultParser.h"
3 #include "AmdaResultParser.h"
4
4
5 #include <Common/DateUtils.h>
5 #include <Common/DateUtils.h>
6 #include <Data/DataProviderParameters.h>
6 #include <Data/DataProviderParameters.h>
7 #include <Network/NetworkController.h>
7 #include <Network/NetworkController.h>
8 #include <SqpApplication.h>
8 #include <SqpApplication.h>
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10
10
11 #include <QNetworkAccessManager>
11 #include <QNetworkAccessManager>
12 #include <QNetworkReply>
12 #include <QNetworkReply>
13 #include <QTemporaryFile>
13 #include <QTemporaryFile>
14 #include <QThread>
14 #include <QThread>
15
15
16 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
16 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
17
17
18 namespace {
18 namespace {
19
19
20 /// URL format for a request on AMDA server. The parameters are as follows:
20 /// URL format for a request on AMDA server. The parameters are as follows:
21 /// - %1: start date
21 /// - %1: start date
22 /// - %2: end date
22 /// - %2: end date
23 /// - %3: parameter id
23 /// - %3: parameter id
24 const auto AMDA_URL_FORMAT = QStringLiteral(
24 const auto AMDA_URL_FORMAT = QStringLiteral(
25 "http://amda.irap.omp.eu/php/rest/"
25 "http://amda.irap.omp.eu/php/rest/"
26 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&outputFormat=ASCII&"
26 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&outputFormat=ASCII&"
27 "timeFormat=ISO8601&gzip=0");
27 "timeFormat=ISO8601&gzip=0");
28
28
29 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
29 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
30 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
30 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
31
31
32 /// Formats a time to a date that can be passed in URL
32 /// Formats a time to a date that can be passed in URL
33 QString dateFormat(double sqpRange) noexcept
33 QString dateFormat(double sqpRange) noexcept
34 {
34 {
35 auto dateTime = DateUtils::dateTime(sqpRange);
35 auto dateTime = DateUtils::dateTime(sqpRange);
36 return dateTime.toString(AMDA_TIME_FORMAT);
36 return dateTime.toString(AMDA_TIME_FORMAT);
37 }
37 }
38
38
39 AmdaResultParser::ValueType valueType(const QString &valueType)
39 AmdaResultParser::ValueType valueType(const QString &valueType)
40 {
40 {
41 if (valueType == QStringLiteral("scalar")) {
41 if (valueType == QStringLiteral("scalar")) {
42 return AmdaResultParser::ValueType::SCALAR;
42 return AmdaResultParser::ValueType::SCALAR;
43 }
43 }
44 else if (valueType == QStringLiteral("vector")) {
44 else if (valueType == QStringLiteral("vector")) {
45 return AmdaResultParser::ValueType::VECTOR;
45 return AmdaResultParser::ValueType::VECTOR;
46 }
46 }
47 else {
47 else {
48 return AmdaResultParser::ValueType::UNKNOWN;
48 return AmdaResultParser::ValueType::UNKNOWN;
49 }
49 }
50 }
50 }
51
51
52 } // namespace
52 } // namespace
53
53
54 AmdaProvider::AmdaProvider()
54 AmdaProvider::AmdaProvider()
55 {
55 {
56 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
56 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
57 if (auto app = sqpApp) {
57 if (auto app = sqpApp) {
58 auto &networkController = app->networkController();
58 auto &networkController = app->networkController();
59 connect(this, SIGNAL(requestConstructed(QNetworkRequest, QUuid,
59 connect(this, SIGNAL(requestConstructed(QNetworkRequest, QUuid,
60 std::function<void(QNetworkReply *, QUuid)>)),
60 std::function<void(QNetworkReply *, QUuid)>)),
61 &networkController,
61 &networkController,
62 SLOT(onProcessRequested(QNetworkRequest, QUuid,
62 SLOT(onProcessRequested(QNetworkRequest, QUuid,
63 std::function<void(QNetworkReply *, QUuid)>)));
63 std::function<void(QNetworkReply *, QUuid)>)));
64
64
65
65
66 connect(&sqpApp->networkController(), SIGNAL(replyDownloadProgress(QUuid, double)), this,
66 connect(&sqpApp->networkController(), SIGNAL(replyDownloadProgress(QUuid, double)), this,
67 SIGNAL(dataProvidedProgress(QUuid, double)));
67 SIGNAL(dataProvidedProgress(QUuid, double)));
68 }
68 }
69 }
69 }
70
70
71 std::shared_ptr<IDataProvider> AmdaProvider::clone() const
72 {
73 // No copy is made in the clone
74 return std::make_shared<AmdaProvider>();
75 }
76
71 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
77 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
72 {
78 {
73 // NOTE: Try to use multithread if possible
79 // NOTE: Try to use multithread if possible
74 const auto times = parameters.m_Times;
80 const auto times = parameters.m_Times;
75 const auto data = parameters.m_Data;
81 const auto data = parameters.m_Data;
76 for (const auto &dateTime : qAsConst(times)) {
82 for (const auto &dateTime : qAsConst(times)) {
77 this->retrieveData(acqIdentifier, dateTime, data);
83 this->retrieveData(acqIdentifier, dateTime, data);
78
84
79 // TORM when AMDA will support quick asynchrone request
85 // TORM when AMDA will support quick asynchrone request
80 QThread::msleep(1000);
86 QThread::msleep(1000);
81 }
87 }
82 }
88 }
83
89
84 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
90 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
85 {
91 {
86 if (auto app = sqpApp) {
92 if (auto app = sqpApp) {
87 auto &networkController = app->networkController();
93 auto &networkController = app->networkController();
88 networkController.onReplyCanceled(acqIdentifier);
94 networkController.onReplyCanceled(acqIdentifier);
89 }
95 }
90 }
96 }
91
97
92 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
98 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
93 {
99 {
94 // Retrieves product ID from data: if the value is invalid, no request is made
100 // Retrieves product ID from data: if the value is invalid, no request is made
95 auto productId = data.value(AMDA_XML_ID_KEY).toString();
101 auto productId = data.value(AMDA_XML_ID_KEY).toString();
96 if (productId.isNull()) {
102 if (productId.isNull()) {
97 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
103 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
98 return;
104 return;
99 }
105 }
100 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData") << dateTime;
106 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData") << dateTime;
101
107
102 // Retrieves the data type that determines whether the expected format for the result file is
108 // Retrieves the data type that determines whether the expected format for the result file is
103 // scalar, vector...
109 // scalar, vector...
104 auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString());
110 auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString());
105
111
106 // /////////// //
112 // /////////// //
107 // Creates URL //
113 // Creates URL //
108 // /////////// //
114 // /////////// //
109
115
110 auto startDate = dateFormat(dateTime.m_TStart);
116 auto startDate = dateFormat(dateTime.m_TStart);
111 auto endDate = dateFormat(dateTime.m_TEnd);
117 auto endDate = dateFormat(dateTime.m_TEnd);
112
118
113 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
119 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
114 qCInfo(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
120 qCInfo(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
115 auto tempFile = std::make_shared<QTemporaryFile>();
121 auto tempFile = std::make_shared<QTemporaryFile>();
116
122
117 // LAMBDA
123 // LAMBDA
118 auto httpDownloadFinished = [this, dateTime, tempFile,
124 auto httpDownloadFinished = [this, dateTime, tempFile,
119 productValueType](QNetworkReply *reply, QUuid dataId) noexcept {
125 productValueType](QNetworkReply *reply, QUuid dataId) noexcept {
120
126
121 // Don't do anything if the reply was abort
127 // Don't do anything if the reply was abort
122 if (reply->error() != QNetworkReply::OperationCanceledError) {
128 if (reply->error() != QNetworkReply::OperationCanceledError) {
123
129
124 if (tempFile) {
130 if (tempFile) {
125 auto replyReadAll = reply->readAll();
131 auto replyReadAll = reply->readAll();
126 if (!replyReadAll.isEmpty()) {
132 if (!replyReadAll.isEmpty()) {
127 tempFile->write(replyReadAll);
133 tempFile->write(replyReadAll);
128 }
134 }
129 tempFile->close();
135 tempFile->close();
130
136
131 // Parse results file
137 // Parse results file
132 if (auto dataSeries
138 if (auto dataSeries
133 = AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) {
139 = AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) {
134 emit dataProvided(dataId, dataSeries, dateTime);
140 emit dataProvided(dataId, dataSeries, dateTime);
135 }
141 }
136 else {
142 else {
137 /// @todo ALX : debug
143 /// @todo ALX : debug
138 }
144 }
139 }
145 }
140 }
146 }
141
147
142 };
148 };
143 auto httpFinishedLambda
149 auto httpFinishedLambda
144 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
150 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
145
151
146 // Don't do anything if the reply was abort
152 // Don't do anything if the reply was abort
147 if (reply->error() != QNetworkReply::OperationCanceledError) {
153 if (reply->error() != QNetworkReply::OperationCanceledError) {
148 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
154 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
149
155
150
156
151 qCInfo(LOG_AmdaProvider())
157 qCInfo(LOG_AmdaProvider())
152 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
158 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
153 // Executes request for downloading file //
159 // Executes request for downloading file //
154
160
155 // Creates destination file
161 // Creates destination file
156 if (tempFile->open()) {
162 if (tempFile->open()) {
157 // Executes request
163 // Executes request
158 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId,
164 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId,
159 httpDownloadFinished);
165 httpDownloadFinished);
160 }
166 }
161 }
167 }
162 };
168 };
163
169
164 // //////////////// //
170 // //////////////// //
165 // Executes request //
171 // Executes request //
166 // //////////////// //
172 // //////////////// //
167 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
173 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
168 }
174 }
@@ -1,34 +1,36
1 #ifndef SCIQLOP_COSINUSPROVIDER_H
1 #ifndef SCIQLOP_COSINUSPROVIDER_H
2 #define SCIQLOP_COSINUSPROVIDER_H
2 #define SCIQLOP_COSINUSPROVIDER_H
3
3
4 #include "MockPluginGlobal.h"
4 #include "MockPluginGlobal.h"
5
5
6 #include <Data/IDataProvider.h>
6 #include <Data/IDataProvider.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QUuid>
9 #include <QUuid>
10
10
11 #include <QHash>
11 #include <QHash>
12 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
13
13
14 /**
14 /**
15 * @brief The CosinusProvider class is an example of how a data provider can generate data
15 * @brief The CosinusProvider class is an example of how a data provider can generate data
16 */
16 */
17 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
17 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
18 public:
18 public:
19 std::shared_ptr<IDataProvider> clone() const override;
20
19 /// @sa IDataProvider::requestDataLoading(). The current impl isn't thread safe.
21 /// @sa IDataProvider::requestDataLoading(). The current impl isn't thread safe.
20 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override;
22 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override;
21
23
22
24
23 /// @sa IDataProvider::requestDataAborting(). The current impl isn't thread safe.
25 /// @sa IDataProvider::requestDataAborting(). The current impl isn't thread safe.
24 void requestDataAborting(QUuid acqIdentifier) override;
26 void requestDataAborting(QUuid acqIdentifier) override;
25
27
26
28
27 private:
29 private:
28 std::shared_ptr<IDataSeries> retrieveData(QUuid acqIdentifier,
30 std::shared_ptr<IDataSeries> retrieveData(QUuid acqIdentifier,
29 const SqpRange &dataRangeRequested);
31 const SqpRange &dataRangeRequested);
30
32
31 QHash<QUuid, bool> m_VariableToEnableProvider;
33 QHash<QUuid, bool> m_VariableToEnableProvider;
32 };
34 };
33
35
34 #endif // SCIQLOP_COSINUSPROVIDER_H
36 #endif // SCIQLOP_COSINUSPROVIDER_H
@@ -1,103 +1,109
1 #include "CosinusProvider.h"
1 #include "CosinusProvider.h"
2
2
3 #include <Data/DataProviderParameters.h>
3 #include <Data/DataProviderParameters.h>
4 #include <Data/ScalarSeries.h>
4 #include <Data/ScalarSeries.h>
5
5
6 #include <cmath>
6 #include <cmath>
7
7
8 #include <QFuture>
8 #include <QFuture>
9 #include <QThread>
9 #include <QThread>
10 #include <QtConcurrent/QtConcurrent>
10 #include <QtConcurrent/QtConcurrent>
11
11
12 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
12 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
13
13
14 std::shared_ptr<IDataProvider> CosinusProvider::clone() const
15 {
16 // No copy is made in clone
17 return std::make_shared<CosinusProvider>();
18 }
19
14 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(QUuid acqIdentifier,
20 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(QUuid acqIdentifier,
15 const SqpRange &dataRangeRequested)
21 const SqpRange &dataRangeRequested)
16 {
22 {
17 // TODO: Add Mutex
23 // TODO: Add Mutex
18 auto dataIndex = 0;
24 auto dataIndex = 0;
19
25
20 // Gets the timerange from the parameters
26 // Gets the timerange from the parameters
21 double freq = 100.0;
27 double freq = 100.0;
22 double start = std::ceil(dataRangeRequested.m_TStart * freq); // 100 htz
28 double start = std::ceil(dataRangeRequested.m_TStart * freq); // 100 htz
23 double end = std::floor(dataRangeRequested.m_TEnd * freq); // 100 htz
29 double end = std::floor(dataRangeRequested.m_TEnd * freq); // 100 htz
24
30
25 // We assure that timerange is valid
31 // We assure that timerange is valid
26 if (end < start) {
32 if (end < start) {
27 std::swap(start, end);
33 std::swap(start, end);
28 }
34 }
29
35
30 // Generates scalar series containing cosinus values (one value per second)
36 // Generates scalar series containing cosinus values (one value per second)
31 auto dataCount = end - start;
37 auto dataCount = end - start;
32
38
33 auto xAxisData = std::vector<double>{};
39 auto xAxisData = std::vector<double>{};
34 xAxisData.resize(dataCount);
40 xAxisData.resize(dataCount);
35
41
36 auto valuesData = std::vector<double>{};
42 auto valuesData = std::vector<double>{};
37 valuesData.resize(dataCount);
43 valuesData.resize(dataCount);
38
44
39 int progress = 0;
45 int progress = 0;
40 auto progressEnd = dataCount;
46 auto progressEnd = dataCount;
41 for (auto time = start; time < end; ++time, ++dataIndex) {
47 for (auto time = start; time < end; ++time, ++dataIndex) {
42 auto it = m_VariableToEnableProvider.find(acqIdentifier);
48 auto it = m_VariableToEnableProvider.find(acqIdentifier);
43 if (it != m_VariableToEnableProvider.end() && it.value()) {
49 if (it != m_VariableToEnableProvider.end() && it.value()) {
44 const auto timeOnFreq = time / freq;
50 const auto timeOnFreq = time / freq;
45
51
46 xAxisData[dataIndex] = timeOnFreq;
52 xAxisData[dataIndex] = timeOnFreq;
47 valuesData[dataIndex] = std::cos(timeOnFreq);
53 valuesData[dataIndex] = std::cos(timeOnFreq);
48
54
49 // progression
55 // progression
50 int currentProgress = (time - start) * 100.0 / progressEnd;
56 int currentProgress = (time - start) * 100.0 / progressEnd;
51 if (currentProgress != progress) {
57 if (currentProgress != progress) {
52 progress = currentProgress;
58 progress = currentProgress;
53
59
54 emit dataProvidedProgress(acqIdentifier, progress);
60 emit dataProvidedProgress(acqIdentifier, progress);
55 }
61 }
56 }
62 }
57 else {
63 else {
58 if (!it.value()) {
64 if (!it.value()) {
59 qCDebug(LOG_CosinusProvider())
65 qCDebug(LOG_CosinusProvider())
60 << "CosinusProvider::retrieveData: ARRET De l'acquisition detectΓ©"
66 << "CosinusProvider::retrieveData: ARRET De l'acquisition detectΓ©"
61 << end - time;
67 << end - time;
62 }
68 }
63 }
69 }
64 }
70 }
65 emit dataProvidedProgress(acqIdentifier, 0.0);
71 emit dataProvidedProgress(acqIdentifier, 0.0);
66
72
67 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
73 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
68 Unit{QStringLiteral("t"), true}, Unit{});
74 Unit{QStringLiteral("t"), true}, Unit{});
69 }
75 }
70
76
71 void CosinusProvider::requestDataLoading(QUuid acqIdentifier,
77 void CosinusProvider::requestDataLoading(QUuid acqIdentifier,
72 const DataProviderParameters &parameters)
78 const DataProviderParameters &parameters)
73 {
79 {
74 // TODO: Add Mutex
80 // TODO: Add Mutex
75 m_VariableToEnableProvider[acqIdentifier] = true;
81 m_VariableToEnableProvider[acqIdentifier] = true;
76 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::requestDataLoading"
82 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::requestDataLoading"
77 << QThread::currentThread()->objectName();
83 << QThread::currentThread()->objectName();
78 // NOTE: Try to use multithread if possible
84 // NOTE: Try to use multithread if possible
79 const auto times = parameters.m_Times;
85 const auto times = parameters.m_Times;
80
86
81 for (const auto &dateTime : qAsConst(times)) {
87 for (const auto &dateTime : qAsConst(times)) {
82 if (m_VariableToEnableProvider[acqIdentifier]) {
88 if (m_VariableToEnableProvider[acqIdentifier]) {
83 auto scalarSeries = this->retrieveData(acqIdentifier, dateTime);
89 auto scalarSeries = this->retrieveData(acqIdentifier, dateTime);
84 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::dataProvided";
90 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::dataProvided";
85 emit dataProvided(acqIdentifier, scalarSeries, dateTime);
91 emit dataProvided(acqIdentifier, scalarSeries, dateTime);
86 }
92 }
87 }
93 }
88 }
94 }
89
95
90 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
96 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
91 {
97 {
92 // TODO: Add Mutex
98 // TODO: Add Mutex
93 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << acqIdentifier
99 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << acqIdentifier
94 << QThread::currentThread()->objectName();
100 << QThread::currentThread()->objectName();
95 auto it = m_VariableToEnableProvider.find(acqIdentifier);
101 auto it = m_VariableToEnableProvider.find(acqIdentifier);
96 if (it != m_VariableToEnableProvider.end()) {
102 if (it != m_VariableToEnableProvider.end()) {
97 it.value() = false;
103 it.value() = false;
98 }
104 }
99 else {
105 else {
100 qCWarning(LOG_CosinusProvider())
106 qCWarning(LOG_CosinusProvider())
101 << tr("Aborting progression of inexistant identifier detected !!!");
107 << tr("Aborting progression of inexistant identifier detected !!!");
102 }
108 }
103 }
109 }
General Comments 0
You need to be logged in to leave comments. Login now