##// END OF EJS Templates
Merge branch 'feature/AmdaProviderImprovements' into develop
Alexandre Leroux -
r385:0ec770a1fa8f merge
parent child
Show More
@@ -0,0 +1,16
1 #ifndef SCIQLOP_AMDADEFS_H
2 #define SCIQLOP_AMDADEFS_H
3
4 #include <QString>
5
6 // ////////////// //
7 // AMDA constants //
8 // ////////////// //
9
10 // Relevant keys in JSON file
11 extern const QString AMDA_COMPONENT_KEY;
12 extern const QString AMDA_PRODUCT_KEY;
13 extern const QString AMDA_ROOT_KEY;
14 extern const QString AMDA_XML_ID_KEY;
15
16 #endif // SCIQLOP_AMDADEFS_H
@@ -0,0 +1,6
1 #include "AmdaDefs.h"
2
3 const QString AMDA_COMPONENT_KEY = QStringLiteral("component");
4 const QString AMDA_PRODUCT_KEY = QStringLiteral("parameter");
5 const QString AMDA_ROOT_KEY = QStringLiteral("dataCenter");
6 const QString AMDA_XML_ID_KEY = QStringLiteral("xml:id");
@@ -1,15 +1,18
1 #ifndef SCIQLOP_DATAPROVIDERPARAMETERS_H
1 #ifndef SCIQLOP_DATAPROVIDERPARAMETERS_H
2 #define SCIQLOP_DATAPROVIDERPARAMETERS_H
2 #define SCIQLOP_DATAPROVIDERPARAMETERS_H
3
3
4 #include "SqpDateTime.h"
4 #include "SqpDateTime.h"
5
5
6 /**
6 /**
7 * @brief The DataProviderParameters struct holds the information needed to retrieve data from a
7 * @brief The DataProviderParameters struct holds the information needed to retrieve data from a
8 * data provider
8 * data provider
9 * @sa IDataProvider
9 * @sa IDataProvider
10 */
10 */
11 struct DataProviderParameters {
11 struct DataProviderParameters {
12 SqpDateTime m_Time;
12 /// Times for which retrieve data
13 QVector<SqpDateTime> m_Times;
14 /// Extra data that can be used by the provider to retrieve data
15 QVariantHash m_Data;
13 };
16 };
14
17
15 #endif // SCIQLOP_DATAPROVIDERPARAMETERS_H
18 #endif // SCIQLOP_DATAPROVIDERPARAMETERS_H
@@ -1,60 +1,59
1 #ifndef SCIQLOP_IDATAPROVIDER_H
1 #ifndef SCIQLOP_IDATAPROVIDER_H
2 #define SCIQLOP_IDATAPROVIDER_H
2 #define SCIQLOP_IDATAPROVIDER_H
3
3
4 #include <memory>
4 #include <memory>
5
5
6 #include <QObject>
6 #include <QObject>
7 #include <QUuid>
7 #include <QUuid>
8
8
9 #include <Common/MetaTypes.h>
9 #include <Common/MetaTypes.h>
10
10
11 #include <Data/SqpDateTime.h>
11 #include <Data/SqpDateTime.h>
12
12
13 class DataProviderParameters;
13 class DataProviderParameters;
14 class IDataSeries;
14 class IDataSeries;
15 class QNetworkReply;
15 class QNetworkReply;
16 class QNetworkRequest;
16 class QNetworkRequest;
17
17
18 /**
18 /**
19 * @brief The IDataProvider interface aims to declare a data provider.
19 * @brief The IDataProvider interface aims to declare a data provider.
20 *
20 *
21 * A data provider is an entity that generates data and returns it according to various parameters
21 * A data provider is an entity that generates data and returns it according to various parameters
22 * (time interval, product to retrieve the data, etc.)
22 * (time interval, product to retrieve the data, etc.)
23 *
23 *
24 * @sa IDataSeries
24 * @sa IDataSeries
25 */
25 */
26 class IDataProvider : public QObject {
26 class IDataProvider : public QObject {
27
27
28 Q_OBJECT
28 Q_OBJECT
29 public:
29 public:
30 virtual ~IDataProvider() noexcept = default;
30 virtual ~IDataProvider() noexcept = default;
31
31
32 /**
32 /**
33 * @brief requestDataLoading provide datas for the data identified by identifier for all
33 * @brief requestDataLoading provide datas for the data identified by identifier and parameters
34 * SqpDateTime of dateTimeList
35 */
34 */
36 virtual void requestDataLoading(QUuid identifier, const QVector<SqpDateTime> &dateTimeList) = 0;
35 virtual void requestDataLoading(QUuid identifier, const DataProviderParameters &parameters) = 0;
37
36
38 signals:
37 signals:
39 /**
38 /**
40 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
39 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
41 * identified by identifier
40 * identified by identifier
42 */
41 */
43 void dataProvided(QUuid identifier, std::shared_ptr<IDataSeries> dateSerie,
42 void dataProvided(QUuid identifier, std::shared_ptr<IDataSeries> dateSerie,
44 const SqpDateTime &dateTime);
43 const SqpDateTime &dateTime);
45
44
46
45
47 /**
46 /**
48 * @brief requestConstructed send a request for the data identified by identifier
47 * @brief requestConstructed send a request for the data identified by identifier
49 * @callback is the methode call by the reply of the request when it is finished.
48 * @callback is the methode call by the reply of the request when it is finished.
50 */
49 */
51 void requestConstructed(const QNetworkRequest &request, QUuid identifier,
50 void requestConstructed(const QNetworkRequest &request, QUuid identifier,
52 std::function<void(QNetworkReply *, QUuid)> callback);
51 std::function<void(QNetworkReply *, QUuid)> callback);
53 };
52 };
54
53
55 // Required for using shared_ptr in signals/slots
54 // Required for using shared_ptr in signals/slots
56 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
55 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
57 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
56 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
58 std::function<void(QNetworkReply *, QUuid)>)
57 std::function<void(QNetworkReply *, QUuid)>)
59
58
60 #endif // SCIQLOP_IDATAPROVIDER_H
59 #endif // SCIQLOP_IDATAPROVIDER_H
@@ -1,90 +1,92
1 #ifndef SCIQLOP_DATASOURCECONTROLLER_H
1 #ifndef SCIQLOP_DATASOURCECONTROLLER_H
2 #define SCIQLOP_DATASOURCECONTROLLER_H
2 #define SCIQLOP_DATASOURCECONTROLLER_H
3
3
4 #include <QLoggingCategory>
4 #include <QLoggingCategory>
5 #include <QObject>
5 #include <QObject>
6 #include <QUuid>
6 #include <QUuid>
7
7
8 #include <Common/spimpl.h>
8 #include <Common/spimpl.h>
9
9
10 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController)
10 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController)
11
11
12 class DataSourceItem;
12 class DataSourceItem;
13 class IDataProvider;
13 class IDataProvider;
14
14
15 /**
15 /**
16 * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This
16 * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This
17 * is the intermediate class that SciQlop has to use in the way to connect a data source. Please
17 * is the intermediate class that SciQlop has to use in the way to connect a data source. Please
18 * first use register method to initialize a plugin specified by its metadata name (JSON plugin
18 * first use register method to initialize a plugin specified by its metadata name (JSON plugin
19 * source) then others specifics method will be able to access it. You can load a data source driver
19 * source) then others specifics method will be able to access it. You can load a data source driver
20 * plugin then create a data source.
20 * plugin then create a data source.
21 */
21 */
22 class DataSourceController : public QObject {
22 class DataSourceController : public QObject {
23 Q_OBJECT
23 Q_OBJECT
24 public:
24 public:
25 explicit DataSourceController(QObject *parent = 0);
25 explicit DataSourceController(QObject *parent = 0);
26 virtual ~DataSourceController();
26 virtual ~DataSourceController();
27
27
28 /**
28 /**
29 * Registers a data source. The method delivers a unique id that can be used afterwards to
29 * Registers a data source. The method delivers a unique id that can be used afterwards to
30 * access to the data source properties (structure, connection parameters, data provider, etc.)
30 * access to the data source properties (structure, connection parameters, data provider, etc.)
31 * @param dataSourceName the name of the data source
31 * @param dataSourceName the name of the data source
32 * @return the unique id with which the data source has been registered
32 * @return the unique id with which the data source has been registered
33 */
33 */
34 QUuid registerDataSource(const QString &dataSourceName) noexcept;
34 QUuid registerDataSource(const QString &dataSourceName) noexcept;
35
35
36 /**
36 /**
37 * Sets the structure of a data source. The controller takes ownership of the structure.
37 * Sets the structure of a data source. The controller takes ownership of the structure.
38 * @param dataSourceUid the unique id with which the data source has been registered into the
38 * @param dataSourceUid the unique id with which the data source has been registered into the
39 * controller. If it is invalid, the method has no effect.
39 * controller. If it is invalid, the method has no effect.
40 * @param dataSourceItem the structure of the data source. It must be not null to be registered
40 * @param dataSourceItem the structure of the data source. It must be not null to be registered
41 * @sa registerDataSource()
41 * @sa registerDataSource()
42 */
42 */
43 void setDataSourceItem(const QUuid &dataSourceUid,
43 void setDataSourceItem(const QUuid &dataSourceUid,
44 std::unique_ptr<DataSourceItem> dataSourceItem) noexcept;
44 std::unique_ptr<DataSourceItem> dataSourceItem) noexcept;
45
45
46 /**
46 /**
47 * Sets the data provider used to retrieve data from of a data source. The controller takes
47 * Sets the data provider used to retrieve data from of a data source. The controller takes
48 * ownership of the provider.
48 * ownership of the provider.
49 * @param dataSourceUid the unique id with which the data source has been registered into the
49 * @param dataSourceUid the unique id with which the data source has been registered into the
50 * controller. If it is invalid, the method has no effect.
50 * controller. If it is invalid, the method has no effect.
51 * @param dataProvider the provider of the data source
51 * @param dataProvider the provider of the data source
52 * @sa registerDataSource()
52 * @sa registerDataSource()
53 */
53 */
54 void setDataProvider(const QUuid &dataSourceUid,
54 void setDataProvider(const QUuid &dataSourceUid,
55 std::unique_ptr<IDataProvider> dataProvider) noexcept;
55 std::unique_ptr<IDataProvider> dataProvider) noexcept;
56
56
57 /**
57 /**
58 * Loads an item (product) as a variable in SciQlop
58 * Loads an item (product) as a variable in SciQlop
59 * @param dataSourceUid the unique id of the data source containing the item. It is used to get
59 * @param dataSourceUid the unique id of the data source containing the item. It is used to get
60 * the data provider associated to the data source, and pass it to for the variable creation
60 * the data provider associated to the data source, and pass it to for the variable creation
61 * @param productItem the item to load
61 * @param productItem the item to load
62 */
62 */
63 void loadProductItem(const QUuid &dataSourceUid, const DataSourceItem &productItem) noexcept;
63 void loadProductItem(const QUuid &dataSourceUid, const DataSourceItem &productItem) noexcept;
64
64
65 public slots:
65 public slots:
66 /// Manage init/end of the controller
66 /// Manage init/end of the controller
67 void initialize();
67 void initialize();
68 void finalize();
68 void finalize();
69
69
70 signals:
70 signals:
71 /// Signal emitted when a structure has been set for a data source
71 /// Signal emitted when a structure has been set for a data source
72 void dataSourceItemSet(DataSourceItem *dataSourceItem);
72 void dataSourceItemSet(DataSourceItem *dataSourceItem);
73
73
74 /**
74 /**
75 * Signal emitted when a variable creation is asked for a product
75 * Signal emitted when a variable creation is asked for a product
76 * @param variableName the name of the variable
76 * @param variableName the name of the variable
77 * @param variableMetadata the metadata of the variable
77 * @param variableProvider the provider that will be used to retrieve the data of the variable
78 * @param variableProvider the provider that will be used to retrieve the data of the variable
78 * (can be null)
79 * (can be null)
79 */
80 */
80 void variableCreationRequested(const QString &variableName,
81 void variableCreationRequested(const QString &variableName,
82 const QVariantHash &variableMetadata,
81 std::shared_ptr<IDataProvider> variableProvider);
83 std::shared_ptr<IDataProvider> variableProvider);
82
84
83 private:
85 private:
84 void waitForFinish();
86 void waitForFinish();
85
87
86 class DataSourceControllerPrivate;
88 class DataSourceControllerPrivate;
87 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
89 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
88 };
90 };
89
91
90 #endif // SCIQLOP_DATASOURCECONTROLLER_H
92 #endif // SCIQLOP_DATASOURCECONTROLLER_H
@@ -1,94 +1,94
1 #ifndef SCIQLOP_DATASOURCEITEM_H
1 #ifndef SCIQLOP_DATASOURCEITEM_H
2 #define SCIQLOP_DATASOURCEITEM_H
2 #define SCIQLOP_DATASOURCEITEM_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5
5
6 #include <QVariant>
6 #include <QVariant>
7 #include <QVector>
7 #include <QVector>
8
8
9 class DataSourceItemAction;
9 class DataSourceItemAction;
10
10
11 /**
11 /**
12 * Possible types of an item
12 * Possible types of an item
13 */
13 */
14 enum class DataSourceItemType { NODE, PRODUCT, COMPONENT };
14 enum class DataSourceItemType { NODE, PRODUCT, COMPONENT };
15
15
16 /**
16 /**
17 * @brief The DataSourceItem class aims to represent a structure element of a data source.
17 * @brief The DataSourceItem class aims to represent a structure element of a data source.
18 * A data source has a tree structure that is made up of a main DataSourceItem object (root)
18 * A data source has a tree structure that is made up of a main DataSourceItem object (root)
19 * containing other DataSourceItem objects (children).
19 * containing other DataSourceItem objects (children).
20 * For each DataSourceItem can be associated a set of data representing it.
20 * For each DataSourceItem can be associated a set of data representing it.
21 */
21 */
22 class DataSourceItem {
22 class DataSourceItem {
23 public:
23 public:
24 /// Key associated with the name of the item
24 /// Key associated with the name of the item
25 static const QString NAME_DATA_KEY;
25 static const QString NAME_DATA_KEY;
26
26
27 explicit DataSourceItem(DataSourceItemType type, const QString &name);
27 explicit DataSourceItem(DataSourceItemType type, const QString &name);
28 explicit DataSourceItem(DataSourceItemType type, QHash<QString, QVariant> data = {});
28 explicit DataSourceItem(DataSourceItemType type, QVariantHash data = {});
29
29
30 /// @return the actions of the item as a vector
30 /// @return the actions of the item as a vector
31 QVector<DataSourceItemAction *> actions() const noexcept;
31 QVector<DataSourceItemAction *> actions() const noexcept;
32
32
33 /**
33 /**
34 * Adds an action to the item. The item takes ownership of the action, and the action is
34 * Adds an action to the item. The item takes ownership of the action, and the action is
35 * automatically associated to the item
35 * automatically associated to the item
36 * @param action the action to add
36 * @param action the action to add
37 */
37 */
38 void addAction(std::unique_ptr<DataSourceItemAction> action) noexcept;
38 void addAction(std::unique_ptr<DataSourceItemAction> action) noexcept;
39
39
40 /**
40 /**
41 * Adds a child to the item. The item takes ownership of the child.
41 * Adds a child to the item. The item takes ownership of the child.
42 * @param child the child to add
42 * @param child the child to add
43 */
43 */
44 void appendChild(std::unique_ptr<DataSourceItem> child) noexcept;
44 void appendChild(std::unique_ptr<DataSourceItem> child) noexcept;
45
45
46 /**
46 /**
47 * Returns the item's child associated to an index
47 * Returns the item's child associated to an index
48 * @param childIndex the index to search
48 * @param childIndex the index to search
49 * @return a pointer to the child if index is valid, nullptr otherwise
49 * @return a pointer to the child if index is valid, nullptr otherwise
50 */
50 */
51 DataSourceItem *child(int childIndex) const noexcept;
51 DataSourceItem *child(int childIndex) const noexcept;
52
52
53 int childCount() const noexcept;
53 int childCount() const noexcept;
54
54
55 /**
55 /**
56 * Get the data associated to a key
56 * Get the data associated to a key
57 * @param key the key to search
57 * @param key the key to search
58 * @return the data found if key is valid, default QVariant otherwise
58 * @return the data found if key is valid, default QVariant otherwise
59 */
59 */
60 QVariant data(const QString &key) const noexcept;
60 QVariant data(const QString &key) const noexcept;
61
61
62 /// Gets all data
62 /// Gets all data
63 const QHash<QString, QVariant> &data() const noexcept;
63 QVariantHash data() const noexcept;
64
64
65 bool isRoot() const noexcept;
65 bool isRoot() const noexcept;
66
66
67 QString name() const noexcept;
67 QString name() const noexcept;
68
68
69 /**
69 /**
70 * Get the item's parent
70 * Get the item's parent
71 * @return a pointer to the parent if it exists, nullptr if the item is a root
71 * @return a pointer to the parent if it exists, nullptr if the item is a root
72 */
72 */
73 DataSourceItem *parentItem() const noexcept;
73 DataSourceItem *parentItem() const noexcept;
74
74
75 /**
75 /**
76 * Sets or appends a value to a key
76 * Sets or appends a value to a key
77 * @param key the key
77 * @param key the key
78 * @param value the value
78 * @param value the value
79 * @param append if true, the value is added to the values already existing for the key,
79 * @param append if true, the value is added to the values already existing for the key,
80 * otherwise it replaces the existing values
80 * otherwise it replaces the existing values
81 */
81 */
82 void setData(const QString &key, const QVariant &value, bool append = false) noexcept;
82 void setData(const QString &key, const QVariant &value, bool append = false) noexcept;
83
83
84 DataSourceItemType type() const noexcept;
84 DataSourceItemType type() const noexcept;
85
85
86 bool operator==(const DataSourceItem &other);
86 bool operator==(const DataSourceItem &other);
87 bool operator!=(const DataSourceItem &other);
87 bool operator!=(const DataSourceItem &other);
88
88
89 private:
89 private:
90 class DataSourceItemPrivate;
90 class DataSourceItemPrivate;
91 spimpl::unique_impl_ptr<DataSourceItemPrivate> impl;
91 spimpl::unique_impl_ptr<DataSourceItemPrivate> impl;
92 };
92 };
93
93
94 #endif // SCIQLOP_DATASOURCEITEMMODEL_H
94 #endif // SCIQLOP_DATASOURCEITEMMODEL_H
@@ -1,55 +1,55
1 #ifndef SCIQLOP_VARIABLE_H
1 #ifndef SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
3
3
4 #include <Data/SqpDateTime.h>
4 #include <Data/SqpDateTime.h>
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QObject>
7 #include <QObject>
8
8
9 #include <Common/MetaTypes.h>
9 #include <Common/MetaTypes.h>
10 #include <Common/spimpl.h>
10 #include <Common/spimpl.h>
11
11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
13
13
14 class IDataSeries;
14 class IDataSeries;
15 class QString;
15 class QString;
16
16
17 /**
17 /**
18 * @brief The Variable class represents a variable in SciQlop.
18 * @brief The Variable class represents a variable in SciQlop.
19 */
19 */
20 class Variable : public QObject {
20 class Variable : public QObject {
21
21
22 Q_OBJECT
22 Q_OBJECT
23
23
24 public:
24 public:
25 explicit Variable(const QString &name, const QString &unit, const QString &mission,
25 explicit Variable(const QString &name, const SqpDateTime &dateTime,
26 const SqpDateTime &dateTime);
26 const QVariantHash &metadata = {});
27
27
28 QString name() const noexcept;
28 QString name() const noexcept;
29 QString mission() const noexcept;
30 QString unit() const noexcept;
31 SqpDateTime dateTime() const noexcept;
29 SqpDateTime dateTime() const noexcept;
32 void setDateTime(const SqpDateTime &dateTime) noexcept;
30 void setDateTime(const SqpDateTime &dateTime) noexcept;
33
31
34 /// @return the data of the variable, nullptr if there is no data
32 /// @return the data of the variable, nullptr if there is no data
35 IDataSeries *dataSeries() const noexcept;
33 IDataSeries *dataSeries() const noexcept;
36
34
35 QVariantHash metadata() const noexcept;
36
37 bool contains(const SqpDateTime &dateTime) const noexcept;
37 bool contains(const SqpDateTime &dateTime) const noexcept;
38 bool intersect(const SqpDateTime &dateTime) const noexcept;
38 bool intersect(const SqpDateTime &dateTime) const noexcept;
39 bool isInside(const SqpDateTime &dateTime) const noexcept;
39 bool isInside(const SqpDateTime &dateTime) const noexcept;
40
40
41 public slots:
41 public slots:
42 void setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
42 void setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
43
43
44 signals:
44 signals:
45 void updated();
45 void updated();
46
46
47 private:
47 private:
48 class VariablePrivate;
48 class VariablePrivate;
49 spimpl::unique_impl_ptr<VariablePrivate> impl;
49 spimpl::unique_impl_ptr<VariablePrivate> impl;
50 };
50 };
51
51
52 // Required for using shared_ptr in signals/slots
52 // Required for using shared_ptr in signals/slots
53 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
53 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
54
54
55 #endif // SCIQLOP_VARIABLE_H
55 #endif // SCIQLOP_VARIABLE_H
@@ -1,83 +1,85
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
3
3
4 #include <Data/SqpDateTime.h>
4 #include <Data/SqpDateTime.h>
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QObject>
7 #include <QObject>
8
8
9 #include <Common/spimpl.h>
9 #include <Common/spimpl.h>
10
10
11 class IDataProvider;
11 class IDataProvider;
12 class QItemSelectionModel;
12 class QItemSelectionModel;
13 class TimeController;
13 class TimeController;
14 class Variable;
14 class Variable;
15 class VariableModel;
15 class VariableModel;
16
16
17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
18
18
19 /**
19 /**
20 * @brief The VariableController class aims to handle the variables in SciQlop.
20 * @brief The VariableController class aims to handle the variables in SciQlop.
21 */
21 */
22 class VariableController : public QObject {
22 class VariableController : public QObject {
23 Q_OBJECT
23 Q_OBJECT
24 public:
24 public:
25 explicit VariableController(QObject *parent = 0);
25 explicit VariableController(QObject *parent = 0);
26 virtual ~VariableController();
26 virtual ~VariableController();
27
27
28 VariableModel *variableModel() noexcept;
28 VariableModel *variableModel() noexcept;
29 QItemSelectionModel *variableSelectionModel() noexcept;
29 QItemSelectionModel *variableSelectionModel() noexcept;
30
30
31 void setTimeController(TimeController *timeController) noexcept;
31 void setTimeController(TimeController *timeController) noexcept;
32
32
33 /**
33 /**
34 * Deletes from the controller the variable passed in parameter.
34 * Deletes from the controller the variable passed in parameter.
35 *
35 *
36 * Delete a variable includes:
36 * Delete a variable includes:
37 * - the deletion of the various references to the variable in SciQlop
37 * - the deletion of the various references to the variable in SciQlop
38 * - the deletion of the model variable
38 * - the deletion of the model variable
39 * - the deletion of the provider associated with the variable
39 * - the deletion of the provider associated with the variable
40 * - removing the cache associated with the variable
40 * - removing the cache associated with the variable
41 *
41 *
42 * @param variable the variable to delete from the controller.
42 * @param variable the variable to delete from the controller.
43 */
43 */
44 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
44 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
45
45
46 /**
46 /**
47 * Deletes from the controller the variables passed in parameter.
47 * Deletes from the controller the variables passed in parameter.
48 * @param variables the variables to delete from the controller.
48 * @param variables the variables to delete from the controller.
49 * @sa deleteVariable()
49 * @sa deleteVariable()
50 */
50 */
51 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
51 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
52
52
53 signals:
53 signals:
54 /// Signal emitted when a variable is about to be deleted from the controller
54 /// Signal emitted when a variable is about to be deleted from the controller
55 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
55 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
56
56
57 public slots:
57 public slots:
58 /// Request the data loading of the variable whithin dateTime
58 /// Request the data loading of the variable whithin dateTime
59 void onRequestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
59 void onRequestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
60 /**
60 /**
61 * Creates a new variable and adds it to the model
61 * Creates a new variable and adds it to the model
62 * @param name the name of the new variable
62 * @param name the name of the new variable
63 * @param metadata the metadata of the new variable
63 * @param provider the data provider for the new variable
64 * @param provider the data provider for the new variable
64 */
65 */
65 void createVariable(const QString &name, std::shared_ptr<IDataProvider> provider) noexcept;
66 void createVariable(const QString &name, const QVariantHash &metadata,
67 std::shared_ptr<IDataProvider> provider) noexcept;
66
68
67 /// Update the temporal parameters of every selected variable to dateTime
69 /// Update the temporal parameters of every selected variable to dateTime
68 void onDateTimeOnSelection(const SqpDateTime &dateTime);
70 void onDateTimeOnSelection(const SqpDateTime &dateTime);
69
71
70
72
71 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
73 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
72
74
73 void initialize();
75 void initialize();
74 void finalize();
76 void finalize();
75
77
76 private:
78 private:
77 void waitForFinish();
79 void waitForFinish();
78
80
79 class VariableControllerPrivate;
81 class VariableControllerPrivate;
80 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
82 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
81 };
83 };
82
84
83 #endif // SCIQLOP_VARIABLECONTROLLER_H
85 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,70 +1,71
1 #ifndef SCIQLOP_VARIABLEMODEL_H
1 #ifndef SCIQLOP_VARIABLEMODEL_H
2 #define SCIQLOP_VARIABLEMODEL_H
2 #define SCIQLOP_VARIABLEMODEL_H
3
3
4
4
5 #include <Data/SqpDateTime.h>
5 #include <Data/SqpDateTime.h>
6
6
7 #include <QAbstractTableModel>
7 #include <QAbstractTableModel>
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9
9
10 #include <Common/MetaTypes.h>
10 #include <Common/MetaTypes.h>
11 #include <Common/spimpl.h>
11 #include <Common/spimpl.h>
12
12
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
14
14
15 enum VariableRoles { ProgressRole = Qt::UserRole };
15 enum VariableRoles { ProgressRole = Qt::UserRole };
16
16
17
17
18 class IDataSeries;
18 class IDataSeries;
19 class Variable;
19 class Variable;
20
20
21 /**
21 /**
22 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
22 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
23 */
23 */
24 class VariableModel : public QAbstractTableModel {
24 class VariableModel : public QAbstractTableModel {
25 public:
25 public:
26 explicit VariableModel(QObject *parent = nullptr);
26 explicit VariableModel(QObject *parent = nullptr);
27
27
28 /**
28 /**
29 * Creates a new variable in the model
29 * Creates a new variable in the model
30 * @param name the name of the new variable
30 * @param name the name of the new variable
31 * @param dateTime the dateTime of the new variable
31 * @param dateTime the dateTime of the new variable
32 * @param metadata the metadata associated to the new variable
32 * @return the pointer to the new variable
33 * @return the pointer to the new variable
33 */
34 */
34 std::shared_ptr<Variable> createVariable(const QString &name,
35 std::shared_ptr<Variable> createVariable(const QString &name, const SqpDateTime &dateTime,
35 const SqpDateTime &dateTime) noexcept;
36 const QVariantHash &metadata) noexcept;
36
37
37 /**
38 /**
38 * Deletes a variable from the model, if it exists
39 * Deletes a variable from the model, if it exists
39 * @param variable the variable to delete
40 * @param variable the variable to delete
40 */
41 */
41 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
42 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
42
43
43
44
44 std::shared_ptr<Variable> variable(int index) const;
45 std::shared_ptr<Variable> variable(int index) const;
45
46
46 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
47 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
47
48
48 // /////////////////////////// //
49 // /////////////////////////// //
49 // QAbstractTableModel methods //
50 // QAbstractTableModel methods //
50 // /////////////////////////// //
51 // /////////////////////////// //
51
52
52 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
53 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
53 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
54 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
54 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
55 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
55 virtual QVariant headerData(int section, Qt::Orientation orientation,
56 virtual QVariant headerData(int section, Qt::Orientation orientation,
56 int role = Qt::DisplayRole) const override;
57 int role = Qt::DisplayRole) const override;
57
58
58 private:
59 private:
59 class VariableModelPrivate;
60 class VariableModelPrivate;
60 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
61 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
61
62
62 private slots:
63 private slots:
63 /// Slot called when data of a variable has been updated
64 /// Slot called when data of a variable has been updated
64 void onVariableUpdated() noexcept;
65 void onVariableUpdated() noexcept;
65 };
66 };
66
67
67 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
68 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
68 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
69 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
69
70
70 #endif // SCIQLOP_VARIABLEMODEL_H
71 #endif // SCIQLOP_VARIABLEMODEL_H
@@ -1,120 +1,120
1 #include "DataSource/DataSourceController.h"
1 #include "DataSource/DataSourceController.h"
2 #include "DataSource/DataSourceItem.h"
2 #include "DataSource/DataSourceItem.h"
3
3
4 #include <Data/IDataProvider.h>
4 #include <Data/IDataProvider.h>
5
5
6 #include <QMutex>
6 #include <QMutex>
7 #include <QThread>
7 #include <QThread>
8
8
9 #include <QDir>
9 #include <QDir>
10 #include <QStandardPaths>
10 #include <QStandardPaths>
11
11
12 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
12 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
13
13
14 class DataSourceController::DataSourceControllerPrivate {
14 class DataSourceController::DataSourceControllerPrivate {
15 public:
15 public:
16 QMutex m_WorkingMutex;
16 QMutex m_WorkingMutex;
17 /// Data sources registered
17 /// Data sources registered
18 QHash<QUuid, QString> m_DataSources;
18 QHash<QUuid, QString> m_DataSources;
19 /// Data sources structures
19 /// Data sources structures
20 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
20 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
21 /// Data providers registered
21 /// Data providers registered
22 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
22 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
23 /// continue to live without necessarily the data source controller
23 /// continue to live without necessarily the data source controller
24 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
24 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
25 };
25 };
26
26
27 DataSourceController::DataSourceController(QObject *parent)
27 DataSourceController::DataSourceController(QObject *parent)
28 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
28 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
29 {
29 {
30 qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction")
30 qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction")
31 << QThread::currentThread();
31 << QThread::currentThread();
32 }
32 }
33
33
34 DataSourceController::~DataSourceController()
34 DataSourceController::~DataSourceController()
35 {
35 {
36 qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction")
36 qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction")
37 << QThread::currentThread();
37 << QThread::currentThread();
38 this->waitForFinish();
38 this->waitForFinish();
39 }
39 }
40
40
41 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
41 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
42 {
42 {
43 auto dataSourceUid = QUuid::createUuid();
43 auto dataSourceUid = QUuid::createUuid();
44 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
44 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
45
45
46 return dataSourceUid;
46 return dataSourceUid;
47 }
47 }
48
48
49 void DataSourceController::setDataSourceItem(
49 void DataSourceController::setDataSourceItem(
50 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
50 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
51 {
51 {
52 if (!dataSourceItem) {
52 if (!dataSourceItem) {
53 qCWarning(LOG_DataSourceController())
53 qCWarning(LOG_DataSourceController())
54 << tr("Data source item can't be registered (null item)");
54 << tr("Data source item can't be registered (null item)");
55 return;
55 return;
56 }
56 }
57
57
58 if (impl->m_DataSources.contains(dataSourceUid)) {
58 if (impl->m_DataSources.contains(dataSourceUid)) {
59 // The data provider is implicitly converted to a shared_ptr
59 // The data provider is implicitly converted to a shared_ptr
60 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
60 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
61
61
62 // Retrieves the data source item to emit the signal with it
62 // Retrieves the data source item to emit the signal with it
63 auto it = impl->m_DataSourceItems.find(dataSourceUid);
63 auto it = impl->m_DataSourceItems.find(dataSourceUid);
64 if (it != impl->m_DataSourceItems.end()) {
64 if (it != impl->m_DataSourceItems.end()) {
65 emit dataSourceItemSet(it->second.get());
65 emit dataSourceItemSet(it->second.get());
66 }
66 }
67 }
67 }
68 else {
68 else {
69 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
69 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
70 "data source has been registered with the uid")
70 "data source has been registered with the uid")
71 .arg(dataSourceUid.toString());
71 .arg(dataSourceUid.toString());
72 }
72 }
73 }
73 }
74
74
75 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
75 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
76 std::unique_ptr<IDataProvider> dataProvider) noexcept
76 std::unique_ptr<IDataProvider> dataProvider) noexcept
77 {
77 {
78 if (impl->m_DataSources.contains(dataSourceUid)) {
78 if (impl->m_DataSources.contains(dataSourceUid)) {
79 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
79 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
80 }
80 }
81 else {
81 else {
82 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
82 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
83 "source has been registered with the uid")
83 "source has been registered with the uid")
84 .arg(dataSourceUid.toString());
84 .arg(dataSourceUid.toString());
85 }
85 }
86 }
86 }
87
87
88 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
88 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
89 const DataSourceItem &productItem) noexcept
89 const DataSourceItem &productItem) noexcept
90 {
90 {
91 if (productItem.type() == DataSourceItemType::PRODUCT) {
91 if (productItem.type() == DataSourceItemType::PRODUCT
92 || productItem.type() == DataSourceItemType::COMPONENT) {
92 /// Retrieves the data provider of the data source (if any)
93 /// Retrieves the data provider of the data source (if any)
93 auto it = impl->m_DataProviders.find(dataSourceUid);
94 auto it = impl->m_DataProviders.find(dataSourceUid);
94 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
95 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
95
96
96 /// @todo retrieve timerange, and pass it to the signal
97 emit variableCreationRequested(productItem.name(), productItem.data(), dataProvider);
97 emit variableCreationRequested(productItem.name(), dataProvider);
98 }
98 }
99 else {
99 else {
100 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
100 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
101 }
101 }
102 }
102 }
103
103
104 void DataSourceController::initialize()
104 void DataSourceController::initialize()
105 {
105 {
106 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init")
106 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init")
107 << QThread::currentThread();
107 << QThread::currentThread();
108 impl->m_WorkingMutex.lock();
108 impl->m_WorkingMutex.lock();
109 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
109 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
110 }
110 }
111
111
112 void DataSourceController::finalize()
112 void DataSourceController::finalize()
113 {
113 {
114 impl->m_WorkingMutex.unlock();
114 impl->m_WorkingMutex.unlock();
115 }
115 }
116
116
117 void DataSourceController::waitForFinish()
117 void DataSourceController::waitForFinish()
118 {
118 {
119 QMutexLocker locker{&impl->m_WorkingMutex};
119 QMutexLocker locker{&impl->m_WorkingMutex};
120 }
120 }
@@ -1,140 +1,140
1 #include <DataSource/DataSourceItem.h>
1 #include <DataSource/DataSourceItem.h>
2 #include <DataSource/DataSourceItemAction.h>
2 #include <DataSource/DataSourceItemAction.h>
3
3
4 #include <QVector>
4 #include <QVector>
5
5
6 const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name");
6 const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name");
7
7
8 struct DataSourceItem::DataSourceItemPrivate {
8 struct DataSourceItem::DataSourceItemPrivate {
9 explicit DataSourceItemPrivate(DataSourceItemType type, QHash<QString, QVariant> data)
9 explicit DataSourceItemPrivate(DataSourceItemType type, QVariantHash data)
10 : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{}
10 : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{}
11 {
11 {
12 }
12 }
13
13
14 DataSourceItem *m_Parent;
14 DataSourceItem *m_Parent;
15 std::vector<std::unique_ptr<DataSourceItem> > m_Children;
15 std::vector<std::unique_ptr<DataSourceItem> > m_Children;
16 DataSourceItemType m_Type;
16 DataSourceItemType m_Type;
17 QHash<QString, QVariant> m_Data;
17 QVariantHash m_Data;
18 std::vector<std::unique_ptr<DataSourceItemAction> > m_Actions;
18 std::vector<std::unique_ptr<DataSourceItemAction> > m_Actions;
19 };
19 };
20
20
21 DataSourceItem::DataSourceItem(DataSourceItemType type, const QString &name)
21 DataSourceItem::DataSourceItem(DataSourceItemType type, const QString &name)
22 : DataSourceItem{type, QHash<QString, QVariant>{{NAME_DATA_KEY, name}}}
22 : DataSourceItem{type, QVariantHash{{NAME_DATA_KEY, name}}}
23 {
23 {
24 }
24 }
25
25
26 DataSourceItem::DataSourceItem(DataSourceItemType type, QHash<QString, QVariant> data)
26 DataSourceItem::DataSourceItem(DataSourceItemType type, QVariantHash data)
27 : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))}
27 : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))}
28 {
28 {
29 }
29 }
30
30
31 QVector<DataSourceItemAction *> DataSourceItem::actions() const noexcept
31 QVector<DataSourceItemAction *> DataSourceItem::actions() const noexcept
32 {
32 {
33 auto result = QVector<DataSourceItemAction *>{};
33 auto result = QVector<DataSourceItemAction *>{};
34
34
35 std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions),
35 std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions),
36 std::back_inserter(result), [](const auto &action) { return action.get(); });
36 std::back_inserter(result), [](const auto &action) { return action.get(); });
37
37
38 return result;
38 return result;
39 }
39 }
40
40
41 void DataSourceItem::addAction(std::unique_ptr<DataSourceItemAction> action) noexcept
41 void DataSourceItem::addAction(std::unique_ptr<DataSourceItemAction> action) noexcept
42 {
42 {
43 action->setDataSourceItem(this);
43 action->setDataSourceItem(this);
44 impl->m_Actions.push_back(std::move(action));
44 impl->m_Actions.push_back(std::move(action));
45 }
45 }
46
46
47 void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept
47 void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept
48 {
48 {
49 child->impl->m_Parent = this;
49 child->impl->m_Parent = this;
50 impl->m_Children.push_back(std::move(child));
50 impl->m_Children.push_back(std::move(child));
51 }
51 }
52
52
53 DataSourceItem *DataSourceItem::child(int childIndex) const noexcept
53 DataSourceItem *DataSourceItem::child(int childIndex) const noexcept
54 {
54 {
55 if (childIndex < 0 || childIndex >= childCount()) {
55 if (childIndex < 0 || childIndex >= childCount()) {
56 return nullptr;
56 return nullptr;
57 }
57 }
58 else {
58 else {
59 return impl->m_Children.at(childIndex).get();
59 return impl->m_Children.at(childIndex).get();
60 }
60 }
61 }
61 }
62
62
63 int DataSourceItem::childCount() const noexcept
63 int DataSourceItem::childCount() const noexcept
64 {
64 {
65 return impl->m_Children.size();
65 return impl->m_Children.size();
66 }
66 }
67
67
68 QVariant DataSourceItem::data(const QString &key) const noexcept
68 QVariant DataSourceItem::data(const QString &key) const noexcept
69 {
69 {
70 return impl->m_Data.value(key);
70 return impl->m_Data.value(key);
71 }
71 }
72
72
73 const QHash<QString, QVariant> &DataSourceItem::data() const noexcept
73 QVariantHash DataSourceItem::data() const noexcept
74 {
74 {
75 return impl->m_Data;
75 return impl->m_Data;
76 }
76 }
77
77
78 bool DataSourceItem::isRoot() const noexcept
78 bool DataSourceItem::isRoot() const noexcept
79 {
79 {
80 return impl->m_Parent == nullptr;
80 return impl->m_Parent == nullptr;
81 }
81 }
82
82
83 QString DataSourceItem::name() const noexcept
83 QString DataSourceItem::name() const noexcept
84 {
84 {
85 return data(NAME_DATA_KEY).toString();
85 return data(NAME_DATA_KEY).toString();
86 }
86 }
87
87
88 DataSourceItem *DataSourceItem::parentItem() const noexcept
88 DataSourceItem *DataSourceItem::parentItem() const noexcept
89 {
89 {
90 return impl->m_Parent;
90 return impl->m_Parent;
91 }
91 }
92
92
93 void DataSourceItem::setData(const QString &key, const QVariant &value, bool append) noexcept
93 void DataSourceItem::setData(const QString &key, const QVariant &value, bool append) noexcept
94 {
94 {
95 auto it = impl->m_Data.constFind(key);
95 auto it = impl->m_Data.constFind(key);
96 if (append && it != impl->m_Data.constEnd()) {
96 if (append && it != impl->m_Data.constEnd()) {
97 // Case of an existing value to which we want to add to the new value
97 // Case of an existing value to which we want to add to the new value
98 if (it->canConvert<QVariantList>()) {
98 if (it->canConvert<QVariantList>()) {
99 auto variantList = it->value<QVariantList>();
99 auto variantList = it->value<QVariantList>();
100 variantList.append(value);
100 variantList.append(value);
101
101
102 impl->m_Data.insert(key, variantList);
102 impl->m_Data.insert(key, variantList);
103 }
103 }
104 else {
104 else {
105 impl->m_Data.insert(key, QVariantList{*it, value});
105 impl->m_Data.insert(key, QVariantList{*it, value});
106 }
106 }
107 }
107 }
108 else {
108 else {
109 // Other cases :
109 // Other cases :
110 // - new value in map OR
110 // - new value in map OR
111 // - replacement of an existing value (not appending)
111 // - replacement of an existing value (not appending)
112 impl->m_Data.insert(key, value);
112 impl->m_Data.insert(key, value);
113 }
113 }
114 }
114 }
115
115
116 DataSourceItemType DataSourceItem::type() const noexcept
116 DataSourceItemType DataSourceItem::type() const noexcept
117 {
117 {
118 return impl->m_Type;
118 return impl->m_Type;
119 }
119 }
120
120
121 bool DataSourceItem::operator==(const DataSourceItem &other)
121 bool DataSourceItem::operator==(const DataSourceItem &other)
122 {
122 {
123 // Compares items' attributes
123 // Compares items' attributes
124 if (std::tie(impl->m_Type, impl->m_Data) == std::tie(other.impl->m_Type, other.impl->m_Data)) {
124 if (std::tie(impl->m_Type, impl->m_Data) == std::tie(other.impl->m_Type, other.impl->m_Data)) {
125 // Compares contents of items' children
125 // Compares contents of items' children
126 return std::equal(std::cbegin(impl->m_Children), std::cend(impl->m_Children),
126 return std::equal(std::cbegin(impl->m_Children), std::cend(impl->m_Children),
127 std::cbegin(other.impl->m_Children),
127 std::cbegin(other.impl->m_Children),
128 [](const auto &itemChild, const auto &otherChild) {
128 [](const auto &itemChild, const auto &otherChild) {
129 return *itemChild == *otherChild;
129 return *itemChild == *otherChild;
130 });
130 });
131 }
131 }
132 else {
132 else {
133 return false;
133 return false;
134 }
134 }
135 }
135 }
136
136
137 bool DataSourceItem::operator!=(const DataSourceItem &other)
137 bool DataSourceItem::operator!=(const DataSourceItem &other)
138 {
138 {
139 return !(*this == other);
139 return !(*this == other);
140 }
140 }
@@ -1,101 +1,90
1 #include "Variable/Variable.h"
1 #include "Variable/Variable.h"
2
2
3 #include <Data/IDataSeries.h>
3 #include <Data/IDataSeries.h>
4 #include <Data/SqpDateTime.h>
4 #include <Data/SqpDateTime.h>
5
5
6 #include <QReadWriteLock>
6 #include <QReadWriteLock>
7 #include <QThread>
7 #include <QThread>
8
8
9 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
9 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
10
10
11 struct Variable::VariablePrivate {
11 struct Variable::VariablePrivate {
12 explicit VariablePrivate(const QString &name, const QString &unit, const QString &mission,
12 explicit VariablePrivate(const QString &name, const SqpDateTime &dateTime,
13 const SqpDateTime &dateTime)
13 const QVariantHash &metadata)
14 : m_Name{name},
14 : m_Name{name}, m_DateTime{dateTime}, m_Metadata{metadata}, m_DataSeries{nullptr}
15 m_Unit{unit},
16 m_Mission{mission},
17 m_DateTime{dateTime},
18 m_DataSeries{nullptr}
19 {
15 {
20 }
16 }
21
17
22 QString m_Name;
18 QString m_Name;
23 QString m_Unit;
24 QString m_Mission;
25
19
26 SqpDateTime m_DateTime; // The dateTime available in the view and loaded. not the cache.
20 SqpDateTime m_DateTime; // The dateTime available in the view and loaded. not the cache.
21 QVariantHash m_Metadata;
27 std::unique_ptr<IDataSeries> m_DataSeries;
22 std::unique_ptr<IDataSeries> m_DataSeries;
28 };
23 };
29
24
30 Variable::Variable(const QString &name, const QString &unit, const QString &mission,
25 Variable::Variable(const QString &name, const SqpDateTime &dateTime, const QVariantHash &metadata)
31 const SqpDateTime &dateTime)
26 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
32 : impl{spimpl::make_unique_impl<VariablePrivate>(name, unit, mission, dateTime)}
33 {
27 {
34 }
28 }
35
29
36 QString Variable::name() const noexcept
30 QString Variable::name() const noexcept
37 {
31 {
38 return impl->m_Name;
32 return impl->m_Name;
39 }
33 }
40
34
41 QString Variable::mission() const noexcept
42 {
43 return impl->m_Mission;
44 }
45
46 QString Variable::unit() const noexcept
47 {
48 return impl->m_Unit;
49 }
50
51 SqpDateTime Variable::dateTime() const noexcept
35 SqpDateTime Variable::dateTime() const noexcept
52 {
36 {
53 return impl->m_DateTime;
37 return impl->m_DateTime;
54 }
38 }
55
39
56 void Variable::setDateTime(const SqpDateTime &dateTime) noexcept
40 void Variable::setDateTime(const SqpDateTime &dateTime) noexcept
57 {
41 {
58 impl->m_DateTime = dateTime;
42 impl->m_DateTime = dateTime;
59 }
43 }
60
44
61 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
45 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
62 {
46 {
63 qCDebug(LOG_Variable()) << "Variable::setDataSeries" << QThread::currentThread()->objectName();
47 qCDebug(LOG_Variable()) << "Variable::setDataSeries" << QThread::currentThread()->objectName();
64 if (!dataSeries) {
48 if (!dataSeries) {
65 /// @todo ALX : log
49 /// @todo ALX : log
66 return;
50 return;
67 }
51 }
68
52
69 // Inits the data series of the variable
53 // Inits the data series of the variable
70 if (!impl->m_DataSeries) {
54 if (!impl->m_DataSeries) {
71 impl->m_DataSeries = dataSeries->clone();
55 impl->m_DataSeries = dataSeries->clone();
72 }
56 }
73 else {
57 else {
74 dataSeries->lockWrite();
58 dataSeries->lockWrite();
75 impl->m_DataSeries->lockWrite();
59 impl->m_DataSeries->lockWrite();
76 impl->m_DataSeries->merge(dataSeries.get());
60 impl->m_DataSeries->merge(dataSeries.get());
77 impl->m_DataSeries->unlock();
61 impl->m_DataSeries->unlock();
78 dataSeries->unlock();
62 dataSeries->unlock();
79 emit updated();
63 emit updated();
80 }
64 }
81 }
65 }
82
66
83 IDataSeries *Variable::dataSeries() const noexcept
67 IDataSeries *Variable::dataSeries() const noexcept
84 {
68 {
85 return impl->m_DataSeries.get();
69 return impl->m_DataSeries.get();
86 }
70 }
87
71
72 QVariantHash Variable::metadata() const noexcept
73 {
74 return impl->m_Metadata;
75 }
76
88 bool Variable::contains(const SqpDateTime &dateTime) const noexcept
77 bool Variable::contains(const SqpDateTime &dateTime) const noexcept
89 {
78 {
90 return impl->m_DateTime.contains(dateTime);
79 return impl->m_DateTime.contains(dateTime);
91 }
80 }
92
81
93 bool Variable::intersect(const SqpDateTime &dateTime) const noexcept
82 bool Variable::intersect(const SqpDateTime &dateTime) const noexcept
94 {
83 {
95 return impl->m_DateTime.intersect(dateTime);
84 return impl->m_DateTime.intersect(dateTime);
96 }
85 }
97
86
98 bool Variable::isInside(const SqpDateTime &dateTime) const noexcept
87 bool Variable::isInside(const SqpDateTime &dateTime) const noexcept
99 {
88 {
100 return dateTime.contains(SqpDateTime{impl->m_DateTime.m_TStart, impl->m_DateTime.m_TEnd});
89 return dateTime.contains(SqpDateTime{impl->m_DateTime.m_TStart, impl->m_DateTime.m_TEnd});
101 }
90 }
@@ -1,216 +1,212
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableCacheController.h>
2 #include <Variable/VariableCacheController.h>
3 #include <Variable/VariableController.h>
3 #include <Variable/VariableController.h>
4 #include <Variable/VariableModel.h>
4 #include <Variable/VariableModel.h>
5
5
6 #include <Data/DataProviderParameters.h>
6 #include <Data/DataProviderParameters.h>
7 #include <Data/IDataProvider.h>
7 #include <Data/IDataProvider.h>
8 #include <Data/IDataSeries.h>
8 #include <Data/IDataSeries.h>
9 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
10
10
11 #include <QDateTime>
11 #include <QDateTime>
12 #include <QMutex>
12 #include <QMutex>
13 #include <QThread>
13 #include <QThread>
14 #include <QUuid>
14 #include <QUuid>
15 #include <QtCore/QItemSelectionModel>
15 #include <QtCore/QItemSelectionModel>
16
16
17 #include <unordered_map>
17 #include <unordered_map>
18
18
19 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
19 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
20
20
21 struct VariableController::VariableControllerPrivate {
21 struct VariableController::VariableControllerPrivate {
22 explicit VariableControllerPrivate(VariableController *parent)
22 explicit VariableControllerPrivate(VariableController *parent)
23 : m_WorkingMutex{},
23 : m_WorkingMutex{},
24 m_VariableModel{new VariableModel{parent}},
24 m_VariableModel{new VariableModel{parent}},
25 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
25 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
26 m_VariableCacheController{std::make_unique<VariableCacheController>()}
26 m_VariableCacheController{std::make_unique<VariableCacheController>()}
27 {
27 {
28 }
28 }
29
29
30 QMutex m_WorkingMutex;
30 QMutex m_WorkingMutex;
31 /// Variable model. The VariableController has the ownership
31 /// Variable model. The VariableController has the ownership
32 VariableModel *m_VariableModel;
32 VariableModel *m_VariableModel;
33 QItemSelectionModel *m_VariableSelectionModel;
33 QItemSelectionModel *m_VariableSelectionModel;
34
34
35
35
36 TimeController *m_TimeController{nullptr};
36 TimeController *m_TimeController{nullptr};
37 std::unique_ptr<VariableCacheController> m_VariableCacheController;
37 std::unique_ptr<VariableCacheController> m_VariableCacheController;
38
38
39 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
39 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
40 m_VariableToProviderMap;
40 m_VariableToProviderMap;
41 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifier;
41 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifier;
42 };
42 };
43
43
44 VariableController::VariableController(QObject *parent)
44 VariableController::VariableController(QObject *parent)
45 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
45 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
46 {
46 {
47 qCDebug(LOG_VariableController()) << tr("VariableController construction")
47 qCDebug(LOG_VariableController()) << tr("VariableController construction")
48 << QThread::currentThread();
48 << QThread::currentThread();
49 }
49 }
50
50
51 VariableController::~VariableController()
51 VariableController::~VariableController()
52 {
52 {
53 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
53 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
54 << QThread::currentThread();
54 << QThread::currentThread();
55 this->waitForFinish();
55 this->waitForFinish();
56 }
56 }
57
57
58 VariableModel *VariableController::variableModel() noexcept
58 VariableModel *VariableController::variableModel() noexcept
59 {
59 {
60 return impl->m_VariableModel;
60 return impl->m_VariableModel;
61 }
61 }
62
62
63 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
63 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
64 {
64 {
65 return impl->m_VariableSelectionModel;
65 return impl->m_VariableSelectionModel;
66 }
66 }
67
67
68 void VariableController::setTimeController(TimeController *timeController) noexcept
68 void VariableController::setTimeController(TimeController *timeController) noexcept
69 {
69 {
70 impl->m_TimeController = timeController;
70 impl->m_TimeController = timeController;
71 }
71 }
72
72
73 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
73 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
74 {
74 {
75 if (!variable) {
75 if (!variable) {
76 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
76 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
77 return;
77 return;
78 }
78 }
79
79
80 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
80 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
81 // make some treatments before the deletion
81 // make some treatments before the deletion
82 emit variableAboutToBeDeleted(variable);
82 emit variableAboutToBeDeleted(variable);
83
83
84 // Deletes provider
84 // Deletes provider
85 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
85 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
86 qCDebug(LOG_VariableController())
86 qCDebug(LOG_VariableController())
87 << tr("Number of providers deleted for variable %1: %2")
87 << tr("Number of providers deleted for variable %1: %2")
88 .arg(variable->name(), QString::number(nbProvidersDeleted));
88 .arg(variable->name(), QString::number(nbProvidersDeleted));
89
89
90 // Clears cache
90 // Clears cache
91 impl->m_VariableCacheController->clear(variable);
91 impl->m_VariableCacheController->clear(variable);
92
92
93 // Deletes from model
93 // Deletes from model
94 impl->m_VariableModel->deleteVariable(variable);
94 impl->m_VariableModel->deleteVariable(variable);
95 }
95 }
96
96
97 void VariableController::deleteVariables(
97 void VariableController::deleteVariables(
98 const QVector<std::shared_ptr<Variable> > &variables) noexcept
98 const QVector<std::shared_ptr<Variable> > &variables) noexcept
99 {
99 {
100 for (auto variable : qAsConst(variables)) {
100 for (auto variable : qAsConst(variables)) {
101 deleteVariable(variable);
101 deleteVariable(variable);
102 }
102 }
103 }
103 }
104
104
105 void VariableController::createVariable(const QString &name,
105 void VariableController::createVariable(const QString &name, const QVariantHash &metadata,
106 std::shared_ptr<IDataProvider> provider) noexcept
106 std::shared_ptr<IDataProvider> provider) noexcept
107 {
107 {
108
108
109 if (!impl->m_TimeController) {
109 if (!impl->m_TimeController) {
110 qCCritical(LOG_VariableController())
110 qCCritical(LOG_VariableController())
111 << tr("Impossible to create variable: The time controller is null");
111 << tr("Impossible to create variable: The time controller is null");
112 return;
112 return;
113 }
113 }
114
114
115
116 /// @todo : for the moment :
117 /// - the provider is only used to retrieve data from the variable for its initialization, but
118 /// it will be retained later
119 /// - default data are generated for the variable, without taking into account the timerange set
120 /// in sciqlop
121 auto dateTime = impl->m_TimeController->dateTime();
115 auto dateTime = impl->m_TimeController->dateTime();
122 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime)) {
116
117 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime, metadata)) {
123 auto identifier = QUuid::createUuid();
118 auto identifier = QUuid::createUuid();
124
119
125 // store the provider
120 // store the provider
126 impl->m_VariableToProviderMap[newVariable] = provider;
121 impl->m_VariableToProviderMap[newVariable] = provider;
127 impl->m_VariableToIdentifier[newVariable] = identifier;
122 impl->m_VariableToIdentifier[newVariable] = identifier;
128
123
129 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
124 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
130 QUuid identifier, auto dataSeriesAcquired, auto dateTimeToPutInCache)
125 QUuid identifier, auto dataSeriesAcquired, auto dateTimeToPutInCache)
131 {
126 {
132 if (auto variable = varW.lock()) {
127 if (auto variable = varW.lock()) {
133 auto varIdentifier = impl->m_VariableToIdentifier.at(variable);
128 auto varIdentifier = impl->m_VariableToIdentifier.at(variable);
134 if (varIdentifier == identifier) {
129 if (varIdentifier == identifier) {
135 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
130 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
136 variable->setDataSeries(dataSeriesAcquired);
131 variable->setDataSeries(dataSeriesAcquired);
137 }
132 }
138 }
133 }
139 };
134 };
140
135
141 connect(provider.get(), &IDataProvider::dataProvided, addDateTimeAcquired);
136 connect(provider.get(), &IDataProvider::dataProvided, addDateTimeAcquired);
142 this->onRequestDataLoading(newVariable, dateTime);
137 this->onRequestDataLoading(newVariable, dateTime);
143 }
138 }
144 }
139 }
145
140
146 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
141 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
147 {
142 {
148 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
143 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
149 << QThread::currentThread()->objectName();
144 << QThread::currentThread()->objectName();
150 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
145 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
151
146
152 for (const auto &selectedRow : qAsConst(selectedRows)) {
147 for (const auto &selectedRow : qAsConst(selectedRows)) {
153 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
148 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
154 selectedVariable->setDateTime(dateTime);
149 selectedVariable->setDateTime(dateTime);
155 this->onRequestDataLoading(selectedVariable, dateTime);
150 this->onRequestDataLoading(selectedVariable, dateTime);
156 }
151 }
157 }
152 }
158 }
153 }
159
154
160 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
155 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
161 {
156 {
162 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
157 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
163
158
164 auto end = impl->m_VariableToIdentifier.cend();
159 auto end = impl->m_VariableToIdentifier.cend();
165 auto it = std::find_if(impl->m_VariableToIdentifier.cbegin(), end, findReply);
160 auto it = std::find_if(impl->m_VariableToIdentifier.cbegin(), end, findReply);
166 if (it != end) {
161 if (it != end) {
167 impl->m_VariableModel->setDataProgress(it->first, progress);
162 impl->m_VariableModel->setDataProgress(it->first, progress);
168 }
163 }
169 }
164 }
170
165
171
166
172 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
167 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
173 const SqpDateTime &dateTime)
168 const SqpDateTime &dateTime)
174 {
169 {
175 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
170 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
176 << QThread::currentThread()->objectName();
171 << QThread::currentThread()->objectName();
177 // we want to load data of the variable for the dateTime.
172 // we want to load data of the variable for the dateTime.
178 // First we check if the cache contains some of them.
173 // First we check if the cache contains some of them.
179 // For the other, we ask the provider to give them.
174 // For the other, we ask the provider to give them.
180 if (variable) {
175 if (variable) {
181
176
182 auto dateTimeListNotInCache
177 auto dateTimeListNotInCache
183 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
178 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
184
179
185 if (!dateTimeListNotInCache.empty()) {
180 if (!dateTimeListNotInCache.empty()) {
186 // Ask the provider for each data on the dateTimeListNotInCache
181 // Ask the provider for each data on the dateTimeListNotInCache
187 auto identifier = impl->m_VariableToIdentifier.at(variable);
182 auto identifier = impl->m_VariableToIdentifier.at(variable);
188 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
183 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
189 identifier, std::move(dateTimeListNotInCache));
184 identifier,
185 DataProviderParameters{std::move(dateTimeListNotInCache), variable->metadata()});
190 }
186 }
191 else {
187 else {
192 emit variable->updated();
188 emit variable->updated();
193 }
189 }
194 }
190 }
195 else {
191 else {
196 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
192 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
197 }
193 }
198 }
194 }
199
195
200
196
201 void VariableController::initialize()
197 void VariableController::initialize()
202 {
198 {
203 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
199 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
204 impl->m_WorkingMutex.lock();
200 impl->m_WorkingMutex.lock();
205 qCDebug(LOG_VariableController()) << tr("VariableController init END");
201 qCDebug(LOG_VariableController()) << tr("VariableController init END");
206 }
202 }
207
203
208 void VariableController::finalize()
204 void VariableController::finalize()
209 {
205 {
210 impl->m_WorkingMutex.unlock();
206 impl->m_WorkingMutex.unlock();
211 }
207 }
212
208
213 void VariableController::waitForFinish()
209 void VariableController::waitForFinish()
214 {
210 {
215 QMutexLocker locker{&impl->m_WorkingMutex};
211 QMutexLocker locker{&impl->m_WorkingMutex};
216 }
212 }
@@ -1,236 +1,235
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableModel.h>
2 #include <Variable/VariableModel.h>
3
3
4 #include <Data/IDataSeries.h>
4 #include <Data/IDataSeries.h>
5
5
6 #include <QDateTime>
6 #include <QDateTime>
7 #include <QSize>
7 #include <QSize>
8 #include <unordered_map>
8 #include <unordered_map>
9
9
10 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
10 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
11
11
12 namespace {
12 namespace {
13
13
14 // Column indexes
14 // Column indexes
15 const auto NAME_COLUMN = 0;
15 const auto NAME_COLUMN = 0;
16 const auto TSTART_COLUMN = 1;
16 const auto TSTART_COLUMN = 1;
17 const auto TEND_COLUMN = 2;
17 const auto TEND_COLUMN = 2;
18 const auto NB_COLUMNS = 3;
18 const auto NB_COLUMNS = 3;
19
19
20 // Column properties
20 // Column properties
21 const auto DEFAULT_HEIGHT = 25;
21 const auto DEFAULT_HEIGHT = 25;
22 const auto DEFAULT_WIDTH = 100;
22 const auto DEFAULT_WIDTH = 100;
23
23
24 struct ColumnProperties {
24 struct ColumnProperties {
25 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
25 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
26 int height = DEFAULT_HEIGHT)
26 int height = DEFAULT_HEIGHT)
27 : m_Name{name}, m_Width{width}, m_Height{height}
27 : m_Name{name}, m_Width{width}, m_Height{height}
28 {
28 {
29 }
29 }
30
30
31 QString m_Name;
31 QString m_Name;
32 int m_Width;
32 int m_Width;
33 int m_Height;
33 int m_Height;
34 };
34 };
35
35
36 const auto COLUMN_PROPERTIES
36 const auto COLUMN_PROPERTIES
37 = QHash<int, ColumnProperties>{{NAME_COLUMN, {QObject::tr("Name")}},
37 = QHash<int, ColumnProperties>{{NAME_COLUMN, {QObject::tr("Name")}},
38 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
38 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
39 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}};
39 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}};
40
40
41 /// Format for datetimes
41 /// Format for datetimes
42 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
42 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
43
43
44
44
45 } // namespace
45 } // namespace
46
46
47 struct VariableModel::VariableModelPrivate {
47 struct VariableModel::VariableModelPrivate {
48 /// Variables created in SciQlop
48 /// Variables created in SciQlop
49 std::vector<std::shared_ptr<Variable> > m_Variables;
49 std::vector<std::shared_ptr<Variable> > m_Variables;
50 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
50 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
51
51
52
52
53 /// Return the row index of the variable. -1 if it's not found
53 /// Return the row index of the variable. -1 if it's not found
54 int indexOfVariable(Variable *variable) const noexcept;
54 int indexOfVariable(Variable *variable) const noexcept;
55 };
55 };
56
56
57 VariableModel::VariableModel(QObject *parent)
57 VariableModel::VariableModel(QObject *parent)
58 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
58 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
59 {
59 {
60 }
60 }
61
61
62 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
62 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
63 const SqpDateTime &dateTime) noexcept
63 const SqpDateTime &dateTime,
64 const QVariantHash &metadata) noexcept
64 {
65 {
65 auto insertIndex = rowCount();
66 auto insertIndex = rowCount();
66 beginInsertRows({}, insertIndex, insertIndex);
67 beginInsertRows({}, insertIndex, insertIndex);
67
68
68 /// @todo For the moment, the other data of the variable is initialized with default values
69 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
69 auto variable = std::make_shared<Variable>(name, QStringLiteral("unit"),
70 QStringLiteral("mission"), dateTime);
71
70
72 impl->m_Variables.push_back(variable);
71 impl->m_Variables.push_back(variable);
73 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
72 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
74
73
75 endInsertRows();
74 endInsertRows();
76
75
77 return variable;
76 return variable;
78 }
77 }
79
78
80 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
79 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
81 {
80 {
82 if (!variable) {
81 if (!variable) {
83 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
82 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
84 return;
83 return;
85 }
84 }
86
85
87 // Finds variable in the model
86 // Finds variable in the model
88 auto begin = impl->m_Variables.cbegin();
87 auto begin = impl->m_Variables.cbegin();
89 auto end = impl->m_Variables.cend();
88 auto end = impl->m_Variables.cend();
90 auto it = std::find(begin, end, variable);
89 auto it = std::find(begin, end, variable);
91 if (it != end) {
90 if (it != end) {
92 auto removeIndex = std::distance(begin, it);
91 auto removeIndex = std::distance(begin, it);
93
92
94 // Deletes variable
93 // Deletes variable
95 beginRemoveRows({}, removeIndex, removeIndex);
94 beginRemoveRows({}, removeIndex, removeIndex);
96 impl->m_Variables.erase(it);
95 impl->m_Variables.erase(it);
97 endRemoveRows();
96 endRemoveRows();
98 }
97 }
99 else {
98 else {
100 qCritical(LOG_VariableModel())
99 qCritical(LOG_VariableModel())
101 << tr("Can't delete variable %1 from the model: the variable is not in the model")
100 << tr("Can't delete variable %1 from the model: the variable is not in the model")
102 .arg(variable->name());
101 .arg(variable->name());
103 }
102 }
104 }
103 }
105
104
106
105
107 std::shared_ptr<Variable> VariableModel::variable(int index) const
106 std::shared_ptr<Variable> VariableModel::variable(int index) const
108 {
107 {
109 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
108 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
110 }
109 }
111
110
112 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
111 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
113 {
112 {
114
113
115 impl->m_VariableToProgress[variable] = progress;
114 impl->m_VariableToProgress[variable] = progress;
116 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
115 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
117
116
118 emit dataChanged(modelIndex, modelIndex);
117 emit dataChanged(modelIndex, modelIndex);
119 }
118 }
120
119
121 int VariableModel::columnCount(const QModelIndex &parent) const
120 int VariableModel::columnCount(const QModelIndex &parent) const
122 {
121 {
123 Q_UNUSED(parent);
122 Q_UNUSED(parent);
124
123
125 return NB_COLUMNS;
124 return NB_COLUMNS;
126 }
125 }
127
126
128 int VariableModel::rowCount(const QModelIndex &parent) const
127 int VariableModel::rowCount(const QModelIndex &parent) const
129 {
128 {
130 Q_UNUSED(parent);
129 Q_UNUSED(parent);
131
130
132 return impl->m_Variables.size();
131 return impl->m_Variables.size();
133 }
132 }
134
133
135 QVariant VariableModel::data(const QModelIndex &index, int role) const
134 QVariant VariableModel::data(const QModelIndex &index, int role) const
136 {
135 {
137 if (!index.isValid()) {
136 if (!index.isValid()) {
138 return QVariant{};
137 return QVariant{};
139 }
138 }
140
139
141 if (index.row() < 0 || index.row() >= rowCount()) {
140 if (index.row() < 0 || index.row() >= rowCount()) {
142 return QVariant{};
141 return QVariant{};
143 }
142 }
144
143
145 if (role == Qt::DisplayRole) {
144 if (role == Qt::DisplayRole) {
146 if (auto variable = impl->m_Variables.at(index.row()).get()) {
145 if (auto variable = impl->m_Variables.at(index.row()).get()) {
147 /// Lambda function that builds the variant to return for a time value
146 /// Lambda function that builds the variant to return for a time value
148 auto dateTimeVariant = [](double time) {
147 auto dateTimeVariant = [](double time) {
149 auto dateTime = QDateTime::fromMSecsSinceEpoch(time * 1000.);
148 auto dateTime = QDateTime::fromMSecsSinceEpoch(time * 1000.);
150 return dateTime.toString(DATETIME_FORMAT);
149 return dateTime.toString(DATETIME_FORMAT);
151 };
150 };
152
151
153 switch (index.column()) {
152 switch (index.column()) {
154 case NAME_COLUMN:
153 case NAME_COLUMN:
155 return variable->name();
154 return variable->name();
156 case TSTART_COLUMN:
155 case TSTART_COLUMN:
157 return dateTimeVariant(variable->dateTime().m_TStart);
156 return dateTimeVariant(variable->dateTime().m_TStart);
158 case TEND_COLUMN:
157 case TEND_COLUMN:
159 return dateTimeVariant(variable->dateTime().m_TEnd);
158 return dateTimeVariant(variable->dateTime().m_TEnd);
160 default:
159 default:
161 // No action
160 // No action
162 break;
161 break;
163 }
162 }
164
163
165 qWarning(LOG_VariableModel())
164 qWarning(LOG_VariableModel())
166 << tr("Can't get data (unknown column %1)").arg(index.column());
165 << tr("Can't get data (unknown column %1)").arg(index.column());
167 }
166 }
168 else {
167 else {
169 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
168 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
170 }
169 }
171 }
170 }
172 else if (role == VariableRoles::ProgressRole) {
171 else if (role == VariableRoles::ProgressRole) {
173 if (auto variable = impl->m_Variables.at(index.row())) {
172 if (auto variable = impl->m_Variables.at(index.row())) {
174
173
175 auto it = impl->m_VariableToProgress.find(variable);
174 auto it = impl->m_VariableToProgress.find(variable);
176 if (it != impl->m_VariableToProgress.cend()) {
175 if (it != impl->m_VariableToProgress.cend()) {
177 return it->second;
176 return it->second;
178 }
177 }
179 }
178 }
180 }
179 }
181
180
182 return QVariant{};
181 return QVariant{};
183 }
182 }
184
183
185 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
184 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
186 {
185 {
187 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
186 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
188 return QVariant{};
187 return QVariant{};
189 }
188 }
190
189
191 if (orientation == Qt::Horizontal) {
190 if (orientation == Qt::Horizontal) {
192 auto propertiesIt = COLUMN_PROPERTIES.find(section);
191 auto propertiesIt = COLUMN_PROPERTIES.find(section);
193 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
192 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
194 // Role is either DisplayRole or SizeHintRole
193 // Role is either DisplayRole or SizeHintRole
195 return (role == Qt::DisplayRole)
194 return (role == Qt::DisplayRole)
196 ? QVariant{propertiesIt->m_Name}
195 ? QVariant{propertiesIt->m_Name}
197 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
196 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
198 }
197 }
199 else {
198 else {
200 qWarning(LOG_VariableModel())
199 qWarning(LOG_VariableModel())
201 << tr("Can't get header data (unknown column %1)").arg(section);
200 << tr("Can't get header data (unknown column %1)").arg(section);
202 }
201 }
203 }
202 }
204
203
205 return QVariant{};
204 return QVariant{};
206 }
205 }
207
206
208 void VariableModel::onVariableUpdated() noexcept
207 void VariableModel::onVariableUpdated() noexcept
209 {
208 {
210 // Finds variable that has been updated in the model
209 // Finds variable that has been updated in the model
211 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
210 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
212 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
211 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
213
212
214 if (updatedVariableIndex > -1) {
213 if (updatedVariableIndex > -1) {
215 emit dataChanged(createIndex(updatedVariableIndex, 0),
214 emit dataChanged(createIndex(updatedVariableIndex, 0),
216 createIndex(updatedVariableIndex, columnCount() - 1));
215 createIndex(updatedVariableIndex, columnCount() - 1));
217 }
216 }
218 }
217 }
219 }
218 }
220
219
221 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
220 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
222 {
221 {
223 auto begin = std::cbegin(m_Variables);
222 auto begin = std::cbegin(m_Variables);
224 auto end = std::cend(m_Variables);
223 auto end = std::cend(m_Variables);
225 auto it
224 auto it
226 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
225 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
227
226
228 if (it != end) {
227 if (it != end) {
229 // Gets the index of the variable in the model: we assume here that views have the same
228 // Gets the index of the variable in the model: we assume here that views have the same
230 // order as the model
229 // order as the model
231 return std::distance(begin, it);
230 return std::distance(begin, it);
232 }
231 }
233 else {
232 else {
234 return -1;
233 return -1;
235 }
234 }
236 }
235 }
@@ -1,353 +1,353
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableCacheController.h>
2 #include <Variable/VariableCacheController.h>
3
3
4 #include <QObject>
4 #include <QObject>
5 #include <QtTest>
5 #include <QtTest>
6
6
7 #include <memory>
7 #include <memory>
8
8
9 class TestVariableCacheController : public QObject {
9 class TestVariableCacheController : public QObject {
10 Q_OBJECT
10 Q_OBJECT
11
11
12 private slots:
12 private slots:
13 void testProvideNotInCacheDateTimeList();
13 void testProvideNotInCacheDateTimeList();
14
14
15 void testAddDateTime();
15 void testAddDateTime();
16 };
16 };
17
17
18
18
19 void TestVariableCacheController::testProvideNotInCacheDateTimeList()
19 void TestVariableCacheController::testProvideNotInCacheDateTimeList()
20 {
20 {
21 VariableCacheController variableCacheController{};
21 VariableCacheController variableCacheController{};
22
22
23 auto ts0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}};
23 auto ts0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}};
24 auto te0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
24 auto te0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
25 auto sqp0 = SqpDateTime{static_cast<double>(ts0.toMSecsSinceEpoch()),
25 auto sqp0 = SqpDateTime{static_cast<double>(ts0.toMSecsSinceEpoch()),
26 static_cast<double>(te0.toMSecsSinceEpoch())};
26 static_cast<double>(te0.toMSecsSinceEpoch())};
27
27
28 auto ts1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 6, 0, 0}};
28 auto ts1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 6, 0, 0}};
29 auto te1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 8, 0, 0}};
29 auto te1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 8, 0, 0}};
30 auto sqp1 = SqpDateTime{static_cast<double>(ts1.toMSecsSinceEpoch()),
30 auto sqp1 = SqpDateTime{static_cast<double>(ts1.toMSecsSinceEpoch()),
31 static_cast<double>(te1.toMSecsSinceEpoch())};
31 static_cast<double>(te1.toMSecsSinceEpoch())};
32
32
33 auto ts2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 18, 0, 0}};
33 auto ts2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 18, 0, 0}};
34 auto te2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 20, 0, 0}};
34 auto te2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 20, 0, 0}};
35 auto sqp2 = SqpDateTime{static_cast<double>(ts2.toMSecsSinceEpoch()),
35 auto sqp2 = SqpDateTime{static_cast<double>(ts2.toMSecsSinceEpoch()),
36 static_cast<double>(te2.toMSecsSinceEpoch())};
36 static_cast<double>(te2.toMSecsSinceEpoch())};
37
37
38 auto var0 = std::make_shared<Variable>("", "", "", sqp0);
38 auto var0 = std::make_shared<Variable>("", sqp0);
39
39
40 variableCacheController.addDateTime(var0, sqp0);
40 variableCacheController.addDateTime(var0, sqp0);
41 variableCacheController.addDateTime(var0, sqp1);
41 variableCacheController.addDateTime(var0, sqp1);
42 variableCacheController.addDateTime(var0, sqp2);
42 variableCacheController.addDateTime(var0, sqp2);
43
43
44 // first case [ts,te] < ts0
44 // first case [ts,te] < ts0
45 auto ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
45 auto ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
46 auto te = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}};
46 auto te = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}};
47 auto sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
47 auto sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
48 static_cast<double>(te.toMSecsSinceEpoch())};
48 static_cast<double>(te.toMSecsSinceEpoch())};
49
49
50
50
51 auto notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
51 auto notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
52
52
53 QCOMPARE(notInCach.size(), 1);
53 QCOMPARE(notInCach.size(), 1);
54 auto notInCacheSqp = notInCach.first();
54 auto notInCacheSqp = notInCach.first();
55 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
55 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
56 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
56 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
57
57
58
58
59 // second case ts < ts0 && ts0 < te <= te0
59 // second case ts < ts0 && ts0 < te <= te0
60 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
60 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
61 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
61 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
62 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
62 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
63 static_cast<double>(te.toMSecsSinceEpoch())};
63 static_cast<double>(te.toMSecsSinceEpoch())};
64
64
65
65
66 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
66 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
67
67
68 QCOMPARE(notInCach.size(), 1);
68 QCOMPARE(notInCach.size(), 1);
69 notInCacheSqp = notInCach.first();
69 notInCacheSqp = notInCach.first();
70 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
70 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
71 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts0.toMSecsSinceEpoch()));
71 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts0.toMSecsSinceEpoch()));
72
72
73 // 3th case ts < ts0 && te0 < te <= ts1
73 // 3th case ts < ts0 && te0 < te <= ts1
74 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
74 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
75 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
75 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
76 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
76 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
77 static_cast<double>(te.toMSecsSinceEpoch())};
77 static_cast<double>(te.toMSecsSinceEpoch())};
78
78
79
79
80 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
80 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
81
81
82 QCOMPARE(notInCach.size(), 2);
82 QCOMPARE(notInCach.size(), 2);
83 notInCacheSqp = notInCach.first();
83 notInCacheSqp = notInCach.first();
84 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
84 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
85 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts0.toMSecsSinceEpoch()));
85 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts0.toMSecsSinceEpoch()));
86
86
87 notInCacheSqp = notInCach.at(1);
87 notInCacheSqp = notInCach.at(1);
88 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te0.toMSecsSinceEpoch()));
88 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te0.toMSecsSinceEpoch()));
89 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
89 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
90
90
91 // 4th case ts < ts0 && ts1 < te <= te1
91 // 4th case ts < ts0 && ts1 < te <= te1
92 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
92 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
93 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 7, 0, 0}};
93 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 7, 0, 0}};
94 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
94 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
95 static_cast<double>(te.toMSecsSinceEpoch())};
95 static_cast<double>(te.toMSecsSinceEpoch())};
96
96
97
97
98 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
98 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
99
99
100 QCOMPARE(notInCach.size(), 2);
100 QCOMPARE(notInCach.size(), 2);
101 notInCacheSqp = notInCach.first();
101 notInCacheSqp = notInCach.first();
102 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
102 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
103 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts0.toMSecsSinceEpoch()));
103 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts0.toMSecsSinceEpoch()));
104
104
105 notInCacheSqp = notInCach.at(1);
105 notInCacheSqp = notInCach.at(1);
106 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te0.toMSecsSinceEpoch()));
106 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te0.toMSecsSinceEpoch()));
107 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts1.toMSecsSinceEpoch()));
107 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts1.toMSecsSinceEpoch()));
108
108
109 // 5th case ts < ts0 && te3 < te
109 // 5th case ts < ts0 && te3 < te
110 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
110 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
111 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 22, 0, 0}};
111 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 22, 0, 0}};
112 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
112 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
113 static_cast<double>(te.toMSecsSinceEpoch())};
113 static_cast<double>(te.toMSecsSinceEpoch())};
114
114
115
115
116 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
116 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
117
117
118 QCOMPARE(notInCach.size(), 4);
118 QCOMPARE(notInCach.size(), 4);
119 notInCacheSqp = notInCach.first();
119 notInCacheSqp = notInCach.first();
120 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
120 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
121 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts0.toMSecsSinceEpoch()));
121 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts0.toMSecsSinceEpoch()));
122
122
123 notInCacheSqp = notInCach.at(1);
123 notInCacheSqp = notInCach.at(1);
124 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te0.toMSecsSinceEpoch()));
124 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te0.toMSecsSinceEpoch()));
125 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts1.toMSecsSinceEpoch()));
125 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts1.toMSecsSinceEpoch()));
126
126
127 notInCacheSqp = notInCach.at(2);
127 notInCacheSqp = notInCach.at(2);
128 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te1.toMSecsSinceEpoch()));
128 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te1.toMSecsSinceEpoch()));
129 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts2.toMSecsSinceEpoch()));
129 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts2.toMSecsSinceEpoch()));
130
130
131 notInCacheSqp = notInCach.at(3);
131 notInCacheSqp = notInCach.at(3);
132 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te2.toMSecsSinceEpoch()));
132 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te2.toMSecsSinceEpoch()));
133 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
133 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
134
134
135
135
136 // 6th case ts2 < ts
136 // 6th case ts2 < ts
137 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 45, 0, 0}};
137 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 45, 0, 0}};
138 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 47, 0, 0}};
138 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 47, 0, 0}};
139 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
139 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
140 static_cast<double>(te.toMSecsSinceEpoch())};
140 static_cast<double>(te.toMSecsSinceEpoch())};
141
141
142
142
143 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
143 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
144
144
145 QCOMPARE(notInCach.size(), 1);
145 QCOMPARE(notInCach.size(), 1);
146 notInCacheSqp = notInCach.first();
146 notInCacheSqp = notInCach.first();
147 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
147 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
148 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
148 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
149
149
150 // 7th case ts = te0 && te < ts1
150 // 7th case ts = te0 && te < ts1
151 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
151 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
152 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
152 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
153 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
153 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
154 static_cast<double>(te.toMSecsSinceEpoch())};
154 static_cast<double>(te.toMSecsSinceEpoch())};
155
155
156
156
157 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
157 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
158
158
159 QCOMPARE(notInCach.size(), 1);
159 QCOMPARE(notInCach.size(), 1);
160 notInCacheSqp = notInCach.first();
160 notInCacheSqp = notInCach.first();
161 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te0.toMSecsSinceEpoch()));
161 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te0.toMSecsSinceEpoch()));
162 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
162 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
163
163
164 // 8th case ts0 < ts < te0 && te < ts1
164 // 8th case ts0 < ts < te0 && te < ts1
165 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
165 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
166 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
166 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
167 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
167 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
168 static_cast<double>(te.toMSecsSinceEpoch())};
168 static_cast<double>(te.toMSecsSinceEpoch())};
169
169
170
170
171 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
171 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
172
172
173 QCOMPARE(notInCach.size(), 1);
173 QCOMPARE(notInCach.size(), 1);
174 notInCacheSqp = notInCach.first();
174 notInCacheSqp = notInCach.first();
175 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te0.toMSecsSinceEpoch()));
175 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te0.toMSecsSinceEpoch()));
176 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
176 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
177
177
178 // 9th case ts0 < ts < te0 && ts1 < te < te1
178 // 9th case ts0 < ts < te0 && ts1 < te < te1
179 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
179 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
180 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 7, 0, 0}};
180 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 7, 0, 0}};
181 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
181 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
182 static_cast<double>(te.toMSecsSinceEpoch())};
182 static_cast<double>(te.toMSecsSinceEpoch())};
183
183
184
184
185 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
185 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
186
186
187 QCOMPARE(notInCach.size(), 1);
187 QCOMPARE(notInCach.size(), 1);
188 notInCacheSqp = notInCach.first();
188 notInCacheSqp = notInCach.first();
189 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te0.toMSecsSinceEpoch()));
189 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te0.toMSecsSinceEpoch()));
190 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts1.toMSecsSinceEpoch()));
190 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts1.toMSecsSinceEpoch()));
191
191
192 // 10th case te1 < ts < te < ts2
192 // 10th case te1 < ts < te < ts2
193 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 9, 0, 0}};
193 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 9, 0, 0}};
194 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 10, 0, 0}};
194 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 10, 0, 0}};
195 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
195 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
196 static_cast<double>(te.toMSecsSinceEpoch())};
196 static_cast<double>(te.toMSecsSinceEpoch())};
197
197
198
198
199 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
199 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
200
200
201 QCOMPARE(notInCach.size(), 1);
201 QCOMPARE(notInCach.size(), 1);
202 notInCacheSqp = notInCach.first();
202 notInCacheSqp = notInCach.first();
203 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
203 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
204 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
204 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
205
205
206 // 11th case te0 < ts < ts1 && te3 < te
206 // 11th case te0 < ts < ts1 && te3 < te
207 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
207 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
208 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 47, 0, 0}};
208 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 47, 0, 0}};
209 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
209 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
210 static_cast<double>(te.toMSecsSinceEpoch())};
210 static_cast<double>(te.toMSecsSinceEpoch())};
211
211
212
212
213 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
213 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
214
214
215 QCOMPARE(notInCach.size(), 3);
215 QCOMPARE(notInCach.size(), 3);
216 notInCacheSqp = notInCach.first();
216 notInCacheSqp = notInCach.first();
217 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
217 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
218 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts1.toMSecsSinceEpoch()));
218 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts1.toMSecsSinceEpoch()));
219
219
220 notInCacheSqp = notInCach.at(1);
220 notInCacheSqp = notInCach.at(1);
221 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te1.toMSecsSinceEpoch()));
221 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te1.toMSecsSinceEpoch()));
222 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts2.toMSecsSinceEpoch()));
222 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts2.toMSecsSinceEpoch()));
223
223
224 notInCacheSqp = notInCach.at(2);
224 notInCacheSqp = notInCach.at(2);
225 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te2.toMSecsSinceEpoch()));
225 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te2.toMSecsSinceEpoch()));
226 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
226 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
227
227
228 // 12th case te0 < ts < ts1 && te3 < te
228 // 12th case te0 < ts < ts1 && te3 < te
229 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
229 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
230 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 10, 0, 0}};
230 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 10, 0, 0}};
231 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
231 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
232 static_cast<double>(te.toMSecsSinceEpoch())};
232 static_cast<double>(te.toMSecsSinceEpoch())};
233
233
234 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
234 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
235
235
236 QCOMPARE(notInCach.size(), 2);
236 QCOMPARE(notInCach.size(), 2);
237 notInCacheSqp = notInCach.first();
237 notInCacheSqp = notInCach.first();
238 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
238 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(ts.toMSecsSinceEpoch()));
239 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts1.toMSecsSinceEpoch()));
239 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(ts1.toMSecsSinceEpoch()));
240
240
241 notInCacheSqp = notInCach.at(1);
241 notInCacheSqp = notInCach.at(1);
242 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te1.toMSecsSinceEpoch()));
242 QCOMPARE(notInCacheSqp.m_TStart, static_cast<double>(te1.toMSecsSinceEpoch()));
243 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
243 QCOMPARE(notInCacheSqp.m_TEnd, static_cast<double>(te.toMSecsSinceEpoch()));
244
244
245
245
246 // 12th case ts0 < ts < te0
246 // 12th case ts0 < ts < te0
247 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 10, 0}};
247 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 10, 0}};
248 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 50, 0}};
248 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 50, 0}};
249 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
249 sqp = SqpDateTime{static_cast<double>(ts.toMSecsSinceEpoch()),
250 static_cast<double>(te.toMSecsSinceEpoch())};
250 static_cast<double>(te.toMSecsSinceEpoch())};
251
251
252 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
252 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
253 QCOMPARE(notInCach.size(), 0);
253 QCOMPARE(notInCach.size(), 0);
254 }
254 }
255
255
256
256
257 void TestVariableCacheController::testAddDateTime()
257 void TestVariableCacheController::testAddDateTime()
258 {
258 {
259 VariableCacheController variableCacheController{};
259 VariableCacheController variableCacheController{};
260
260
261 auto ts0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}};
261 auto ts0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}};
262 auto te0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
262 auto te0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
263 auto sqp0 = SqpDateTime{static_cast<double>(ts0.toMSecsSinceEpoch()),
263 auto sqp0 = SqpDateTime{static_cast<double>(ts0.toMSecsSinceEpoch()),
264 static_cast<double>(te0.toMSecsSinceEpoch())};
264 static_cast<double>(te0.toMSecsSinceEpoch())};
265
265
266 auto ts1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 6, 0, 0}};
266 auto ts1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 6, 0, 0}};
267 auto te1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 8, 0, 0}};
267 auto te1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 8, 0, 0}};
268 auto sqp1 = SqpDateTime{static_cast<double>(ts1.toMSecsSinceEpoch()),
268 auto sqp1 = SqpDateTime{static_cast<double>(ts1.toMSecsSinceEpoch()),
269 static_cast<double>(te1.toMSecsSinceEpoch())};
269 static_cast<double>(te1.toMSecsSinceEpoch())};
270
270
271 auto ts2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 18, 0, 0}};
271 auto ts2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 18, 0, 0}};
272 auto te2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 20, 0, 0}};
272 auto te2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 20, 0, 0}};
273 auto sqp2 = SqpDateTime{static_cast<double>(ts2.toMSecsSinceEpoch()),
273 auto sqp2 = SqpDateTime{static_cast<double>(ts2.toMSecsSinceEpoch()),
274 static_cast<double>(te2.toMSecsSinceEpoch())};
274 static_cast<double>(te2.toMSecsSinceEpoch())};
275
275
276 auto ts01 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
276 auto ts01 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
277 auto te01 = QDateTime{QDate{2017, 01, 01}, QTime{2, 6, 0, 0}};
277 auto te01 = QDateTime{QDate{2017, 01, 01}, QTime{2, 6, 0, 0}};
278 auto sqp01 = SqpDateTime{static_cast<double>(ts01.toMSecsSinceEpoch()),
278 auto sqp01 = SqpDateTime{static_cast<double>(ts01.toMSecsSinceEpoch()),
279 static_cast<double>(te01.toMSecsSinceEpoch())};
279 static_cast<double>(te01.toMSecsSinceEpoch())};
280
280
281 auto ts3 = QDateTime{QDate{2017, 01, 01}, QTime{2, 14, 0, 0}};
281 auto ts3 = QDateTime{QDate{2017, 01, 01}, QTime{2, 14, 0, 0}};
282 auto te3 = QDateTime{QDate{2017, 01, 01}, QTime{2, 16, 0, 0}};
282 auto te3 = QDateTime{QDate{2017, 01, 01}, QTime{2, 16, 0, 0}};
283 auto sqp3 = SqpDateTime{static_cast<double>(ts3.toMSecsSinceEpoch()),
283 auto sqp3 = SqpDateTime{static_cast<double>(ts3.toMSecsSinceEpoch()),
284 static_cast<double>(te3.toMSecsSinceEpoch())};
284 static_cast<double>(te3.toMSecsSinceEpoch())};
285
285
286 auto ts03 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
286 auto ts03 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
287 auto te03 = QDateTime{QDate{2017, 01, 01}, QTime{2, 22, 0, 0}};
287 auto te03 = QDateTime{QDate{2017, 01, 01}, QTime{2, 22, 0, 0}};
288 auto sqp03 = SqpDateTime{static_cast<double>(ts03.toMSecsSinceEpoch()),
288 auto sqp03 = SqpDateTime{static_cast<double>(ts03.toMSecsSinceEpoch()),
289 static_cast<double>(te03.toMSecsSinceEpoch())};
289 static_cast<double>(te03.toMSecsSinceEpoch())};
290
290
291
291
292 auto var0 = std::make_shared<Variable>("", "", "", sqp0);
292 auto var0 = std::make_shared<Variable>("", sqp0);
293
293
294
294
295 // First case: add the first interval to the variable :sqp0
295 // First case: add the first interval to the variable :sqp0
296 variableCacheController.addDateTime(var0, sqp0);
296 variableCacheController.addDateTime(var0, sqp0);
297 auto dateCacheList = variableCacheController.dateCacheList(var0);
297 auto dateCacheList = variableCacheController.dateCacheList(var0);
298 QCOMPARE(dateCacheList.count(), 1);
298 QCOMPARE(dateCacheList.count(), 1);
299 auto dateCache = dateCacheList.at(0);
299 auto dateCache = dateCacheList.at(0);
300 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts0.toMSecsSinceEpoch()));
300 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts0.toMSecsSinceEpoch()));
301 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te0.toMSecsSinceEpoch()));
301 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te0.toMSecsSinceEpoch()));
302
302
303 // 2nd case: add a second interval : sqp1 > sqp0
303 // 2nd case: add a second interval : sqp1 > sqp0
304 variableCacheController.addDateTime(var0, sqp1);
304 variableCacheController.addDateTime(var0, sqp1);
305 dateCacheList = variableCacheController.dateCacheList(var0);
305 dateCacheList = variableCacheController.dateCacheList(var0);
306 QCOMPARE(dateCacheList.count(), 2);
306 QCOMPARE(dateCacheList.count(), 2);
307 dateCache = dateCacheList.at(0);
307 dateCache = dateCacheList.at(0);
308 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts0.toMSecsSinceEpoch()));
308 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts0.toMSecsSinceEpoch()));
309 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te0.toMSecsSinceEpoch()));
309 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te0.toMSecsSinceEpoch()));
310
310
311 dateCache = dateCacheList.at(1);
311 dateCache = dateCacheList.at(1);
312 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts1.toMSecsSinceEpoch()));
312 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts1.toMSecsSinceEpoch()));
313 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te1.toMSecsSinceEpoch()));
313 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te1.toMSecsSinceEpoch()));
314
314
315 // 3th case: merge sqp0 & sqp1 with sqp01
315 // 3th case: merge sqp0 & sqp1 with sqp01
316 variableCacheController.addDateTime(var0, sqp01);
316 variableCacheController.addDateTime(var0, sqp01);
317 dateCacheList = variableCacheController.dateCacheList(var0);
317 dateCacheList = variableCacheController.dateCacheList(var0);
318 QCOMPARE(dateCacheList.count(), 1);
318 QCOMPARE(dateCacheList.count(), 1);
319 dateCache = dateCacheList.at(0);
319 dateCache = dateCacheList.at(0);
320 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts0.toMSecsSinceEpoch()));
320 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts0.toMSecsSinceEpoch()));
321 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te1.toMSecsSinceEpoch()));
321 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te1.toMSecsSinceEpoch()));
322
322
323
323
324 // 4th case: add a second interval : sqp1 > sqp0
324 // 4th case: add a second interval : sqp1 > sqp0
325 variableCacheController.addDateTime(var0, sqp2);
325 variableCacheController.addDateTime(var0, sqp2);
326 variableCacheController.addDateTime(var0, sqp3);
326 variableCacheController.addDateTime(var0, sqp3);
327 dateCacheList = variableCacheController.dateCacheList(var0);
327 dateCacheList = variableCacheController.dateCacheList(var0);
328 QCOMPARE(dateCacheList.count(), 3);
328 QCOMPARE(dateCacheList.count(), 3);
329 dateCache = dateCacheList.at(0);
329 dateCache = dateCacheList.at(0);
330 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts0.toMSecsSinceEpoch()));
330 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts0.toMSecsSinceEpoch()));
331 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te1.toMSecsSinceEpoch()));
331 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te1.toMSecsSinceEpoch()));
332
332
333 dateCache = dateCacheList.at(1);
333 dateCache = dateCacheList.at(1);
334 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts3.toMSecsSinceEpoch()));
334 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts3.toMSecsSinceEpoch()));
335 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te3.toMSecsSinceEpoch()));
335 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te3.toMSecsSinceEpoch()));
336
336
337 dateCache = dateCacheList.at(2);
337 dateCache = dateCacheList.at(2);
338 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts2.toMSecsSinceEpoch()));
338 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts2.toMSecsSinceEpoch()));
339 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te2.toMSecsSinceEpoch()));
339 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te2.toMSecsSinceEpoch()));
340
340
341
341
342 // 5th case: merge all interval
342 // 5th case: merge all interval
343 variableCacheController.addDateTime(var0, sqp03);
343 variableCacheController.addDateTime(var0, sqp03);
344 dateCacheList = variableCacheController.dateCacheList(var0);
344 dateCacheList = variableCacheController.dateCacheList(var0);
345 QCOMPARE(dateCacheList.count(), 1);
345 QCOMPARE(dateCacheList.count(), 1);
346 dateCache = dateCacheList.at(0);
346 dateCache = dateCacheList.at(0);
347 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts0.toMSecsSinceEpoch()));
347 QCOMPARE(dateCache.m_TStart, static_cast<double>(ts0.toMSecsSinceEpoch()));
348 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te03.toMSecsSinceEpoch()));
348 QCOMPARE(dateCache.m_TEnd, static_cast<double>(te03.toMSecsSinceEpoch()));
349 }
349 }
350
350
351
351
352 QTEST_MAIN(TestVariableCacheController)
352 QTEST_MAIN(TestVariableCacheController)
353 #include "TestVariableCacheController.moc"
353 #include "TestVariableCacheController.moc"
@@ -1,60 +1,61
1 #ifndef SCIQLOP_MENUBUILDER_H
1 #ifndef SCIQLOP_MENUBUILDER_H
2 #define SCIQLOP_MENUBUILDER_H
2 #define SCIQLOP_MENUBUILDER_H
3
3
4 #include <QLoggingCategory>
4 #include <QLoggingCategory>
5 #include <QMenu>
5 #include <QMenu>
6 #include <QStack>
6 #include <QStack>
7
7
8 Q_DECLARE_LOGGING_CATEGORY(LOG_MenuBuilder)
8 Q_DECLARE_LOGGING_CATEGORY(LOG_MenuBuilder)
9
9
10 /// Helper assigned to build a hierarchical menu
10 /// Helper assigned to build a hierarchical menu
11 class MenuBuilder {
11 class MenuBuilder {
12 public:
12 public:
13 /**
13 /**
14 * Ctor
14 * Ctor
15 * @param menu the parent menu
15 * @param menu the parent menu
16 */
16 */
17 explicit MenuBuilder(QMenu *menu);
17 explicit MenuBuilder(QMenu *menu);
18
18
19 /**
19 /**
20 * Adds action to the current menu
20 * Adds action to the current menu
21 * @param actionName the name of the action
21 * @param actionName the name of the action
22 * @param actionFunction the function that will be executed when the action is triggered
22 * @param actionFunction the function that will be executed when the action is triggered
23 */
23 */
24 template <typename ActionFun>
24 template <typename ActionFun>
25 void addAction(const QString &actionName, ActionFun actionFunction);
25 void addAction(const QString &actionName, ActionFun actionFunction);
26
26
27 /**
27 /**
28 * Adds a new menu to the current menu
28 * Adds a new menu to the current menu and returns it
29 * @param name the name of the menu
29 * @param name the name of the menu
30 * @param icon the icon of the menu (can be null)
30 * @param icon the icon of the menu (can be null)
31 * @returns the created menu, nullptr if it couldn't be created
31 */
32 */
32 void addMenu(const QString &name, const QIcon &icon = {});
33 QMenu *addMenu(const QString &name, const QIcon &icon = {});
33
34
34 /// Adds a separator to the current menu. The separator is added only if the menu already
35 /// Adds a separator to the current menu. The separator is added only if the menu already
35 /// contains entries
36 /// contains entries
36 void addSeparator();
37 void addSeparator();
37
38
38 /// Closes the current menu
39 /// Closes the current menu
39 void closeMenu();
40 void closeMenu();
40
41
41 private:
42 private:
42 /// @return the current menu (i.e. the top menu of the stack), nullptr if there is no menu
43 /// @return the current menu (i.e. the top menu of the stack), nullptr if there is no menu
43 QMenu *currentMenu() const;
44 QMenu *currentMenu() const;
44
45
45 /// Stack of all menus currently opened
46 /// Stack of all menus currently opened
46 QStack<QMenu *> m_Menus{};
47 QStack<QMenu *> m_Menus{};
47 };
48 };
48
49
49 template <typename ActionFun>
50 template <typename ActionFun>
50 void MenuBuilder::addAction(const QString &actionName, ActionFun actionFunction)
51 void MenuBuilder::addAction(const QString &actionName, ActionFun actionFunction)
51 {
52 {
52 if (auto currMenu = currentMenu()) {
53 if (auto currMenu = currentMenu()) {
53 currMenu->addAction(actionName, actionFunction);
54 currMenu->addAction(actionName, actionFunction);
54 }
55 }
55 else {
56 else {
56 qCCritical(LOG_MenuBuilder()) << QObject::tr("No current menu to attach the action");
57 qCCritical(LOG_MenuBuilder()) << QObject::tr("No current menu to attach the action");
57 }
58 }
58 }
59 }
59
60
60 #endif // SCIQLOP_MENUBUILDER_H
61 #endif // SCIQLOP_MENUBUILDER_H
@@ -1,145 +1,147
1 #include "SqpApplication.h"
1 #include "SqpApplication.h"
2
2
3 #include <Data/IDataProvider.h>
3 #include <Data/IDataProvider.h>
4 #include <DataSource/DataSourceController.h>
4 #include <DataSource/DataSourceController.h>
5 #include <Network/NetworkController.h>
5 #include <Network/NetworkController.h>
6 #include <QThread>
6 #include <QThread>
7 #include <Time/TimeController.h>
7 #include <Time/TimeController.h>
8 #include <Variable/Variable.h>
8 #include <Variable/Variable.h>
9 #include <Variable/VariableController.h>
9 #include <Variable/VariableController.h>
10 #include <Visualization/VisualizationController.h>
10 #include <Visualization/VisualizationController.h>
11
11
12 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
12 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
13
13
14 class SqpApplication::SqpApplicationPrivate {
14 class SqpApplication::SqpApplicationPrivate {
15 public:
15 public:
16 SqpApplicationPrivate()
16 SqpApplicationPrivate()
17 : m_DataSourceController{std::make_unique<DataSourceController>()},
17 : m_DataSourceController{std::make_unique<DataSourceController>()},
18 m_NetworkController{std::make_unique<NetworkController>()},
18 m_NetworkController{std::make_unique<NetworkController>()},
19 m_TimeController{std::make_unique<TimeController>()},
19 m_TimeController{std::make_unique<TimeController>()},
20 m_VariableController{std::make_unique<VariableController>()},
20 m_VariableController{std::make_unique<VariableController>()},
21 m_VisualizationController{std::make_unique<VisualizationController>()}
21 m_VisualizationController{std::make_unique<VisualizationController>()}
22 {
22 {
23 // /////////////////////////////// //
23 // /////////////////////////////// //
24 // Connections between controllers //
24 // Connections between controllers //
25 // /////////////////////////////// //
25 // /////////////////////////////// //
26
26
27 // VariableController <-> DataSourceController
27 // VariableController <-> DataSourceController
28 connect(m_DataSourceController.get(),
28 connect(m_DataSourceController.get(),
29 SIGNAL(variableCreationRequested(const QString &, std::shared_ptr<IDataProvider>)),
29 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
30 std::shared_ptr<IDataProvider>)),
30 m_VariableController.get(),
31 m_VariableController.get(),
31 SLOT(createVariable(const QString &, std::shared_ptr<IDataProvider>)));
32 SLOT(createVariable(const QString &, const QVariantHash &,
33 std::shared_ptr<IDataProvider>)));
32
34
33 // VariableController <-> VisualizationController
35 // VariableController <-> VisualizationController
34 connect(m_VariableController.get(),
36 connect(m_VariableController.get(),
35 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
37 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
36 m_VisualizationController.get(),
38 m_VisualizationController.get(),
37 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
39 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
38
40
39
41
40 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
42 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
41 m_NetworkController->moveToThread(&m_NetworkControllerThread);
43 m_NetworkController->moveToThread(&m_NetworkControllerThread);
42 m_VariableController->moveToThread(&m_VariableControllerThread);
44 m_VariableController->moveToThread(&m_VariableControllerThread);
43 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
45 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
44
46
45
47
46 // Additionnal init
48 // Additionnal init
47 m_VariableController->setTimeController(m_TimeController.get());
49 m_VariableController->setTimeController(m_TimeController.get());
48 }
50 }
49
51
50 virtual ~SqpApplicationPrivate()
52 virtual ~SqpApplicationPrivate()
51 {
53 {
52 qCInfo(LOG_SqpApplication()) << tr("SqpApplicationPrivate destruction");
54 qCInfo(LOG_SqpApplication()) << tr("SqpApplicationPrivate destruction");
53 m_DataSourceControllerThread.quit();
55 m_DataSourceControllerThread.quit();
54 m_DataSourceControllerThread.wait();
56 m_DataSourceControllerThread.wait();
55
57
56 m_NetworkControllerThread.quit();
58 m_NetworkControllerThread.quit();
57 m_NetworkControllerThread.wait();
59 m_NetworkControllerThread.wait();
58
60
59 m_VariableControllerThread.quit();
61 m_VariableControllerThread.quit();
60 m_VariableControllerThread.wait();
62 m_VariableControllerThread.wait();
61
63
62 m_VisualizationControllerThread.quit();
64 m_VisualizationControllerThread.quit();
63 m_VisualizationControllerThread.wait();
65 m_VisualizationControllerThread.wait();
64 }
66 }
65
67
66 std::unique_ptr<DataSourceController> m_DataSourceController;
68 std::unique_ptr<DataSourceController> m_DataSourceController;
67 std::unique_ptr<VariableController> m_VariableController;
69 std::unique_ptr<VariableController> m_VariableController;
68 std::unique_ptr<TimeController> m_TimeController;
70 std::unique_ptr<TimeController> m_TimeController;
69 std::unique_ptr<NetworkController> m_NetworkController;
71 std::unique_ptr<NetworkController> m_NetworkController;
70 std::unique_ptr<VisualizationController> m_VisualizationController;
72 std::unique_ptr<VisualizationController> m_VisualizationController;
71 QThread m_DataSourceControllerThread;
73 QThread m_DataSourceControllerThread;
72 QThread m_NetworkControllerThread;
74 QThread m_NetworkControllerThread;
73 QThread m_VariableControllerThread;
75 QThread m_VariableControllerThread;
74 QThread m_VisualizationControllerThread;
76 QThread m_VisualizationControllerThread;
75 };
77 };
76
78
77
79
78 SqpApplication::SqpApplication(int &argc, char **argv)
80 SqpApplication::SqpApplication(int &argc, char **argv)
79 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
81 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
80 {
82 {
81 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
83 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
82
84
83 connect(&impl->m_DataSourceControllerThread, &QThread::started,
85 connect(&impl->m_DataSourceControllerThread, &QThread::started,
84 impl->m_DataSourceController.get(), &DataSourceController::initialize);
86 impl->m_DataSourceController.get(), &DataSourceController::initialize);
85 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
87 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
86 impl->m_DataSourceController.get(), &DataSourceController::finalize);
88 impl->m_DataSourceController.get(), &DataSourceController::finalize);
87
89
88 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
90 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
89 &NetworkController::initialize);
91 &NetworkController::initialize);
90 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
92 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
91 &NetworkController::finalize);
93 &NetworkController::finalize);
92
94
93 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
95 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
94 &VariableController::initialize);
96 &VariableController::initialize);
95 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
97 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
96 &VariableController::finalize);
98 &VariableController::finalize);
97
99
98 connect(&impl->m_VisualizationControllerThread, &QThread::started,
100 connect(&impl->m_VisualizationControllerThread, &QThread::started,
99 impl->m_VisualizationController.get(), &VisualizationController::initialize);
101 impl->m_VisualizationController.get(), &VisualizationController::initialize);
100 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
102 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
101 impl->m_VisualizationController.get(), &VisualizationController::finalize);
103 impl->m_VisualizationController.get(), &VisualizationController::finalize);
102
104
103 impl->m_DataSourceControllerThread.start();
105 impl->m_DataSourceControllerThread.start();
104 impl->m_NetworkControllerThread.start();
106 impl->m_NetworkControllerThread.start();
105 impl->m_VariableControllerThread.start();
107 impl->m_VariableControllerThread.start();
106 impl->m_VisualizationControllerThread.start();
108 impl->m_VisualizationControllerThread.start();
107
109
108 // Core connections:
110 // Core connections:
109 // NetworkController <-> VariableController
111 // NetworkController <-> VariableController
110 connect(&sqpApp->networkController(), &NetworkController::replyDownloadProgress,
112 connect(&sqpApp->networkController(), &NetworkController::replyDownloadProgress,
111 &sqpApp->variableController(), &VariableController::onVariableRetrieveDataInProgress);
113 &sqpApp->variableController(), &VariableController::onVariableRetrieveDataInProgress);
112 }
114 }
113
115
114 SqpApplication::~SqpApplication()
116 SqpApplication::~SqpApplication()
115 {
117 {
116 }
118 }
117
119
118 void SqpApplication::initialize()
120 void SqpApplication::initialize()
119 {
121 {
120 }
122 }
121
123
122 DataSourceController &SqpApplication::dataSourceController() noexcept
124 DataSourceController &SqpApplication::dataSourceController() noexcept
123 {
125 {
124 return *impl->m_DataSourceController;
126 return *impl->m_DataSourceController;
125 }
127 }
126
128
127 NetworkController &SqpApplication::networkController() noexcept
129 NetworkController &SqpApplication::networkController() noexcept
128 {
130 {
129 return *impl->m_NetworkController;
131 return *impl->m_NetworkController;
130 }
132 }
131
133
132 TimeController &SqpApplication::timeController() noexcept
134 TimeController &SqpApplication::timeController() noexcept
133 {
135 {
134 return *impl->m_TimeController;
136 return *impl->m_TimeController;
135 }
137 }
136
138
137 VariableController &SqpApplication::variableController() noexcept
139 VariableController &SqpApplication::variableController() noexcept
138 {
140 {
139 return *impl->m_VariableController;
141 return *impl->m_VariableController;
140 }
142 }
141
143
142 VisualizationController &SqpApplication::visualizationController() noexcept
144 VisualizationController &SqpApplication::visualizationController() noexcept
143 {
145 {
144 return *impl->m_VisualizationController;
146 return *impl->m_VisualizationController;
145 }
147 }
@@ -1,196 +1,200
1 #include "Visualization/operations/GenerateVariableMenuOperation.h"
1 #include "Visualization/operations/GenerateVariableMenuOperation.h"
2 #include "Visualization/operations/MenuBuilder.h"
2 #include "Visualization/operations/MenuBuilder.h"
3
3
4 #include "Visualization/VisualizationGraphWidget.h"
4 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationTabWidget.h"
5 #include "Visualization/VisualizationTabWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7
7
8 #include <Variable/Variable.h>
8 #include <Variable/Variable.h>
9
9
10 #include <QMenu>
10 #include <QMenu>
11 #include <QStack>
11 #include <QStack>
12
12
13 Q_LOGGING_CATEGORY(LOG_GenerateVariableMenuOperation, "GenerateVariableMenuOperation")
13 Q_LOGGING_CATEGORY(LOG_GenerateVariableMenuOperation, "GenerateVariableMenuOperation")
14
14
15 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
15 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
16 explicit GenerateVariableMenuOperationPrivate(QMenu *menu, std::shared_ptr<Variable> variable)
16 explicit GenerateVariableMenuOperationPrivate(QMenu *menu, std::shared_ptr<Variable> variable)
17 : m_Variable{variable}, m_PlotMenuBuilder{menu}, m_UnplotMenuBuilder{menu}
17 : m_Variable{variable}, m_PlotMenuBuilder{menu}, m_UnplotMenuBuilder{menu}
18 {
18 {
19 }
19 }
20
20
21 void visitRootEnter()
21 void visitRootEnter()
22 {
22 {
23 // Creates the root menu
23 // Creates the root menu
24 m_PlotMenuBuilder.addMenu(QObject::tr("Plot"), QIcon{":/icones/plot.png"});
24 if (auto plotMenu
25 = m_PlotMenuBuilder.addMenu(QObject::tr("Plot"), QIcon{":/icones/plot.png"})) {
26 plotMenu->setEnabled(m_Variable && m_Variable->dataSeries() != nullptr);
27 }
28
25 m_UnplotMenuBuilder.addMenu(QObject::tr("Unplot"), QIcon{":/icones/unplot.png"});
29 m_UnplotMenuBuilder.addMenu(QObject::tr("Unplot"), QIcon{":/icones/unplot.png"});
26 }
30 }
27
31
28 void visitRootLeave()
32 void visitRootLeave()
29 {
33 {
30 // Closes the root menu
34 // Closes the root menu
31 m_PlotMenuBuilder.closeMenu();
35 m_PlotMenuBuilder.closeMenu();
32 m_UnplotMenuBuilder.closeMenu();
36 m_UnplotMenuBuilder.closeMenu();
33 }
37 }
34
38
35 void visitNodeEnter(const IVisualizationWidget &container)
39 void visitNodeEnter(const IVisualizationWidget &container)
36 {
40 {
37 // Opens a new menu associated to the node
41 // Opens a new menu associated to the node
38 m_PlotMenuBuilder.addMenu(container.name());
42 m_PlotMenuBuilder.addMenu(container.name());
39 m_UnplotMenuBuilder.addMenu(container.name());
43 m_UnplotMenuBuilder.addMenu(container.name());
40 }
44 }
41
45
42 template <typename ActionFun>
46 template <typename ActionFun>
43 void visitNodeLeavePlot(const IVisualizationWidget &container, const QString &actionName,
47 void visitNodeLeavePlot(const IVisualizationWidget &container, const QString &actionName,
44 ActionFun actionFunction)
48 ActionFun actionFunction)
45 {
49 {
46 if (m_Variable && container.canDrop(*m_Variable)) {
50 if (m_Variable && container.canDrop(*m_Variable)) {
47 m_PlotMenuBuilder.addSeparator();
51 m_PlotMenuBuilder.addSeparator();
48 m_PlotMenuBuilder.addAction(actionName, actionFunction);
52 m_PlotMenuBuilder.addAction(actionName, actionFunction);
49 }
53 }
50
54
51 // Closes the menu associated to the node
55 // Closes the menu associated to the node
52 m_PlotMenuBuilder.closeMenu();
56 m_PlotMenuBuilder.closeMenu();
53 }
57 }
54
58
55 void visitNodeLeaveUnplot()
59 void visitNodeLeaveUnplot()
56 {
60 {
57 // Closes the menu associated to the node
61 // Closes the menu associated to the node
58 m_UnplotMenuBuilder.closeMenu();
62 m_UnplotMenuBuilder.closeMenu();
59 }
63 }
60
64
61 template <typename ActionFun>
65 template <typename ActionFun>
62 void visitLeafPlot(const IVisualizationWidget &container, const QString &actionName,
66 void visitLeafPlot(const IVisualizationWidget &container, const QString &actionName,
63 ActionFun actionFunction)
67 ActionFun actionFunction)
64 {
68 {
65 if (m_Variable && container.canDrop(*m_Variable)) {
69 if (m_Variable && container.canDrop(*m_Variable)) {
66 m_PlotMenuBuilder.addAction(actionName, actionFunction);
70 m_PlotMenuBuilder.addAction(actionName, actionFunction);
67 }
71 }
68 }
72 }
69
73
70 template <typename ActionFun>
74 template <typename ActionFun>
71 void visitLeafUnplot(const IVisualizationWidget &container, const QString &actionName,
75 void visitLeafUnplot(const IVisualizationWidget &container, const QString &actionName,
72 ActionFun actionFunction)
76 ActionFun actionFunction)
73 {
77 {
74 if (m_Variable && container.contains(*m_Variable)) {
78 if (m_Variable && container.contains(*m_Variable)) {
75 m_UnplotMenuBuilder.addAction(actionName, actionFunction);
79 m_UnplotMenuBuilder.addAction(actionName, actionFunction);
76 }
80 }
77 }
81 }
78
82
79 std::shared_ptr<Variable> m_Variable;
83 std::shared_ptr<Variable> m_Variable;
80 MenuBuilder m_PlotMenuBuilder; ///< Builder for the 'Plot' menu
84 MenuBuilder m_PlotMenuBuilder; ///< Builder for the 'Plot' menu
81 MenuBuilder m_UnplotMenuBuilder; ///< Builder for the 'Unplot' menu
85 MenuBuilder m_UnplotMenuBuilder; ///< Builder for the 'Unplot' menu
82 };
86 };
83
87
84 GenerateVariableMenuOperation::GenerateVariableMenuOperation(QMenu *menu,
88 GenerateVariableMenuOperation::GenerateVariableMenuOperation(QMenu *menu,
85 std::shared_ptr<Variable> variable)
89 std::shared_ptr<Variable> variable)
86 : impl{spimpl::make_unique_impl<GenerateVariableMenuOperationPrivate>(menu, variable)}
90 : impl{spimpl::make_unique_impl<GenerateVariableMenuOperationPrivate>(menu, variable)}
87 {
91 {
88 }
92 }
89
93
90 void GenerateVariableMenuOperation::visitEnter(VisualizationWidget *widget)
94 void GenerateVariableMenuOperation::visitEnter(VisualizationWidget *widget)
91 {
95 {
92 // VisualizationWidget is not intended to accommodate a variable
96 // VisualizationWidget is not intended to accommodate a variable
93 Q_UNUSED(widget)
97 Q_UNUSED(widget)
94
98
95 // 'Plot' and 'Unplot' menus
99 // 'Plot' and 'Unplot' menus
96 impl->visitRootEnter();
100 impl->visitRootEnter();
97 }
101 }
98
102
99 void GenerateVariableMenuOperation::visitLeave(VisualizationWidget *widget)
103 void GenerateVariableMenuOperation::visitLeave(VisualizationWidget *widget)
100 {
104 {
101 // VisualizationWidget is not intended to accommodate a variable
105 // VisualizationWidget is not intended to accommodate a variable
102 Q_UNUSED(widget)
106 Q_UNUSED(widget)
103
107
104 // 'Plot' and 'Unplot' menus
108 // 'Plot' and 'Unplot' menus
105 impl->visitRootLeave();
109 impl->visitRootLeave();
106 }
110 }
107
111
108 void GenerateVariableMenuOperation::visitEnter(VisualizationTabWidget *tabWidget)
112 void GenerateVariableMenuOperation::visitEnter(VisualizationTabWidget *tabWidget)
109 {
113 {
110 if (tabWidget) {
114 if (tabWidget) {
111 // 'Plot' and 'Unplot' menus
115 // 'Plot' and 'Unplot' menus
112 impl->visitNodeEnter(*tabWidget);
116 impl->visitNodeEnter(*tabWidget);
113 }
117 }
114 else {
118 else {
115 qCCritical(LOG_GenerateVariableMenuOperation(),
119 qCCritical(LOG_GenerateVariableMenuOperation(),
116 "Can't visit enter VisualizationTabWidget : the widget is null");
120 "Can't visit enter VisualizationTabWidget : the widget is null");
117 }
121 }
118 }
122 }
119
123
120 void GenerateVariableMenuOperation::visitLeave(VisualizationTabWidget *tabWidget)
124 void GenerateVariableMenuOperation::visitLeave(VisualizationTabWidget *tabWidget)
121 {
125 {
122 if (tabWidget) {
126 if (tabWidget) {
123 // 'Plot' menu
127 // 'Plot' menu
124 impl->visitNodeLeavePlot(*tabWidget, QObject::tr("Open in a new zone"),
128 impl->visitNodeLeavePlot(*tabWidget, QObject::tr("Open in a new zone"),
125 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, tabWidget ]() {
129 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, tabWidget ]() {
126 if (auto var = varW.lock()) {
130 if (auto var = varW.lock()) {
127 tabWidget->createZone(var);
131 tabWidget->createZone(var);
128 }
132 }
129 });
133 });
130
134
131 // 'Unplot' menu
135 // 'Unplot' menu
132 impl->visitNodeLeaveUnplot();
136 impl->visitNodeLeaveUnplot();
133 }
137 }
134 else {
138 else {
135 qCCritical(LOG_GenerateVariableMenuOperation(),
139 qCCritical(LOG_GenerateVariableMenuOperation(),
136 "Can't visit leave VisualizationTabWidget : the widget is null");
140 "Can't visit leave VisualizationTabWidget : the widget is null");
137 }
141 }
138 }
142 }
139
143
140 void GenerateVariableMenuOperation::visitEnter(VisualizationZoneWidget *zoneWidget)
144 void GenerateVariableMenuOperation::visitEnter(VisualizationZoneWidget *zoneWidget)
141 {
145 {
142 if (zoneWidget) {
146 if (zoneWidget) {
143 // 'Plot' and 'Unplot' menus
147 // 'Plot' and 'Unplot' menus
144 impl->visitNodeEnter(*zoneWidget);
148 impl->visitNodeEnter(*zoneWidget);
145 }
149 }
146 else {
150 else {
147 qCCritical(LOG_GenerateVariableMenuOperation(),
151 qCCritical(LOG_GenerateVariableMenuOperation(),
148 "Can't visit enter VisualizationZoneWidget : the widget is null");
152 "Can't visit enter VisualizationZoneWidget : the widget is null");
149 }
153 }
150 }
154 }
151
155
152 void GenerateVariableMenuOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
156 void GenerateVariableMenuOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
153 {
157 {
154 if (zoneWidget) {
158 if (zoneWidget) {
155 // 'Plot' menu
159 // 'Plot' menu
156 impl->visitNodeLeavePlot(
160 impl->visitNodeLeavePlot(
157 *zoneWidget, QObject::tr("Open in a new graph"),
161 *zoneWidget, QObject::tr("Open in a new graph"),
158 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, zoneWidget ]() {
162 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, zoneWidget ]() {
159 if (auto var = varW.lock()) {
163 if (auto var = varW.lock()) {
160 zoneWidget->createGraph(var);
164 zoneWidget->createGraph(var);
161 }
165 }
162 });
166 });
163
167
164 // 'Unplot' menu
168 // 'Unplot' menu
165 impl->visitNodeLeaveUnplot();
169 impl->visitNodeLeaveUnplot();
166 }
170 }
167 else {
171 else {
168 qCCritical(LOG_GenerateVariableMenuOperation(),
172 qCCritical(LOG_GenerateVariableMenuOperation(),
169 "Can't visit leave VisualizationZoneWidget : the widget is null");
173 "Can't visit leave VisualizationZoneWidget : the widget is null");
170 }
174 }
171 }
175 }
172
176
173 void GenerateVariableMenuOperation::visit(VisualizationGraphWidget *graphWidget)
177 void GenerateVariableMenuOperation::visit(VisualizationGraphWidget *graphWidget)
174 {
178 {
175 if (graphWidget) {
179 if (graphWidget) {
176 // 'Plot' menu
180 // 'Plot' menu
177 impl->visitLeafPlot(*graphWidget, QObject::tr("Open in %1").arg(graphWidget->name()),
181 impl->visitLeafPlot(*graphWidget, QObject::tr("Open in %1").arg(graphWidget->name()),
178 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
182 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
179 if (auto var = varW.lock()) {
183 if (auto var = varW.lock()) {
180 graphWidget->addVariableUsingGraph(var);
184 graphWidget->addVariableUsingGraph(var);
181 }
185 }
182 });
186 });
183
187
184 // 'Unplot' menu
188 // 'Unplot' menu
185 impl->visitLeafUnplot(*graphWidget, QObject::tr("Remove from %1").arg(graphWidget->name()),
189 impl->visitLeafUnplot(*graphWidget, QObject::tr("Remove from %1").arg(graphWidget->name()),
186 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
190 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
187 if (auto var = varW.lock()) {
191 if (auto var = varW.lock()) {
188 graphWidget->removeVariable(var);
192 graphWidget->removeVariable(var);
189 }
193 }
190 });
194 });
191 }
195 }
192 else {
196 else {
193 qCCritical(LOG_GenerateVariableMenuOperation(),
197 qCCritical(LOG_GenerateVariableMenuOperation(),
194 "Can't visit VisualizationGraphWidget : the widget is null");
198 "Can't visit VisualizationGraphWidget : the widget is null");
195 }
199 }
196 }
200 }
@@ -1,55 +1,58
1 #include "Visualization/operations/MenuBuilder.h"
1 #include "Visualization/operations/MenuBuilder.h"
2
2
3 Q_LOGGING_CATEGORY(LOG_MenuBuilder, "MenuBuilder")
3 Q_LOGGING_CATEGORY(LOG_MenuBuilder, "MenuBuilder")
4
4
5 MenuBuilder::MenuBuilder(QMenu *menu)
5 MenuBuilder::MenuBuilder(QMenu *menu)
6 {
6 {
7 if (menu) {
7 if (menu) {
8 m_Menus.push(menu);
8 m_Menus.push(menu);
9 }
9 }
10 else {
10 else {
11 qCCritical(LOG_MenuBuilder()) << QObject::tr("No parent menu has been defined");
11 qCCritical(LOG_MenuBuilder()) << QObject::tr("No parent menu has been defined");
12 }
12 }
13 }
13 }
14
14
15 void MenuBuilder::addMenu(const QString &name, const QIcon &icon)
15 QMenu *MenuBuilder::addMenu(const QString &name, const QIcon &icon)
16 {
16 {
17 if (auto currMenu = currentMenu()) {
17 if (auto currMenu = currentMenu()) {
18 m_Menus.push(currMenu->addMenu(icon, name));
18 auto menu = currMenu->addMenu(icon, name);
19 m_Menus.push(menu);
20 return menu;
19 }
21 }
20 else {
22 else {
21 qCCritical(LOG_MenuBuilder()) << QObject::tr("No current menu to attach the new menu");
23 qCCritical(LOG_MenuBuilder()) << QObject::tr("No current menu to attach the new menu");
24 return nullptr;
22 }
25 }
23 }
26 }
24
27
25 void MenuBuilder::addSeparator()
28 void MenuBuilder::addSeparator()
26 {
29 {
27 if (auto currMenu = currentMenu()) {
30 if (auto currMenu = currentMenu()) {
28 if (!currMenu->isEmpty()) {
31 if (!currMenu->isEmpty()) {
29 currMenu->addSeparator();
32 currMenu->addSeparator();
30 }
33 }
31 }
34 }
32 else {
35 else {
33 qCCritical(LOG_MenuBuilder()) << QObject::tr("No current menu to attach the separator");
36 qCCritical(LOG_MenuBuilder()) << QObject::tr("No current menu to attach the separator");
34 }
37 }
35 }
38 }
36
39
37 void MenuBuilder::closeMenu()
40 void MenuBuilder::closeMenu()
38 {
41 {
39 if (!m_Menus.isEmpty()) {
42 if (!m_Menus.isEmpty()) {
40 if (auto closedMenu = m_Menus.pop()) {
43 if (auto closedMenu = m_Menus.pop()) {
41 // Purge menu : if the closed menu has no entries, we remove it from its parent (the
44 // Purge menu : if the closed menu has no entries, we remove it from its parent (the
42 // current menu)
45 // current menu)
43 if (auto currMenu = currentMenu()) {
46 if (auto currMenu = currentMenu()) {
44 if (closedMenu->isEmpty()) {
47 if (closedMenu->isEmpty()) {
45 currMenu->removeAction(closedMenu->menuAction());
48 currMenu->removeAction(closedMenu->menuAction());
46 }
49 }
47 }
50 }
48 }
51 }
49 }
52 }
50 }
53 }
51
54
52 QMenu *MenuBuilder::currentMenu() const
55 QMenu *MenuBuilder::currentMenu() const
53 {
56 {
54 return !m_Menus.isEmpty() ? m_Menus.top() : nullptr;
57 return !m_Menus.isEmpty() ? m_Menus.top() : nullptr;
55 }
58 }
@@ -1,38 +1,28
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 <Common/spimpl.h>
7
8 #include <Data/IDataProvider.h>
6 #include <Data/IDataProvider.h>
9
7
10 #include <QLoggingCategory>
8 #include <QLoggingCategory>
11
9
12
10
13 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
11 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
14
12
15 class QNetworkReply;
13 class QNetworkReply;
16
14
17 /**
15 /**
18 * @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
19 */
17 */
20 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
18 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
21 public:
19 public:
22 explicit AmdaProvider();
20 explicit AmdaProvider();
23
21
24 void requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList) override;
22 void requestDataLoading(QUuid token, const DataProviderParameters &parameters) override;
25
23
26 private:
24 private:
27 void retrieveData(QUuid token, const DataProviderParameters &parameters);
25 void retrieveData(QUuid token, const SqpDateTime &dateTime, const QVariantHash &data);
28
29 class AmdaProviderPrivate;
30 spimpl::unique_impl_ptr<AmdaProviderPrivate> impl;
31
32 // private slots:
33 // void httpFinished(QNetworkReply *reply, QUuid dataId) noexcept;
34 // void httpDownloadFinished(QNetworkReply *reply, QUuid dataId) noexcept;
35 // void httpDownloadReadyRead(QNetworkReply *reply, QUuid dataId) noexcept;
36 };
26 };
37
27
38 #endif // SCIQLOP_AMDAPROVIDER_H
28 #endif // SCIQLOP_AMDAPROVIDER_H
@@ -1,129 +1,125
1 #include "AmdaParser.h"
1 #include "AmdaParser.h"
2 #include "AmdaDefs.h"
2
3
3 #include <DataSource/DataSourceItem.h>
4 #include <DataSource/DataSourceItem.h>
4
5
5 #include <QFile>
6 #include <QFile>
6 #include <QJsonArray>
7 #include <QJsonArray>
7 #include <QJsonDocument>
8 #include <QJsonDocument>
8 #include <QJsonObject>
9 #include <QJsonObject>
9
10
10 Q_LOGGING_CATEGORY(LOG_AmdaParser, "AmdaParser")
11 Q_LOGGING_CATEGORY(LOG_AmdaParser, "AmdaParser")
11
12
12 namespace {
13 namespace {
13
14
14 // Significant keys of an AMDA's JSON file
15 const auto COMPONENT_KEY = QStringLiteral("component");
16 const auto PRODUCT_KEY = QStringLiteral("parameter");
17 const auto ROOT_KEY = QStringLiteral("dataCenter");
18
19 /// Returns the correct item type according to the key passed in parameter
15 /// Returns the correct item type according to the key passed in parameter
20 DataSourceItemType itemType(const QString &key) noexcept
16 DataSourceItemType itemType(const QString &key) noexcept
21 {
17 {
22 if (key == PRODUCT_KEY) {
18 if (key == AMDA_PRODUCT_KEY) {
23 return DataSourceItemType::PRODUCT;
19 return DataSourceItemType::PRODUCT;
24 }
20 }
25 else if (key == COMPONENT_KEY) {
21 else if (key == AMDA_COMPONENT_KEY) {
26 return DataSourceItemType::COMPONENT;
22 return DataSourceItemType::COMPONENT;
27 }
23 }
28 else {
24 else {
29 return DataSourceItemType::NODE;
25 return DataSourceItemType::NODE;
30 }
26 }
31 }
27 }
32
28
33 /**
29 /**
34 * Processes an entry of the JSON file to populate/create data source items
30 * Processes an entry of the JSON file to populate/create data source items
35 * @param jsonKey the entry's key
31 * @param jsonKey the entry's key
36 * @param jsonValue the entry's value
32 * @param jsonValue the entry's value
37 * @param item the current item for which the entry processing will be applied
33 * @param item the current item for which the entry processing will be applied
38 * @param appendData flag indicating that the entry is part of an array. In the case of an array of
34 * @param appendData flag indicating that the entry is part of an array. In the case of an array of
39 * values, each value will be concatenated to the others (rather than replacing the others)
35 * values, each value will be concatenated to the others (rather than replacing the others)
40 */
36 */
41 void parseEntry(const QString &jsonKey, const QJsonValue &jsonValue, DataSourceItem &item,
37 void parseEntry(const QString &jsonKey, const QJsonValue &jsonValue, DataSourceItem &item,
42 bool isArrayEntry = false)
38 bool isArrayEntry = false)
43 {
39 {
44 if (jsonValue.isObject()) {
40 if (jsonValue.isObject()) {
45 // Case of an object:
41 // Case of an object:
46 // - a new data source item is created and
42 // - a new data source item is created and
47 // - parsing is called recursively to process the new item
43 // - parsing is called recursively to process the new item
48 // - the new item is then added as a child of the former item
44 // - the new item is then added as a child of the former item
49 auto object = jsonValue.toObject();
45 auto object = jsonValue.toObject();
50
46
51 auto newItem = std::make_unique<DataSourceItem>(itemType(jsonKey));
47 auto newItem = std::make_unique<DataSourceItem>(itemType(jsonKey));
52
48
53 for (auto it = object.constBegin(), end = object.constEnd(); it != end; ++it) {
49 for (auto it = object.constBegin(), end = object.constEnd(); it != end; ++it) {
54 parseEntry(it.key(), it.value(), *newItem);
50 parseEntry(it.key(), it.value(), *newItem);
55 }
51 }
56
52
57 item.appendChild(std::move(newItem));
53 item.appendChild(std::move(newItem));
58 }
54 }
59 else if (jsonValue.isArray()) {
55 else if (jsonValue.isArray()) {
60 // Case of an array: the item is populated with the arrays' content
56 // Case of an array: the item is populated with the arrays' content
61 auto object = jsonValue.toArray();
57 auto object = jsonValue.toArray();
62
58
63 for (auto it = object.constBegin(), end = object.constEnd(); it != end; ++it) {
59 for (auto it = object.constBegin(), end = object.constEnd(); it != end; ++it) {
64 parseEntry(jsonKey, *it, item, true);
60 parseEntry(jsonKey, *it, item, true);
65 }
61 }
66 }
62 }
67 else {
63 else {
68 // Case of a simple value: we add a data to the item. If the simple value is a part of an
64 // Case of a simple value: we add a data to the item. If the simple value is a part of an
69 // array, it is concatenated to the values already existing for this key
65 // array, it is concatenated to the values already existing for this key
70 item.setData(jsonKey, jsonValue.toVariant(), isArrayEntry);
66 item.setData(jsonKey, jsonValue.toVariant(), isArrayEntry);
71 }
67 }
72 }
68 }
73
69
74 } // namespace
70 } // namespace
75
71
76 std::unique_ptr<DataSourceItem> AmdaParser::readJson(const QString &filePath) noexcept
72 std::unique_ptr<DataSourceItem> AmdaParser::readJson(const QString &filePath) noexcept
77 {
73 {
78 QFile jsonFile{filePath};
74 QFile jsonFile{filePath};
79
75
80 if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
76 if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
81 qCCritical(LOG_AmdaParser())
77 qCCritical(LOG_AmdaParser())
82 << QObject::tr("Can't retrieve data source tree from file %1: %2")
78 << QObject::tr("Can't retrieve data source tree from file %1: %2")
83 .arg(filePath, jsonFile.errorString());
79 .arg(filePath, jsonFile.errorString());
84 return nullptr;
80 return nullptr;
85 }
81 }
86
82
87 auto json = jsonFile.readAll();
83 auto json = jsonFile.readAll();
88 auto jsonDocument = QJsonDocument::fromJson(json);
84 auto jsonDocument = QJsonDocument::fromJson(json);
89
85
90 // Check preconditions for parsing
86 // Check preconditions for parsing
91 if (!jsonDocument.isObject()) {
87 if (!jsonDocument.isObject()) {
92 qCCritical(LOG_AmdaParser())
88 qCCritical(LOG_AmdaParser())
93 << QObject::tr(
89 << QObject::tr(
94 "Can't retrieve data source tree from file %1: the file is malformed (there is "
90 "Can't retrieve data source tree from file %1: the file is malformed (there is "
95 "not one and only one root object)")
91 "not one and only one root object)")
96 .arg(filePath);
92 .arg(filePath);
97 return nullptr;
93 return nullptr;
98 }
94 }
99
95
100 auto jsonDocumentObject = jsonDocument.object();
96 auto jsonDocumentObject = jsonDocument.object();
101 if (!jsonDocumentObject.contains(ROOT_KEY)) {
97 if (!jsonDocumentObject.contains(AMDA_ROOT_KEY)) {
102 qCCritical(LOG_AmdaParser())
98 qCCritical(LOG_AmdaParser())
103 << QObject::tr(
99 << QObject::tr(
104 "Can't retrieve data source tree from file %1: the file is malformed (the key "
100 "Can't retrieve data source tree from file %1: the file is malformed (the key "
105 "for the root element was not found (%2))")
101 "for the root element was not found (%2))")
106 .arg(filePath, ROOT_KEY);
102 .arg(filePath, AMDA_ROOT_KEY);
107 return nullptr;
103 return nullptr;
108 }
104 }
109
105
110 auto rootValue = jsonDocumentObject.value(ROOT_KEY);
106 auto rootValue = jsonDocumentObject.value(AMDA_ROOT_KEY);
111 if (!rootValue.isObject()) {
107 if (!rootValue.isObject()) {
112 qCCritical(LOG_AmdaParser())
108 qCCritical(LOG_AmdaParser())
113 << QObject::tr(
109 << QObject::tr(
114 "Can't retrieve data source tree from file %1: the file is malformed (the root "
110 "Can't retrieve data source tree from file %1: the file is malformed (the root "
115 "element is of the wrong type)")
111 "element is of the wrong type)")
116 .arg(filePath);
112 .arg(filePath);
117 return nullptr;
113 return nullptr;
118 }
114 }
119
115
120 // Makes the parsing
116 // Makes the parsing
121 auto rootObject = rootValue.toObject();
117 auto rootObject = rootValue.toObject();
122 auto rootItem = std::make_unique<DataSourceItem>(DataSourceItemType::NODE);
118 auto rootItem = std::make_unique<DataSourceItem>(DataSourceItemType::NODE);
123
119
124 for (auto it = rootObject.constBegin(), end = rootObject.constEnd(); it != end; ++it) {
120 for (auto it = rootObject.constBegin(), end = rootObject.constEnd(); it != end; ++it) {
125 parseEntry(it.key(), it.value(), *rootItem);
121 parseEntry(it.key(), it.value(), *rootItem);
126 }
122 }
127
123
128 return rootItem;
124 return rootItem;
129 }
125 }
@@ -1,68 +1,83
1 #include "AmdaPlugin.h"
1 #include "AmdaPlugin.h"
2 #include "AmdaDefs.h"
2 #include "AmdaParser.h"
3 #include "AmdaParser.h"
3 #include "AmdaProvider.h"
4 #include "AmdaProvider.h"
4
5
5 #include <DataSource/DataSourceController.h>
6 #include <DataSource/DataSourceController.h>
6 #include <DataSource/DataSourceItem.h>
7 #include <DataSource/DataSourceItem.h>
7 #include <DataSource/DataSourceItemAction.h>
8 #include <DataSource/DataSourceItemAction.h>
8
9
9 #include <SqpApplication.h>
10 #include <SqpApplication.h>
10
11
11 Q_LOGGING_CATEGORY(LOG_AmdaPlugin, "AmdaPlugin")
12 Q_LOGGING_CATEGORY(LOG_AmdaPlugin, "AmdaPlugin")
12
13
13 namespace {
14 namespace {
14
15
15 /// Name of the data source
16 /// Name of the data source
16 const auto DATA_SOURCE_NAME = QStringLiteral("AMDA");
17 const auto DATA_SOURCE_NAME = QStringLiteral("AMDA");
17
18
18 /// Path of the file used to generate the data source item for AMDA
19 /// Path of the file used to generate the data source item for AMDA
19 const auto JSON_FILE_PATH = QStringLiteral(":/samples/AmdaSample.json");
20 const auto JSON_FILE_PATH = QStringLiteral(":/samples/AmdaSample.json");
20
21
21 void associateActions(DataSourceItem &item, const QUuid &dataSourceUid)
22 void associateActions(DataSourceItem &item, const QUuid &dataSourceUid)
22 {
23 {
23 if (item.type() == DataSourceItemType::PRODUCT) {
24 auto addLoadAction = [&item, dataSourceUid](const QString &label) {
24 auto itemName = item.name();
25 item.addAction(
25
26 std::make_unique<DataSourceItemAction>(label, [dataSourceUid](DataSourceItem &item) {
26 item.addAction(std::make_unique<DataSourceItemAction>(
27 QObject::tr("Load %1 product").arg(itemName),
28 [itemName, dataSourceUid](DataSourceItem &item) {
29 if (auto app = sqpApp) {
27 if (auto app = sqpApp) {
30 app->dataSourceController().loadProductItem(dataSourceUid, item);
28 app->dataSourceController().loadProductItem(dataSourceUid, item);
31 }
29 }
32 }));
30 }));
31 };
32
33 const auto itemType = item.type();
34 if (itemType == DataSourceItemType::PRODUCT) {
35 /// @todo : As for the moment we do not manage the loading of vectors, in the case of a
36 /// parameter, we update the identifier of download of the data:
37 /// - if the parameter has no component, the identifier remains the same
38 /// - if the parameter has at least one component, the identifier is that of the first
39 /// component (for example, "imf" becomes "imf (0)")
40 if (item.childCount() != 0) {
41 item.setData(AMDA_XML_ID_KEY, item.child(0)->data(AMDA_XML_ID_KEY));
42 }
43
44 addLoadAction(QObject::tr("Load %1 product").arg(item.name()));
45 }
46 else if (itemType == DataSourceItemType::COMPONENT) {
47 addLoadAction(QObject::tr("Load %1 component").arg(item.name()));
33 }
48 }
34
49
35 auto count = item.childCount();
50 auto count = item.childCount();
36 for (auto i = 0; i < count; ++i) {
51 for (auto i = 0; i < count; ++i) {
37 if (auto child = item.child(i)) {
52 if (auto child = item.child(i)) {
38 associateActions(*child, dataSourceUid);
53 associateActions(*child, dataSourceUid);
39 }
54 }
40 }
55 }
41 }
56 }
42
57
43 } // namespace
58 } // namespace
44
59
45 void AmdaPlugin::initialize()
60 void AmdaPlugin::initialize()
46 {
61 {
47 if (auto app = sqpApp) {
62 if (auto app = sqpApp) {
48 // Registers to the data source controller
63 // Registers to the data source controller
49 auto &dataSourceController = app->dataSourceController();
64 auto &dataSourceController = app->dataSourceController();
50 auto dataSourceUid = dataSourceController.registerDataSource(DATA_SOURCE_NAME);
65 auto dataSourceUid = dataSourceController.registerDataSource(DATA_SOURCE_NAME);
51
66
52 // Sets data source tree
67 // Sets data source tree
53 if (auto dataSourceItem = AmdaParser::readJson(JSON_FILE_PATH)) {
68 if (auto dataSourceItem = AmdaParser::readJson(JSON_FILE_PATH)) {
54 associateActions(*dataSourceItem, dataSourceUid);
69 associateActions(*dataSourceItem, dataSourceUid);
55
70
56 dataSourceController.setDataSourceItem(dataSourceUid, std::move(dataSourceItem));
71 dataSourceController.setDataSourceItem(dataSourceUid, std::move(dataSourceItem));
57 }
72 }
58 else {
73 else {
59 qCCritical(LOG_AmdaPlugin()) << tr("No data source item could be generated for AMDA");
74 qCCritical(LOG_AmdaPlugin()) << tr("No data source item could be generated for AMDA");
60 }
75 }
61
76
62 // Sets data provider
77 // Sets data provider
63 dataSourceController.setDataProvider(dataSourceUid, std::make_unique<AmdaProvider>());
78 dataSourceController.setDataProvider(dataSourceUid, std::make_unique<AmdaProvider>());
64 }
79 }
65 else {
80 else {
66 qCWarning(LOG_AmdaPlugin()) << tr("Can't access to SciQlop application");
81 qCWarning(LOG_AmdaPlugin()) << tr("Can't access to SciQlop application");
67 }
82 }
68 }
83 }
@@ -1,128 +1,129
1 #include "AmdaProvider.h"
1 #include "AmdaProvider.h"
2 #include "AmdaDefs.h"
2 #include "AmdaResultParser.h"
3 #include "AmdaResultParser.h"
3
4
4 #include <Data/DataProviderParameters.h>
5 #include <Data/DataProviderParameters.h>
5 #include <Network/NetworkController.h>
6 #include <Network/NetworkController.h>
6 #include <SqpApplication.h>
7 #include <SqpApplication.h>
7 #include <Variable/Variable.h>
8 #include <Variable/Variable.h>
8
9
9 #include <QNetworkAccessManager>
10 #include <QNetworkAccessManager>
10 #include <QNetworkReply>
11 #include <QNetworkReply>
11 #include <QTemporaryFile>
12 #include <QTemporaryFile>
12 #include <QThread>
13 #include <QThread>
13
14
14 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
15 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
15
16
16 namespace {
17 namespace {
17
18
18 /// URL format for a request on AMDA server. The parameters are as follows:
19 /// URL format for a request on AMDA server. The parameters are as follows:
19 /// - %1: start date
20 /// - %1: start date
20 /// - %2: end date
21 /// - %2: end date
21 /// - %3: parameter id
22 /// - %3: parameter id
22 const auto AMDA_URL_FORMAT = QStringLiteral(
23 const auto AMDA_URL_FORMAT = QStringLiteral(
23 "http://amda.irap.omp.eu/php/rest/"
24 "http://amda.irap.omp.eu/php/rest/"
24 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&sampling=60&outputFormat=ASCII&"
25 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&sampling=60&outputFormat=ASCII&"
25 "timeFormat=ISO8601&gzip=0");
26 "timeFormat=ISO8601&gzip=0");
26
27
27 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
28 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
28 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:ss");
29 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:ss");
29
30
30 /// Formats a time to a date that can be passed in URL
31 /// Formats a time to a date that can be passed in URL
31 QString dateFormat(double sqpDateTime) noexcept
32 QString dateFormat(double sqpDateTime) noexcept
32 {
33 {
33 auto dateTime = QDateTime::fromMSecsSinceEpoch(sqpDateTime * 1000.);
34 auto dateTime = QDateTime::fromMSecsSinceEpoch(sqpDateTime * 1000.);
34 return dateTime.toString(AMDA_TIME_FORMAT);
35 return dateTime.toString(AMDA_TIME_FORMAT);
35 }
36 }
36
37
37
38 } // namespace
38 } // namespace
39
39
40 struct AmdaProvider::AmdaProviderPrivate {
40 AmdaProvider::AmdaProvider()
41 DataProviderParameters m_Params{};
42 std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
43 QNetworkReply *m_Reply{nullptr};
44 // std::unique_ptr<QTemporaryFile> m_File{nullptr};
45 QUuid m_Token;
46 };
47
48 AmdaProvider::AmdaProvider() : impl{spimpl::make_unique_impl<AmdaProviderPrivate>()}
49 {
41 {
50 qCDebug(LOG_NetworkController()) << tr("AmdaProvider::AmdaProvider")
42 qCDebug(LOG_NetworkController()) << tr("AmdaProvider::AmdaProvider")
51 << QThread::currentThread();
43 << QThread::currentThread();
52 if (auto app = sqpApp) {
44 if (auto app = sqpApp) {
53 auto &networkController = app->networkController();
45 auto &networkController = app->networkController();
54 connect(this, &AmdaProvider::requestConstructed, &networkController,
46 connect(this, SIGNAL(requestConstructed(QNetworkRequest, QUuid,
55 &NetworkController::onProcessRequested);
47 std::function<void(QNetworkReply *, QUuid)>)),
48 &networkController,
49 SLOT(onProcessRequested(QNetworkRequest, QUuid,
50 std::function<void(QNetworkReply *, QUuid)>)));
56 }
51 }
57 }
52 }
58
53
59 void AmdaProvider::requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList)
54 void AmdaProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
60 {
55 {
61 // NOTE: Try to use multithread if possible
56 // NOTE: Try to use multithread if possible
62 for (const auto &dateTime : dateTimeList) {
57 const auto times = parameters.m_Times;
63 retrieveData(token, DataProviderParameters{dateTime});
58 const auto data = parameters.m_Data;
59 for (const auto &dateTime : qAsConst(times)) {
60 retrieveData(token, dateTime, data);
64 }
61 }
65 }
62 }
66
63
67 void AmdaProvider::retrieveData(QUuid token, const DataProviderParameters &parameters)
64 void AmdaProvider::retrieveData(QUuid token, const SqpDateTime &dateTime, const QVariantHash &data)
68 {
65 {
66 // Retrieves product ID from data: if the value is invalid, no request is made
67 auto productId = data.value(AMDA_XML_ID_KEY).toString();
68 if (productId.isNull()) {
69 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
70 return;
71 }
72
69 // /////////// //
73 // /////////// //
70 // Creates URL //
74 // Creates URL //
71 // /////////// //
75 // /////////// //
72
76
73 auto startDate = dateFormat(parameters.m_Time.m_TStart);
77 auto startDate = dateFormat(dateTime.m_TStart);
74 auto endDate = dateFormat(parameters.m_Time.m_TEnd);
78 auto endDate = dateFormat(dateTime.m_TEnd);
75 auto productId = QStringLiteral("imf(0)");
76
79
77 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
80 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
78
81
79 auto tempFile = std::make_shared<QTemporaryFile>();
82 auto tempFile = std::make_shared<QTemporaryFile>();
80
83
81
82 // LAMBDA
84 // LAMBDA
83 auto httpDownloadFinished = [this, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
85 auto httpDownloadFinished
84
86 = [this, dateTime, tempFile, token](QNetworkReply *reply, QUuid dataId) noexcept {
85 if (tempFile) {
87 Q_UNUSED(dataId);
86 auto replyReadAll = reply->readAll();
88
87 if (!replyReadAll.isEmpty()) {
89 if (tempFile) {
88 tempFile->write(replyReadAll);
90 auto replyReadAll = reply->readAll();
89 }
91 if (!replyReadAll.isEmpty()) {
90 tempFile->close();
92 tempFile->write(replyReadAll);
91
93 }
92 // Parse results file
94 tempFile->close();
93 if (auto dataSeries = AmdaResultParser::readTxt(tempFile->fileName())) {
95
94 emit dataProvided(impl->m_Token, dataSeries, impl->m_Params.m_Time);
96 // Parse results file
95 }
97 if (auto dataSeries = AmdaResultParser::readTxt(tempFile->fileName())) {
96 else {
98 emit dataProvided(token, dataSeries, dateTime);
97 /// @todo ALX : debug
99 }
98 }
100 else {
99 }
101 /// @todo ALX : debug
100
102 }
101 // Deletes reply
103 }
102 reply->deleteLater();
104
103 reply = nullptr;
105 // Deletes reply
104 };
106 reply->deleteLater();
107 reply = nullptr;
108 };
105 auto httpFinishedLambda = [this, httpDownloadFinished, tempFile](QNetworkReply *reply,
109 auto httpFinishedLambda = [this, httpDownloadFinished, tempFile](QNetworkReply *reply,
106 QUuid dataId) noexcept {
110 QUuid dataId) noexcept {
107
111
108 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
112 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
109 // Deletes old reply
113 // Deletes old reply
110 reply->deleteLater();
114 reply->deleteLater();
111
115
112 // Executes request for downloading file //
116 // Executes request for downloading file //
113
117
114 // Creates destination file
118 // Creates destination file
115 if (tempFile->open()) {
119 if (tempFile->open()) {
116 // Executes request
120 // Executes request
117 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId, httpDownloadFinished);
121 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId, httpDownloadFinished);
118 }
122 }
119 };
123 };
120
124
121 // //////////////// //
125 // //////////////// //
122 // Executes request //
126 // Executes request //
123 // //////////////// //
127 // //////////////// //
124
125 impl->m_Token = token;
126 impl->m_Params = parameters;
127 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
128 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
128 }
129 }
@@ -1,26 +1,25
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
9
10 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
10 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
11
11
12 /**
12 /**
13 * @brief The CosinusProvider class is an example of how a data provider can generate data
13 * @brief The CosinusProvider class is an example of how a data provider can generate data
14 */
14 */
15 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
15 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
16 public:
16 public:
17 void requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList) override;
17 void requestDataLoading(QUuid token, const DataProviderParameters &parameters) override;
18
18
19
19
20 private:
20 private:
21 /// @sa IDataProvider::retrieveData()
21 /// @sa IDataProvider::retrieveData()
22 std::shared_ptr<IDataSeries> retrieveData(const DataProviderParameters &parameters) const;
22 std::shared_ptr<IDataSeries> retrieveData(const SqpDateTime &dateTime) const;
23 std::shared_ptr<IDataSeries> retrieveDataSeries(const SqpDateTime &dateTime);
24 };
23 };
25
24
26 #endif // SCIQLOP_COSINUSPROVIDER_H
25 #endif // SCIQLOP_COSINUSPROVIDER_H
@@ -1,50 +1,48
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 <QDateTime>
8 #include <QDateTime>
9 #include <QThread>
9 #include <QThread>
10
10
11 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
11 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
12
12
13 std::shared_ptr<IDataSeries>
13 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(const SqpDateTime &dateTime) const
14 CosinusProvider::retrieveData(const DataProviderParameters &parameters) const
15 {
14 {
16 auto dateTime = parameters.m_Time;
17
18 auto dataIndex = 0;
15 auto dataIndex = 0;
19
16
20 // Gets the timerange from the parameters
17 // Gets the timerange from the parameters
21 double freq = 100.0;
18 double freq = 100.0;
22 double start = dateTime.m_TStart * freq; // 100 htz
19 double start = dateTime.m_TStart * freq; // 100 htz
23 double end = dateTime.m_TEnd * freq; // 100 htz
20 double end = dateTime.m_TEnd * freq; // 100 htz
24
21
25 // We assure that timerange is valid
22 // We assure that timerange is valid
26 if (end < start) {
23 if (end < start) {
27 std::swap(start, end);
24 std::swap(start, end);
28 }
25 }
29
26
30 // Generates scalar series containing cosinus values (one value per second)
27 // Generates scalar series containing cosinus values (one value per second)
31 auto scalarSeries
28 auto scalarSeries
32 = std::make_shared<ScalarSeries>(end - start, Unit{QStringLiteral("t"), true}, Unit{});
29 = std::make_shared<ScalarSeries>(end - start, Unit{QStringLiteral("t"), true}, Unit{});
33
30
34 for (auto time = start; time < end; ++time, ++dataIndex) {
31 for (auto time = start; time < end; ++time, ++dataIndex) {
35 const auto timeOnFreq = time / freq;
32 const auto timeOnFreq = time / freq;
36 scalarSeries->setData(dataIndex, timeOnFreq, std::cos(timeOnFreq));
33 scalarSeries->setData(dataIndex, timeOnFreq, std::cos(timeOnFreq));
37 }
34 }
38 return scalarSeries;
35 return scalarSeries;
39 }
36 }
40
37
41 void CosinusProvider::requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList)
38 void CosinusProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
42 {
39 {
43 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataLoading"
40 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataLoading"
44 << QThread::currentThread()->objectName();
41 << QThread::currentThread()->objectName();
45 // NOTE: Try to use multithread if possible
42 // NOTE: Try to use multithread if possible
46 for (const auto &dateTime : dateTimeList) {
43 const auto times = parameters.m_Times;
47 auto scalarSeries = this->retrieveData(DataProviderParameters{dateTime});
44 for (const auto &dateTime : qAsConst(times)) {
45 auto scalarSeries = this->retrieveData(dateTime);
48 emit dataProvided(token, scalarSeries, dateTime);
46 emit dataProvided(token, scalarSeries, dateTime);
49 }
47 }
50 }
48 }
General Comments 0
You need to be logged in to leave comments. Login now