##// END OF EJS Templates
Some WIP refactoring, trying to remove TimeController object...
jeandet -
r1345:ce477e992869
parent child
Show More
@@ -1,48 +1,48
1 #ifndef SCIQLOP_TIMECONTROLLER_H
1 #ifndef SCIQLOP_TIMECONTROLLER_H
2 #define SCIQLOP_TIMECONTROLLER_H
2 #define SCIQLOP_TIMECONTROLLER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QObject>
9 #include <QObject>
10
10
11 #include <Common/spimpl.h>
11 #include <Common/spimpl.h>
12
12
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_TimeController)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_TimeController)
15
15
16 /**
16 /**
17 * @brief The TimeController class aims to handle the Time parameters notification in SciQlop.
17 * @brief The TimeController class aims to handle the Time parameters notification in SciQlop.
18 */
18 */
19 class SCIQLOP_CORE_EXPORT TimeController : public QObject {
19 class SCIQLOP_CORE_EXPORT TimeController : public QObject {
20 Q_OBJECT
20 Q_OBJECT
21 public:
21 public:
22 explicit TimeController(QObject *parent = 0);
22 explicit TimeController(QObject *parent = 0);
23
23
24 SqpRange dateTime() const noexcept;
24 SqpRange dateTime() const noexcept;
25
25
26 /// Returns the MIME data associated to a time range
26 /// Returns the MIME data associated to a time range
27 static QByteArray mimeDataForTimeRange(const SqpRange &timeRange);
27 static QByteArray mimeDataForTimeRange(const SqpRange &timeRange);
28
28
29 /// Returns the time range contained in a MIME data
29 /// Returns the time range contained in a MIME data
30 static SqpRange timeRangeForMimeData(const QByteArray &mimeData);
30 static SqpRange timeRangeForMimeData(const QByteArray &mimeData);
31
31
32 signals:
32 signals:
33 /// Signal emitted to notify that time parameters has beed updated
33 /// Signal emitted to notify that time parameters has beed updated
34 void timeUpdated(SqpRange time);
34 void timeUpdated(SqpRange time);
35
35
36 public slots:
36 public slots:
37 /// Slot called when a new dateTime has been defined.
37 /// Slot called when a new dateTime has been defined.
38 void onTimeToUpdate(SqpRange dateTime);
38 void setDateTimeRange(SqpRange dateTime);
39
39
40 /// Slot called when the dateTime has to be notified. Call timeUpdated signal
40 /// Slot called when the dateTime has to be notified. Call timeUpdated signal
41 void onTimeNotify();
41 void onTimeNotify();
42
42
43 private:
43 private:
44 class TimeControllerPrivate;
44 class TimeControllerPrivate;
45 spimpl::unique_impl_ptr<TimeControllerPrivate> impl;
45 spimpl::unique_impl_ptr<TimeControllerPrivate> impl;
46 };
46 };
47
47
48 #endif // SCIQLOP_TIMECONTROLLER_H
48 #endif // SCIQLOP_TIMECONTROLLER_H
@@ -1,148 +1,147
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/AcquisitionDataPacket.h>
6 #include <Data/AcquisitionDataPacket.h>
7 #include <Data/SqpRange.h>
7 #include <Data/SqpRange.h>
8
8
9 #include <QLoggingCategory>
9 #include <QLoggingCategory>
10 #include <QObject>
10 #include <QObject>
11 #include <QUuid>
11 #include <QUuid>
12
12
13 #include <Common/spimpl.h>
13 #include <Common/spimpl.h>
14
14
15 class IDataProvider;
15 class IDataProvider;
16 class QItemSelectionModel;
16 class QItemSelectionModel;
17 class TimeController;
17 class TimeController;
18 class Variable;
18 class Variable;
19 class VariableModel;
19 class VariableModel;
20
20
21 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
21 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
22
22
23
23
24 /**
24 /**
25 * Possible types of zoom operation
25 * Possible types of zoom operation
26 */
26 */
27 enum class AcquisitionZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
27 enum class AcquisitionZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
28
28
29
29
30 /**
30 /**
31 * @brief The VariableController class aims to handle the variables in SciQlop.
31 * @brief The VariableController class aims to handle the variables in SciQlop.
32 */
32 */
33 class SCIQLOP_CORE_EXPORT VariableController : public QObject {
33 class SCIQLOP_CORE_EXPORT VariableController : public QObject {
34 Q_OBJECT
34 Q_OBJECT
35 public:
35 public:
36 explicit VariableController(QObject *parent = 0);
36 explicit VariableController(QObject *parent = 0);
37 virtual ~VariableController();
37 virtual ~VariableController();
38
38
39 VariableModel *variableModel() noexcept;
39 VariableModel *variableModel() noexcept;
40 QItemSelectionModel *variableSelectionModel() noexcept;
40 QItemSelectionModel *variableSelectionModel() noexcept;
41
41
42 void setTimeController(TimeController *timeController) noexcept;
43
42
44 /**
43 /**
45 * Clones the variable passed in parameter and adds the duplicate to the controller
44 * Clones the variable passed in parameter and adds the duplicate to the controller
46 * @param variable the variable to duplicate
45 * @param variable the variable to duplicate
47 * @return the duplicate created, nullptr if the variable couldn't be created
46 * @return the duplicate created, nullptr if the variable couldn't be created
48 */
47 */
49 std::shared_ptr<Variable> cloneVariable(std::shared_ptr<Variable> variable) noexcept;
48 std::shared_ptr<Variable> cloneVariable(std::shared_ptr<Variable> variable) noexcept;
50
49
51 /// Returns the MIME data associated to a list of variables
50 /// Returns the MIME data associated to a list of variables
52 QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const;
51 QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const;
53
52
54 /// Returns the list of variables contained in a MIME data
53 /// Returns the list of variables contained in a MIME data
55 QList<std::shared_ptr<Variable> > variablesForMimeData(const QByteArray &mimeData) const;
54 QList<std::shared_ptr<Variable> > variablesForMimeData(const QByteArray &mimeData) const;
56
55
57 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
56 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
58
57
59 /// Returns True if there are pending downloads
58 /// Returns True if there are pending downloads
60 bool hasPendingDownloads();
59 bool hasPendingDownloads();
61 signals:
60 signals:
62 /// Signal emitted when a variable is about to be deleted from the controller
61 /// Signal emitted when a variable is about to be deleted from the controller
63 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
62 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
64
63
65 /// Signal emitted when a data acquisition is requested on a range for a variable
64 /// Signal emitted when a data acquisition is requested on a range for a variable
66 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
65 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
67
66
68 /// Signal emitted when a sub range of the cacheRange of the variable can be displayed
67 /// Signal emitted when a sub range of the cacheRange of the variable can be displayed
69 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
68 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
70
69
71 /// Signal emitted when all acquisitions related to the variables have been completed (whether
70 /// Signal emitted when all acquisitions related to the variables have been completed (whether
72 /// validated, canceled, or failed)
71 /// validated, canceled, or failed)
73 void acquisitionFinished();
72 void acquisitionFinished();
74
73
75 void variableAdded(const std::shared_ptr<Variable> &variable);
74 void variableAdded(const std::shared_ptr<Variable> &variable);
76
75
77 public slots:
76 public slots:
78 /**
77 /**
79 * Deletes from the controller the variable passed in parameter.
78 * Deletes from the controller the variable passed in parameter.
80 *
79 *
81 * Delete a variable includes:
80 * Delete a variable includes:
82 * - the deletion of the various references to the variable in SciQlop
81 * - the deletion of the various references to the variable in SciQlop
83 * - the deletion of the model variable
82 * - the deletion of the model variable
84 * - the deletion of the provider associated with the variable
83 * - the deletion of the provider associated with the variable
85 * - removing the cache associated with the variable
84 * - removing the cache associated with the variable
86 *
85 *
87 * @param variable the variable to delete from the controller.
86 * @param variable the variable to delete from the controller.
88 */
87 */
89 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
88 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
90
89
91 /**
90 /**
92 * Deletes from the controller the variables passed in parameter.
91 * Deletes from the controller the variables passed in parameter.
93 * @param variables the variables to delete from the controller.
92 * @param variables the variables to delete from the controller.
94 * @sa deleteVariable()
93 * @sa deleteVariable()
95 */
94 */
96 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
95 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
97
96
98 /// Request the data loading of the variable whithin range
97 /// Request the data loading of the variable whithin range
99 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
98 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
100 bool synchronise);
99 bool synchronise);
101 /**
100 /**
102 * Creates a new variable and adds it to the model
101 * Creates a new variable and adds it to the model
103 * @param name the name of the new variable
102 * @param name the name of the new variable
104 * @param metadata the metadata of the new variable
103 * @param metadata the metadata of the new variable
105 * @param provider the data provider for the new variable
104 * @param provider the data provider for the new variable
106 * @return the pointer to the new variable or nullptr if the creation failed
105 * @return the pointer to the new variable or nullptr if the creation failed
107 */
106 */
108 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
107 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
109 std::shared_ptr<IDataProvider> provider) noexcept;
108 std::shared_ptr<IDataProvider> provider, const SqpRange &range) noexcept;
110
109
111 /// Update the temporal parameters of every selected variable to dateTime
110 /// Update the temporal parameters of every selected variable to dateTime
112 void onDateTimeOnSelection(const SqpRange &dateTime);
111 void onDateTimeOnSelection(const SqpRange &dateTime);
113
112
114 /// Update the temporal parameters of the specified variable
113 /// Update the temporal parameters of the specified variable
115 void onUpdateDateTime(std::shared_ptr<Variable> variable, const SqpRange &dateTime);
114 void onUpdateDateTime(std::shared_ptr<Variable> variable, const SqpRange &dateTime);
116
115
117
116
118 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
117 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
119 const SqpRange &cacheRangeRequested,
118 const SqpRange &cacheRangeRequested,
120 QVector<AcquisitionDataPacket> dataAcquired);
119 QVector<AcquisitionDataPacket> dataAcquired);
121
120
122 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
121 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
123
122
124 /// Cancel the current request for the variable
123 /// Cancel the current request for the variable
125 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
124 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
126 void onAbortAcquisitionRequested(QUuid vIdentifier);
125 void onAbortAcquisitionRequested(QUuid vIdentifier);
127
126
128 // synchronization group methods
127 // synchronization group methods
129 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
128 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
130 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
129 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
131 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
130 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
132
131
133 /// Desynchronizes the variable of the group whose identifier is passed in parameter
132 /// Desynchronizes the variable of the group whose identifier is passed in parameter
134 /// @remarks the method does nothing if the variable is not part of the group
133 /// @remarks the method does nothing if the variable is not part of the group
135 void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
134 void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
136
135
137 void initialize();
136 void initialize();
138 void finalize();
137 void finalize();
139
138
140 private:
139 private:
141 void waitForFinish();
140 void waitForFinish();
142
141
143 class VariableControllerPrivate;
142 class VariableControllerPrivate;
144 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
143 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
145 };
144 };
146
145
147
146
148 #endif // SCIQLOP_VARIABLECONTROLLER_H
147 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,51 +1,51
1 #include "Time/TimeController.h"
1 #include "Time/TimeController.h"
2
2
3 #include <QDataStream>
3 #include <QDataStream>
4
4
5 Q_LOGGING_CATEGORY(LOG_TimeController, "TimeController")
5 Q_LOGGING_CATEGORY(LOG_TimeController, "TimeController")
6
6
7 struct TimeController::TimeControllerPrivate {
7 struct TimeController::TimeControllerPrivate {
8
8
9 SqpRange m_DateTime;
9 SqpRange m_DateTime;
10 };
10 };
11
11
12 TimeController::TimeController(QObject *parent)
12 TimeController::TimeController(QObject *parent)
13 : QObject{parent}, impl{spimpl::make_unique_impl<TimeControllerPrivate>()}
13 : QObject{parent}, impl{spimpl::make_unique_impl<TimeControllerPrivate>()}
14 {
14 {
15 qCDebug(LOG_TimeController()) << tr("TimeController construction");
15 qCDebug(LOG_TimeController()) << tr("TimeController construction");
16 }
16 }
17
17
18 SqpRange TimeController::dateTime() const noexcept
18 SqpRange TimeController::dateTime() const noexcept
19 {
19 {
20 return impl->m_DateTime;
20 return impl->m_DateTime;
21 }
21 }
22
22
23 QByteArray TimeController::mimeDataForTimeRange(const SqpRange &timeRange)
23 QByteArray TimeController::mimeDataForTimeRange(const SqpRange &timeRange)
24 {
24 {
25 QByteArray encodedData;
25 QByteArray encodedData;
26 QDataStream stream{&encodedData, QIODevice::WriteOnly};
26 QDataStream stream{&encodedData, QIODevice::WriteOnly};
27
27
28 stream << timeRange.m_TStart << timeRange.m_TEnd;
28 stream << timeRange.m_TStart << timeRange.m_TEnd;
29
29
30 return encodedData;
30 return encodedData;
31 }
31 }
32
32
33 SqpRange TimeController::timeRangeForMimeData(const QByteArray &mimeData)
33 SqpRange TimeController::timeRangeForMimeData(const QByteArray &mimeData)
34 {
34 {
35 QDataStream stream{mimeData};
35 QDataStream stream{mimeData};
36
36
37 SqpRange timeRange;
37 SqpRange timeRange;
38 stream >> timeRange.m_TStart >> timeRange.m_TEnd;
38 stream >> timeRange.m_TStart >> timeRange.m_TEnd;
39
39
40 return timeRange;
40 return timeRange;
41 }
41 }
42
42
43 void TimeController::onTimeToUpdate(SqpRange dateTime)
43 void TimeController::setDateTimeRange(SqpRange dateTime)
44 {
44 {
45 impl->m_DateTime = dateTime;
45 impl->m_DateTime = dateTime;
46 }
46 }
47
47
48 void TimeController::onTimeNotify()
48 void TimeController::onTimeNotify()
49 {
49 {
50 emit timeUpdated(impl->m_DateTime);
50 emit timeUpdated(impl->m_DateTime);
51 }
51 }
@@ -1,1114 +1,1108
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableAcquisitionWorker.h>
2 #include <Variable/VariableAcquisitionWorker.h>
3 #include <Variable/VariableCacheStrategy.h>
3 #include <Variable/VariableCacheStrategy.h>
4 #include <Variable/VariableCacheStrategyFactory.h>
4 #include <Variable/VariableCacheStrategyFactory.h>
5 #include <Variable/VariableController.h>
5 #include <Variable/VariableController.h>
6 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
7 #include <Variable/VariableSynchronizationGroup.h>
7 #include <Variable/VariableSynchronizationGroup.h>
8
8
9 #include <Data/DataProviderParameters.h>
9 #include <Data/DataProviderParameters.h>
10 #include <Data/IDataProvider.h>
10 #include <Data/IDataProvider.h>
11 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
12 #include <Data/VariableRequest.h>
12 #include <Data/VariableRequest.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14
14
15 #include <QDataStream>
15 #include <QDataStream>
16 #include <QMutex>
16 #include <QMutex>
17 #include <QThread>
17 #include <QThread>
18 #include <QUuid>
18 #include <QUuid>
19 #include <QtCore/QItemSelectionModel>
19 #include <QtCore/QItemSelectionModel>
20
20
21 #include <deque>
21 #include <deque>
22 #include <set>
22 #include <set>
23 #include <unordered_map>
23 #include <unordered_map>
24
24
25 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
25 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
26
26
27 namespace {
27 namespace {
28
28
29 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
29 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
30 const SqpRange &oldGraphRange)
30 const SqpRange &oldGraphRange)
31 {
31 {
32 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
32 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
33
33
34 auto varRangeRequested = varRange;
34 auto varRangeRequested = varRange;
35 switch (zoomType) {
35 switch (zoomType) {
36 case AcquisitionZoomType::ZoomIn: {
36 case AcquisitionZoomType::ZoomIn: {
37 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
37 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
38 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
38 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
39 varRangeRequested.m_TStart += deltaLeft;
39 varRangeRequested.m_TStart += deltaLeft;
40 varRangeRequested.m_TEnd -= deltaRight;
40 varRangeRequested.m_TEnd -= deltaRight;
41 break;
41 break;
42 }
42 }
43
43
44 case AcquisitionZoomType::ZoomOut: {
44 case AcquisitionZoomType::ZoomOut: {
45 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
45 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
46 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
46 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
47 varRangeRequested.m_TStart -= deltaLeft;
47 varRangeRequested.m_TStart -= deltaLeft;
48 varRangeRequested.m_TEnd += deltaRight;
48 varRangeRequested.m_TEnd += deltaRight;
49 break;
49 break;
50 }
50 }
51 case AcquisitionZoomType::PanRight: {
51 case AcquisitionZoomType::PanRight: {
52 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
52 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
53 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
53 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
54 varRangeRequested.m_TStart += deltaLeft;
54 varRangeRequested.m_TStart += deltaLeft;
55 varRangeRequested.m_TEnd += deltaRight;
55 varRangeRequested.m_TEnd += deltaRight;
56 break;
56 break;
57 }
57 }
58 case AcquisitionZoomType::PanLeft: {
58 case AcquisitionZoomType::PanLeft: {
59 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
59 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
60 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
60 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
61 varRangeRequested.m_TStart -= deltaLeft;
61 varRangeRequested.m_TStart -= deltaLeft;
62 varRangeRequested.m_TEnd -= deltaRight;
62 varRangeRequested.m_TEnd -= deltaRight;
63 break;
63 break;
64 }
64 }
65 case AcquisitionZoomType::Unknown: {
65 case AcquisitionZoomType::Unknown: {
66 qCCritical(LOG_VariableController())
66 qCCritical(LOG_VariableController())
67 << VariableController::tr("Impossible to synchronize: zoom type unknown");
67 << VariableController::tr("Impossible to synchronize: zoom type unknown");
68 break;
68 break;
69 }
69 }
70 default:
70 default:
71 qCCritical(LOG_VariableController()) << VariableController::tr(
71 qCCritical(LOG_VariableController()) << VariableController::tr(
72 "Impossible to synchronize: zoom type not take into account");
72 "Impossible to synchronize: zoom type not take into account");
73 // No action
73 // No action
74 break;
74 break;
75 }
75 }
76
76
77 return varRangeRequested;
77 return varRangeRequested;
78 }
78 }
79 }
79 }
80
80
81 enum class VariableRequestHandlerState { OFF, RUNNING, PENDING };
81 enum class VariableRequestHandlerState { OFF, RUNNING, PENDING };
82
82
83 struct VariableRequestHandler {
83 struct VariableRequestHandler {
84
84
85 VariableRequestHandler()
85 VariableRequestHandler()
86 {
86 {
87 m_CanUpdate = false;
87 m_CanUpdate = false;
88 m_State = VariableRequestHandlerState::OFF;
88 m_State = VariableRequestHandlerState::OFF;
89 }
89 }
90
90
91 QUuid m_VarId;
91 QUuid m_VarId;
92 VariableRequest m_RunningVarRequest;
92 VariableRequest m_RunningVarRequest;
93 VariableRequest m_PendingVarRequest;
93 VariableRequest m_PendingVarRequest;
94 VariableRequestHandlerState m_State;
94 VariableRequestHandlerState m_State;
95 bool m_CanUpdate;
95 bool m_CanUpdate;
96 };
96 };
97
97
98 struct VariableController::VariableControllerPrivate {
98 struct VariableController::VariableControllerPrivate {
99 explicit VariableControllerPrivate(VariableController *parent)
99 explicit VariableControllerPrivate(VariableController *parent)
100 : m_WorkingMutex{},
100 : m_WorkingMutex{},
101 m_VariableModel{new VariableModel{parent}},
101 m_VariableModel{new VariableModel{parent}},
102 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
102 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
103 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
103 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
104 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
104 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
105 CacheStrategy::SingleThreshold)},
105 CacheStrategy::SingleThreshold)},
106 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
106 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
107 q{parent}
107 q{parent}
108 {
108 {
109
109
110 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
110 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
111 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
111 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
112 }
112 }
113
113
114
114
115 virtual ~VariableControllerPrivate()
115 virtual ~VariableControllerPrivate()
116 {
116 {
117 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
117 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
118 m_VariableAcquisitionWorkerThread.quit();
118 m_VariableAcquisitionWorkerThread.quit();
119 m_VariableAcquisitionWorkerThread.wait();
119 m_VariableAcquisitionWorkerThread.wait();
120 }
120 }
121
121
122
122
123 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
123 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
124 QUuid varRequestId);
124 QUuid varRequestId);
125
125
126 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
126 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
127 std::shared_ptr<IDataSeries>
127 std::shared_ptr<IDataSeries>
128 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
128 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
129
129
130 void registerProvider(std::shared_ptr<IDataProvider> provider);
130 void registerProvider(std::shared_ptr<IDataProvider> provider);
131
131
132 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
132 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
133 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
133 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
134 void updateVariables(QUuid varRequestId);
134 void updateVariables(QUuid varRequestId);
135 void updateVariableRequest(QUuid varRequestId);
135 void updateVariableRequest(QUuid varRequestId);
136 void cancelVariableRequest(QUuid varRequestId);
136 void cancelVariableRequest(QUuid varRequestId);
137 void executeVarRequest(std::shared_ptr<Variable> var, VariableRequest &varRequest);
137 void executeVarRequest(std::shared_ptr<Variable> var, VariableRequest &varRequest);
138 bool hasPendingDownloads();
138 bool hasPendingDownloads();
139 template <typename VariableIterator>
139 template <typename VariableIterator>
140 void desynchronize(VariableIterator variableIt, const QUuid &syncGroupId);
140 void desynchronize(VariableIterator variableIt, const QUuid &syncGroupId);
141
141
142 QMutex m_WorkingMutex;
142 QMutex m_WorkingMutex;
143 /// Variable model. The VariableController has the ownership
143 /// Variable model. The VariableController has the ownership
144 VariableModel *m_VariableModel;
144 VariableModel *m_VariableModel;
145 QItemSelectionModel *m_VariableSelectionModel;
145 QItemSelectionModel *m_VariableSelectionModel;
146
146
147
147
148 TimeController *m_TimeController{nullptr};
149 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
148 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
150 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
149 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
151 QThread m_VariableAcquisitionWorkerThread;
150 QThread m_VariableAcquisitionWorkerThread;
152
151
153 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
152 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
154 m_VariableToProviderMap;
153 m_VariableToProviderMap;
155 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
154 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
156 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
155 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
157 m_GroupIdToVariableSynchronizationGroupMap;
156 m_GroupIdToVariableSynchronizationGroupMap;
158 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
157 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
159 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
158 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
160
159
161 std::map<QUuid, std::list<QUuid> > m_VarGroupIdToVarIds;
160 std::map<QUuid, std::list<QUuid> > m_VarGroupIdToVarIds;
162 std::map<QUuid, std::unique_ptr<VariableRequestHandler> > m_VarIdToVarRequestHandler;
161 std::map<QUuid, std::unique_ptr<VariableRequestHandler> > m_VarIdToVarRequestHandler;
163
162
164 VariableController *q;
163 VariableController *q;
165 };
164 };
166
165
167
166
168 VariableController::VariableController(QObject *parent)
167 VariableController::VariableController(QObject *parent)
169 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
168 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
170 {
169 {
171 qCDebug(LOG_VariableController()) << tr("VariableController construction")
170 qCDebug(LOG_VariableController()) << tr("VariableController construction")
172 << QThread::currentThread();
171 << QThread::currentThread();
173
172
174 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
173 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
175 &VariableController::onAbortProgressRequested);
174 &VariableController::onAbortProgressRequested);
176
175
177 connect(impl->m_VariableAcquisitionWorker.get(),
176 connect(impl->m_VariableAcquisitionWorker.get(),
178 &VariableAcquisitionWorker::variableCanceledRequested, this,
177 &VariableAcquisitionWorker::variableCanceledRequested, this,
179 &VariableController::onAbortAcquisitionRequested);
178 &VariableController::onAbortAcquisitionRequested);
180
179
181 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
180 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
182 &VariableController::onDataProvided);
181 &VariableController::onDataProvided);
183 connect(impl->m_VariableAcquisitionWorker.get(),
182 connect(impl->m_VariableAcquisitionWorker.get(),
184 &VariableAcquisitionWorker::variableRequestInProgress, this,
183 &VariableAcquisitionWorker::variableRequestInProgress, this,
185 &VariableController::onVariableRetrieveDataInProgress);
184 &VariableController::onVariableRetrieveDataInProgress);
186
185
187
186
188 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
187 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
189 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
188 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
190 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
189 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
191 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
190 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
192
191
193 connect(impl->m_VariableModel, &VariableModel::requestVariableRangeUpdate, this,
192 connect(impl->m_VariableModel, &VariableModel::requestVariableRangeUpdate, this,
194 &VariableController::onUpdateDateTime);
193 &VariableController::onUpdateDateTime);
195
194
196 impl->m_VariableAcquisitionWorkerThread.start();
195 impl->m_VariableAcquisitionWorkerThread.start();
197 }
196 }
198
197
199 VariableController::~VariableController()
198 VariableController::~VariableController()
200 {
199 {
201 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
200 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
202 << QThread::currentThread();
201 << QThread::currentThread();
203 this->waitForFinish();
202 this->waitForFinish();
204 }
203 }
205
204
206 VariableModel *VariableController::variableModel() noexcept
205 VariableModel *VariableController::variableModel() noexcept
207 {
206 {
208 return impl->m_VariableModel;
207 return impl->m_VariableModel;
209 }
208 }
210
209
211 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
210 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
212 {
211 {
213 return impl->m_VariableSelectionModel;
212 return impl->m_VariableSelectionModel;
214 }
213 }
215
214
216 void VariableController::setTimeController(TimeController *timeController) noexcept
217 {
218 impl->m_TimeController = timeController;
219 }
220
221 std::shared_ptr<Variable>
215 std::shared_ptr<Variable>
222 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
216 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
223 {
217 {
224 if (impl->m_VariableModel->containsVariable(variable)) {
218 if (impl->m_VariableModel->containsVariable(variable)) {
225 // Clones variable
219 // Clones variable
226 auto duplicate = variable->clone();
220 auto duplicate = variable->clone();
227
221
228 // Adds clone to model
222 // Adds clone to model
229 impl->m_VariableModel->addVariable(duplicate);
223 impl->m_VariableModel->addVariable(duplicate);
230
224
231 // Generates clone identifier
225 // Generates clone identifier
232 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
226 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
233
227
234 // Registers provider
228 // Registers provider
235 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
229 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
236 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
230 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
237
231
238 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
232 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
239 if (duplicateProvider) {
233 if (duplicateProvider) {
240 impl->registerProvider(duplicateProvider);
234 impl->registerProvider(duplicateProvider);
241 }
235 }
242
236
243 return duplicate;
237 return duplicate;
244 }
238 }
245 else {
239 else {
246 qCCritical(LOG_VariableController())
240 qCCritical(LOG_VariableController())
247 << tr("Can't create duplicate of variable %1: variable not registered in the model")
241 << tr("Can't create duplicate of variable %1: variable not registered in the model")
248 .arg(variable->name());
242 .arg(variable->name());
249 return nullptr;
243 return nullptr;
250 }
244 }
251 }
245 }
252
246
253 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
247 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
254 {
248 {
255 if (!variable) {
249 if (!variable) {
256 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
250 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
257 return;
251 return;
258 }
252 }
259
253
260 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
254 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
261 // make some treatments before the deletion
255 // make some treatments before the deletion
262 emit variableAboutToBeDeleted(variable);
256 emit variableAboutToBeDeleted(variable);
263
257
264 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
258 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
265 Q_ASSERT(variableIt != impl->m_VariableToIdentifierMap.cend());
259 Q_ASSERT(variableIt != impl->m_VariableToIdentifierMap.cend());
266
260
267 auto variableId = variableIt->second;
261 auto variableId = variableIt->second;
268
262
269 // Removes variable's handler
263 // Removes variable's handler
270 impl->m_VarIdToVarRequestHandler.erase(variableId);
264 impl->m_VarIdToVarRequestHandler.erase(variableId);
271
265
272 // Desynchronizes variable (if the variable is in a sync group)
266 // Desynchronizes variable (if the variable is in a sync group)
273 auto syncGroupIt = impl->m_VariableIdGroupIdMap.find(variableId);
267 auto syncGroupIt = impl->m_VariableIdGroupIdMap.find(variableId);
274 if (syncGroupIt != impl->m_VariableIdGroupIdMap.cend()) {
268 if (syncGroupIt != impl->m_VariableIdGroupIdMap.cend()) {
275 impl->desynchronize(variableIt, syncGroupIt->second);
269 impl->desynchronize(variableIt, syncGroupIt->second);
276 }
270 }
277
271
278 // Deletes identifier
272 // Deletes identifier
279 impl->m_VariableToIdentifierMap.erase(variableIt);
273 impl->m_VariableToIdentifierMap.erase(variableIt);
280
274
281 // Deletes provider
275 // Deletes provider
282 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
276 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
283 qCDebug(LOG_VariableController())
277 qCDebug(LOG_VariableController())
284 << tr("Number of providers deleted for variable %1: %2")
278 << tr("Number of providers deleted for variable %1: %2")
285 .arg(variable->name(), QString::number(nbProvidersDeleted));
279 .arg(variable->name(), QString::number(nbProvidersDeleted));
286
280
287
281
288 // Deletes from model
282 // Deletes from model
289 impl->m_VariableModel->deleteVariable(variable);
283 impl->m_VariableModel->deleteVariable(variable);
290 }
284 }
291
285
292 void VariableController::deleteVariables(
286 void VariableController::deleteVariables(
293 const QVector<std::shared_ptr<Variable> > &variables) noexcept
287 const QVector<std::shared_ptr<Variable> > &variables) noexcept
294 {
288 {
295 for (auto variable : qAsConst(variables)) {
289 for (auto variable : qAsConst(variables)) {
296 deleteVariable(variable);
290 deleteVariable(variable);
297 }
291 }
298 }
292 }
299
293
300 QByteArray
294 QByteArray
301 VariableController::mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const
295 VariableController::mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const
302 {
296 {
303 auto encodedData = QByteArray{};
297 auto encodedData = QByteArray{};
304
298
305 QVariantList ids;
299 QVariantList ids;
306 for (auto &var : variables) {
300 for (auto &var : variables) {
307 auto itVar = impl->m_VariableToIdentifierMap.find(var);
301 auto itVar = impl->m_VariableToIdentifierMap.find(var);
308 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
302 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
309 qCCritical(LOG_VariableController())
303 qCCritical(LOG_VariableController())
310 << tr("Impossible to find the data for an unknown variable.");
304 << tr("Impossible to find the data for an unknown variable.");
311 }
305 }
312
306
313 ids << itVar->second.toByteArray();
307 ids << itVar->second.toByteArray();
314 }
308 }
315
309
316 QDataStream stream{&encodedData, QIODevice::WriteOnly};
310 QDataStream stream{&encodedData, QIODevice::WriteOnly};
317 stream << ids;
311 stream << ids;
318
312
319 return encodedData;
313 return encodedData;
320 }
314 }
321
315
322 QList<std::shared_ptr<Variable> >
316 QList<std::shared_ptr<Variable> >
323 VariableController::variablesForMimeData(const QByteArray &mimeData) const
317 VariableController::variablesForMimeData(const QByteArray &mimeData) const
324 {
318 {
325 auto variables = QList<std::shared_ptr<Variable> >{};
319 auto variables = QList<std::shared_ptr<Variable> >{};
326 QDataStream stream{mimeData};
320 QDataStream stream{mimeData};
327
321
328 QVariantList ids;
322 QVariantList ids;
329 stream >> ids;
323 stream >> ids;
330
324
331 for (auto id : ids) {
325 for (auto id : ids) {
332 auto uuid = QUuid{id.toByteArray()};
326 auto uuid = QUuid{id.toByteArray()};
333 auto var = impl->findVariable(uuid);
327 auto var = impl->findVariable(uuid);
334 variables << var;
328 variables << var;
335 }
329 }
336
330
337 return variables;
331 return variables;
338 }
332 }
339
333
340 std::shared_ptr<Variable>
334 std::shared_ptr<Variable>
341 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
335 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
342 std::shared_ptr<IDataProvider> provider) noexcept
336 std::shared_ptr<IDataProvider> provider, const SqpRange& range) noexcept
343 {
337 {
344 if (!impl->m_TimeController) {
338 // if (!impl->m_TimeController) {
345 qCCritical(LOG_VariableController())
339 // qCCritical(LOG_VariableController())
346 << tr("Impossible to create variable: The time controller is null");
340 // << tr("Impossible to create variable: The time controller is null");
347 return nullptr;
341 // return nullptr;
348 }
342 // }
349
343
350 auto range = impl->m_TimeController->dateTime();
344 // auto range = impl->m_TimeController->dateTime();
351
345
352 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
346 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
353 auto varId = QUuid::createUuid();
347 auto varId = QUuid::createUuid();
354
348
355 // Create the handler
349 // Create the handler
356 auto varRequestHandler = std::make_unique<VariableRequestHandler>();
350 auto varRequestHandler = std::make_unique<VariableRequestHandler>();
357 varRequestHandler->m_VarId = varId;
351 varRequestHandler->m_VarId = varId;
358
352
359 impl->m_VarIdToVarRequestHandler.insert(
353 impl->m_VarIdToVarRequestHandler.insert(
360 std::make_pair(varId, std::move(varRequestHandler)));
354 std::make_pair(varId, std::move(varRequestHandler)));
361
355
362 // store the provider
356 // store the provider
363 impl->registerProvider(provider);
357 impl->registerProvider(provider);
364
358
365 // Associate the provider
359 // Associate the provider
366 impl->m_VariableToProviderMap[newVariable] = provider;
360 impl->m_VariableToProviderMap[newVariable] = provider;
367 impl->m_VariableToIdentifierMap[newVariable] = varId;
361 impl->m_VariableToIdentifierMap[newVariable] = varId;
368
362
369 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{newVariable}, range, false);
363 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{newVariable}, range, false);
370
364
371 // auto varRequestId = QUuid::createUuid();
365 // auto varRequestId = QUuid::createUuid();
372 // qCInfo(LOG_VariableController()) << "createVariable: " << varId << varRequestId;
366 // qCInfo(LOG_VariableController()) << "createVariable: " << varId << varRequestId;
373 // impl->processRequest(newVariable, range, varRequestId);
367 // impl->processRequest(newVariable, range, varRequestId);
374 // impl->updateVariableRequest(varRequestId);
368 // impl->updateVariableRequest(varRequestId);
375
369
376 emit variableAdded(newVariable);
370 emit variableAdded(newVariable);
377
371
378 return newVariable;
372 return newVariable;
379 }
373 }
380
374
381 qCCritical(LOG_VariableController()) << tr("Impossible to create variable");
375 qCCritical(LOG_VariableController()) << tr("Impossible to create variable");
382 return nullptr;
376 return nullptr;
383 }
377 }
384
378
385 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
379 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
386 {
380 {
387 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
381 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
388 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
382 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
389 << QThread::currentThread()->objectName();
383 << QThread::currentThread()->objectName();
390 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
384 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
391
385
392 // NOTE we only permit the time modification for one variable
386 // NOTE we only permit the time modification for one variable
393 // DEPRECATED
387 // DEPRECATED
394 // auto variables = QVector<std::shared_ptr<Variable> >{};
388 // auto variables = QVector<std::shared_ptr<Variable> >{};
395 // for (const auto &selectedRow : qAsConst(selectedRows)) {
389 // for (const auto &selectedRow : qAsConst(selectedRows)) {
396 // if (auto selectedVariable =
390 // if (auto selectedVariable =
397 // impl->m_VariableModel->variable(selectedRow.row())) {
391 // impl->m_VariableModel->variable(selectedRow.row())) {
398 // variables << selectedVariable;
392 // variables << selectedVariable;
399
393
400 // // notify that rescale operation has to be done
394 // // notify that rescale operation has to be done
401 // emit rangeChanged(selectedVariable, dateTime);
395 // emit rangeChanged(selectedVariable, dateTime);
402 // }
396 // }
403 // }
397 // }
404 // if (!variables.isEmpty()) {
398 // if (!variables.isEmpty()) {
405 // this->onRequestDataLoading(variables, dateTime, synchro);
399 // this->onRequestDataLoading(variables, dateTime, synchro);
406 // }
400 // }
407 if (selectedRows.size() == 1) {
401 if (selectedRows.size() == 1) {
408
402
409 if (auto selectedVariable
403 if (auto selectedVariable
410 = impl->m_VariableModel->variable(qAsConst(selectedRows).first().row())) {
404 = impl->m_VariableModel->variable(qAsConst(selectedRows).first().row())) {
411
405
412 onUpdateDateTime(selectedVariable, dateTime);
406 onUpdateDateTime(selectedVariable, dateTime);
413 }
407 }
414 }
408 }
415 else if (selectedRows.size() > 1) {
409 else if (selectedRows.size() > 1) {
416 qCCritical(LOG_VariableController())
410 qCCritical(LOG_VariableController())
417 << tr("Impossible to set time for more than 1 variable in the same time");
411 << tr("Impossible to set time for more than 1 variable in the same time");
418 }
412 }
419 else {
413 else {
420 qCWarning(LOG_VariableController())
414 qCWarning(LOG_VariableController())
421 << tr("There is no variable selected to set the time one");
415 << tr("There is no variable selected to set the time one");
422 }
416 }
423 }
417 }
424
418
425 void VariableController::onUpdateDateTime(std::shared_ptr<Variable> variable,
419 void VariableController::onUpdateDateTime(std::shared_ptr<Variable> variable,
426 const SqpRange &dateTime)
420 const SqpRange &dateTime)
427 {
421 {
428 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
422 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
429 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
423 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
430 qCCritical(LOG_VariableController())
424 qCCritical(LOG_VariableController())
431 << tr("Impossible to onDateTimeOnSelection request for unknown variable");
425 << tr("Impossible to onDateTimeOnSelection request for unknown variable");
432 return;
426 return;
433 }
427 }
434
428
435 // notify that rescale operation has to be done
429 // notify that rescale operation has to be done
436 emit rangeChanged(variable, dateTime);
430 emit rangeChanged(variable, dateTime);
437
431
438 auto synchro
432 auto synchro
439 = impl->m_VariableIdGroupIdMap.find(itVar->second) != impl->m_VariableIdGroupIdMap.cend();
433 = impl->m_VariableIdGroupIdMap.find(itVar->second) != impl->m_VariableIdGroupIdMap.cend();
440
434
441 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{variable}, dateTime, synchro);
435 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{variable}, dateTime, synchro);
442 }
436 }
443
437
444 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
438 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
445 const SqpRange &cacheRangeRequested,
439 const SqpRange &cacheRangeRequested,
446 QVector<AcquisitionDataPacket> dataAcquired)
440 QVector<AcquisitionDataPacket> dataAcquired)
447 {
441 {
448 qCDebug(LOG_VariableController()) << tr("onDataProvided") << QThread::currentThread();
442 qCDebug(LOG_VariableController()) << tr("onDataProvided") << QThread::currentThread();
449 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
443 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
450 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
444 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
451 if (!varRequestId.isNull()) {
445 if (!varRequestId.isNull()) {
452 impl->updateVariables(varRequestId);
446 impl->updateVariables(varRequestId);
453 }
447 }
454 }
448 }
455
449
456 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
450 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
457 {
451 {
458 qCDebug(LOG_VariableController())
452 qCDebug(LOG_VariableController())
459 << "TORM: variableController::onVariableRetrieveDataInProgress"
453 << "TORM: variableController::onVariableRetrieveDataInProgress"
460 << QThread::currentThread()->objectName() << progress;
454 << QThread::currentThread()->objectName() << progress;
461 if (auto var = impl->findVariable(identifier)) {
455 if (auto var = impl->findVariable(identifier)) {
462 impl->m_VariableModel->setDataProgress(var, progress);
456 impl->m_VariableModel->setDataProgress(var, progress);
463 }
457 }
464 else {
458 else {
465 qCCritical(LOG_VariableController())
459 qCCritical(LOG_VariableController())
466 << tr("Impossible to notify progression of a null variable");
460 << tr("Impossible to notify progression of a null variable");
467 }
461 }
468 }
462 }
469
463
470 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
464 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
471 {
465 {
472 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortProgressRequested"
466 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortProgressRequested"
473 << QThread::currentThread()->objectName() << variable->name();
467 << QThread::currentThread()->objectName() << variable->name();
474
468
475 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
469 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
476 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
470 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
477 qCCritical(LOG_VariableController())
471 qCCritical(LOG_VariableController())
478 << tr("Impossible to onAbortProgressRequested request for unknown variable");
472 << tr("Impossible to onAbortProgressRequested request for unknown variable");
479 return;
473 return;
480 }
474 }
481
475
482 auto varId = itVar->second;
476 auto varId = itVar->second;
483
477
484 auto itVarHandler = impl->m_VarIdToVarRequestHandler.find(varId);
478 auto itVarHandler = impl->m_VarIdToVarRequestHandler.find(varId);
485 if (itVarHandler == impl->m_VarIdToVarRequestHandler.cend()) {
479 if (itVarHandler == impl->m_VarIdToVarRequestHandler.cend()) {
486 qCCritical(LOG_VariableController())
480 qCCritical(LOG_VariableController())
487 << tr("Impossible to onAbortProgressRequested for variable with unknown handler");
481 << tr("Impossible to onAbortProgressRequested for variable with unknown handler");
488 return;
482 return;
489 }
483 }
490
484
491 auto varHandler = itVarHandler->second.get();
485 auto varHandler = itVarHandler->second.get();
492
486
493 // case where a variable has a running request
487 // case where a variable has a running request
494 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
488 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
495 impl->cancelVariableRequest(varHandler->m_RunningVarRequest.m_VariableGroupId);
489 impl->cancelVariableRequest(varHandler->m_RunningVarRequest.m_VariableGroupId);
496 }
490 }
497 }
491 }
498
492
499 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
493 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
500 {
494 {
501 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
495 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
502 << QThread::currentThread()->objectName() << vIdentifier;
496 << QThread::currentThread()->objectName() << vIdentifier;
503
497
504 if (auto var = impl->findVariable(vIdentifier)) {
498 if (auto var = impl->findVariable(vIdentifier)) {
505 this->onAbortProgressRequested(var);
499 this->onAbortProgressRequested(var);
506 }
500 }
507 else {
501 else {
508 qCCritical(LOG_VariableController())
502 qCCritical(LOG_VariableController())
509 << tr("Impossible to abort Acquisition Requestof a null variable");
503 << tr("Impossible to abort Acquisition Requestof a null variable");
510 }
504 }
511 }
505 }
512
506
513 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
507 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
514 {
508 {
515 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
509 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
516 << QThread::currentThread()->objectName()
510 << QThread::currentThread()->objectName()
517 << synchronizationGroupId;
511 << synchronizationGroupId;
518 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
512 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
519 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
513 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
520 std::make_pair(synchronizationGroupId, vSynchroGroup));
514 std::make_pair(synchronizationGroupId, vSynchroGroup));
521 }
515 }
522
516
523 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
517 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
524 {
518 {
525 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
519 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
526 }
520 }
527
521
528 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
522 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
529 QUuid synchronizationGroupId)
523 QUuid synchronizationGroupId)
530
524
531 {
525 {
532 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
526 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
533 << synchronizationGroupId;
527 << synchronizationGroupId;
534 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
528 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
535 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
529 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
536 auto groupIdToVSGIt
530 auto groupIdToVSGIt
537 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
531 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
538 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
532 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
539 impl->m_VariableIdGroupIdMap.insert(
533 impl->m_VariableIdGroupIdMap.insert(
540 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
534 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
541 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
535 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
542 }
536 }
543 else {
537 else {
544 qCCritical(LOG_VariableController())
538 qCCritical(LOG_VariableController())
545 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
539 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
546 << variable->name();
540 << variable->name();
547 }
541 }
548 }
542 }
549 else {
543 else {
550 qCCritical(LOG_VariableController())
544 qCCritical(LOG_VariableController())
551 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
545 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
552 }
546 }
553 }
547 }
554
548
555 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
549 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
556 QUuid synchronizationGroupId)
550 QUuid synchronizationGroupId)
557 {
551 {
558 // Gets variable id
552 // Gets variable id
559 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
553 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
560 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
554 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
561 qCCritical(LOG_VariableController())
555 qCCritical(LOG_VariableController())
562 << tr("Can't desynchronize variable %1: variable identifier not found")
556 << tr("Can't desynchronize variable %1: variable identifier not found")
563 .arg(variable->name());
557 .arg(variable->name());
564 return;
558 return;
565 }
559 }
566
560
567 impl->desynchronize(variableIt, synchronizationGroupId);
561 impl->desynchronize(variableIt, synchronizationGroupId);
568 }
562 }
569
563
570 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
564 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
571 const SqpRange &range, bool synchronise)
565 const SqpRange &range, bool synchronise)
572 {
566 {
573 // variables is assumed synchronized
567 // variables is assumed synchronized
574 // TODO: Asser variables synchronization
568 // TODO: Asser variables synchronization
575 // we want to load data of the variable for the dateTime.
569 // we want to load data of the variable for the dateTime.
576 if (variables.isEmpty()) {
570 if (variables.isEmpty()) {
577 return;
571 return;
578 }
572 }
579
573
580 auto varRequestId = QUuid::createUuid();
574 auto varRequestId = QUuid::createUuid();
581 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
575 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
582 << QThread::currentThread()->objectName() << varRequestId
576 << QThread::currentThread()->objectName() << varRequestId
583 << range << synchronise;
577 << range << synchronise;
584
578
585 if (!synchronise) {
579 if (!synchronise) {
586 auto varIds = std::list<QUuid>{};
580 auto varIds = std::list<QUuid>{};
587 for (const auto &var : variables) {
581 for (const auto &var : variables) {
588 auto vId = impl->m_VariableToIdentifierMap.at(var);
582 auto vId = impl->m_VariableToIdentifierMap.at(var);
589 varIds.push_back(vId);
583 varIds.push_back(vId);
590 }
584 }
591 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
585 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
592 for (const auto &var : variables) {
586 for (const auto &var : variables) {
593 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId
587 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId
594 << varIds.size();
588 << varIds.size();
595 impl->processRequest(var, range, varRequestId);
589 impl->processRequest(var, range, varRequestId);
596 }
590 }
597 }
591 }
598 else {
592 else {
599 auto vId = impl->m_VariableToIdentifierMap.at(variables.first());
593 auto vId = impl->m_VariableToIdentifierMap.at(variables.first());
600 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
594 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
601 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
595 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
602 auto groupId = varIdToGroupIdIt->second;
596 auto groupId = varIdToGroupIdIt->second;
603
597
604 auto vSynchronizationGroup
598 auto vSynchronizationGroup
605 = impl->m_GroupIdToVariableSynchronizationGroupMap.at(groupId);
599 = impl->m_GroupIdToVariableSynchronizationGroupMap.at(groupId);
606 auto vSyncIds = vSynchronizationGroup->getIds();
600 auto vSyncIds = vSynchronizationGroup->getIds();
607
601
608 auto varIds = std::list<QUuid>{};
602 auto varIds = std::list<QUuid>{};
609 for (auto vId : vSyncIds) {
603 for (auto vId : vSyncIds) {
610 varIds.push_back(vId);
604 varIds.push_back(vId);
611 }
605 }
612 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
606 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
613
607
614 for (auto vId : vSyncIds) {
608 for (auto vId : vSyncIds) {
615 auto var = impl->findVariable(vId);
609 auto var = impl->findVariable(vId);
616
610
617 // Don't process already processed var
611 // Don't process already processed var
618 if (var != nullptr) {
612 if (var != nullptr) {
619 qCDebug(LOG_VariableController()) << "processRequest synchro for" << var->name()
613 qCDebug(LOG_VariableController()) << "processRequest synchro for" << var->name()
620 << varRequestId;
614 << varRequestId;
621 auto vSyncRangeRequested
615 auto vSyncRangeRequested
622 = variables.contains(var)
616 = variables.contains(var)
623 ? range
617 ? range
624 : computeSynchroRangeRequested(var->range(), range,
618 : computeSynchroRangeRequested(var->range(), range,
625 variables.first()->range());
619 variables.first()->range());
626 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
620 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
627 impl->processRequest(var, vSyncRangeRequested, varRequestId);
621 impl->processRequest(var, vSyncRangeRequested, varRequestId);
628 }
622 }
629 else {
623 else {
630 qCCritical(LOG_VariableController())
624 qCCritical(LOG_VariableController())
631
625
632 << tr("Impossible to synchronize a null variable");
626 << tr("Impossible to synchronize a null variable");
633 }
627 }
634 }
628 }
635 }
629 }
636 }
630 }
637
631
638 impl->updateVariables(varRequestId);
632 impl->updateVariables(varRequestId);
639 }
633 }
640
634
641
635
642 void VariableController::initialize()
636 void VariableController::initialize()
643 {
637 {
644 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
638 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
645 impl->m_WorkingMutex.lock();
639 impl->m_WorkingMutex.lock();
646 qCDebug(LOG_VariableController()) << tr("VariableController init END");
640 qCDebug(LOG_VariableController()) << tr("VariableController init END");
647 }
641 }
648
642
649 void VariableController::finalize()
643 void VariableController::finalize()
650 {
644 {
651 impl->m_WorkingMutex.unlock();
645 impl->m_WorkingMutex.unlock();
652 }
646 }
653
647
654 void VariableController::waitForFinish()
648 void VariableController::waitForFinish()
655 {
649 {
656 QMutexLocker locker{&impl->m_WorkingMutex};
650 QMutexLocker locker{&impl->m_WorkingMutex};
657 }
651 }
658
652
659 bool VariableController::hasPendingDownloads()
653 bool VariableController::hasPendingDownloads()
660 {
654 {
661 return impl->hasPendingDownloads();
655 return impl->hasPendingDownloads();
662 }
656 }
663
657
664 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
658 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
665 {
659 {
666 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
660 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
667 auto zoomType = AcquisitionZoomType::Unknown;
661 auto zoomType = AcquisitionZoomType::Unknown;
668 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
662 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
669 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
663 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
670 zoomType = AcquisitionZoomType::ZoomOut;
664 zoomType = AcquisitionZoomType::ZoomOut;
671 }
665 }
672 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
666 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
673 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
667 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
674 zoomType = AcquisitionZoomType::PanRight;
668 zoomType = AcquisitionZoomType::PanRight;
675 }
669 }
676 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
670 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
677 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
671 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
678 zoomType = AcquisitionZoomType::PanLeft;
672 zoomType = AcquisitionZoomType::PanLeft;
679 }
673 }
680 else if (range.m_TStart >= oldRange.m_TStart && oldRange.m_TEnd >= range.m_TEnd) {
674 else if (range.m_TStart >= oldRange.m_TStart && oldRange.m_TEnd >= range.m_TEnd) {
681 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
675 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
682 zoomType = AcquisitionZoomType::ZoomIn;
676 zoomType = AcquisitionZoomType::ZoomIn;
683 }
677 }
684 else {
678 else {
685 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
679 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
686 }
680 }
687 return zoomType;
681 return zoomType;
688 }
682 }
689
683
690 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
684 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
691 const SqpRange &rangeRequested,
685 const SqpRange &rangeRequested,
692 QUuid varRequestId)
686 QUuid varRequestId)
693 {
687 {
694 auto itVar = m_VariableToIdentifierMap.find(var);
688 auto itVar = m_VariableToIdentifierMap.find(var);
695 if (itVar == m_VariableToIdentifierMap.cend()) {
689 if (itVar == m_VariableToIdentifierMap.cend()) {
696 qCCritical(LOG_VariableController())
690 qCCritical(LOG_VariableController())
697 << tr("Impossible to process request for unknown variable");
691 << tr("Impossible to process request for unknown variable");
698 return;
692 return;
699 }
693 }
700
694
701 auto varId = itVar->second;
695 auto varId = itVar->second;
702
696
703 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
697 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
704 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
698 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
705 qCCritical(LOG_VariableController())
699 qCCritical(LOG_VariableController())
706 << tr("Impossible to process request for variable with unknown handler");
700 << tr("Impossible to process request for variable with unknown handler");
707 return;
701 return;
708 }
702 }
709
703
710 auto oldRange = var->range();
704 auto oldRange = var->range();
711
705
712 auto varHandler = itVarHandler->second.get();
706 auto varHandler = itVarHandler->second.get();
713
707
714 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
708 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
715 oldRange = varHandler->m_RunningVarRequest.m_RangeRequested;
709 oldRange = varHandler->m_RunningVarRequest.m_RangeRequested;
716 }
710 }
717
711
718 auto varRequest = VariableRequest{};
712 auto varRequest = VariableRequest{};
719 varRequest.m_VariableGroupId = varRequestId;
713 varRequest.m_VariableGroupId = varRequestId;
720 auto varStrategyRangesRequested
714 auto varStrategyRangesRequested
721 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
715 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
722 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
716 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
723 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
717 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
724
718
725 switch (varHandler->m_State) {
719 switch (varHandler->m_State) {
726 case VariableRequestHandlerState::OFF: {
720 case VariableRequestHandlerState::OFF: {
727 qCDebug(LOG_VariableController()) << tr("Process Request OFF")
721 qCDebug(LOG_VariableController()) << tr("Process Request OFF")
728 << varRequest.m_RangeRequested
722 << varRequest.m_RangeRequested
729 << varRequest.m_CacheRangeRequested;
723 << varRequest.m_CacheRangeRequested;
730 varHandler->m_RunningVarRequest = varRequest;
724 varHandler->m_RunningVarRequest = varRequest;
731 varHandler->m_State = VariableRequestHandlerState::RUNNING;
725 varHandler->m_State = VariableRequestHandlerState::RUNNING;
732 executeVarRequest(var, varRequest);
726 executeVarRequest(var, varRequest);
733 break;
727 break;
734 }
728 }
735 case VariableRequestHandlerState::RUNNING: {
729 case VariableRequestHandlerState::RUNNING: {
736 qCDebug(LOG_VariableController()) << tr("Process Request RUNNING")
730 qCDebug(LOG_VariableController()) << tr("Process Request RUNNING")
737 << varRequest.m_RangeRequested
731 << varRequest.m_RangeRequested
738 << varRequest.m_CacheRangeRequested;
732 << varRequest.m_CacheRangeRequested;
739 varHandler->m_State = VariableRequestHandlerState::PENDING;
733 varHandler->m_State = VariableRequestHandlerState::PENDING;
740 varHandler->m_PendingVarRequest = varRequest;
734 varHandler->m_PendingVarRequest = varRequest;
741 break;
735 break;
742 }
736 }
743 case VariableRequestHandlerState::PENDING: {
737 case VariableRequestHandlerState::PENDING: {
744 qCDebug(LOG_VariableController()) << tr("Process Request PENDING")
738 qCDebug(LOG_VariableController()) << tr("Process Request PENDING")
745 << varRequest.m_RangeRequested
739 << varRequest.m_RangeRequested
746 << varRequest.m_CacheRangeRequested;
740 << varRequest.m_CacheRangeRequested;
747 auto variableGroupIdToCancel = varHandler->m_PendingVarRequest.m_VariableGroupId;
741 auto variableGroupIdToCancel = varHandler->m_PendingVarRequest.m_VariableGroupId;
748 cancelVariableRequest(variableGroupIdToCancel);
742 cancelVariableRequest(variableGroupIdToCancel);
749 // Cancel variable can make state downgrade
743 // Cancel variable can make state downgrade
750 varHandler->m_State = VariableRequestHandlerState::PENDING;
744 varHandler->m_State = VariableRequestHandlerState::PENDING;
751 varHandler->m_PendingVarRequest = varRequest;
745 varHandler->m_PendingVarRequest = varRequest;
752
746
753 break;
747 break;
754 }
748 }
755 default:
749 default:
756 qCCritical(LOG_VariableController())
750 qCCritical(LOG_VariableController())
757 << QObject::tr("Unknown VariableRequestHandlerState");
751 << QObject::tr("Unknown VariableRequestHandlerState");
758 }
752 }
759 }
753 }
760
754
761 std::shared_ptr<Variable>
755 std::shared_ptr<Variable>
762 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
756 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
763 {
757 {
764 std::shared_ptr<Variable> var;
758 std::shared_ptr<Variable> var;
765 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
759 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
766
760
767 auto end = m_VariableToIdentifierMap.cend();
761 auto end = m_VariableToIdentifierMap.cend();
768 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
762 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
769 if (it != end) {
763 if (it != end) {
770 var = it->first;
764 var = it->first;
771 }
765 }
772 else {
766 else {
773 qCCritical(LOG_VariableController())
767 qCCritical(LOG_VariableController())
774 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
768 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
775 }
769 }
776
770
777 return var;
771 return var;
778 }
772 }
779
773
780 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
774 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
781 const QVector<AcquisitionDataPacket> acqDataPacketVector)
775 const QVector<AcquisitionDataPacket> acqDataPacketVector)
782 {
776 {
783 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
777 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
784 << acqDataPacketVector.size();
778 << acqDataPacketVector.size();
785 std::shared_ptr<IDataSeries> dataSeries;
779 std::shared_ptr<IDataSeries> dataSeries;
786 if (!acqDataPacketVector.isEmpty()) {
780 if (!acqDataPacketVector.isEmpty()) {
787 dataSeries = acqDataPacketVector[0].m_DateSeries;
781 dataSeries = acqDataPacketVector[0].m_DateSeries;
788 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
782 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
789 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
783 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
790 }
784 }
791 }
785 }
792 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
786 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
793 << acqDataPacketVector.size();
787 << acqDataPacketVector.size();
794 return dataSeries;
788 return dataSeries;
795 }
789 }
796
790
797 void VariableController::VariableControllerPrivate::registerProvider(
791 void VariableController::VariableControllerPrivate::registerProvider(
798 std::shared_ptr<IDataProvider> provider)
792 std::shared_ptr<IDataProvider> provider)
799 {
793 {
800 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
794 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
801 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
795 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
802 << provider->objectName();
796 << provider->objectName();
803 m_ProviderSet.insert(provider);
797 m_ProviderSet.insert(provider);
804 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
798 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
805 &VariableAcquisitionWorker::onVariableDataAcquired);
799 &VariableAcquisitionWorker::onVariableDataAcquired);
806 connect(provider.get(), &IDataProvider::dataProvidedProgress,
800 connect(provider.get(), &IDataProvider::dataProvidedProgress,
807 m_VariableAcquisitionWorker.get(),
801 m_VariableAcquisitionWorker.get(),
808 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
802 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
809 connect(provider.get(), &IDataProvider::dataProvidedFailed,
803 connect(provider.get(), &IDataProvider::dataProvidedFailed,
810 m_VariableAcquisitionWorker.get(),
804 m_VariableAcquisitionWorker.get(),
811 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
805 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
812 }
806 }
813 else {
807 else {
814 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
808 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
815 }
809 }
816 }
810 }
817
811
818 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
812 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
819 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
813 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
820 {
814 {
821 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
815 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
822 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
816 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
823 return QUuid();
817 return QUuid();
824 }
818 }
825
819
826 auto varHandler = itVarHandler->second.get();
820 auto varHandler = itVarHandler->second.get();
827 if (varHandler->m_State == VariableRequestHandlerState::OFF) {
821 if (varHandler->m_State == VariableRequestHandlerState::OFF) {
828 qCCritical(LOG_VariableController())
822 qCCritical(LOG_VariableController())
829 << tr("acceptVariableRequest impossible on a variable with OFF state");
823 << tr("acceptVariableRequest impossible on a variable with OFF state");
830 }
824 }
831
825
832 varHandler->m_RunningVarRequest.m_DataSeries = dataSeries;
826 varHandler->m_RunningVarRequest.m_DataSeries = dataSeries;
833 varHandler->m_CanUpdate = true;
827 varHandler->m_CanUpdate = true;
834
828
835 // Element traitΓ©, on a dΓ©jΓ  toutes les donnΓ©es necessaires
829 // Element traitΓ©, on a dΓ©jΓ  toutes les donnΓ©es necessaires
836 auto varGroupId = varHandler->m_RunningVarRequest.m_VariableGroupId;
830 auto varGroupId = varHandler->m_RunningVarRequest.m_VariableGroupId;
837 qCDebug(LOG_VariableController()) << "Variable::acceptVariableRequest" << varGroupId
831 qCDebug(LOG_VariableController()) << "Variable::acceptVariableRequest" << varGroupId
838 << m_VarGroupIdToVarIds.size();
832 << m_VarGroupIdToVarIds.size();
839
833
840 return varHandler->m_RunningVarRequest.m_VariableGroupId;
834 return varHandler->m_RunningVarRequest.m_VariableGroupId;
841 }
835 }
842
836
843 void VariableController::VariableControllerPrivate::updateVariables(QUuid varRequestId)
837 void VariableController::VariableControllerPrivate::updateVariables(QUuid varRequestId)
844 {
838 {
845 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
839 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
846 << QThread::currentThread()->objectName() << varRequestId;
840 << QThread::currentThread()->objectName() << varRequestId;
847
841
848 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
842 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
849 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
843 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
850 qCWarning(LOG_VariableController())
844 qCWarning(LOG_VariableController())
851 << tr("Impossible to updateVariables of unknown variables") << varRequestId;
845 << tr("Impossible to updateVariables of unknown variables") << varRequestId;
852 return;
846 return;
853 }
847 }
854
848
855 auto &varIds = varGroupIdToVarIdsIt->second;
849 auto &varIds = varGroupIdToVarIdsIt->second;
856 auto varIdsEnd = varIds.end();
850 auto varIdsEnd = varIds.end();
857 bool processVariableUpdate = true;
851 bool processVariableUpdate = true;
858 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
852 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
859 << varRequestId << varIds.size();
853 << varRequestId << varIds.size();
860 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd) && processVariableUpdate;
854 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd) && processVariableUpdate;
861 ++varIdsIt) {
855 ++varIdsIt) {
862 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
856 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
863 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
857 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
864 processVariableUpdate &= itVarHandler->second->m_CanUpdate;
858 processVariableUpdate &= itVarHandler->second->m_CanUpdate;
865 }
859 }
866 }
860 }
867
861
868 if (processVariableUpdate) {
862 if (processVariableUpdate) {
869 qCDebug(LOG_VariableController()) << "Final update OK for the var request" << varIds.size();
863 qCDebug(LOG_VariableController()) << "Final update OK for the var request" << varIds.size();
870 for (auto varIdsIt = varIds.begin(); varIdsIt != varIdsEnd; ++varIdsIt) {
864 for (auto varIdsIt = varIds.begin(); varIdsIt != varIdsEnd; ++varIdsIt) {
871 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
865 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
872 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
866 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
873 if (auto var = findVariable(*varIdsIt)) {
867 if (auto var = findVariable(*varIdsIt)) {
874 auto &varRequest = itVarHandler->second->m_RunningVarRequest;
868 auto &varRequest = itVarHandler->second->m_RunningVarRequest;
875 var->setRange(varRequest.m_RangeRequested);
869 var->setRange(varRequest.m_RangeRequested);
876 var->setCacheRange(varRequest.m_CacheRangeRequested);
870 var->setCacheRange(varRequest.m_CacheRangeRequested);
877 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
871 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
878 << varRequest.m_RangeRequested
872 << varRequest.m_RangeRequested
879 << varRequest.m_CacheRangeRequested;
873 << varRequest.m_CacheRangeRequested;
880 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
874 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
881 << var->nbPoints()
875 << var->nbPoints()
882 << varRequest.m_DataSeries->nbPoints();
876 << varRequest.m_DataSeries->nbPoints();
883 var->mergeDataSeries(varRequest.m_DataSeries);
877 var->mergeDataSeries(varRequest.m_DataSeries);
884 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
878 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
885 << var->nbPoints();
879 << var->nbPoints();
886
880
887 emit var->updated();
881 emit var->updated();
888 qCDebug(LOG_VariableController()) << tr("Update OK");
882 qCDebug(LOG_VariableController()) << tr("Update OK");
889 }
883 }
890 else {
884 else {
891 qCCritical(LOG_VariableController())
885 qCCritical(LOG_VariableController())
892 << tr("Impossible to update data to a null variable");
886 << tr("Impossible to update data to a null variable");
893 }
887 }
894 }
888 }
895 }
889 }
896 updateVariableRequest(varRequestId);
890 updateVariableRequest(varRequestId);
897
891
898 // cleaning varRequestId
892 // cleaning varRequestId
899 qCDebug(LOG_VariableController()) << tr("m_VarGroupIdToVarIds erase") << varRequestId;
893 qCDebug(LOG_VariableController()) << tr("m_VarGroupIdToVarIds erase") << varRequestId;
900 m_VarGroupIdToVarIds.erase(varRequestId);
894 m_VarGroupIdToVarIds.erase(varRequestId);
901 if (m_VarGroupIdToVarIds.empty()) {
895 if (m_VarGroupIdToVarIds.empty()) {
902 emit q->acquisitionFinished();
896 emit q->acquisitionFinished();
903 }
897 }
904 }
898 }
905 }
899 }
906
900
907
901
908 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
902 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
909 {
903 {
910 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
904 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
911 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
905 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
912 qCCritical(LOG_VariableController()) << QObject::tr(
906 qCCritical(LOG_VariableController()) << QObject::tr(
913 "Impossible to updateVariableRequest since varGroupdId isn't here anymore");
907 "Impossible to updateVariableRequest since varGroupdId isn't here anymore");
914
908
915 return;
909 return;
916 }
910 }
917
911
918 auto &varIds = varGroupIdToVarIdsIt->second;
912 auto &varIds = varGroupIdToVarIdsIt->second;
919 auto varIdsEnd = varIds.end();
913 auto varIdsEnd = varIds.end();
920 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
914 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
921 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
915 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
922 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
916 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
923
917
924 auto varHandler = itVarHandler->second.get();
918 auto varHandler = itVarHandler->second.get();
925 varHandler->m_CanUpdate = false;
919 varHandler->m_CanUpdate = false;
926
920
927
921
928 switch (varHandler->m_State) {
922 switch (varHandler->m_State) {
929 case VariableRequestHandlerState::OFF: {
923 case VariableRequestHandlerState::OFF: {
930 qCCritical(LOG_VariableController())
924 qCCritical(LOG_VariableController())
931 << QObject::tr("Impossible to update a variable with handler in OFF state");
925 << QObject::tr("Impossible to update a variable with handler in OFF state");
932 } break;
926 } break;
933 case VariableRequestHandlerState::RUNNING: {
927 case VariableRequestHandlerState::RUNNING: {
934 varHandler->m_State = VariableRequestHandlerState::OFF;
928 varHandler->m_State = VariableRequestHandlerState::OFF;
935 varHandler->m_RunningVarRequest = VariableRequest{};
929 varHandler->m_RunningVarRequest = VariableRequest{};
936 break;
930 break;
937 }
931 }
938 case VariableRequestHandlerState::PENDING: {
932 case VariableRequestHandlerState::PENDING: {
939 varHandler->m_State = VariableRequestHandlerState::RUNNING;
933 varHandler->m_State = VariableRequestHandlerState::RUNNING;
940 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
934 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
941 varHandler->m_PendingVarRequest = VariableRequest{};
935 varHandler->m_PendingVarRequest = VariableRequest{};
942 auto var = findVariable(itVarHandler->first);
936 auto var = findVariable(itVarHandler->first);
943 executeVarRequest(var, varHandler->m_RunningVarRequest);
937 executeVarRequest(var, varHandler->m_RunningVarRequest);
944 updateVariables(varHandler->m_RunningVarRequest.m_VariableGroupId);
938 updateVariables(varHandler->m_RunningVarRequest.m_VariableGroupId);
945 break;
939 break;
946 }
940 }
947 default:
941 default:
948 qCCritical(LOG_VariableController())
942 qCCritical(LOG_VariableController())
949 << QObject::tr("Unknown VariableRequestHandlerState");
943 << QObject::tr("Unknown VariableRequestHandlerState");
950 }
944 }
951 }
945 }
952 }
946 }
953 }
947 }
954
948
955
949
956 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
950 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
957 {
951 {
958 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest") << varRequestId;
952 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest") << varRequestId;
959
953
960 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
954 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
961 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
955 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
962 qCCritical(LOG_VariableController())
956 qCCritical(LOG_VariableController())
963 << tr("Impossible to cancelVariableRequest for unknown varGroupdId") << varRequestId;
957 << tr("Impossible to cancelVariableRequest for unknown varGroupdId") << varRequestId;
964 return;
958 return;
965 }
959 }
966
960
967 auto &varIds = varGroupIdToVarIdsIt->second;
961 auto &varIds = varGroupIdToVarIdsIt->second;
968 auto varIdsEnd = varIds.end();
962 auto varIdsEnd = varIds.end();
969 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
963 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
970 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
964 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
971 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
965 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
972
966
973 auto varHandler = itVarHandler->second.get();
967 auto varHandler = itVarHandler->second.get();
974 varHandler->m_VarId = QUuid{};
968 varHandler->m_VarId = QUuid{};
975 switch (varHandler->m_State) {
969 switch (varHandler->m_State) {
976 case VariableRequestHandlerState::OFF: {
970 case VariableRequestHandlerState::OFF: {
977 qCWarning(LOG_VariableController())
971 qCWarning(LOG_VariableController())
978 << QObject::tr("Impossible to cancel a variable with no running request");
972 << QObject::tr("Impossible to cancel a variable with no running request");
979 break;
973 break;
980 }
974 }
981 case VariableRequestHandlerState::RUNNING: {
975 case VariableRequestHandlerState::RUNNING: {
982
976
983 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
977 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
984 auto var = findVariable(itVarHandler->first);
978 auto var = findVariable(itVarHandler->first);
985 auto varProvider = m_VariableToProviderMap.at(var);
979 auto varProvider = m_VariableToProviderMap.at(var);
986 if (varProvider != nullptr) {
980 if (varProvider != nullptr) {
987 m_VariableAcquisitionWorker->abortProgressRequested(
981 m_VariableAcquisitionWorker->abortProgressRequested(
988 itVarHandler->first);
982 itVarHandler->first);
989 }
983 }
990 m_VariableModel->setDataProgress(var, 0.0);
984 m_VariableModel->setDataProgress(var, 0.0);
991 varHandler->m_CanUpdate = false;
985 varHandler->m_CanUpdate = false;
992 varHandler->m_State = VariableRequestHandlerState::OFF;
986 varHandler->m_State = VariableRequestHandlerState::OFF;
993 varHandler->m_RunningVarRequest = VariableRequest{};
987 varHandler->m_RunningVarRequest = VariableRequest{};
994 }
988 }
995 else {
989 else {
996 // TODO: log Impossible to cancel the running variable request beacause its
990 // TODO: log Impossible to cancel the running variable request beacause its
997 // varRequestId isn't not the canceled one
991 // varRequestId isn't not the canceled one
998 }
992 }
999 break;
993 break;
1000 }
994 }
1001 case VariableRequestHandlerState::PENDING: {
995 case VariableRequestHandlerState::PENDING: {
1002 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
996 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
1003 auto var = findVariable(itVarHandler->first);
997 auto var = findVariable(itVarHandler->first);
1004 auto varProvider = m_VariableToProviderMap.at(var);
998 auto varProvider = m_VariableToProviderMap.at(var);
1005 if (varProvider != nullptr) {
999 if (varProvider != nullptr) {
1006 m_VariableAcquisitionWorker->abortProgressRequested(
1000 m_VariableAcquisitionWorker->abortProgressRequested(
1007 itVarHandler->first);
1001 itVarHandler->first);
1008 }
1002 }
1009 m_VariableModel->setDataProgress(var, 0.0);
1003 m_VariableModel->setDataProgress(var, 0.0);
1010 varHandler->m_CanUpdate = false;
1004 varHandler->m_CanUpdate = false;
1011 varHandler->m_State = VariableRequestHandlerState::RUNNING;
1005 varHandler->m_State = VariableRequestHandlerState::RUNNING;
1012 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
1006 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
1013 varHandler->m_PendingVarRequest = VariableRequest{};
1007 varHandler->m_PendingVarRequest = VariableRequest{};
1014 executeVarRequest(var, varHandler->m_RunningVarRequest);
1008 executeVarRequest(var, varHandler->m_RunningVarRequest);
1015 }
1009 }
1016 else if (varHandler->m_PendingVarRequest.m_VariableGroupId == varRequestId) {
1010 else if (varHandler->m_PendingVarRequest.m_VariableGroupId == varRequestId) {
1017 varHandler->m_State = VariableRequestHandlerState::RUNNING;
1011 varHandler->m_State = VariableRequestHandlerState::RUNNING;
1018 varHandler->m_PendingVarRequest = VariableRequest{};
1012 varHandler->m_PendingVarRequest = VariableRequest{};
1019 }
1013 }
1020 else {
1014 else {
1021 // TODO: log Impossible to cancel the variable request beacause its
1015 // TODO: log Impossible to cancel the variable request beacause its
1022 // varRequestId isn't not the canceled one
1016 // varRequestId isn't not the canceled one
1023 }
1017 }
1024 break;
1018 break;
1025 }
1019 }
1026 default:
1020 default:
1027 qCCritical(LOG_VariableController())
1021 qCCritical(LOG_VariableController())
1028 << QObject::tr("Unknown VariableRequestHandlerState");
1022 << QObject::tr("Unknown VariableRequestHandlerState");
1029 }
1023 }
1030 }
1024 }
1031 }
1025 }
1032 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest: erase") << varRequestId;
1026 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest: erase") << varRequestId;
1033 m_VarGroupIdToVarIds.erase(varRequestId);
1027 m_VarGroupIdToVarIds.erase(varRequestId);
1034 if (m_VarGroupIdToVarIds.empty()) {
1028 if (m_VarGroupIdToVarIds.empty()) {
1035 emit q->acquisitionFinished();
1029 emit q->acquisitionFinished();
1036 }
1030 }
1037 }
1031 }
1038
1032
1039 void VariableController::VariableControllerPrivate::executeVarRequest(std::shared_ptr<Variable> var,
1033 void VariableController::VariableControllerPrivate::executeVarRequest(std::shared_ptr<Variable> var,
1040 VariableRequest &varRequest)
1034 VariableRequest &varRequest)
1041 {
1035 {
1042 qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest");
1036 qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest");
1043
1037
1044 auto varIdIt = m_VariableToIdentifierMap.find(var);
1038 auto varIdIt = m_VariableToIdentifierMap.find(var);
1045 if (varIdIt == m_VariableToIdentifierMap.cend()) {
1039 if (varIdIt == m_VariableToIdentifierMap.cend()) {
1046 qCWarning(LOG_VariableController()) << tr(
1040 qCWarning(LOG_VariableController()) << tr(
1047 "Can't execute request of a variable that is not registered (may has been deleted)");
1041 "Can't execute request of a variable that is not registered (may has been deleted)");
1048 return;
1042 return;
1049 }
1043 }
1050
1044
1051 auto varId = varIdIt->second;
1045 auto varId = varIdIt->second;
1052
1046
1053 auto varCacheRange = var->cacheRange();
1047 auto varCacheRange = var->cacheRange();
1054 auto varCacheRangeRequested = varRequest.m_CacheRangeRequested;
1048 auto varCacheRangeRequested = varRequest.m_CacheRangeRequested;
1055 auto notInCacheRangeList
1049 auto notInCacheRangeList
1056 = Variable::provideNotInCacheRangeList(varCacheRange, varCacheRangeRequested);
1050 = Variable::provideNotInCacheRangeList(varCacheRange, varCacheRangeRequested);
1057 auto inCacheRangeList
1051 auto inCacheRangeList
1058 = Variable::provideInCacheRangeList(varCacheRange, varCacheRangeRequested);
1052 = Variable::provideInCacheRangeList(varCacheRange, varCacheRangeRequested);
1059
1053
1060 if (!notInCacheRangeList.empty()) {
1054 if (!notInCacheRangeList.empty()) {
1061
1055
1062 auto varProvider = m_VariableToProviderMap.at(var);
1056 auto varProvider = m_VariableToProviderMap.at(var);
1063 if (varProvider != nullptr) {
1057 if (varProvider != nullptr) {
1064 qCDebug(LOG_VariableController()) << "executeVarRequest " << varRequest.m_RangeRequested
1058 qCDebug(LOG_VariableController()) << "executeVarRequest " << varRequest.m_RangeRequested
1065 << varRequest.m_CacheRangeRequested;
1059 << varRequest.m_CacheRangeRequested;
1066 m_VariableAcquisitionWorker->pushVariableRequest(
1060 m_VariableAcquisitionWorker->pushVariableRequest(
1067 varRequest.m_VariableGroupId, varId, varRequest.m_RangeRequested,
1061 varRequest.m_VariableGroupId, varId, varRequest.m_RangeRequested,
1068 varRequest.m_CacheRangeRequested,
1062 varRequest.m_CacheRangeRequested,
1069 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
1063 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
1070 varProvider);
1064 varProvider);
1071 }
1065 }
1072 else {
1066 else {
1073 qCCritical(LOG_VariableController())
1067 qCCritical(LOG_VariableController())
1074 << "Impossible to provide data with a null provider";
1068 << "Impossible to provide data with a null provider";
1075 }
1069 }
1076
1070
1077 if (!inCacheRangeList.empty()) {
1071 if (!inCacheRangeList.empty()) {
1078 emit q->updateVarDisplaying(var, inCacheRangeList.first());
1072 emit q->updateVarDisplaying(var, inCacheRangeList.first());
1079 }
1073 }
1080 }
1074 }
1081 else {
1075 else {
1082 acceptVariableRequest(varId,
1076 acceptVariableRequest(varId,
1083 var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested));
1077 var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested));
1084 }
1078 }
1085 }
1079 }
1086
1080
1087 bool VariableController::VariableControllerPrivate::hasPendingDownloads()
1081 bool VariableController::VariableControllerPrivate::hasPendingDownloads()
1088 {
1082 {
1089 return !m_VarGroupIdToVarIds.empty();
1083 return !m_VarGroupIdToVarIds.empty();
1090 }
1084 }
1091
1085
1092 template <typename VariableIterator>
1086 template <typename VariableIterator>
1093 void VariableController::VariableControllerPrivate::desynchronize(VariableIterator variableIt,
1087 void VariableController::VariableControllerPrivate::desynchronize(VariableIterator variableIt,
1094 const QUuid &syncGroupId)
1088 const QUuid &syncGroupId)
1095 {
1089 {
1096 const auto &variable = variableIt->first;
1090 const auto &variable = variableIt->first;
1097 const auto &variableId = variableIt->second;
1091 const auto &variableId = variableIt->second;
1098
1092
1099 // Gets synchronization group
1093 // Gets synchronization group
1100 auto groupIt = m_GroupIdToVariableSynchronizationGroupMap.find(syncGroupId);
1094 auto groupIt = m_GroupIdToVariableSynchronizationGroupMap.find(syncGroupId);
1101 if (groupIt == m_GroupIdToVariableSynchronizationGroupMap.cend()) {
1095 if (groupIt == m_GroupIdToVariableSynchronizationGroupMap.cend()) {
1102 qCCritical(LOG_VariableController())
1096 qCCritical(LOG_VariableController())
1103 << tr("Can't desynchronize variable %1: unknown synchronization group")
1097 << tr("Can't desynchronize variable %1: unknown synchronization group")
1104 .arg(variable->name());
1098 .arg(variable->name());
1105 return;
1099 return;
1106 }
1100 }
1107
1101
1108 // Removes variable from synchronization group
1102 // Removes variable from synchronization group
1109 auto synchronizationGroup = groupIt->second;
1103 auto synchronizationGroup = groupIt->second;
1110 synchronizationGroup->removeVariableId(variableId);
1104 synchronizationGroup->removeVariableId(variableId);
1111
1105
1112 // Removes link between variable and synchronization group
1106 // Removes link between variable and synchronization group
1113 m_VariableIdGroupIdMap.erase(variableId);
1107 m_VariableIdGroupIdMap.erase(variableId);
1114 }
1108 }
@@ -1,74 +1,74
1 #include <QObject>
1 #include <QObject>
2 #include <QtTest>
2 #include <QtTest>
3
3
4 #include <Data/IDataProvider.h>
4 #include <Data/IDataProvider.h>
5 #include <Time/TimeController.h>
5 #include <Time/TimeController.h>
6 #include <Variable/Variable.h>
6 #include <Variable/Variable.h>
7 #include <Variable/VariableController.h>
7 #include <Variable/VariableController.h>
8
8
9 #include <memory>
9 #include <memory>
10
10
11 namespace {
11 namespace {
12
12
13 /// Provider used for the tests
13 /// Provider used for the tests
14 class TestProvider : public IDataProvider {
14 class TestProvider : public IDataProvider {
15 std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); }
15 std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); }
16
16
17 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
17 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
18 {
18 {
19 // Does nothing
19 // Does nothing
20 }
20 }
21
21
22 void requestDataAborting(QUuid acqIdentifier) override
22 void requestDataAborting(QUuid acqIdentifier) override
23 {
23 {
24 // Does nothing
24 // Does nothing
25 }
25 }
26 };
26 };
27
27
28 /// Generates a time controller for the tests
28 /// Generates a time controller for the tests
29 std::unique_ptr<TimeController> defaultTimeController()
29 std::unique_ptr<TimeController> defaultTimeController()
30 {
30 {
31 auto timeController = std::make_unique<TimeController>();
31 auto timeController = std::make_unique<TimeController>();
32
32
33 QDateTime start{QDate{2017, 01, 01}, QTime{0, 0, 0, 0}};
33 QDateTime start{QDate{2017, 01, 01}, QTime{0, 0, 0, 0}};
34 QDateTime end{QDate{2017, 01, 02}, QTime{0, 0, 0, 0}};
34 QDateTime end{QDate{2017, 01, 02}, QTime{0, 0, 0, 0}};
35 timeController->onTimeToUpdate(
35 timeController->setDateTimeRange(
36 SqpRange{DateUtils::secondsSinceEpoch(start), DateUtils::secondsSinceEpoch(end)});
36 SqpRange{DateUtils::secondsSinceEpoch(start), DateUtils::secondsSinceEpoch(end)});
37
37
38 return timeController;
38 return timeController;
39 }
39 }
40
40
41 } // namespace
41 } // namespace
42
42
43 class TestVariableController : public QObject {
43 class TestVariableController : public QObject {
44 Q_OBJECT
44 Q_OBJECT
45
45
46 private slots:
46 private slots:
47 /// Test removes variable from controller
47 /// Test removes variable from controller
48 void testDeleteVariable();
48 void testDeleteVariable();
49 };
49 };
50
50
51 void TestVariableController::testDeleteVariable()
51 void TestVariableController::testDeleteVariable()
52 {
52 {
53 // Creates variable controller
53 // Creates variable controller
54 auto timeController = defaultTimeController();
54 auto timeController = defaultTimeController();
55 VariableController variableController{};
55 VariableController variableController{};
56 variableController.setTimeController(timeController.get());
56 //variableController.setTimeController(timeController.get());
57
57
58 // Creates a variable from the controller
58 // Creates a variable from the controller
59 auto variable
59 auto variable
60 = variableController.createVariable("variable", {}, std::make_shared<TestProvider>());
60 = variableController.createVariable("variable", {}, std::make_shared<TestProvider>(), timeController->dateTime());
61
61
62 qDebug() << QString::number(variable.use_count());
62 qDebug() << QString::number(variable.use_count());
63
63
64 // Removes the variable from the controller
64 // Removes the variable from the controller
65 variableController.deleteVariable(variable);
65 variableController.deleteVariable(variable);
66
66
67 // Verifies that the variable has been deleted: this implies that the number of shared_ptr
67 // Verifies that the variable has been deleted: this implies that the number of shared_ptr
68 // objects referring to the variable is 1 (the reference of this scope). Otherwise, the deletion
68 // objects referring to the variable is 1 (the reference of this scope). Otherwise, the deletion
69 // is considered invalid since the variable is still referenced in the controller
69 // is considered invalid since the variable is still referenced in the controller
70 QVERIFY(variable.use_count() == 1);
70 QVERIFY(variable.use_count() == 1);
71 }
71 }
72
72
73 QTEST_MAIN(TestVariableController)
73 QTEST_MAIN(TestVariableController)
74 #include "TestVariableController.moc"
74 #include "TestVariableController.moc"
@@ -1,508 +1,508
1 #include <QObject>
1 #include <QObject>
2 #include <QtTest>
2 #include <QtTest>
3
3
4 #include <memory>
4 #include <memory>
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/ScalarSeries.h>
8 #include <Data/ScalarSeries.h>
9 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
10 #include <Variable/Variable.h>
10 #include <Variable/Variable.h>
11 #include <Variable/VariableController.h>
11 #include <Variable/VariableController.h>
12 #include <Variable/VariableModel.h>
12 #include <Variable/VariableModel.h>
13
13
14 namespace {
14 namespace {
15
15
16 /// Delay after each operation on the variable before validating it (in ms)
16 /// Delay after each operation on the variable before validating it (in ms)
17 const auto OPERATION_DELAY = 100;
17 const auto OPERATION_DELAY = 100;
18
18
19 /**
19 /**
20 * Generates values according to a range. The value generated for a time t is the number of seconds
20 * Generates values according to a range. The value generated for a time t is the number of seconds
21 * of difference between t and a reference value (which is midnight -> 00:00:00)
21 * of difference between t and a reference value (which is midnight -> 00:00:00)
22 *
22 *
23 * Example: For a range between 00:00:10 and 00:00:20, the generated values are
23 * Example: For a range between 00:00:10 and 00:00:20, the generated values are
24 * {10,11,12,13,14,15,16,17,18,19,20}
24 * {10,11,12,13,14,15,16,17,18,19,20}
25 */
25 */
26 std::vector<double> values(const SqpRange &range)
26 std::vector<double> values(const SqpRange &range)
27 {
27 {
28 QTime referenceTime{0, 0};
28 QTime referenceTime{0, 0};
29
29
30 std::vector<double> result{};
30 std::vector<double> result{};
31
31
32 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
32 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
33 auto time = DateUtils::dateTime(i).time();
33 auto time = DateUtils::dateTime(i).time();
34 result.push_back(referenceTime.secsTo(time));
34 result.push_back(referenceTime.secsTo(time));
35 }
35 }
36
36
37 return result;
37 return result;
38 }
38 }
39
39
40 void validateRanges(VariableController &variableController,
40 void validateRanges(VariableController &variableController,
41 const std::map<int, SqpRange> &expectedRanges)
41 const std::map<int, SqpRange> &expectedRanges)
42 {
42 {
43 for (const auto &expectedRangeEntry : expectedRanges) {
43 for (const auto &expectedRangeEntry : expectedRanges) {
44 auto variableIndex = expectedRangeEntry.first;
44 auto variableIndex = expectedRangeEntry.first;
45 auto expectedRange = expectedRangeEntry.second;
45 auto expectedRange = expectedRangeEntry.second;
46
46
47 // Gets the variable in the controller
47 // Gets the variable in the controller
48 auto variable = variableController.variableModel()->variable(variableIndex);
48 auto variable = variableController.variableModel()->variable(variableIndex);
49
49
50 // Compares variable's range to the expected range
50 // Compares variable's range to the expected range
51 QVERIFY(variable != nullptr);
51 QVERIFY(variable != nullptr);
52 auto range = variable->range();
52 auto range = variable->range();
53 qInfo() << "range vs expected range" << range << expectedRange;
53 qInfo() << "range vs expected range" << range << expectedRange;
54 QCOMPARE(range, expectedRange);
54 QCOMPARE(range, expectedRange);
55
55
56 // Compares variable's data with values expected for its range
56 // Compares variable's data with values expected for its range
57 auto dataSeries = variable->dataSeries();
57 auto dataSeries = variable->dataSeries();
58 QVERIFY(dataSeries != nullptr);
58 QVERIFY(dataSeries != nullptr);
59
59
60 auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd);
60 auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd);
61 auto expectedValues = values(range);
61 auto expectedValues = values(range);
62 qInfo() << std::distance(it.first, it.second) << expectedValues.size();
62 qInfo() << std::distance(it.first, it.second) << expectedValues.size();
63 QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(),
63 QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(),
64 [](const auto &dataSeriesIt, const auto &expectedValue) {
64 [](const auto &dataSeriesIt, const auto &expectedValue) {
65 return dataSeriesIt.value() == expectedValue;
65 return dataSeriesIt.value() == expectedValue;
66 }));
66 }));
67 }
67 }
68 }
68 }
69
69
70 /// Provider used for the tests
70 /// Provider used for the tests
71 class TestProvider : public IDataProvider {
71 class TestProvider : public IDataProvider {
72 std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); }
72 std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); }
73
73
74 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
74 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
75 {
75 {
76 const auto &ranges = parameters.m_Times;
76 const auto &ranges = parameters.m_Times;
77
77
78 for (const auto &range : ranges) {
78 for (const auto &range : ranges) {
79 // Generates data series
79 // Generates data series
80 auto valuesData = values(range);
80 auto valuesData = values(range);
81
81
82 std::vector<double> xAxisData{};
82 std::vector<double> xAxisData{};
83 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
83 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
84 xAxisData.push_back(i);
84 xAxisData.push_back(i);
85 }
85 }
86
86
87 auto dataSeries = std::make_shared<ScalarSeries>(
87 auto dataSeries = std::make_shared<ScalarSeries>(
88 std::move(xAxisData), std::move(valuesData), Unit{"t", true}, Unit{});
88 std::move(xAxisData), std::move(valuesData), Unit{"t", true}, Unit{});
89
89
90 emit dataProvided(acqIdentifier, dataSeries, range);
90 emit dataProvided(acqIdentifier, dataSeries, range);
91 }
91 }
92 }
92 }
93
93
94 void requestDataAborting(QUuid acqIdentifier) override
94 void requestDataAborting(QUuid acqIdentifier) override
95 {
95 {
96 // Does nothing
96 // Does nothing
97 }
97 }
98 };
98 };
99
99
100 /**
100 /**
101 * Interface representing an operation performed on a variable controller.
101 * Interface representing an operation performed on a variable controller.
102 * This interface is used in tests to apply a set of operations and check the status of the
102 * This interface is used in tests to apply a set of operations and check the status of the
103 * controller after each operation
103 * controller after each operation
104 */
104 */
105 struct IOperation {
105 struct IOperation {
106 virtual ~IOperation() = default;
106 virtual ~IOperation() = default;
107 /// Executes the operation on the variable controller
107 /// Executes the operation on the variable controller
108 virtual void exec(VariableController &variableController) const = 0;
108 virtual void exec(VariableController &variableController) const = 0;
109 };
109 };
110
110
111 /**
111 /**
112 *Variable creation operation in the controller
112 *Variable creation operation in the controller
113 */
113 */
114 struct Create : public IOperation {
114 struct Create : public IOperation {
115 explicit Create(int index) : m_Index{index} {}
115 explicit Create(int index, const SqpRange &range) : m_Index{index},m_range(range) {}
116
116
117 void exec(VariableController &variableController) const override
117 void exec(VariableController &variableController) const override
118 {
118 {
119 auto variable = variableController.createVariable(QString::number(m_Index), {},
119 auto variable = variableController.createVariable(QString::number(m_Index), {},
120 std::make_unique<TestProvider>());
120 std::make_unique<TestProvider>(), m_range);
121 }
121 }
122
123 int m_Index; ///< The index of the variable to create in the controller
122 int m_Index; ///< The index of the variable to create in the controller
123 SqpRange m_range;
124 };
124 };
125
125
126 /**
126 /**
127 * Variable move/shift operation in the controller
127 * Variable move/shift operation in the controller
128 */
128 */
129 struct Move : public IOperation {
129 struct Move : public IOperation {
130 explicit Move(int index, const SqpRange &newRange, bool shift = false, int delayMS = 10)
130 explicit Move(int index, const SqpRange &newRange, bool shift = false, int delayMS = 10)
131 : m_Index{index}, m_NewRange{newRange}, m_Shift{shift}, m_DelayMs{delayMS}
131 : m_Index{index}, m_NewRange{newRange}, m_Shift{shift}, m_DelayMs{delayMS}
132 {
132 {
133 }
133 }
134
134
135 void exec(VariableController &variableController) const override
135 void exec(VariableController &variableController) const override
136 {
136 {
137 if (auto variable = variableController.variableModel()->variable(m_Index)) {
137 if (auto variable = variableController.variableModel()->variable(m_Index)) {
138 variableController.onRequestDataLoading({variable}, m_NewRange, !m_Shift);
138 variableController.onRequestDataLoading({variable}, m_NewRange, !m_Shift);
139 QTest::qWait(m_DelayMs);
139 QTest::qWait(m_DelayMs);
140 }
140 }
141 }
141 }
142
142
143 int m_Index; ///< The index of the variable to move
143 int m_Index; ///< The index of the variable to move
144 SqpRange m_NewRange; ///< The new range of the variable
144 SqpRange m_NewRange; ///< The new range of the variable
145 bool m_Shift; ///< Performs a shift (
145 bool m_Shift; ///< Performs a shift (
146 int m_DelayMs; ///< wait the delay after running the request (
146 int m_DelayMs; ///< wait the delay after running the request (
147 };
147 };
148
148
149 /**
149 /**
150 * Variable synchronization/desynchronization operation in the controller
150 * Variable synchronization/desynchronization operation in the controller
151 */
151 */
152 struct Synchronize : public IOperation {
152 struct Synchronize : public IOperation {
153 explicit Synchronize(int index, QUuid syncId, bool synchronize = true)
153 explicit Synchronize(int index, QUuid syncId, bool synchronize = true)
154 : m_Index{index}, m_SyncId{syncId}, m_Synchronize{synchronize}
154 : m_Index{index}, m_SyncId{syncId}, m_Synchronize{synchronize}
155 {
155 {
156 }
156 }
157
157
158 void exec(VariableController &variableController) const override
158 void exec(VariableController &variableController) const override
159 {
159 {
160 if (auto variable = variableController.variableModel()->variable(m_Index)) {
160 if (auto variable = variableController.variableModel()->variable(m_Index)) {
161 if (m_Synchronize) {
161 if (m_Synchronize) {
162 variableController.onAddSynchronized(variable, m_SyncId);
162 variableController.onAddSynchronized(variable, m_SyncId);
163 }
163 }
164 else {
164 else {
165 variableController.desynchronize(variable, m_SyncId);
165 variableController.desynchronize(variable, m_SyncId);
166 }
166 }
167 }
167 }
168 }
168 }
169
169
170 int m_Index; ///< The index of the variable to sync/desync
170 int m_Index; ///< The index of the variable to sync/desync
171 QUuid m_SyncId; ///< The synchronization group of the variable
171 QUuid m_SyncId; ///< The synchronization group of the variable
172 bool m_Synchronize; ///< Performs sync or desync operation
172 bool m_Synchronize; ///< Performs sync or desync operation
173 };
173 };
174
174
175 /**
175 /**
176 * Test Iteration
176 * Test Iteration
177 *
177 *
178 * A test iteration includes an operation to be performed, and a set of expected ranges after each
178 * A test iteration includes an operation to be performed, and a set of expected ranges after each
179 * operation. Each range is tested after the operation to ensure that:
179 * operation. Each range is tested after the operation to ensure that:
180 * - the range of the variable is the expected range
180 * - the range of the variable is the expected range
181 * - the data of the variable are those generated for the expected range
181 * - the data of the variable are those generated for the expected range
182 */
182 */
183 struct Iteration {
183 struct Iteration {
184 std::shared_ptr<IOperation> m_Operation; ///< Operation to perform
184 std::shared_ptr<IOperation> m_Operation; ///< Operation to perform
185 std::map<int, SqpRange> m_ExpectedRanges; ///< Expected ranges (by variable index)
185 std::map<int, SqpRange> m_ExpectedRanges; ///< Expected ranges (by variable index)
186 };
186 };
187
187
188 using Iterations = std::vector<Iteration>;
188 using Iterations = std::vector<Iteration>;
189
189
190 } // namespace
190 } // namespace
191
191
192 Q_DECLARE_METATYPE(Iterations)
192 Q_DECLARE_METATYPE(Iterations)
193
193
194 class TestVariableSync : public QObject {
194 class TestVariableSync : public QObject {
195 Q_OBJECT
195 Q_OBJECT
196
196
197 private slots:
197 private slots:
198 void initTestCase() { QSKIP("Temporarily disables TestVariableSync"); }
198 void initTestCase() { QSKIP("Temporarily disables TestVariableSync"); }
199
199
200 /// Input data for @sa testSync()
200 /// Input data for @sa testSync()
201 void testSync_data();
201 void testSync_data();
202
202
203 /// Input data for @sa testSyncOneVar()
203 /// Input data for @sa testSyncOneVar()
204 void testSyncOneVar_data();
204 void testSyncOneVar_data();
205
205
206 /// Tests synchronization between variables through several operations
206 /// Tests synchronization between variables through several operations
207 void testSync();
207 void testSync();
208
208
209 /// Tests synchronization between variables through several operations
209 /// Tests synchronization between variables through several operations
210 void testSyncOneVar();
210 void testSyncOneVar();
211 };
211 };
212
212
213 namespace {
213 namespace {
214
214
215 void testSyncCase1()
215 void testSyncCase1()
216 {
216 {
217 // Id used to synchronize variables in the controller
217 // Id used to synchronize variables in the controller
218 auto syncId = QUuid::createUuid();
218 auto syncId = QUuid::createUuid();
219
219
220 /// Generates a range according to a start time and a end time (the date is the same)
220 /// Generates a range according to a start time and a end time (the date is the same)
221 auto range = [](const QTime &startTime, const QTime &endTime) {
221 auto range = [](const QTime &startTime, const QTime &endTime) {
222 return SqpRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}),
222 return SqpRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}),
223 DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})};
223 DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})};
224 };
224 };
225
225
226 auto initialRange = range({12, 0}, {13, 0});
226 auto initialRange = range({12, 0}, {13, 0});
227
227
228 Iterations iterations{};
228 Iterations iterations{};
229 // Creates variables var0, var1 and var2
229 // Creates variables var0, var1 and var2
230 iterations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
230 iterations.push_back({std::make_shared<Create>(0, initialRange), {{0, initialRange}}});
231 iterations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
231 iterations.push_back({std::make_shared<Create>(1, initialRange), {{0, initialRange}, {1, initialRange}}});
232 iterations.push_back(
232 iterations.push_back(
233 {std::make_shared<Create>(2), {{0, initialRange}, {1, initialRange}, {2, initialRange}}});
233 {std::make_shared<Create>(2, initialRange), {{0, initialRange}, {1, initialRange}, {2, initialRange}}});
234
234
235 // Adds variables into the sync group (ranges don't need to be tested here)
235 // Adds variables into the sync group (ranges don't need to be tested here)
236 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
236 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
237 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
237 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
238 iterations.push_back({std::make_shared<Synchronize>(2, syncId)});
238 iterations.push_back({std::make_shared<Synchronize>(2, syncId)});
239
239
240 // Moves var0: ranges of var0, var1 and var2 change
240 // Moves var0: ranges of var0, var1 and var2 change
241 auto newRange = range({12, 30}, {13, 30});
241 auto newRange = range({12, 30}, {13, 30});
242 iterations.push_back(
242 iterations.push_back(
243 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
243 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
244
244
245 // Moves var1: ranges of var0, var1 and var2 change
245 // Moves var1: ranges of var0, var1 and var2 change
246 newRange = range({13, 0}, {14, 0});
246 newRange = range({13, 0}, {14, 0});
247 iterations.push_back(
247 iterations.push_back(
248 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
248 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
249
249
250 // Moves var2: ranges of var0, var1 and var2 change
250 // Moves var2: ranges of var0, var1 and var2 change
251 newRange = range({13, 30}, {14, 30});
251 newRange = range({13, 30}, {14, 30});
252 iterations.push_back(
252 iterations.push_back(
253 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
253 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
254
254
255 // Desyncs var2 and moves var0:
255 // Desyncs var2 and moves var0:
256 // - ranges of var0 and var1 change
256 // - ranges of var0 and var1 change
257 // - range of var2 doesn't change anymore
257 // - range of var2 doesn't change anymore
258 auto var2Range = newRange;
258 auto var2Range = newRange;
259 newRange = range({13, 45}, {14, 45});
259 newRange = range({13, 45}, {14, 45});
260 iterations.push_back({std::make_shared<Synchronize>(2, syncId, false)});
260 iterations.push_back({std::make_shared<Synchronize>(2, syncId, false)});
261 iterations.push_back(
261 iterations.push_back(
262 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, var2Range}}});
262 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, var2Range}}});
263
263
264 // Shifts var0: although var1 is synchronized with var0, its range doesn't change
264 // Shifts var0: although var1 is synchronized with var0, its range doesn't change
265 auto var1Range = newRange;
265 auto var1Range = newRange;
266 newRange = range({14, 45}, {15, 45});
266 newRange = range({14, 45}, {15, 45});
267 iterations.push_back({std::make_shared<Move>(0, newRange, true),
267 iterations.push_back({std::make_shared<Move>(0, newRange, true),
268 {{0, newRange}, {1, var1Range}, {2, var2Range}}});
268 {{0, newRange}, {1, var1Range}, {2, var2Range}}});
269
269
270 // Moves var0 through several operations:
270 // Moves var0 through several operations:
271 // - range of var0 changes
271 // - range of var0 changes
272 // - range or var1 changes according to the previous shift (one hour)
272 // - range or var1 changes according to the previous shift (one hour)
273 auto moveVar0 = [&iterations](const auto &var0NewRange, const auto &var1ExpectedRange) {
273 auto moveVar0 = [&iterations](const auto &var0NewRange, const auto &var1ExpectedRange) {
274 iterations.push_back(
274 iterations.push_back(
275 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var1ExpectedRange}}});
275 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var1ExpectedRange}}});
276 };
276 };
277
277
278 // Pan left
278 // Pan left
279 moveVar0(range({14, 30}, {15, 30}), range({13, 30}, {14, 30}));
279 moveVar0(range({14, 30}, {15, 30}), range({13, 30}, {14, 30}));
280 // Pan right
280 // Pan right
281 moveVar0(range({16, 0}, {17, 0}), range({15, 0}, {16, 0}));
281 moveVar0(range({16, 0}, {17, 0}), range({15, 0}, {16, 0}));
282 // Zoom in
282 // Zoom in
283 moveVar0(range({16, 30}, {16, 45}), range({15, 30}, {15, 45}));
283 moveVar0(range({16, 30}, {16, 45}), range({15, 30}, {15, 45}));
284 // Zoom out
284 // Zoom out
285 moveVar0(range({16, 15}, {17, 0}), range({15, 15}, {16, 0}));
285 moveVar0(range({16, 15}, {17, 0}), range({15, 15}, {16, 0}));
286
286
287 QTest::newRow("sync1") << syncId << initialRange << std::move(iterations) << 200;
287 QTest::newRow("sync1") << syncId << initialRange << std::move(iterations) << 200;
288 }
288 }
289
289
290 void testSyncCase2()
290 void testSyncCase2()
291 {
291 {
292 // Id used to synchronize variables in the controller
292 // Id used to synchronize variables in the controller
293 auto syncId = QUuid::createUuid();
293 auto syncId = QUuid::createUuid();
294
294
295 /// Generates a range according to a start time and a end time (the date is the same)
295 /// Generates a range according to a start time and a end time (the date is the same)
296 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
296 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
297 return DateUtils::secondsSinceEpoch(
297 return DateUtils::secondsSinceEpoch(
298 QDateTime{{year, month, day}, QTime{hours, minutes, seconds}, Qt::UTC});
298 QDateTime{{year, month, day}, QTime{hours, minutes, seconds}, Qt::UTC});
299 };
299 };
300
300
301 auto initialRange = SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)};
301 auto initialRange = SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)};
302
302
303 Iterations iterations{};
303 Iterations iterations{};
304 // Creates variables var0 and var1
304 // Creates variables var0 and var1
305 iterations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
305 iterations.push_back({std::make_shared<Create>(0, initialRange), {{0, initialRange}}});
306 iterations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
306 iterations.push_back({std::make_shared<Create>(1, initialRange), {{0, initialRange}, {1, initialRange}}});
307
307
308 // Adds variables into the sync group (ranges don't need to be tested here)
308 // Adds variables into the sync group (ranges don't need to be tested here)
309 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
309 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
310 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
310 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
311
311
312
312
313 // Moves var0 through several operations:
313 // Moves var0 through several operations:
314 // - range of var0 changes
314 // - range of var0 changes
315 // - range or var1 changes according to the previous shift (one hour)
315 // - range or var1 changes according to the previous shift (one hour)
316 auto moveVar0 = [&iterations](const auto &var0NewRange) {
316 auto moveVar0 = [&iterations](const auto &var0NewRange) {
317 iterations.push_back(
317 iterations.push_back(
318 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var0NewRange}}});
318 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var0NewRange}}});
319 };
319 };
320 moveVar0(SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)});
320 moveVar0(SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)});
321 moveVar0(SqpRange{dateTime(2017, 1, 1, 14, 0, 0), dateTime(2017, 1, 1, 15, 0, 0)});
321 moveVar0(SqpRange{dateTime(2017, 1, 1, 14, 0, 0), dateTime(2017, 1, 1, 15, 0, 0)});
322 moveVar0(SqpRange{dateTime(2017, 1, 1, 8, 0, 0), dateTime(2017, 1, 1, 9, 0, 0)});
322 moveVar0(SqpRange{dateTime(2017, 1, 1, 8, 0, 0), dateTime(2017, 1, 1, 9, 0, 0)});
323 // moveVar0(SqpRange{dateTime(2017, 1, 1, 7, 30, 0), dateTime(2017, 1, 1, 9, 30, 0)});
323 // moveVar0(SqpRange{dateTime(2017, 1, 1, 7, 30, 0), dateTime(2017, 1, 1, 9, 30, 0)});
324 moveVar0(SqpRange{dateTime(2017, 1, 1, 2, 0, 0), dateTime(2017, 1, 1, 4, 0, 0)});
324 moveVar0(SqpRange{dateTime(2017, 1, 1, 2, 0, 0), dateTime(2017, 1, 1, 4, 0, 0)});
325 moveVar0(SqpRange{dateTime(2017, 1, 1, 6, 0, 0), dateTime(2017, 1, 1, 8, 0, 0)});
325 moveVar0(SqpRange{dateTime(2017, 1, 1, 6, 0, 0), dateTime(2017, 1, 1, 8, 0, 0)});
326
326
327 moveVar0(SqpRange{dateTime(2017, 1, 10, 6, 0, 0), dateTime(2017, 1, 15, 8, 0, 0)});
327 moveVar0(SqpRange{dateTime(2017, 1, 10, 6, 0, 0), dateTime(2017, 1, 15, 8, 0, 0)});
328 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 1, 25, 8, 0, 0)});
328 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 1, 25, 8, 0, 0)});
329 moveVar0(SqpRange{dateTime(2017, 1, 2, 6, 0, 0), dateTime(2017, 1, 8, 8, 0, 0)});
329 moveVar0(SqpRange{dateTime(2017, 1, 2, 6, 0, 0), dateTime(2017, 1, 8, 8, 0, 0)});
330
330
331 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
331 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
332 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
332 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
333 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
333 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
334 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
334 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
335 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
335 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
336 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
336 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
337 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
337 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
338 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
338 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
339 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
339 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
340 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
340 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
341 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
341 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
342 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
342 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
343
343
344
344
345 QTest::newRow("sync2") << syncId << initialRange << iterations << 4000;
345 QTest::newRow("sync2") << syncId << initialRange << iterations << 4000;
346 // QTest::newRow("sync3") << syncId << initialRange << iterations << 5000;
346 // QTest::newRow("sync3") << syncId << initialRange << iterations << 5000;
347 }
347 }
348
348
349 void testSyncOnVarCase1()
349 void testSyncOnVarCase1()
350 {
350 {
351 // Id used to synchronize variables in the controller
351 // Id used to synchronize variables in the controller
352 auto syncId = QUuid::createUuid();
352 auto syncId = QUuid::createUuid();
353
353
354 /// Generates a range according to a start time and a end time (the date is the same)
354 /// Generates a range according to a start time and a end time (the date is the same)
355 auto range = [](const QTime &startTime, const QTime &endTime) {
355 auto range = [](const QTime &startTime, const QTime &endTime) {
356 return SqpRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}),
356 return SqpRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}),
357 DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})};
357 DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})};
358 };
358 };
359
359
360 auto initialRange = range({12, 0}, {13, 0});
360 auto initialRange = range({12, 0}, {13, 0});
361
361
362 Iterations creations{};
362 Iterations creations{};
363 // Creates variables var0, var1 and var2
363 // Creates variables var0, var1 and var2
364 creations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
364 creations.push_back({std::make_shared<Create>(0, initialRange), {{0, initialRange}}});
365
365
366 Iterations synchronization{};
366 Iterations synchronization{};
367 // Adds variables into the sync group (ranges don't need to be tested here)
367 // Adds variables into the sync group (ranges don't need to be tested here)
368 synchronization.push_back({std::make_shared<Synchronize>(0, syncId)});
368 synchronization.push_back({std::make_shared<Synchronize>(0, syncId)});
369
369
370 Iterations iterations{};
370 Iterations iterations{};
371
371
372 // Moves var0 through several operations
372 // Moves var0 through several operations
373 auto moveOp = [&iterations](const auto &requestedRange, const auto &expectedRange, auto delay) {
373 auto moveOp = [&iterations](const auto &requestedRange, const auto &expectedRange, auto delay) {
374 iterations.push_back(
374 iterations.push_back(
375 {std::make_shared<Move>(0, requestedRange, true, delay), {{0, expectedRange}}});
375 {std::make_shared<Move>(0, requestedRange, true, delay), {{0, expectedRange}}});
376 };
376 };
377
377
378 // we assume here 300 ms is enough to finsh a operation
378 // we assume here 300 ms is enough to finsh a operation
379 int delayToFinish = 300;
379 int delayToFinish = 300;
380 // jump to right, let's the operation time to finish
380 // jump to right, let's the operation time to finish
381 moveOp(range({14, 30}, {15, 30}), range({14, 30}, {15, 30}), delayToFinish);
381 moveOp(range({14, 30}, {15, 30}), range({14, 30}, {15, 30}), delayToFinish);
382 // pan to right, let's the operation time to finish
382 // pan to right, let's the operation time to finish
383 moveOp(range({14, 45}, {15, 45}), range({14, 45}, {15, 45}), delayToFinish);
383 moveOp(range({14, 45}, {15, 45}), range({14, 45}, {15, 45}), delayToFinish);
384 // jump to left, let's the operation time to finish
384 // jump to left, let's the operation time to finish
385 moveOp(range({03, 30}, {04, 30}), range({03, 30}, {04, 30}), delayToFinish);
385 moveOp(range({03, 30}, {04, 30}), range({03, 30}, {04, 30}), delayToFinish);
386 // Pan to left, let's the operation time to finish
386 // Pan to left, let's the operation time to finish
387 moveOp(range({03, 10}, {04, 10}), range({03, 10}, {04, 10}), delayToFinish);
387 moveOp(range({03, 10}, {04, 10}), range({03, 10}, {04, 10}), delayToFinish);
388 // Zoom in, let's the operation time to finish
388 // Zoom in, let's the operation time to finish
389 moveOp(range({03, 30}, {04, 00}), range({03, 30}, {04, 00}), delayToFinish);
389 moveOp(range({03, 30}, {04, 00}), range({03, 30}, {04, 00}), delayToFinish);
390 // Zoom out left, let's the operation time to finish
390 // Zoom out left, let's the operation time to finish
391 moveOp(range({01, 10}, {18, 10}), range({01, 10}, {18, 10}), delayToFinish);
391 moveOp(range({01, 10}, {18, 10}), range({01, 10}, {18, 10}), delayToFinish);
392 // Go back to initial range
392 // Go back to initial range
393 moveOp(initialRange, initialRange, delayToFinish);
393 moveOp(initialRange, initialRange, delayToFinish);
394
394
395
395
396 // jump to right, let's the operation time to finish
396 // jump to right, let's the operation time to finish
397 // moveOp(range({14, 30}, {15, 30}), initialRange, delayToFinish);
397 // moveOp(range({14, 30}, {15, 30}), initialRange, delayToFinish);
398 // Zoom out left, let's the operation time to finish
398 // Zoom out left, let's the operation time to finish
399 moveOp(range({01, 10}, {18, 10}), initialRange, delayToFinish);
399 moveOp(range({01, 10}, {18, 10}), initialRange, delayToFinish);
400 // Go back to initial range
400 // Go back to initial range
401 moveOp(initialRange, initialRange, 300);
401 moveOp(initialRange, initialRange, 300);
402
402
403 QTest::newRow("syncOnVarCase1") << syncId << initialRange << std::move(creations)
403 QTest::newRow("syncOnVarCase1") << syncId << initialRange << std::move(creations)
404 << std::move(iterations);
404 << std::move(iterations);
405 }
405 }
406 }
406 }
407
407
408 void TestVariableSync::testSync_data()
408 void TestVariableSync::testSync_data()
409 {
409 {
410 // ////////////// //
410 // ////////////// //
411 // Test structure //
411 // Test structure //
412 // ////////////// //
412 // ////////////// //
413
413
414 QTest::addColumn<QUuid>("syncId");
414 QTest::addColumn<QUuid>("syncId");
415 QTest::addColumn<SqpRange>("initialRange");
415 QTest::addColumn<SqpRange>("initialRange");
416 QTest::addColumn<Iterations>("iterations");
416 QTest::addColumn<Iterations>("iterations");
417 QTest::addColumn<int>("operationDelay");
417 QTest::addColumn<int>("operationDelay");
418
418
419 // ////////// //
419 // ////////// //
420 // Test cases //
420 // Test cases //
421 // ////////// //
421 // ////////// //
422
422
423 testSyncCase1();
423 testSyncCase1();
424 testSyncCase2();
424 testSyncCase2();
425 }
425 }
426
426
427 void TestVariableSync::testSyncOneVar_data()
427 void TestVariableSync::testSyncOneVar_data()
428 {
428 {
429 // ////////////// //
429 // ////////////// //
430 // Test structure //
430 // Test structure //
431 // ////////////// //
431 // ////////////// //
432
432
433 QTest::addColumn<QUuid>("syncId");
433 QTest::addColumn<QUuid>("syncId");
434 QTest::addColumn<SqpRange>("initialRange");
434 QTest::addColumn<SqpRange>("initialRange");
435 QTest::addColumn<Iterations>("creations");
435 QTest::addColumn<Iterations>("creations");
436 QTest::addColumn<Iterations>("iterations");
436 QTest::addColumn<Iterations>("iterations");
437
437
438 // ////////// //
438 // ////////// //
439 // Test cases //
439 // Test cases //
440 // ////////// //
440 // ////////// //
441
441
442 testSyncOnVarCase1();
442 testSyncOnVarCase1();
443 }
443 }
444
444
445 void TestVariableSync::testSync()
445 void TestVariableSync::testSync()
446 {
446 {
447 // Inits controllers
447 // Inits controllers
448 TimeController timeController{};
448 TimeController timeController{};
449 VariableController variableController{};
449 VariableController variableController{};
450 variableController.setTimeController(&timeController);
450 //variableController.setTimeController(&timeController);
451
451
452 QFETCH(QUuid, syncId);
452 QFETCH(QUuid, syncId);
453 QFETCH(SqpRange, initialRange);
453 QFETCH(SqpRange, initialRange);
454 timeController.onTimeToUpdate(initialRange);
454 timeController.setDateTimeRange(initialRange);
455
455
456 // Synchronization group used
456 // Synchronization group used
457 variableController.onAddSynchronizationGroupId(syncId);
457 variableController.onAddSynchronizationGroupId(syncId);
458
458
459 // For each iteration:
459 // For each iteration:
460 // - execute operation
460 // - execute operation
461 // - compare the variables' state to the expected states
461 // - compare the variables' state to the expected states
462 QFETCH(Iterations, iterations);
462 QFETCH(Iterations, iterations);
463 QFETCH(int, operationDelay);
463 QFETCH(int, operationDelay);
464 for (const auto &iteration : iterations) {
464 for (const auto &iteration : iterations) {
465 iteration.m_Operation->exec(variableController);
465 iteration.m_Operation->exec(variableController);
466 QTest::qWait(operationDelay);
466 QTest::qWait(operationDelay);
467
467
468 validateRanges(variableController, iteration.m_ExpectedRanges);
468 validateRanges(variableController, iteration.m_ExpectedRanges);
469 }
469 }
470 }
470 }
471
471
472 void TestVariableSync::testSyncOneVar()
472 void TestVariableSync::testSyncOneVar()
473 {
473 {
474 // Inits controllers
474 // Inits controllers
475 TimeController timeController{};
475 TimeController timeController{};
476 VariableController variableController{};
476 VariableController variableController{};
477 variableController.setTimeController(&timeController);
477 //variableController.setTimeController(&timeController);
478
478
479 QFETCH(QUuid, syncId);
479 QFETCH(QUuid, syncId);
480 QFETCH(SqpRange, initialRange);
480 QFETCH(SqpRange, initialRange);
481 timeController.onTimeToUpdate(initialRange);
481 timeController.setDateTimeRange(initialRange);
482
482
483 // Synchronization group used
483 // Synchronization group used
484 variableController.onAddSynchronizationGroupId(syncId);
484 variableController.onAddSynchronizationGroupId(syncId);
485
485
486 // For each iteration:
486 // For each iteration:
487 // - execute operation
487 // - execute operation
488 // - compare the variables' state to the expected states
488 // - compare the variables' state to the expected states
489 QFETCH(Iterations, iterations);
489 QFETCH(Iterations, iterations);
490 QFETCH(Iterations, creations);
490 QFETCH(Iterations, creations);
491
491
492 for (const auto &creation : creations) {
492 for (const auto &creation : creations) {
493 creation.m_Operation->exec(variableController);
493 creation.m_Operation->exec(variableController);
494 QTest::qWait(300);
494 QTest::qWait(300);
495 }
495 }
496
496
497 for (const auto &iteration : iterations) {
497 for (const auto &iteration : iterations) {
498 iteration.m_Operation->exec(variableController);
498 iteration.m_Operation->exec(variableController);
499 }
499 }
500
500
501 if (!iterations.empty()) {
501 if (!iterations.empty()) {
502 validateRanges(variableController, iterations.back().m_ExpectedRanges);
502 validateRanges(variableController, iterations.back().m_ExpectedRanges);
503 }
503 }
504 }
504 }
505
505
506 QTEST_MAIN(TestVariableSync)
506 QTEST_MAIN(TestVariableSync)
507
507
508 #include "TestVariableSync.moc"
508 #include "TestVariableSync.moc"
@@ -1,207 +1,207
1 #include "SqpApplication.h"
1 #include "SqpApplication.h"
2
2
3 #include <Actions/ActionsGuiController.h>
3 #include <Actions/ActionsGuiController.h>
4 #include <Catalogue/CatalogueController.h>
4 #include <Catalogue/CatalogueController.h>
5 #include <Data/IDataProvider.h>
5 #include <Data/IDataProvider.h>
6 #include <DataSource/DataSourceController.h>
6 #include <DataSource/DataSourceController.h>
7 #include <DragAndDrop/DragDropGuiController.h>
7 #include <DragAndDrop/DragDropGuiController.h>
8 #include <Network/NetworkController.h>
8 #include <Network/NetworkController.h>
9 #include <QThread>
9 #include <QThread>
10 #include <Time/TimeController.h>
10 #include <Time/TimeController.h>
11 #include <Variable/Variable.h>
11 #include <Variable/Variable.h>
12 #include <Variable/VariableController.h>
12 #include <Variable/VariableController.h>
13 #include <Variable/VariableModel.h>
13 #include <Variable/VariableModel.h>
14 #include <Visualization/VisualizationController.h>
14 #include <Visualization/VisualizationController.h>
15
15
16 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
16 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
17
17
18 class SqpApplication::SqpApplicationPrivate {
18 class SqpApplication::SqpApplicationPrivate {
19 public:
19 public:
20 SqpApplicationPrivate()
20 SqpApplicationPrivate()
21 : m_DataSourceController{std::make_unique<DataSourceController>()},
21 : m_DataSourceController{std::make_unique<DataSourceController>()},
22 m_VariableController{std::make_unique<VariableController>()},
22 m_VariableController{std::make_unique<VariableController>()},
23 m_TimeController{std::make_unique<TimeController>()},
23 m_TimeController{std::make_unique<TimeController>()},
24 m_NetworkController{std::make_unique<NetworkController>()},
24 m_NetworkController{std::make_unique<NetworkController>()},
25 m_VisualizationController{std::make_unique<VisualizationController>()},
25 m_VisualizationController{std::make_unique<VisualizationController>()},
26 m_DragDropGuiController{std::make_unique<DragDropGuiController>()},
26 m_DragDropGuiController{std::make_unique<DragDropGuiController>()},
27 m_CatalogueController{std::make_unique<CatalogueController>()},
27 m_CatalogueController{std::make_unique<CatalogueController>()},
28 m_ActionsGuiController{std::make_unique<ActionsGuiController>()},
28 m_ActionsGuiController{std::make_unique<ActionsGuiController>()},
29 m_PlotInterractionMode(SqpApplication::PlotsInteractionMode::None),
29 m_PlotInterractionMode(SqpApplication::PlotsInteractionMode::None),
30 m_PlotCursorMode(SqpApplication::PlotsCursorMode::NoCursor)
30 m_PlotCursorMode(SqpApplication::PlotsCursorMode::NoCursor)
31 {
31 {
32 // /////////////////////////////// //
32 // /////////////////////////////// //
33 // Connections between controllers //
33 // Connections between controllers //
34 // /////////////////////////////// //
34 // /////////////////////////////// //
35
35
36 // VariableController <-> DataSourceController
36 // VariableController <-> DataSourceController
37 connect(m_DataSourceController.get(),
37 connect(m_DataSourceController.get(),
38 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
38 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
39 std::shared_ptr<IDataProvider>)),
39 std::shared_ptr<IDataProvider>)),
40 m_VariableController.get(),
40 m_VariableController.get(),
41 SLOT(createVariable(const QString &, const QVariantHash &,
41 SLOT(createVariable(const QString &, const QVariantHash &,
42 std::shared_ptr<IDataProvider>)));
42 std::shared_ptr<IDataProvider>)));
43
43
44 connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
44 connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
45 m_DataSourceController.get(), &DataSourceController::requestVariable);
45 m_DataSourceController.get(), &DataSourceController::requestVariable);
46
46
47 // VariableController <-> VisualizationController
47 // VariableController <-> VisualizationController
48 connect(m_VariableController.get(),
48 connect(m_VariableController.get(),
49 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
49 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
50 m_VisualizationController.get(),
50 m_VisualizationController.get(),
51 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
51 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
52
52
53 connect(m_VariableController.get(),
53 connect(m_VariableController.get(),
54 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
54 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
55 m_VisualizationController.get(),
55 m_VisualizationController.get(),
56 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
56 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
57
57
58
58
59 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
59 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
60 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
60 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
61 m_NetworkController->moveToThread(&m_NetworkControllerThread);
61 m_NetworkController->moveToThread(&m_NetworkControllerThread);
62 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
62 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
63 m_VariableController->moveToThread(&m_VariableControllerThread);
63 m_VariableController->moveToThread(&m_VariableControllerThread);
64 m_VariableControllerThread.setObjectName("VariableControllerThread");
64 m_VariableControllerThread.setObjectName("VariableControllerThread");
65 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
65 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
66 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
66 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
67
67
68 // Additionnal init
68 // Additionnal init
69 m_VariableController->setTimeController(m_TimeController.get());
69 //m_VariableController->setTimeController(m_TimeController.get());
70 }
70 }
71
71
72 virtual ~SqpApplicationPrivate()
72 virtual ~SqpApplicationPrivate()
73 {
73 {
74 m_DataSourceControllerThread.quit();
74 m_DataSourceControllerThread.quit();
75 m_DataSourceControllerThread.wait();
75 m_DataSourceControllerThread.wait();
76
76
77 m_NetworkControllerThread.quit();
77 m_NetworkControllerThread.quit();
78 m_NetworkControllerThread.wait();
78 m_NetworkControllerThread.wait();
79
79
80 m_VariableControllerThread.quit();
80 m_VariableControllerThread.quit();
81 m_VariableControllerThread.wait();
81 m_VariableControllerThread.wait();
82
82
83 m_VisualizationControllerThread.quit();
83 m_VisualizationControllerThread.quit();
84 m_VisualizationControllerThread.wait();
84 m_VisualizationControllerThread.wait();
85 }
85 }
86
86
87 std::unique_ptr<DataSourceController> m_DataSourceController;
87 std::unique_ptr<DataSourceController> m_DataSourceController;
88 std::unique_ptr<VariableController> m_VariableController;
88 std::unique_ptr<VariableController> m_VariableController;
89 std::unique_ptr<TimeController> m_TimeController;
89 std::unique_ptr<TimeController> m_TimeController;
90 std::unique_ptr<NetworkController> m_NetworkController;
90 std::unique_ptr<NetworkController> m_NetworkController;
91 std::unique_ptr<VisualizationController> m_VisualizationController;
91 std::unique_ptr<VisualizationController> m_VisualizationController;
92 std::unique_ptr<CatalogueController> m_CatalogueController;
92 std::unique_ptr<CatalogueController> m_CatalogueController;
93
93
94 QThread m_DataSourceControllerThread;
94 QThread m_DataSourceControllerThread;
95 QThread m_NetworkControllerThread;
95 QThread m_NetworkControllerThread;
96 QThread m_VariableControllerThread;
96 QThread m_VariableControllerThread;
97 QThread m_VisualizationControllerThread;
97 QThread m_VisualizationControllerThread;
98
98
99 std::unique_ptr<DragDropGuiController> m_DragDropGuiController;
99 std::unique_ptr<DragDropGuiController> m_DragDropGuiController;
100 std::unique_ptr<ActionsGuiController> m_ActionsGuiController;
100 std::unique_ptr<ActionsGuiController> m_ActionsGuiController;
101
101
102 SqpApplication::PlotsInteractionMode m_PlotInterractionMode;
102 SqpApplication::PlotsInteractionMode m_PlotInterractionMode;
103 SqpApplication::PlotsCursorMode m_PlotCursorMode;
103 SqpApplication::PlotsCursorMode m_PlotCursorMode;
104 };
104 };
105
105
106
106
107 SqpApplication::SqpApplication(int &argc, char **argv)
107 SqpApplication::SqpApplication(int &argc, char **argv)
108 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
108 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
109 {
109 {
110 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
110 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
111
111
112 QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
112 QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
113
113
114 connect(&impl->m_DataSourceControllerThread, &QThread::started,
114 connect(&impl->m_DataSourceControllerThread, &QThread::started,
115 impl->m_DataSourceController.get(), &DataSourceController::initialize);
115 impl->m_DataSourceController.get(), &DataSourceController::initialize);
116 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
116 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
117 impl->m_DataSourceController.get(), &DataSourceController::finalize);
117 impl->m_DataSourceController.get(), &DataSourceController::finalize);
118
118
119 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
119 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
120 &NetworkController::initialize);
120 &NetworkController::initialize);
121 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
121 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
122 &NetworkController::finalize);
122 &NetworkController::finalize);
123
123
124 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
124 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
125 &VariableController::initialize);
125 &VariableController::initialize);
126 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
126 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
127 &VariableController::finalize);
127 &VariableController::finalize);
128
128
129 connect(&impl->m_VisualizationControllerThread, &QThread::started,
129 connect(&impl->m_VisualizationControllerThread, &QThread::started,
130 impl->m_VisualizationController.get(), &VisualizationController::initialize);
130 impl->m_VisualizationController.get(), &VisualizationController::initialize);
131 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
131 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
132 impl->m_VisualizationController.get(), &VisualizationController::finalize);
132 impl->m_VisualizationController.get(), &VisualizationController::finalize);
133
133
134 impl->m_DataSourceControllerThread.start();
134 impl->m_DataSourceControllerThread.start();
135 impl->m_NetworkControllerThread.start();
135 impl->m_NetworkControllerThread.start();
136 impl->m_VariableControllerThread.start();
136 impl->m_VariableControllerThread.start();
137 impl->m_VisualizationControllerThread.start();
137 impl->m_VisualizationControllerThread.start();
138 impl->m_CatalogueController->initialize();
138 impl->m_CatalogueController->initialize();
139 }
139 }
140
140
141 SqpApplication::~SqpApplication()
141 SqpApplication::~SqpApplication()
142 {
142 {
143 }
143 }
144
144
145 void SqpApplication::initialize()
145 void SqpApplication::initialize()
146 {
146 {
147 }
147 }
148
148
149 DataSourceController &SqpApplication::dataSourceController() noexcept
149 DataSourceController &SqpApplication::dataSourceController() noexcept
150 {
150 {
151 return *impl->m_DataSourceController;
151 return *impl->m_DataSourceController;
152 }
152 }
153
153
154 NetworkController &SqpApplication::networkController() noexcept
154 NetworkController &SqpApplication::networkController() noexcept
155 {
155 {
156 return *impl->m_NetworkController;
156 return *impl->m_NetworkController;
157 }
157 }
158
158
159 TimeController &SqpApplication::timeController() noexcept
159 TimeController &SqpApplication::timeController() noexcept
160 {
160 {
161 return *impl->m_TimeController;
161 return *impl->m_TimeController;
162 }
162 }
163
163
164 VariableController &SqpApplication::variableController() noexcept
164 VariableController &SqpApplication::variableController() noexcept
165 {
165 {
166 return *impl->m_VariableController;
166 return *impl->m_VariableController;
167 }
167 }
168
168
169 VisualizationController &SqpApplication::visualizationController() noexcept
169 VisualizationController &SqpApplication::visualizationController() noexcept
170 {
170 {
171 return *impl->m_VisualizationController;
171 return *impl->m_VisualizationController;
172 }
172 }
173
173
174 CatalogueController &SqpApplication::catalogueController() noexcept
174 CatalogueController &SqpApplication::catalogueController() noexcept
175 {
175 {
176 return *impl->m_CatalogueController;
176 return *impl->m_CatalogueController;
177 }
177 }
178
178
179 DragDropGuiController &SqpApplication::dragDropGuiController() noexcept
179 DragDropGuiController &SqpApplication::dragDropGuiController() noexcept
180 {
180 {
181 return *impl->m_DragDropGuiController;
181 return *impl->m_DragDropGuiController;
182 }
182 }
183
183
184 ActionsGuiController &SqpApplication::actionsGuiController() noexcept
184 ActionsGuiController &SqpApplication::actionsGuiController() noexcept
185 {
185 {
186 return *impl->m_ActionsGuiController;
186 return *impl->m_ActionsGuiController;
187 }
187 }
188
188
189 SqpApplication::PlotsInteractionMode SqpApplication::plotsInteractionMode() const
189 SqpApplication::PlotsInteractionMode SqpApplication::plotsInteractionMode() const
190 {
190 {
191 return impl->m_PlotInterractionMode;
191 return impl->m_PlotInterractionMode;
192 }
192 }
193
193
194 void SqpApplication::setPlotsInteractionMode(SqpApplication::PlotsInteractionMode mode)
194 void SqpApplication::setPlotsInteractionMode(SqpApplication::PlotsInteractionMode mode)
195 {
195 {
196 impl->m_PlotInterractionMode = mode;
196 impl->m_PlotInterractionMode = mode;
197 }
197 }
198
198
199 SqpApplication::PlotsCursorMode SqpApplication::plotsCursorMode() const
199 SqpApplication::PlotsCursorMode SqpApplication::plotsCursorMode() const
200 {
200 {
201 return impl->m_PlotCursorMode;
201 return impl->m_PlotCursorMode;
202 }
202 }
203
203
204 void SqpApplication::setPlotsCursorMode(SqpApplication::PlotsCursorMode mode)
204 void SqpApplication::setPlotsCursorMode(SqpApplication::PlotsCursorMode mode)
205 {
205 {
206 impl->m_PlotCursorMode = mode;
206 impl->m_PlotCursorMode = mode;
207 }
207 }
@@ -1,154 +1,154
1 #include "TimeWidget/TimeWidget.h"
1 #include "TimeWidget/TimeWidget.h"
2 #include "ui_TimeWidget.h"
2 #include "ui_TimeWidget.h"
3
3
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5 #include <Common/MimeTypesDef.h>
5 #include <Common/MimeTypesDef.h>
6
6
7 #include <DragAndDrop/DragDropGuiController.h>
7 #include <DragAndDrop/DragDropGuiController.h>
8 #include <SqpApplication.h>
8 #include <SqpApplication.h>
9 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
10
10
11 #include <QDrag>
11 #include <QDrag>
12 #include <QDragEnterEvent>
12 #include <QDragEnterEvent>
13 #include <QDropEvent>
13 #include <QDropEvent>
14 #include <QMimeData>
14 #include <QMimeData>
15
15
16
16
17 struct TimeWidget::TimeWidgetPrivate {
17 struct TimeWidget::TimeWidgetPrivate {
18
18
19 explicit TimeWidgetPrivate() {}
19 explicit TimeWidgetPrivate() {}
20
20
21 QPoint m_DragStartPosition;
21 QPoint m_DragStartPosition;
22 };
22 };
23
23
24 TimeWidget::TimeWidget(QWidget *parent)
24 TimeWidget::TimeWidget(QWidget *parent)
25 : QWidget{parent},
25 : QWidget{parent},
26 ui{new Ui::TimeWidget},
26 ui{new Ui::TimeWidget},
27 impl{spimpl::make_unique_impl<TimeWidgetPrivate>()}
27 impl{spimpl::make_unique_impl<TimeWidgetPrivate>()}
28 {
28 {
29 ui->setupUi(this);
29 ui->setupUi(this);
30
30
31 ui->applyToolButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_DialogApplyButton));
31 ui->applyToolButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_DialogApplyButton));
32
32
33 // Connection
33 // Connection
34 connect(ui->startDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
34 connect(ui->startDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
35 &TimeWidget::onTimeUpdateRequested);
35 &TimeWidget::onTimeUpdateRequested);
36
36
37 connect(ui->endDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
37 connect(ui->endDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
38 &TimeWidget::onTimeUpdateRequested);
38 &TimeWidget::onTimeUpdateRequested);
39
39
40
40
41 connect(ui->applyToolButton, &QToolButton::clicked, &sqpApp->timeController(),
41 connect(ui->applyToolButton, &QToolButton::clicked, &sqpApp->timeController(),
42 &TimeController::onTimeNotify);
42 &TimeController::onTimeNotify);
43
43
44 // Initialisation
44 // Initialisation
45 auto endDateTime = QDateTime::currentDateTimeUtc();
45 auto endDateTime = QDateTime::currentDateTimeUtc();
46 auto startDateTime = endDateTime.addSecs(-3600); // one hour before
46 auto startDateTime = endDateTime.addSecs(-3600); // one hour before
47
47
48 ui->startDateTimeEdit->setDateTime(startDateTime);
48 ui->startDateTimeEdit->setDateTime(startDateTime);
49 ui->endDateTimeEdit->setDateTime(endDateTime);
49 ui->endDateTimeEdit->setDateTime(endDateTime);
50
50
51 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(startDateTime),
51 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(startDateTime),
52 DateUtils::secondsSinceEpoch(endDateTime)};
52 DateUtils::secondsSinceEpoch(endDateTime)};
53
53
54 sqpApp->timeController().onTimeToUpdate(dateTime);
54 sqpApp->timeController().setDateTimeRange(dateTime);
55 }
55 }
56
56
57
57
58 TimeWidget::~TimeWidget()
58 TimeWidget::~TimeWidget()
59 {
59 {
60 delete ui;
60 delete ui;
61 }
61 }
62
62
63 void TimeWidget::setTimeRange(SqpRange time)
63 void TimeWidget::setTimeRange(SqpRange time)
64 {
64 {
65 auto startDateTime = DateUtils::dateTime(time.m_TStart);
65 auto startDateTime = DateUtils::dateTime(time.m_TStart);
66 auto endDateTime = DateUtils::dateTime(time.m_TEnd);
66 auto endDateTime = DateUtils::dateTime(time.m_TEnd);
67
67
68 ui->startDateTimeEdit->setDateTime(startDateTime);
68 ui->startDateTimeEdit->setDateTime(startDateTime);
69 ui->endDateTimeEdit->setDateTime(endDateTime);
69 ui->endDateTimeEdit->setDateTime(endDateTime);
70 }
70 }
71
71
72 SqpRange TimeWidget::timeRange() const
72 SqpRange TimeWidget::timeRange() const
73 {
73 {
74 return SqpRange{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
74 return SqpRange{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
75 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
75 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
76 }
76 }
77
77
78 void TimeWidget::onTimeUpdateRequested()
78 void TimeWidget::onTimeUpdateRequested()
79 {
79 {
80 auto dateTime = timeRange();
80 auto dateTime = timeRange();
81 emit timeUpdated(std::move(dateTime));
81 emit timeUpdated(std::move(dateTime));
82 }
82 }
83
83
84 void TimeWidget::dragEnterEvent(QDragEnterEvent *event)
84 void TimeWidget::dragEnterEvent(QDragEnterEvent *event)
85 {
85 {
86 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
86 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
87 event->acceptProposedAction();
87 event->acceptProposedAction();
88 setStyleSheet("QDateTimeEdit{background-color: #BBD5EE; border:2px solid #2A7FD4}");
88 setStyleSheet("QDateTimeEdit{background-color: #BBD5EE; border:2px solid #2A7FD4}");
89 }
89 }
90 else {
90 else {
91 event->ignore();
91 event->ignore();
92 }
92 }
93 }
93 }
94
94
95 void TimeWidget::dragLeaveEvent(QDragLeaveEvent *event)
95 void TimeWidget::dragLeaveEvent(QDragLeaveEvent *event)
96 {
96 {
97 setStyleSheet(QString{});
97 setStyleSheet(QString{});
98 }
98 }
99
99
100 void TimeWidget::dropEvent(QDropEvent *event)
100 void TimeWidget::dropEvent(QDropEvent *event)
101 {
101 {
102 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
102 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
103 auto mimeData = event->mimeData()->data(MIME_TYPE_TIME_RANGE);
103 auto mimeData = event->mimeData()->data(MIME_TYPE_TIME_RANGE);
104 auto timeRange = TimeController::timeRangeForMimeData(mimeData);
104 auto timeRange = TimeController::timeRangeForMimeData(mimeData);
105
105
106 setTimeRange(timeRange);
106 setTimeRange(timeRange);
107 }
107 }
108 else {
108 else {
109 event->ignore();
109 event->ignore();
110 }
110 }
111
111
112 setStyleSheet(QString{});
112 setStyleSheet(QString{});
113 }
113 }
114
114
115
115
116 void TimeWidget::mousePressEvent(QMouseEvent *event)
116 void TimeWidget::mousePressEvent(QMouseEvent *event)
117 {
117 {
118 if (event->button() == Qt::LeftButton) {
118 if (event->button() == Qt::LeftButton) {
119 impl->m_DragStartPosition = event->pos();
119 impl->m_DragStartPosition = event->pos();
120 }
120 }
121
121
122 QWidget::mousePressEvent(event);
122 QWidget::mousePressEvent(event);
123 }
123 }
124
124
125 void TimeWidget::mouseMoveEvent(QMouseEvent *event)
125 void TimeWidget::mouseMoveEvent(QMouseEvent *event)
126 {
126 {
127 if (!(event->buttons() & Qt::LeftButton)) {
127 if (!(event->buttons() & Qt::LeftButton)) {
128 return;
128 return;
129 }
129 }
130
130
131 if ((event->pos() - impl->m_DragStartPosition).manhattanLength()
131 if ((event->pos() - impl->m_DragStartPosition).manhattanLength()
132 < QApplication::startDragDistance()) {
132 < QApplication::startDragDistance()) {
133 return;
133 return;
134 }
134 }
135
135
136 // Note: The management of the drag object is done by Qt
136 // Note: The management of the drag object is done by Qt
137 auto drag = new QDrag{this};
137 auto drag = new QDrag{this};
138
138
139 auto mimeData = new QMimeData;
139 auto mimeData = new QMimeData;
140 auto timeData = TimeController::mimeDataForTimeRange(timeRange());
140 auto timeData = TimeController::mimeDataForTimeRange(timeRange());
141 mimeData->setData(MIME_TYPE_TIME_RANGE, timeData);
141 mimeData->setData(MIME_TYPE_TIME_RANGE, timeData);
142
142
143 drag->setMimeData(mimeData);
143 drag->setMimeData(mimeData);
144
144
145 auto pixmap = QPixmap{":/icones/time.png"};
145 auto pixmap = QPixmap{":/icones/time.png"};
146 drag->setPixmap(pixmap.scaledToWidth(22));
146 drag->setPixmap(pixmap.scaledToWidth(22));
147
147
148 sqpApp->dragDropGuiController().resetDragAndDrop();
148 sqpApp->dragDropGuiController().resetDragAndDrop();
149
149
150 // Note: The exec() is blocking on windows but not on linux and macOS
150 // Note: The exec() is blocking on windows but not on linux and macOS
151 drag->exec(Qt::MoveAction | Qt::CopyAction);
151 drag->exec(Qt::MoveAction | Qt::CopyAction);
152
152
153 QWidget::mouseMoveEvent(event);
153 QWidget::mouseMoveEvent(event);
154 }
154 }
@@ -1,268 +1,268
1 #include "FuzzingOperations.h"
1 #include "FuzzingOperations.h"
2 #include "FuzzingUtils.h"
2 #include "FuzzingUtils.h"
3
3
4 #include <Data/IDataProvider.h>
4 #include <Data/IDataProvider.h>
5
5
6 #include <Variable/Variable.h>
6 #include <Variable/Variable.h>
7 #include <Variable/VariableController.h>
7 #include <Variable/VariableController.h>
8
8
9 #include <QUuid>
9 #include <QUuid>
10
10
11 #include <functional>
11 #include <functional>
12
12
13 Q_LOGGING_CATEGORY(LOG_FuzzingOperations, "FuzzingOperations")
13 Q_LOGGING_CATEGORY(LOG_FuzzingOperations, "FuzzingOperations")
14
14
15 namespace {
15 namespace {
16
16
17 struct CreateOperation : public IFuzzingOperation {
17 struct CreateOperation : public IFuzzingOperation {
18 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
18 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
19 {
19 {
20 // A variable can be created only if it doesn't exist yet
20 // A variable can be created only if it doesn't exist yet
21 return fuzzingState.variableState(variableId).m_Variable == nullptr;
21 return fuzzingState.variableState(variableId).m_Variable == nullptr;
22 }
22 }
23
23
24 void execute(VariableId variableId, FuzzingState &fuzzingState,
24 void execute(VariableId variableId, FuzzingState &fuzzingState,
25 VariableController &variableController,
25 VariableController &variableController,
26 const Properties &properties) const override
26 const Properties &properties) const override
27 {
27 {
28 // Retrieves metadata pool from properties, and choose one of the metadata entries to
28 // Retrieves metadata pool from properties, and choose one of the metadata entries to
29 // associate it with the variable
29 // associate it with the variable
30 auto metaDataPool = properties.value(METADATA_POOL_PROPERTY).value<MetadataPool>();
30 auto metaDataPool = properties.value(METADATA_POOL_PROPERTY).value<MetadataPool>();
31 auto variableMetadata = RandomGenerator::instance().randomChoice(metaDataPool);
31 auto variableMetadata = RandomGenerator::instance().randomChoice(metaDataPool);
32
32
33 // Retrieves provider
33 // Retrieves provider
34 auto variableProvider
34 auto variableProvider
35 = properties.value(PROVIDER_PROPERTY).value<std::shared_ptr<IDataProvider> >();
35 = properties.value(PROVIDER_PROPERTY).value<std::shared_ptr<IDataProvider> >();
36
36
37 auto variableName = QString{"Var_%1"}.arg(QUuid::createUuid().toString());
37 auto variableName = QString{"Var_%1"}.arg(QUuid::createUuid().toString());
38 qCInfo(LOG_FuzzingOperations()).noquote() << "Creating variable" << variableName
38 qCInfo(LOG_FuzzingOperations()).noquote() << "Creating variable" << variableName
39 << "(metadata:" << variableMetadata << ")...";
39 << "(metadata:" << variableMetadata << ")...";
40
40
41 auto newVariable
41 auto newVariable
42 = variableController.createVariable(variableName, variableMetadata, variableProvider);
42 = variableController.createVariable(variableName, variableMetadata, variableProvider, properties.value(INITIAL_RANGE_PROPERTY).value<SqpRange>());
43
43
44 // Updates variable's state
44 // Updates variable's state
45 auto &variableState = fuzzingState.variableState(variableId);
45 auto &variableState = fuzzingState.variableState(variableId);
46 variableState.m_Range = properties.value(INITIAL_RANGE_PROPERTY).value<SqpRange>();
46 variableState.m_Range = properties.value(INITIAL_RANGE_PROPERTY).value<SqpRange>();
47 std::swap(variableState.m_Variable, newVariable);
47 std::swap(variableState.m_Variable, newVariable);
48 }
48 }
49 };
49 };
50
50
51 struct DeleteOperation : public IFuzzingOperation {
51 struct DeleteOperation : public IFuzzingOperation {
52 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
52 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
53 {
53 {
54 // A variable can be delete only if it exists
54 // A variable can be delete only if it exists
55 return fuzzingState.variableState(variableId).m_Variable != nullptr;
55 return fuzzingState.variableState(variableId).m_Variable != nullptr;
56 }
56 }
57
57
58 void execute(VariableId variableId, FuzzingState &fuzzingState,
58 void execute(VariableId variableId, FuzzingState &fuzzingState,
59 VariableController &variableController, const Properties &) const override
59 VariableController &variableController, const Properties &) const override
60 {
60 {
61 auto &variableState = fuzzingState.variableState(variableId);
61 auto &variableState = fuzzingState.variableState(variableId);
62
62
63 qCInfo(LOG_FuzzingOperations()).noquote() << "Deleting variable"
63 qCInfo(LOG_FuzzingOperations()).noquote() << "Deleting variable"
64 << variableState.m_Variable->name() << "...";
64 << variableState.m_Variable->name() << "...";
65 variableController.deleteVariable(variableState.m_Variable);
65 variableController.deleteVariable(variableState.m_Variable);
66
66
67 // Updates variable's state
67 // Updates variable's state
68 variableState.m_Range = INVALID_RANGE;
68 variableState.m_Range = INVALID_RANGE;
69 variableState.m_Variable = nullptr;
69 variableState.m_Variable = nullptr;
70
70
71 // Desynchronizes the variable if it was in a sync group
71 // Desynchronizes the variable if it was in a sync group
72 auto syncGroupId = fuzzingState.syncGroupId(variableId);
72 auto syncGroupId = fuzzingState.syncGroupId(variableId);
73 fuzzingState.desynchronizeVariable(variableId, syncGroupId);
73 fuzzingState.desynchronizeVariable(variableId, syncGroupId);
74 }
74 }
75 };
75 };
76
76
77 /**
77 /**
78 * Defines a move operation through a range.
78 * Defines a move operation through a range.
79 *
79 *
80 * A move operation is determined by three functions:
80 * A move operation is determined by three functions:
81 * - Two 'move' functions, used to indicate in which direction the beginning and the end of a range
81 * - Two 'move' functions, used to indicate in which direction the beginning and the end of a range
82 * are going during the operation. These functions will be:
82 * are going during the operation. These functions will be:
83 * -- {<- / <-} for pan left
83 * -- {<- / <-} for pan left
84 * -- {-> / ->} for pan right
84 * -- {-> / ->} for pan right
85 * -- {-> / <-} for zoom in
85 * -- {-> / <-} for zoom in
86 * -- {<- / ->} for zoom out
86 * -- {<- / ->} for zoom out
87 * - One 'max move' functions, used to compute the max delta at which the operation can move a
87 * - One 'max move' functions, used to compute the max delta at which the operation can move a
88 * range, according to a max range. For exemple, for a range of {1, 5} and a max range of {0, 10},
88 * range, according to a max range. For exemple, for a range of {1, 5} and a max range of {0, 10},
89 * max deltas will be:
89 * max deltas will be:
90 * -- {0, 4} for pan left
90 * -- {0, 4} for pan left
91 * -- {6, 10} for pan right
91 * -- {6, 10} for pan right
92 * -- {3, 3} for zoom in
92 * -- {3, 3} for zoom in
93 * -- {0, 6} for zoom out (same spacing left and right)
93 * -- {0, 6} for zoom out (same spacing left and right)
94 */
94 */
95 struct MoveOperation : public IFuzzingOperation {
95 struct MoveOperation : public IFuzzingOperation {
96 using MoveFunction = std::function<double(double currentValue, double maxValue)>;
96 using MoveFunction = std::function<double(double currentValue, double maxValue)>;
97 using MaxMoveFunction = std::function<double(const SqpRange &range, const SqpRange &maxRange)>;
97 using MaxMoveFunction = std::function<double(const SqpRange &range, const SqpRange &maxRange)>;
98
98
99 explicit MoveOperation(MoveFunction rangeStartMoveFun, MoveFunction rangeEndMoveFun,
99 explicit MoveOperation(MoveFunction rangeStartMoveFun, MoveFunction rangeEndMoveFun,
100 MaxMoveFunction maxMoveFun,
100 MaxMoveFunction maxMoveFun,
101 const QString &label = QStringLiteral("Move operation"))
101 const QString &label = QStringLiteral("Move operation"))
102 : m_RangeStartMoveFun{std::move(rangeStartMoveFun)},
102 : m_RangeStartMoveFun{std::move(rangeStartMoveFun)},
103 m_RangeEndMoveFun{std::move(rangeEndMoveFun)},
103 m_RangeEndMoveFun{std::move(rangeEndMoveFun)},
104 m_MaxMoveFun{std::move(maxMoveFun)},
104 m_MaxMoveFun{std::move(maxMoveFun)},
105 m_Label{label}
105 m_Label{label}
106 {
106 {
107 }
107 }
108
108
109 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
109 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
110 {
110 {
111 return fuzzingState.variableState(variableId).m_Variable != nullptr;
111 return fuzzingState.variableState(variableId).m_Variable != nullptr;
112 }
112 }
113
113
114 void execute(VariableId variableId, FuzzingState &fuzzingState,
114 void execute(VariableId variableId, FuzzingState &fuzzingState,
115 VariableController &variableController,
115 VariableController &variableController,
116 const Properties &properties) const override
116 const Properties &properties) const override
117 {
117 {
118 auto &variableState = fuzzingState.variableState(variableId);
118 auto &variableState = fuzzingState.variableState(variableId);
119 auto variable = variableState.m_Variable;
119 auto variable = variableState.m_Variable;
120
120
121 // Gets the max range defined
121 // Gets the max range defined
122 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
122 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
123 .value<SqpRange>();
123 .value<SqpRange>();
124 auto variableRange = variableState.m_Range;
124 auto variableRange = variableState.m_Range;
125
125
126 if (maxRange == INVALID_RANGE || variableRange.m_TStart < maxRange.m_TStart
126 if (maxRange == INVALID_RANGE || variableRange.m_TStart < maxRange.m_TStart
127 || variableRange.m_TEnd > maxRange.m_TEnd) {
127 || variableRange.m_TEnd > maxRange.m_TEnd) {
128 qCWarning(LOG_FuzzingOperations()) << "Can't execute operation: invalid max range";
128 qCWarning(LOG_FuzzingOperations()) << "Can't execute operation: invalid max range";
129 return;
129 return;
130 }
130 }
131
131
132 // Computes the max delta at which the variable can move, up to the limits of the max range
132 // Computes the max delta at which the variable can move, up to the limits of the max range
133 auto deltaMax = m_MaxMoveFun(variableRange, maxRange);
133 auto deltaMax = m_MaxMoveFun(variableRange, maxRange);
134
134
135 // Generates random delta that will be used to move variable
135 // Generates random delta that will be used to move variable
136 auto delta = RandomGenerator::instance().generateDouble(0, deltaMax);
136 auto delta = RandomGenerator::instance().generateDouble(0, deltaMax);
137
137
138 // Moves variable to its new range
138 // Moves variable to its new range
139 auto isSynchronized = !fuzzingState.syncGroupId(variableId).isNull();
139 auto isSynchronized = !fuzzingState.syncGroupId(variableId).isNull();
140 auto newVariableRange = SqpRange{m_RangeStartMoveFun(variableRange.m_TStart, delta),
140 auto newVariableRange = SqpRange{m_RangeStartMoveFun(variableRange.m_TStart, delta),
141 m_RangeEndMoveFun(variableRange.m_TEnd, delta)};
141 m_RangeEndMoveFun(variableRange.m_TEnd, delta)};
142 qCInfo(LOG_FuzzingOperations()).noquote() << "Performing" << m_Label << "on"
142 qCInfo(LOG_FuzzingOperations()).noquote() << "Performing" << m_Label << "on"
143 << variable->name() << "(from" << variableRange
143 << variable->name() << "(from" << variableRange
144 << "to" << newVariableRange << ")...";
144 << "to" << newVariableRange << ")...";
145 variableController.onRequestDataLoading({variable}, newVariableRange, isSynchronized);
145 variableController.onRequestDataLoading({variable}, newVariableRange, isSynchronized);
146
146
147 // Updates state
147 // Updates state
148 fuzzingState.updateRanges(variableId, newVariableRange);
148 fuzzingState.updateRanges(variableId, newVariableRange);
149 }
149 }
150
150
151 MoveFunction m_RangeStartMoveFun;
151 MoveFunction m_RangeStartMoveFun;
152 MoveFunction m_RangeEndMoveFun;
152 MoveFunction m_RangeEndMoveFun;
153 MaxMoveFunction m_MaxMoveFun;
153 MaxMoveFunction m_MaxMoveFun;
154 QString m_Label;
154 QString m_Label;
155 };
155 };
156
156
157 struct SynchronizeOperation : public IFuzzingOperation {
157 struct SynchronizeOperation : public IFuzzingOperation {
158 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
158 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
159 {
159 {
160 auto variable = fuzzingState.variableState(variableId).m_Variable;
160 auto variable = fuzzingState.variableState(variableId).m_Variable;
161 return variable != nullptr && !fuzzingState.m_SyncGroupsPool.empty()
161 return variable != nullptr && !fuzzingState.m_SyncGroupsPool.empty()
162 && fuzzingState.syncGroupId(variableId).isNull();
162 && fuzzingState.syncGroupId(variableId).isNull();
163 }
163 }
164
164
165 void execute(VariableId variableId, FuzzingState &fuzzingState,
165 void execute(VariableId variableId, FuzzingState &fuzzingState,
166 VariableController &variableController, const Properties &) const override
166 VariableController &variableController, const Properties &) const override
167 {
167 {
168 auto &variableState = fuzzingState.variableState(variableId);
168 auto &variableState = fuzzingState.variableState(variableId);
169
169
170 // Chooses a random synchronization group and adds the variable into sync group
170 // Chooses a random synchronization group and adds the variable into sync group
171 auto syncGroupId = RandomGenerator::instance().randomChoice(fuzzingState.syncGroupsIds());
171 auto syncGroupId = RandomGenerator::instance().randomChoice(fuzzingState.syncGroupsIds());
172 qCInfo(LOG_FuzzingOperations()).noquote() << "Adding" << variableState.m_Variable->name()
172 qCInfo(LOG_FuzzingOperations()).noquote() << "Adding" << variableState.m_Variable->name()
173 << "into synchronization group" << syncGroupId
173 << "into synchronization group" << syncGroupId
174 << "...";
174 << "...";
175 variableController.onAddSynchronized(variableState.m_Variable, syncGroupId);
175 variableController.onAddSynchronized(variableState.m_Variable, syncGroupId);
176
176
177 // Updates state
177 // Updates state
178 fuzzingState.synchronizeVariable(variableId, syncGroupId);
178 fuzzingState.synchronizeVariable(variableId, syncGroupId);
179
179
180 variableController.onRequestDataLoading({variableState.m_Variable}, variableState.m_Range,
180 variableController.onRequestDataLoading({variableState.m_Variable}, variableState.m_Range,
181 false);
181 false);
182 }
182 }
183 };
183 };
184
184
185 struct DesynchronizeOperation : public IFuzzingOperation {
185 struct DesynchronizeOperation : public IFuzzingOperation {
186 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
186 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
187 {
187 {
188 auto variable = fuzzingState.variableState(variableId).m_Variable;
188 auto variable = fuzzingState.variableState(variableId).m_Variable;
189 return variable != nullptr && !fuzzingState.syncGroupId(variableId).isNull();
189 return variable != nullptr && !fuzzingState.syncGroupId(variableId).isNull();
190 }
190 }
191
191
192 void execute(VariableId variableId, FuzzingState &fuzzingState,
192 void execute(VariableId variableId, FuzzingState &fuzzingState,
193 VariableController &variableController, const Properties &) const override
193 VariableController &variableController, const Properties &) const override
194 {
194 {
195 auto &variableState = fuzzingState.variableState(variableId);
195 auto &variableState = fuzzingState.variableState(variableId);
196
196
197 // Gets the sync group of the variable
197 // Gets the sync group of the variable
198 auto syncGroupId = fuzzingState.syncGroupId(variableId);
198 auto syncGroupId = fuzzingState.syncGroupId(variableId);
199
199
200 qCInfo(LOG_FuzzingOperations()).noquote() << "Removing" << variableState.m_Variable->name()
200 qCInfo(LOG_FuzzingOperations()).noquote() << "Removing" << variableState.m_Variable->name()
201 << "from synchronization group" << syncGroupId
201 << "from synchronization group" << syncGroupId
202 << "...";
202 << "...";
203 variableController.desynchronize(variableState.m_Variable, syncGroupId);
203 variableController.desynchronize(variableState.m_Variable, syncGroupId);
204
204
205 // Updates state
205 // Updates state
206 fuzzingState.desynchronizeVariable(variableId, syncGroupId);
206 fuzzingState.desynchronizeVariable(variableId, syncGroupId);
207 }
207 }
208 };
208 };
209
209
210 struct UnknownOperation : public IFuzzingOperation {
210 struct UnknownOperation : public IFuzzingOperation {
211 bool canExecute(VariableId, const FuzzingState &) const override { return false; }
211 bool canExecute(VariableId, const FuzzingState &) const override { return false; }
212
212
213 void execute(VariableId, FuzzingState &, VariableController &,
213 void execute(VariableId, FuzzingState &, VariableController &,
214 const Properties &) const override
214 const Properties &) const override
215 {
215 {
216 }
216 }
217 };
217 };
218
218
219 } // namespace
219 } // namespace
220
220
221 std::unique_ptr<IFuzzingOperation> FuzzingOperationFactory::create(FuzzingOperationType type)
221 std::unique_ptr<IFuzzingOperation> FuzzingOperationFactory::create(FuzzingOperationType type)
222 {
222 {
223 switch (type) {
223 switch (type) {
224 case FuzzingOperationType::CREATE:
224 case FuzzingOperationType::CREATE:
225 return std::make_unique<CreateOperation>();
225 return std::make_unique<CreateOperation>();
226 case FuzzingOperationType::DELETE:
226 case FuzzingOperationType::DELETE:
227 return std::make_unique<DeleteOperation>();
227 return std::make_unique<DeleteOperation>();
228 case FuzzingOperationType::PAN_LEFT:
228 case FuzzingOperationType::PAN_LEFT:
229 return std::make_unique<MoveOperation>(
229 return std::make_unique<MoveOperation>(
230 std::minus<double>(), std::minus<double>(),
230 std::minus<double>(), std::minus<double>(),
231 [](const SqpRange &range, const SqpRange &maxRange) {
231 [](const SqpRange &range, const SqpRange &maxRange) {
232 return range.m_TStart - maxRange.m_TStart;
232 return range.m_TStart - maxRange.m_TStart;
233 },
233 },
234 QStringLiteral("Pan left operation"));
234 QStringLiteral("Pan left operation"));
235 case FuzzingOperationType::PAN_RIGHT:
235 case FuzzingOperationType::PAN_RIGHT:
236 return std::make_unique<MoveOperation>(
236 return std::make_unique<MoveOperation>(
237 std::plus<double>(), std::plus<double>(),
237 std::plus<double>(), std::plus<double>(),
238 [](const SqpRange &range, const SqpRange &maxRange) {
238 [](const SqpRange &range, const SqpRange &maxRange) {
239 return maxRange.m_TEnd - range.m_TEnd;
239 return maxRange.m_TEnd - range.m_TEnd;
240 },
240 },
241 QStringLiteral("Pan right operation"));
241 QStringLiteral("Pan right operation"));
242 case FuzzingOperationType::ZOOM_IN:
242 case FuzzingOperationType::ZOOM_IN:
243 return std::make_unique<MoveOperation>(
243 return std::make_unique<MoveOperation>(
244 std::plus<double>(), std::minus<double>(),
244 std::plus<double>(), std::minus<double>(),
245 [](const SqpRange &range, const SqpRange &maxRange) {
245 [](const SqpRange &range, const SqpRange &maxRange) {
246 Q_UNUSED(maxRange)
246 Q_UNUSED(maxRange)
247 return range.m_TEnd - (range.m_TStart + range.m_TEnd) / 2.;
247 return range.m_TEnd - (range.m_TStart + range.m_TEnd) / 2.;
248 },
248 },
249 QStringLiteral("Zoom in operation"));
249 QStringLiteral("Zoom in operation"));
250 case FuzzingOperationType::ZOOM_OUT:
250 case FuzzingOperationType::ZOOM_OUT:
251 return std::make_unique<MoveOperation>(
251 return std::make_unique<MoveOperation>(
252 std::minus<double>(), std::plus<double>(),
252 std::minus<double>(), std::plus<double>(),
253 [](const SqpRange &range, const SqpRange &maxRange) {
253 [](const SqpRange &range, const SqpRange &maxRange) {
254 return std::min(range.m_TStart - maxRange.m_TStart,
254 return std::min(range.m_TStart - maxRange.m_TStart,
255 maxRange.m_TEnd - range.m_TEnd);
255 maxRange.m_TEnd - range.m_TEnd);
256 },
256 },
257 QStringLiteral("Zoom out operation"));
257 QStringLiteral("Zoom out operation"));
258 case FuzzingOperationType::SYNCHRONIZE:
258 case FuzzingOperationType::SYNCHRONIZE:
259 return std::make_unique<SynchronizeOperation>();
259 return std::make_unique<SynchronizeOperation>();
260 case FuzzingOperationType::DESYNCHRONIZE:
260 case FuzzingOperationType::DESYNCHRONIZE:
261 return std::make_unique<DesynchronizeOperation>();
261 return std::make_unique<DesynchronizeOperation>();
262 default:
262 default:
263 // Default case returns unknown operation
263 // Default case returns unknown operation
264 break;
264 break;
265 }
265 }
266
266
267 return std::make_unique<UnknownOperation>();
267 return std::make_unique<UnknownOperation>();
268 }
268 }
@@ -1,135 +1,135
1 /*------------------------------------------------------------------------------
1 /*------------------------------------------------------------------------------
2 -- This file is a part of the SciQLOP Software
2 -- This file is a part of the SciQLOP Software
3 -- Copyright (C) 2018, Plasma Physics Laboratory - CNRS
3 -- Copyright (C) 2018, Plasma Physics Laboratory - CNRS
4 --
4 --
5 -- This program is free software; you can redistribute it and/or modify
5 -- This program is free software; you can redistribute it and/or modify
6 -- it under the terms of the GNU General Public License as published by
6 -- it under the terms of the GNU General Public License as published by
7 -- the Free Software Foundation; either version 2 of the License, or
7 -- the Free Software Foundation; either version 2 of the License, or
8 -- (at your option) any later version.
8 -- (at your option) any later version.
9 --
9 --
10 -- This program is distributed in the hope that it will be useful,
10 -- This program is distributed in the hope that it will be useful,
11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 -- GNU General Public License for more details.
13 -- GNU General Public License for more details.
14 --
14 --
15 -- You should have received a copy of the GNU General Public License
15 -- You should have received a copy of the GNU General Public License
16 -- along with this program; if not, write to the Free Software
16 -- along with this program; if not, write to the Free Software
17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 -------------------------------------------------------------------------------*/
18 -------------------------------------------------------------------------------*/
19 /*-- Author : Alexis Jeandet
19 /*-- Author : Alexis Jeandet
20 -- Mail : alexis.jeandet@member.fsf.org
20 -- Mail : alexis.jeandet@member.fsf.org
21 ----------------------------------------------------------------------------*/
21 ----------------------------------------------------------------------------*/
22 #include <string>
22 #include <string>
23 #include <sstream>
23 #include <sstream>
24 #include <memory>
24 #include <memory>
25
25
26 #include <pybind11/pybind11.h>
26 #include <pybind11/pybind11.h>
27 #include <pybind11/operators.h>
27 #include <pybind11/operators.h>
28 #include <pybind11/embed.h>
28 #include <pybind11/embed.h>
29 #include <pybind11/numpy.h>
29 #include <pybind11/numpy.h>
30 #include <pybind11/chrono.h>
30 #include <pybind11/chrono.h>
31
31
32 #include <SqpApplication.h>
32 #include <SqpApplication.h>
33 #include <Variable/VariableController.h>
33 #include <Variable/VariableController.h>
34 #include <Time/TimeController.h>
34 #include <Time/TimeController.h>
35 #include <Data/SqpRange.h>
35 #include <Data/SqpRange.h>
36 #include <Data/DataSeriesType.h>
36 #include <Data/DataSeriesType.h>
37 #include <Common/DateUtils.h>
37 #include <Common/DateUtils.h>
38 #include <Variable/Variable.h>
38 #include <Variable/Variable.h>
39 #include <Data/ScalarSeries.h>
39 #include <Data/ScalarSeries.h>
40 #include <Data/VectorSeries.h>
40 #include <Data/VectorSeries.h>
41
41
42 #include <AmdaProvider.h>
42 #include <AmdaProvider.h>
43 #include <AmdaResultParser.h>
43 #include <AmdaResultParser.h>
44
44
45 //#include <QDate>
45 //#include <QDate>
46 //#include <QTime>
46 //#include <QTime>
47 //#include <QUuid>
47 //#include <QUuid>
48 //#include <QString>
48 //#include <QString>
49 #include <QFile>
49 #include <QFile>
50
50
51 #include <pywrappers_common.h>
51 #include <pywrappers_common.h>
52 #include <CoreWrappers.h>
52 #include <CoreWrappers.h>
53
53
54
54
55 using namespace std::chrono;
55 using namespace std::chrono;
56 namespace py = pybind11;
56 namespace py = pybind11;
57
57
58
58
59
59
60
60
61 PYBIND11_MODULE(pytestamda, m){
61 PYBIND11_MODULE(pytestamda, m){
62
62
63 int argc = 0;
63 int argc = 0;
64 char ** argv=nullptr;
64 char ** argv=nullptr;
65 SqpApplication::setOrganizationName("LPP");
65 SqpApplication::setOrganizationName("LPP");
66 SqpApplication::setOrganizationDomain("lpp.fr");
66 SqpApplication::setOrganizationDomain("lpp.fr");
67 SqpApplication::setApplicationName("SciQLop");
67 SqpApplication::setApplicationName("SciQLop");
68 static SqpApplication app(argc, argv);
68 static SqpApplication app(argc, argv);
69
69
70 auto qtmod = py::module::import("sciqlopqt");
70 auto qtmod = py::module::import("sciqlopqt");
71 auto sciqlopmod = py::module::import("pysciqlopcore");
71 auto sciqlopmod = py::module::import("pysciqlopcore");
72
72
73 m.doc() = "hello";
73 m.doc() = "hello";
74
74
75 py::class_<VariableController>(m, "VariableController")
75 py::class_<VariableController>(m, "VariableController")
76 .def_static("createVariable",[](const QString &name,
76 .def_static("createVariable",[](const QString &name,
77 std::shared_ptr<IDataProvider> provider){
77 std::shared_ptr<IDataProvider> provider, const SqpRange& range){
78 return sqpApp->variableController().createVariable(name, {{"dataType", "vector"}, {"xml:id", "c1_b"}}, provider);
78 return sqpApp->variableController().createVariable(name, {{"dataType", "vector"}, {"xml:id", "c1_b"}}, provider, range);
79 })
79 })
80 .def_static("hasPendingDownloads",
80 .def_static("hasPendingDownloads",
81 [](){return sqpApp->variableController().hasPendingDownloads();}
81 [](){return sqpApp->variableController().hasPendingDownloads();}
82 )
82 )
83 .def_static("addSynchronizationGroup",
83 .def_static("addSynchronizationGroup",
84 [](QUuid uuid){sqpApp->variableController().onAddSynchronizationGroupId(uuid);}
84 [](QUuid uuid){sqpApp->variableController().onAddSynchronizationGroupId(uuid);}
85 )
85 )
86 .def_static("removeSynchronizationGroup",
86 .def_static("removeSynchronizationGroup",
87 [](QUuid uuid){sqpApp->variableController().onRemoveSynchronizationGroupId(uuid);}
87 [](QUuid uuid){sqpApp->variableController().onRemoveSynchronizationGroupId(uuid);}
88 )
88 )
89 .def_static("synchronizeVar",
89 .def_static("synchronizeVar",
90 [](std::shared_ptr<Variable> variable, QUuid uuid){sqpApp->variableController().onAddSynchronized(variable, uuid);}
90 [](std::shared_ptr<Variable> variable, QUuid uuid){sqpApp->variableController().onAddSynchronized(variable, uuid);}
91 )
91 )
92 .def_static("deSynchronizeVar",
92 .def_static("deSynchronizeVar",
93 [](std::shared_ptr<Variable> variable, QUuid uuid){sqpApp->variableController().desynchronize(variable, uuid);}
93 [](std::shared_ptr<Variable> variable, QUuid uuid){sqpApp->variableController().desynchronize(variable, uuid);}
94 )
94 )
95 .def_static("deleteVariable",
95 .def_static("deleteVariable",
96 [](std::shared_ptr<Variable> variable){
96 [](std::shared_ptr<Variable> variable){
97 sqpApp->variableController().deleteVariable(variable);}
97 sqpApp->variableController().deleteVariable(variable);}
98 )
98 )
99 .def_static("update_range",[](std::shared_ptr<Variable> variable, const SqpRange &range, bool synchronise){
99 .def_static("update_range",[](std::shared_ptr<Variable> variable, const SqpRange &range, bool synchronise){
100 sqpApp->variableController().onRequestDataLoading({variable}, range, synchronise);
100 sqpApp->variableController().onRequestDataLoading({variable}, range, synchronise);
101 })
101 })
102 .def_static("wait_for_downloads",[](){
102 .def_static("wait_for_downloads",[](){
103 while (sqpApp->variableController().hasPendingDownloads()) {
103 while (sqpApp->variableController().hasPendingDownloads()) {
104 usleep(100);
104 usleep(100);
105 }
105 }
106 });
106 });
107
107
108 py::class_<TimeController>(m,"TimeController")
108 py::class_<TimeController>(m,"TimeController")
109 .def_static("setTime", [](SqpRange range){sqpApp->timeController().onTimeToUpdate(range);});
109 .def_static("setTime", [](SqpRange range){sqpApp->timeController().setDateTimeRange(range);});
110
110
111
111
112 auto amda_provider = std::make_shared<AmdaProvider>();
112 auto amda_provider = std::make_shared<AmdaProvider>();
113 m.def("amda_provider",[amda_provider](){return amda_provider;}, py::return_value_policy::copy);
113 m.def("amda_provider",[amda_provider](){return amda_provider;}, py::return_value_policy::copy);
114
114
115 py::class_<AmdaProvider, std::shared_ptr<AmdaProvider>, IDataProvider>(m, "AmdaProvider");
115 py::class_<AmdaProvider, std::shared_ptr<AmdaProvider>, IDataProvider>(m, "AmdaProvider");
116
116
117 py::class_<AmdaResultParser>(m, "AmdaResultParser")
117 py::class_<AmdaResultParser>(m, "AmdaResultParser")
118 .def_static("readTxt", AmdaResultParser::readTxt)
118 .def_static("readTxt", AmdaResultParser::readTxt)
119 .def("readScalarTxt", [](const QString& path){
119 .def("readScalarTxt", [](const QString& path){
120 return std::dynamic_pointer_cast<ScalarSeries>(AmdaResultParser::readTxt(path, DataSeriesType::SCALAR));
120 return std::dynamic_pointer_cast<ScalarSeries>(AmdaResultParser::readTxt(path, DataSeriesType::SCALAR));
121 }, py::return_value_policy::copy);
121 }, py::return_value_policy::copy);
122
122
123
123
124 }
124 }
125
125
126
126
127 int pytestamda_test(const char* testScriptPath )
127 int pytestamda_test(const char* testScriptPath )
128 {
128 {
129 py::scoped_interpreter guard{};
129 py::scoped_interpreter guard{};
130 py::globals()["__file__"] = py::str(testScriptPath);
130 py::globals()["__file__"] = py::str(testScriptPath);
131 py::eval_file(testScriptPath);
131 py::eval_file(testScriptPath);
132 return 0;
132 return 0;
133 }
133 }
134
134
135
135
@@ -1,164 +1,164
1 #include "AmdaProvider.h"
1 #include "AmdaProvider.h"
2 #include "AmdaResultParser.h"
2 #include "AmdaResultParser.h"
3
3
4 #include "SqpApplication.h"
4 #include "SqpApplication.h"
5 #include <Data/DataSeries.h>
5 #include <Data/DataSeries.h>
6 #include <Data/IDataSeries.h>
6 #include <Data/IDataSeries.h>
7 #include <Data/ScalarSeries.h>
7 #include <Data/ScalarSeries.h>
8 #include <Time/TimeController.h>
8 #include <Time/TimeController.h>
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
11
11
12 #include <QObject>
12 #include <QObject>
13 #include <QtTest>
13 #include <QtTest>
14
14
15 #include <memory>
15 #include <memory>
16
16
17 // TEST with REF:
17 // TEST with REF:
18 // AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00
18 // AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00
19 // imf(0) - Type : Local Parameter @ CDPP/AMDA -
19 // imf(0) - Type : Local Parameter @ CDPP/AMDA -
20 // Name : bx_gse - Units : nT - Size : 1 -
20 // Name : bx_gse - Units : nT - Size : 1 -
21 // Frame : GSE - Mission : ACE -
21 // Frame : GSE - Mission : ACE -
22 // Instrument : MFI - Dataset : mfi_final-prelim
22 // Instrument : MFI - Dataset : mfi_final-prelim
23 // REFERENCE DOWNLOAD FILE =
23 // REFERENCE DOWNLOAD FILE =
24 // http://amdatest.irap.omp.eu/php/rest/getParameter.php?startTime=2012-01-01T12:00:00&stopTime=2012-01-03T12:00:00&parameterID=imf(0)&outputFormat=ASCII&timeFormat=ISO8601&gzip=0
24 // http://amdatest.irap.omp.eu/php/rest/getParameter.php?startTime=2012-01-01T12:00:00&stopTime=2012-01-03T12:00:00&parameterID=imf(0)&outputFormat=ASCII&timeFormat=ISO8601&gzip=0
25
25
26 namespace {
26 namespace {
27
27
28 /// Path for the tests
28 /// Path for the tests
29 const auto TESTS_RESOURCES_PATH
29 const auto TESTS_RESOURCES_PATH
30 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaAcquisition"}.absoluteFilePath();
30 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaAcquisition"}.absoluteFilePath();
31
31
32 /// Delay after each operation on the variable before validating it (in ms)
32 /// Delay after each operation on the variable before validating it (in ms)
33 const auto OPERATION_DELAY = 10000;
33 const auto OPERATION_DELAY = 10000;
34
34
35 template <typename T>
35 template <typename T>
36 bool compareDataSeries(std::shared_ptr<IDataSeries> candidate, SqpRange candidateCacheRange,
36 bool compareDataSeries(std::shared_ptr<IDataSeries> candidate, SqpRange candidateCacheRange,
37 std::shared_ptr<IDataSeries> reference)
37 std::shared_ptr<IDataSeries> reference)
38 {
38 {
39 auto compareLambda = [](const auto &it1, const auto &it2) {
39 auto compareLambda = [](const auto &it1, const auto &it2) {
40 return (it1.x() == it2.x()) && (it1.value() == it2.value());
40 return (it1.x() == it2.x()) && (it1.value() == it2.value());
41 };
41 };
42
42
43 auto candidateDS = std::dynamic_pointer_cast<T>(candidate);
43 auto candidateDS = std::dynamic_pointer_cast<T>(candidate);
44 auto referenceDS = std::dynamic_pointer_cast<T>(reference);
44 auto referenceDS = std::dynamic_pointer_cast<T>(reference);
45
45
46 if (candidateDS && referenceDS) {
46 if (candidateDS && referenceDS) {
47
47
48 auto itRefs
48 auto itRefs
49 = referenceDS->xAxisRange(candidateCacheRange.m_TStart, candidateCacheRange.m_TEnd);
49 = referenceDS->xAxisRange(candidateCacheRange.m_TStart, candidateCacheRange.m_TEnd);
50 qDebug() << " DISTANCE" << std::distance(candidateDS->cbegin(), candidateDS->cend())
50 qDebug() << " DISTANCE" << std::distance(candidateDS->cbegin(), candidateDS->cend())
51 << std::distance(itRefs.first, itRefs.second);
51 << std::distance(itRefs.first, itRefs.second);
52
52
53 return std::equal(candidateDS->cbegin(), candidateDS->cend(), itRefs.first, itRefs.second,
53 return std::equal(candidateDS->cbegin(), candidateDS->cend(), itRefs.first, itRefs.second,
54 compareLambda);
54 compareLambda);
55 }
55 }
56 else {
56 else {
57 return false;
57 return false;
58 }
58 }
59 }
59 }
60 }
60 }
61
61
62 class TestAmdaAcquisition : public QObject {
62 class TestAmdaAcquisition : public QObject {
63 Q_OBJECT
63 Q_OBJECT
64
64
65 private slots:
65 private slots:
66 /// Input data for @sa testAcquisition()
66 /// Input data for @sa testAcquisition()
67 void testAcquisition_data();
67 void testAcquisition_data();
68 void testAcquisition();
68 void testAcquisition();
69 };
69 };
70
70
71 void TestAmdaAcquisition::testAcquisition_data()
71 void TestAmdaAcquisition::testAcquisition_data()
72 {
72 {
73 // ////////////// //
73 // ////////////// //
74 // Test structure //
74 // Test structure //
75 // ////////////// //
75 // ////////////// //
76
76
77 QTest::addColumn<QString>("dataFilename"); // File containing expected data of acquisitions
77 QTest::addColumn<QString>("dataFilename"); // File containing expected data of acquisitions
78 QTest::addColumn<SqpRange>("initialRange"); // First acquisition
78 QTest::addColumn<SqpRange>("initialRange"); // First acquisition
79 QTest::addColumn<std::vector<SqpRange> >("operations"); // Acquisitions to make
79 QTest::addColumn<std::vector<SqpRange> >("operations"); // Acquisitions to make
80
80
81 // ////////// //
81 // ////////// //
82 // Test cases //
82 // Test cases //
83 // ////////// //
83 // ////////// //
84
84
85 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
85 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
86 return DateUtils::secondsSinceEpoch(
86 return DateUtils::secondsSinceEpoch(
87 QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC});
87 QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC});
88 };
88 };
89
89
90
90
91 QTest::newRow("amda")
91 QTest::newRow("amda")
92 << "AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00.txt"
92 << "AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00.txt"
93 << SqpRange{dateTime(2012, 1, 2, 2, 3, 0), dateTime(2012, 1, 2, 2, 4, 0)}
93 << SqpRange{dateTime(2012, 1, 2, 2, 3, 0), dateTime(2012, 1, 2, 2, 4, 0)}
94 << std::vector<SqpRange>{
94 << std::vector<SqpRange>{
95 // 2 : pan (jump) left for two min
95 // 2 : pan (jump) left for two min
96 SqpRange{dateTime(2012, 1, 2, 2, 1, 0), dateTime(2012, 1, 2, 2, 2, 0)},
96 SqpRange{dateTime(2012, 1, 2, 2, 1, 0), dateTime(2012, 1, 2, 2, 2, 0)},
97 // 3 : pan (jump) right for four min
97 // 3 : pan (jump) right for four min
98 SqpRange{dateTime(2012, 1, 2, 2, 5, 0), dateTime(2012, 1, 2, 2, 6, 0)},
98 SqpRange{dateTime(2012, 1, 2, 2, 5, 0), dateTime(2012, 1, 2, 2, 6, 0)},
99 // 4 : pan (overlay) right for 30 sec
99 // 4 : pan (overlay) right for 30 sec
100 /*SqpRange{dateTime(2012, 1, 2, 2, 5, 30), dateTime(2012, 1, 2, 2, 6, 30)},
100 /*SqpRange{dateTime(2012, 1, 2, 2, 5, 30), dateTime(2012, 1, 2, 2, 6, 30)},
101 // 5 : pan (overlay) left for 30 sec
101 // 5 : pan (overlay) left for 30 sec
102 SqpRange{dateTime(2012, 1, 2, 2, 5, 0), dateTime(2012, 1, 2, 2, 6, 0)},
102 SqpRange{dateTime(2012, 1, 2, 2, 5, 0), dateTime(2012, 1, 2, 2, 6, 0)},
103 // 6 : pan (overlay) left for 30 sec - BIS
103 // 6 : pan (overlay) left for 30 sec - BIS
104 SqpRange{dateTime(2012, 1, 2, 2, 4, 30), dateTime(2012, 1, 2, 2, 5, 30)},
104 SqpRange{dateTime(2012, 1, 2, 2, 4, 30), dateTime(2012, 1, 2, 2, 5, 30)},
105 // 7 : Zoom in Inside 20 sec range
105 // 7 : Zoom in Inside 20 sec range
106 SqpRange{dateTime(2012, 1, 2, 2, 4, 50), dateTime(2012, 1, 2, 2, 5, 10)},
106 SqpRange{dateTime(2012, 1, 2, 2, 4, 50), dateTime(2012, 1, 2, 2, 5, 10)},
107 // 8 : Zoom out Inside 20 sec range
107 // 8 : Zoom out Inside 20 sec range
108 SqpRange{dateTime(2012, 1, 2, 2, 4, 30), dateTime(2012, 1, 2, 2, 5, 30)}*/};
108 SqpRange{dateTime(2012, 1, 2, 2, 4, 30), dateTime(2012, 1, 2, 2, 5, 30)}*/};
109 }
109 }
110
110
111 void TestAmdaAcquisition::testAcquisition()
111 void TestAmdaAcquisition::testAcquisition()
112 {
112 {
113 /// @todo: update test to be compatible with AMDA v2
113 /// @todo: update test to be compatible with AMDA v2
114
114
115 // Retrieves data file
115 // Retrieves data file
116 QFETCH(QString, dataFilename);
116 QFETCH(QString, dataFilename);
117 auto filePath = QFileInfo{TESTS_RESOURCES_PATH, dataFilename}.absoluteFilePath();
117 auto filePath = QFileInfo{TESTS_RESOURCES_PATH, dataFilename}.absoluteFilePath();
118 auto results = AmdaResultParser::readTxt(filePath, DataSeriesType::SCALAR);
118 auto results = AmdaResultParser::readTxt(filePath, DataSeriesType::SCALAR);
119
119
120 /// Lambda used to validate a variable at each step
120 /// Lambda used to validate a variable at each step
121 auto validateVariable = [results](std::shared_ptr<Variable> variable, const SqpRange &range) {
121 auto validateVariable = [results](std::shared_ptr<Variable> variable, const SqpRange &range) {
122 // Checks that the variable's range has changed
122 // Checks that the variable's range has changed
123 qInfo() << tr("Compare var range vs range") << variable->range() << range;
123 qInfo() << tr("Compare var range vs range") << variable->range() << range;
124 QCOMPARE(variable->range(), range);
124 QCOMPARE(variable->range(), range);
125
125
126 // Checks the variable's data series
126 // Checks the variable's data series
127 QVERIFY(compareDataSeries<ScalarSeries>(variable->dataSeries(), variable->cacheRange(),
127 QVERIFY(compareDataSeries<ScalarSeries>(variable->dataSeries(), variable->cacheRange(),
128 results));
128 results));
129 qInfo() << "\n";
129 qInfo() << "\n";
130 };
130 };
131
131
132 // Creates variable
132 // Creates variable
133 QFETCH(SqpRange, initialRange);
133 QFETCH(SqpRange, initialRange);
134 sqpApp->timeController().onTimeToUpdate(initialRange);
134 sqpApp->timeController().setDateTimeRange(initialRange);
135 auto provider = std::make_shared<AmdaProvider>();
135 auto provider = std::make_shared<AmdaProvider>();
136 auto variable = sqpApp->variableController().createVariable(
136 auto variable = sqpApp->variableController().createVariable(
137 "bx_gse", {{"dataType", "scalar"}, {"xml:id", "imf(0)"}}, provider);
137 "bx_gse", {{"dataType", "scalar"}, {"xml:id", "imf(0)"}}, provider, initialRange);
138
138
139 QTest::qWait(OPERATION_DELAY);
139 QTest::qWait(OPERATION_DELAY);
140 validateVariable(variable, initialRange);
140 validateVariable(variable, initialRange);
141
141
142 // Makes operations on the variable
142 // Makes operations on the variable
143 QFETCH(std::vector<SqpRange>, operations);
143 QFETCH(std::vector<SqpRange>, operations);
144 for (const auto &operation : operations) {
144 for (const auto &operation : operations) {
145 // Asks request on the variable and waits during its execution
145 // Asks request on the variable and waits during its execution
146 sqpApp->variableController().onRequestDataLoading({variable}, operation, false);
146 sqpApp->variableController().onRequestDataLoading({variable}, operation, false);
147
147
148 QTest::qWait(OPERATION_DELAY);
148 QTest::qWait(OPERATION_DELAY);
149 validateVariable(variable, operation);
149 validateVariable(variable, operation);
150 }
150 }
151 }
151 }
152
152
153 int main(int argc, char *argv[])
153 int main(int argc, char *argv[])
154 {
154 {
155 SqpApplication app(argc, argv);
155 SqpApplication app(argc, argv);
156 app.setAttribute(Qt::AA_Use96Dpi, true);
156 app.setAttribute(Qt::AA_Use96Dpi, true);
157 TestAmdaAcquisition tc;
157 TestAmdaAcquisition tc;
158 QTEST_SET_MAIN_SOURCE_PATH
158 QTEST_SET_MAIN_SOURCE_PATH
159 return QTest::qExec(&tc, argc, argv);
159 return QTest::qExec(&tc, argc, argv);
160 }
160 }
161
161
162 // QTEST_MAIN(TestAmdaAcquisition)
162 // QTEST_MAIN(TestAmdaAcquisition)
163
163
164 #include "TestAmdaAcquisition.moc"
164 #include "TestAmdaAcquisition.moc"
@@ -1,395 +1,395
1 #include "FuzzingDefs.h"
1 #include "FuzzingDefs.h"
2 #include "FuzzingOperations.h"
2 #include "FuzzingOperations.h"
3 #include "FuzzingUtils.h"
3 #include "FuzzingUtils.h"
4 #include "FuzzingValidators.h"
4 #include "FuzzingValidators.h"
5
5
6 #include "AmdaProvider.h"
6 #include "AmdaProvider.h"
7
7
8 #include <Common/SignalWaiter.h>
8 #include <Common/SignalWaiter.h>
9 #include <Network/NetworkController.h>
9 #include <Network/NetworkController.h>
10 #include <Settings/SqpSettingsDefs.h>
10 #include <Settings/SqpSettingsDefs.h>
11 #include <SqpApplication.h>
11 #include <SqpApplication.h>
12 #include <Time/TimeController.h>
12 #include <Time/TimeController.h>
13 #include <Variable/Variable.h>
13 #include <Variable/Variable.h>
14 #include <Variable/VariableController.h>
14 #include <Variable/VariableController.h>
15
15
16 #include <QLoggingCategory>
16 #include <QLoggingCategory>
17 #include <QObject>
17 #include <QObject>
18 #include <QtTest>
18 #include <QtTest>
19
19
20 #include <memory>
20 #include <memory>
21
21
22 Q_LOGGING_CATEGORY(LOG_TestAmdaFuzzing, "TestAmdaFuzzing")
22 Q_LOGGING_CATEGORY(LOG_TestAmdaFuzzing, "TestAmdaFuzzing")
23
23
24 /**
24 /**
25 * Macro used to generate a getter for a property in @sa FuzzingTest. The macro generates a static
25 * Macro used to generate a getter for a property in @sa FuzzingTest. The macro generates a static
26 * attribute that is initialized by searching in properties the property and use a default value if
26 * attribute that is initialized by searching in properties the property and use a default value if
27 * it's not present. Macro arguments are:
27 * it's not present. Macro arguments are:
28 * - GETTER_NAME : name of the getter
28 * - GETTER_NAME : name of the getter
29 * - PROPERTY_NAME: used to generate constants for property's name ({PROPERTY_NAME}_PROPERTY) and
29 * - PROPERTY_NAME: used to generate constants for property's name ({PROPERTY_NAME}_PROPERTY) and
30 * default value ({PROPERTY_NAME}_DEFAULT_VALUE)
30 * default value ({PROPERTY_NAME}_DEFAULT_VALUE)
31 * - TYPE : return type of the getter
31 * - TYPE : return type of the getter
32 */
32 */
33 // clang-format off
33 // clang-format off
34 #define DECLARE_PROPERTY_GETTER(GETTER_NAME, PROPERTY_NAME, TYPE) \
34 #define DECLARE_PROPERTY_GETTER(GETTER_NAME, PROPERTY_NAME, TYPE) \
35 TYPE GETTER_NAME() const \
35 TYPE GETTER_NAME() const \
36 { \
36 { \
37 static auto result = m_Properties.value(PROPERTY_NAME##_PROPERTY, PROPERTY_NAME##_DEFAULT_VALUE).value<TYPE>(); \
37 static auto result = m_Properties.value(PROPERTY_NAME##_PROPERTY, PROPERTY_NAME##_DEFAULT_VALUE).value<TYPE>(); \
38 return result; \
38 return result; \
39 } \
39 } \
40 // clang-format on
40 // clang-format on
41
41
42 namespace {
42 namespace {
43
43
44 // /////// //
44 // /////// //
45 // Aliases //
45 // Aliases //
46 // /////// //
46 // /////// //
47
47
48 using IntPair = std::pair<int, int>;
48 using IntPair = std::pair<int, int>;
49 using Weight = double;
49 using Weight = double;
50 using Weights = std::vector<Weight>;
50 using Weights = std::vector<Weight>;
51
51
52 struct OperationProperty {
52 struct OperationProperty {
53 Weight m_Weight{1.};
53 Weight m_Weight{1.};
54 bool m_WaitAcquisition{false};
54 bool m_WaitAcquisition{false};
55 };
55 };
56
56
57 using VariableOperation = std::pair<VariableId, std::shared_ptr<IFuzzingOperation> >;
57 using VariableOperation = std::pair<VariableId, std::shared_ptr<IFuzzingOperation> >;
58 using VariablesOperations = std::vector<VariableOperation>;
58 using VariablesOperations = std::vector<VariableOperation>;
59
59
60 using OperationsTypes = std::map<FuzzingOperationType, OperationProperty>;
60 using OperationsTypes = std::map<FuzzingOperationType, OperationProperty>;
61 using OperationsPool = std::map<std::shared_ptr<IFuzzingOperation>, OperationProperty>;
61 using OperationsPool = std::map<std::shared_ptr<IFuzzingOperation>, OperationProperty>;
62
62
63 using Validators = std::vector<std::shared_ptr<IFuzzingValidator> >;
63 using Validators = std::vector<std::shared_ptr<IFuzzingValidator> >;
64
64
65 // ///////// //
65 // ///////// //
66 // Constants //
66 // Constants //
67 // ///////// //
67 // ///////// //
68
68
69 // Defaults values used when the associated properties have not been set for the test
69 // Defaults values used when the associated properties have not been set for the test
70 const auto ACQUISITION_TIMEOUT_DEFAULT_VALUE = 30000;
70 const auto ACQUISITION_TIMEOUT_DEFAULT_VALUE = 30000;
71 const auto NB_MAX_OPERATIONS_DEFAULT_VALUE = 100;
71 const auto NB_MAX_OPERATIONS_DEFAULT_VALUE = 100;
72 const auto NB_MAX_SYNC_GROUPS_DEFAULT_VALUE = 1;
72 const auto NB_MAX_SYNC_GROUPS_DEFAULT_VALUE = 1;
73 const auto NB_MAX_VARIABLES_DEFAULT_VALUE = 1;
73 const auto NB_MAX_VARIABLES_DEFAULT_VALUE = 1;
74 const auto AVAILABLE_OPERATIONS_DEFAULT_VALUE = QVariant::fromValue(
74 const auto AVAILABLE_OPERATIONS_DEFAULT_VALUE = QVariant::fromValue(
75 OperationsTypes{{FuzzingOperationType::CREATE, {1., true}},
75 OperationsTypes{{FuzzingOperationType::CREATE, {1., true}},
76 {FuzzingOperationType::DELETE, {0.1}}, // Delete operation is less frequent
76 {FuzzingOperationType::DELETE, {0.1}}, // Delete operation is less frequent
77 {FuzzingOperationType::PAN_LEFT, {1.}},
77 {FuzzingOperationType::PAN_LEFT, {1.}},
78 {FuzzingOperationType::PAN_RIGHT, {1.}},
78 {FuzzingOperationType::PAN_RIGHT, {1.}},
79 {FuzzingOperationType::ZOOM_IN, {1.}},
79 {FuzzingOperationType::ZOOM_IN, {1.}},
80 {FuzzingOperationType::ZOOM_OUT, {1.}},
80 {FuzzingOperationType::ZOOM_OUT, {1.}},
81 {FuzzingOperationType::SYNCHRONIZE, {0.8}},
81 {FuzzingOperationType::SYNCHRONIZE, {0.8}},
82 {FuzzingOperationType::DESYNCHRONIZE, {0.4}}});
82 {FuzzingOperationType::DESYNCHRONIZE, {0.4}}});
83 const auto CACHE_TOLERANCE_DEFAULT_VALUE = 0.2;
83 const auto CACHE_TOLERANCE_DEFAULT_VALUE = 0.2;
84
84
85 /// Min/max delays between each operation (in ms)
85 /// Min/max delays between each operation (in ms)
86 const auto OPERATION_DELAY_BOUNDS_DEFAULT_VALUE = QVariant::fromValue(std::make_pair(100, 3000));
86 const auto OPERATION_DELAY_BOUNDS_DEFAULT_VALUE = QVariant::fromValue(std::make_pair(100, 3000));
87
87
88 /// Validators for the tests (executed in the order in which they're defined)
88 /// Validators for the tests (executed in the order in which they're defined)
89 const auto VALIDATORS_DEFAULT_VALUE = QVariant::fromValue(
89 const auto VALIDATORS_DEFAULT_VALUE = QVariant::fromValue(
90 ValidatorsTypes{{FuzzingValidatorType::RANGE, FuzzingValidatorType::DATA}});
90 ValidatorsTypes{{FuzzingValidatorType::RANGE, FuzzingValidatorType::DATA}});
91
91
92 /// Min/max number of operations to execute before calling validation
92 /// Min/max number of operations to execute before calling validation
93 const auto VALIDATION_FREQUENCY_BOUNDS_DEFAULT_VALUE = QVariant::fromValue(std::make_pair(1, 10));
93 const auto VALIDATION_FREQUENCY_BOUNDS_DEFAULT_VALUE = QVariant::fromValue(std::make_pair(1, 10));
94
94
95 // /////// //
95 // /////// //
96 // Methods //
96 // Methods //
97 // /////// //
97 // /////// //
98
98
99 /// Goes through the variables pool and operations pool to determine the set of {variable/operation}
99 /// Goes through the variables pool and operations pool to determine the set of {variable/operation}
100 /// pairs that are valid (i.e. operation that can be executed on variable)
100 /// pairs that are valid (i.e. operation that can be executed on variable)
101 std::pair<VariablesOperations, Weights> availableOperations(const FuzzingState &fuzzingState,
101 std::pair<VariablesOperations, Weights> availableOperations(const FuzzingState &fuzzingState,
102 const OperationsPool &operationsPool)
102 const OperationsPool &operationsPool)
103 {
103 {
104 VariablesOperations result{};
104 VariablesOperations result{};
105 Weights weights{};
105 Weights weights{};
106
106
107 for (const auto &variablesPoolEntry : fuzzingState.m_VariablesPool) {
107 for (const auto &variablesPoolEntry : fuzzingState.m_VariablesPool) {
108 auto variableId = variablesPoolEntry.first;
108 auto variableId = variablesPoolEntry.first;
109
109
110 for (const auto &operationsPoolEntry : operationsPool) {
110 for (const auto &operationsPoolEntry : operationsPool) {
111 auto operation = operationsPoolEntry.first;
111 auto operation = operationsPoolEntry.first;
112 auto operationProperty = operationsPoolEntry.second;
112 auto operationProperty = operationsPoolEntry.second;
113
113
114 // A pair is valid if the current operation can be executed on the current variable
114 // A pair is valid if the current operation can be executed on the current variable
115 if (operation->canExecute(variableId, fuzzingState)) {
115 if (operation->canExecute(variableId, fuzzingState)) {
116 result.push_back({variableId, operation});
116 result.push_back({variableId, operation});
117 weights.push_back(operationProperty.m_Weight);
117 weights.push_back(operationProperty.m_Weight);
118 }
118 }
119 }
119 }
120 }
120 }
121
121
122 return {result, weights};
122 return {result, weights};
123 }
123 }
124
124
125 OperationsPool createOperationsPool(const OperationsTypes &types)
125 OperationsPool createOperationsPool(const OperationsTypes &types)
126 {
126 {
127 OperationsPool result{};
127 OperationsPool result{};
128
128
129 std::transform(
129 std::transform(
130 types.cbegin(), types.cend(), std::inserter(result, result.end()), [](const auto &type) {
130 types.cbegin(), types.cend(), std::inserter(result, result.end()), [](const auto &type) {
131 return std::make_pair(FuzzingOperationFactory::create(type.first), type.second);
131 return std::make_pair(FuzzingOperationFactory::create(type.first), type.second);
132 });
132 });
133
133
134 return result;
134 return result;
135 }
135 }
136
136
137 Validators createValidators(const ValidatorsTypes &types)
137 Validators createValidators(const ValidatorsTypes &types)
138 {
138 {
139 Validators result{};
139 Validators result{};
140
140
141 std::transform(types.cbegin(), types.cend(), std::inserter(result, result.end()),
141 std::transform(types.cbegin(), types.cend(), std::inserter(result, result.end()),
142 [](const auto &type) { return FuzzingValidatorFactory::create(type); });
142 [](const auto &type) { return FuzzingValidatorFactory::create(type); });
143
143
144 return result;
144 return result;
145 }
145 }
146
146
147 /**
147 /**
148 * Validates all the variables' states passed in parameter, according to a set of validators
148 * Validates all the variables' states passed in parameter, according to a set of validators
149 * @param variablesPool the variables' states
149 * @param variablesPool the variables' states
150 * @param validators the validators used for validation
150 * @param validators the validators used for validation
151 */
151 */
152 void validate(const VariablesPool &variablesPool, const Validators &validators)
152 void validate(const VariablesPool &variablesPool, const Validators &validators)
153 {
153 {
154 for (const auto &variablesPoolEntry : variablesPool) {
154 for (const auto &variablesPoolEntry : variablesPool) {
155 auto variableId = variablesPoolEntry.first;
155 auto variableId = variablesPoolEntry.first;
156 const auto &variableState = variablesPoolEntry.second;
156 const auto &variableState = variablesPoolEntry.second;
157
157
158 auto variableMessage = variableState.m_Variable ? variableState.m_Variable->name()
158 auto variableMessage = variableState.m_Variable ? variableState.m_Variable->name()
159 : QStringLiteral("null variable");
159 : QStringLiteral("null variable");
160 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validating state of variable at index"
160 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validating state of variable at index"
161 << variableId << "(" << variableMessage << ")...";
161 << variableId << "(" << variableMessage << ")...";
162
162
163 for (const auto &validator : validators) {
163 for (const auto &validator : validators) {
164 validator->validate(VariableState{variableState});
164 validator->validate(VariableState{variableState});
165 }
165 }
166
166
167 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validation completed.";
167 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validation completed.";
168 }
168 }
169 }
169 }
170
170
171 /**
171 /**
172 * Class to run random tests
172 * Class to run random tests
173 */
173 */
174 class FuzzingTest {
174 class FuzzingTest {
175 public:
175 public:
176 explicit FuzzingTest(VariableController &variableController, Properties properties)
176 explicit FuzzingTest(VariableController &variableController, Properties properties)
177 : m_VariableController{variableController},
177 : m_VariableController{variableController},
178 m_Properties{std::move(properties)},
178 m_Properties{std::move(properties)},
179 m_FuzzingState{}
179 m_FuzzingState{}
180 {
180 {
181 // Inits variables pool: at init, all variables are null
181 // Inits variables pool: at init, all variables are null
182 for (auto variableId = 0; variableId < nbMaxVariables(); ++variableId) {
182 for (auto variableId = 0; variableId < nbMaxVariables(); ++variableId) {
183 m_FuzzingState.m_VariablesPool[variableId] = VariableState{};
183 m_FuzzingState.m_VariablesPool[variableId] = VariableState{};
184 }
184 }
185
185
186 // Inits sync groups and registers them into the variable controller
186 // Inits sync groups and registers them into the variable controller
187 for (auto i = 0; i < nbMaxSyncGroups(); ++i) {
187 for (auto i = 0; i < nbMaxSyncGroups(); ++i) {
188 auto syncGroupId = SyncGroupId::createUuid();
188 auto syncGroupId = SyncGroupId::createUuid();
189 variableController.onAddSynchronizationGroupId(syncGroupId);
189 variableController.onAddSynchronizationGroupId(syncGroupId);
190 m_FuzzingState.m_SyncGroupsPool[syncGroupId] = SyncGroup{};
190 m_FuzzingState.m_SyncGroupsPool[syncGroupId] = SyncGroup{};
191 }
191 }
192 }
192 }
193
193
194 void execute()
194 void execute()
195 {
195 {
196 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Running" << nbMaxOperations() << "operations on"
196 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Running" << nbMaxOperations() << "operations on"
197 << nbMaxVariables() << "variable(s)...";
197 << nbMaxVariables() << "variable(s)...";
198
198
199
199
200 // Inits the count of the number of operations before the next validation
200 // Inits the count of the number of operations before the next validation
201 int nextValidationCounter = 0;
201 int nextValidationCounter = 0;
202 auto updateValidationCounter = [this, &nextValidationCounter]() {
202 auto updateValidationCounter = [this, &nextValidationCounter]() {
203 nextValidationCounter = RandomGenerator::instance().generateInt(
203 nextValidationCounter = RandomGenerator::instance().generateInt(
204 validationFrequencies().first, validationFrequencies().second);
204 validationFrequencies().first, validationFrequencies().second);
205 qCInfo(LOG_TestAmdaFuzzing()).noquote()
205 qCInfo(LOG_TestAmdaFuzzing()).noquote()
206 << "Next validation in " << nextValidationCounter << "operation(s)...";
206 << "Next validation in " << nextValidationCounter << "operation(s)...";
207 };
207 };
208 updateValidationCounter();
208 updateValidationCounter();
209
209
210 auto canExecute = true;
210 auto canExecute = true;
211 for (auto i = 0; i < nbMaxOperations() && canExecute; ++i) {
211 for (auto i = 0; i < nbMaxOperations() && canExecute; ++i) {
212 // Retrieves all operations that can be executed in the current context
212 // Retrieves all operations that can be executed in the current context
213 VariablesOperations variableOperations{};
213 VariablesOperations variableOperations{};
214 Weights weights{};
214 Weights weights{};
215 std::tie(variableOperations, weights)
215 std::tie(variableOperations, weights)
216 = availableOperations(m_FuzzingState, operationsPool());
216 = availableOperations(m_FuzzingState, operationsPool());
217
217
218 canExecute = !variableOperations.empty();
218 canExecute = !variableOperations.empty();
219 if (canExecute) {
219 if (canExecute) {
220 --nextValidationCounter;
220 --nextValidationCounter;
221
221
222 // Of the operations available, chooses a random operation and executes it
222 // Of the operations available, chooses a random operation and executes it
223 auto variableOperation
223 auto variableOperation
224 = RandomGenerator::instance().randomChoice(variableOperations, weights);
224 = RandomGenerator::instance().randomChoice(variableOperations, weights);
225
225
226 auto variableId = variableOperation.first;
226 auto variableId = variableOperation.first;
227 auto fuzzingOperation = variableOperation.second;
227 auto fuzzingOperation = variableOperation.second;
228
228
229 auto waitAcquisition = nextValidationCounter == 0
229 auto waitAcquisition = nextValidationCounter == 0
230 || operationsPool().at(fuzzingOperation).m_WaitAcquisition;
230 || operationsPool().at(fuzzingOperation).m_WaitAcquisition;
231
231
232 fuzzingOperation->execute(variableId, m_FuzzingState, m_VariableController,
232 fuzzingOperation->execute(variableId, m_FuzzingState, m_VariableController,
233 m_Properties);
233 m_Properties);
234
234
235 if (waitAcquisition) {
235 if (waitAcquisition) {
236 qCDebug(LOG_TestAmdaFuzzing()) << "Waiting for acquisition to finish...";
236 qCDebug(LOG_TestAmdaFuzzing()) << "Waiting for acquisition to finish...";
237 SignalWaiter{m_VariableController, SIGNAL(acquisitionFinished())}.wait(
237 SignalWaiter{m_VariableController, SIGNAL(acquisitionFinished())}.wait(
238 acquisitionTimeout());
238 acquisitionTimeout());
239
239
240 // Validates variables
240 // Validates variables
241 if (nextValidationCounter == 0) {
241 if (nextValidationCounter == 0) {
242 validate(m_FuzzingState.m_VariablesPool, validators());
242 validate(m_FuzzingState.m_VariablesPool, validators());
243 updateValidationCounter();
243 updateValidationCounter();
244 }
244 }
245 }
245 }
246 else {
246 else {
247 // Delays the next operation with a randomly generated time
247 // Delays the next operation with a randomly generated time
248 auto delay = RandomGenerator::instance().generateInt(operationDelays().first,
248 auto delay = RandomGenerator::instance().generateInt(operationDelays().first,
249 operationDelays().second);
249 operationDelays().second);
250 qCDebug(LOG_TestAmdaFuzzing())
250 qCDebug(LOG_TestAmdaFuzzing())
251 << "Waiting " << delay << "ms before the next operation...";
251 << "Waiting " << delay << "ms before the next operation...";
252 QTest::qWait(delay);
252 QTest::qWait(delay);
253 }
253 }
254 }
254 }
255 else {
255 else {
256 qCInfo(LOG_TestAmdaFuzzing()).noquote()
256 qCInfo(LOG_TestAmdaFuzzing()).noquote()
257 << "No more operations are available, the execution of the test will stop...";
257 << "No more operations are available, the execution of the test will stop...";
258 }
258 }
259 }
259 }
260
260
261 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Execution of the test completed.";
261 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Execution of the test completed.";
262 }
262 }
263
263
264 private:
264 private:
265 OperationsPool operationsPool() const
265 OperationsPool operationsPool() const
266 {
266 {
267 static auto result = createOperationsPool(
267 static auto result = createOperationsPool(
268 m_Properties.value(AVAILABLE_OPERATIONS_PROPERTY, AVAILABLE_OPERATIONS_DEFAULT_VALUE)
268 m_Properties.value(AVAILABLE_OPERATIONS_PROPERTY, AVAILABLE_OPERATIONS_DEFAULT_VALUE)
269 .value<OperationsTypes>());
269 .value<OperationsTypes>());
270 return result;
270 return result;
271 }
271 }
272
272
273 Validators validators() const
273 Validators validators() const
274 {
274 {
275 static auto result
275 static auto result
276 = createValidators(m_Properties.value(VALIDATORS_PROPERTY, VALIDATORS_DEFAULT_VALUE)
276 = createValidators(m_Properties.value(VALIDATORS_PROPERTY, VALIDATORS_DEFAULT_VALUE)
277 .value<ValidatorsTypes>());
277 .value<ValidatorsTypes>());
278 return result;
278 return result;
279 }
279 }
280
280
281 DECLARE_PROPERTY_GETTER(nbMaxOperations, NB_MAX_OPERATIONS, int)
281 DECLARE_PROPERTY_GETTER(nbMaxOperations, NB_MAX_OPERATIONS, int)
282 DECLARE_PROPERTY_GETTER(nbMaxSyncGroups, NB_MAX_SYNC_GROUPS, int)
282 DECLARE_PROPERTY_GETTER(nbMaxSyncGroups, NB_MAX_SYNC_GROUPS, int)
283 DECLARE_PROPERTY_GETTER(nbMaxVariables, NB_MAX_VARIABLES, int)
283 DECLARE_PROPERTY_GETTER(nbMaxVariables, NB_MAX_VARIABLES, int)
284 DECLARE_PROPERTY_GETTER(operationDelays, OPERATION_DELAY_BOUNDS, IntPair)
284 DECLARE_PROPERTY_GETTER(operationDelays, OPERATION_DELAY_BOUNDS, IntPair)
285 DECLARE_PROPERTY_GETTER(validationFrequencies, VALIDATION_FREQUENCY_BOUNDS, IntPair)
285 DECLARE_PROPERTY_GETTER(validationFrequencies, VALIDATION_FREQUENCY_BOUNDS, IntPair)
286 DECLARE_PROPERTY_GETTER(acquisitionTimeout, ACQUISITION_TIMEOUT, int)
286 DECLARE_PROPERTY_GETTER(acquisitionTimeout, ACQUISITION_TIMEOUT, int)
287
287
288 VariableController &m_VariableController;
288 VariableController &m_VariableController;
289 Properties m_Properties;
289 Properties m_Properties;
290 FuzzingState m_FuzzingState;
290 FuzzingState m_FuzzingState;
291 };
291 };
292
292
293 } // namespace
293 } // namespace
294
294
295 Q_DECLARE_METATYPE(OperationsTypes)
295 Q_DECLARE_METATYPE(OperationsTypes)
296
296
297 class TestAmdaFuzzing : public QObject {
297 class TestAmdaFuzzing : public QObject {
298 Q_OBJECT
298 Q_OBJECT
299
299
300 private slots:
300 private slots:
301 /// Input data for @sa testFuzzing()
301 /// Input data for @sa testFuzzing()
302 void testFuzzing_data();
302 void testFuzzing_data();
303 void testFuzzing();
303 void testFuzzing();
304 };
304 };
305
305
306 void TestAmdaFuzzing::testFuzzing_data()
306 void TestAmdaFuzzing::testFuzzing_data()
307 {
307 {
308 // Note: Comment this line to run fuzzing tests
308 // Note: Comment this line to run fuzzing tests
309 QSKIP("Fuzzing tests are disabled by default");
309 QSKIP("Fuzzing tests are disabled by default");
310
310
311 // ////////////// //
311 // ////////////// //
312 // Test structure //
312 // Test structure //
313 // ////////////// //
313 // ////////////// //
314
314
315 QTest::addColumn<Properties>("properties"); // Properties for random test
315 QTest::addColumn<Properties>("properties"); // Properties for random test
316
316
317 // ////////// //
317 // ////////// //
318 // Test cases //
318 // Test cases //
319 // ////////// //
319 // ////////// //
320
320
321 auto maxRange = SqpRange::fromDateTime({2017, 1, 1}, {0, 0}, {2017, 1, 5}, {0, 0});
321 auto maxRange = SqpRange::fromDateTime({2017, 1, 1}, {0, 0}, {2017, 1, 5}, {0, 0});
322 MetadataPool metadataPool{{{"dataType", "vector"}, {"xml:id", "imf"}}};
322 MetadataPool metadataPool{{{"dataType", "vector"}, {"xml:id", "imf"}}};
323
323
324 // Note: we don't use auto here as we want to pass std::shared_ptr<IDataProvider> as is in the
324 // Note: we don't use auto here as we want to pass std::shared_ptr<IDataProvider> as is in the
325 // QVariant
325 // QVariant
326 std::shared_ptr<IDataProvider> provider = std::make_shared<AmdaProvider>();
326 std::shared_ptr<IDataProvider> provider = std::make_shared<AmdaProvider>();
327
327
328 QTest::newRow("fuzzingTest") << Properties{
328 QTest::newRow("fuzzingTest") << Properties{
329 {MAX_RANGE_PROPERTY, QVariant::fromValue(maxRange)},
329 {MAX_RANGE_PROPERTY, QVariant::fromValue(maxRange)},
330 {METADATA_POOL_PROPERTY, QVariant::fromValue(metadataPool)},
330 {METADATA_POOL_PROPERTY, QVariant::fromValue(metadataPool)},
331 {PROVIDER_PROPERTY, QVariant::fromValue(provider)}};
331 {PROVIDER_PROPERTY, QVariant::fromValue(provider)}};
332 }
332 }
333
333
334 void TestAmdaFuzzing::testFuzzing()
334 void TestAmdaFuzzing::testFuzzing()
335 {
335 {
336 QFETCH(Properties, properties);
336 QFETCH(Properties, properties);
337
337
338 // Sets cache property
338 // Sets cache property
339 QSettings settings{};
339 QSettings settings{};
340 auto cacheTolerance = properties.value(CACHE_TOLERANCE_PROPERTY, CACHE_TOLERANCE_DEFAULT_VALUE);
340 auto cacheTolerance = properties.value(CACHE_TOLERANCE_PROPERTY, CACHE_TOLERANCE_DEFAULT_VALUE);
341 settings.setValue(GENERAL_TOLERANCE_AT_INIT_KEY, cacheTolerance);
341 settings.setValue(GENERAL_TOLERANCE_AT_INIT_KEY, cacheTolerance);
342 settings.setValue(GENERAL_TOLERANCE_AT_UPDATE_KEY, cacheTolerance);
342 settings.setValue(GENERAL_TOLERANCE_AT_UPDATE_KEY, cacheTolerance);
343
343
344 auto &variableController = sqpApp->variableController();
344 auto &variableController = sqpApp->variableController();
345 auto &timeController = sqpApp->timeController();
345 auto &timeController = sqpApp->timeController();
346
346
347 // Generates random initial range (bounded to max range)
347 // Generates random initial range (bounded to max range)
348 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
348 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
349 .value<SqpRange>();
349 .value<SqpRange>();
350
350
351 QVERIFY(maxRange != INVALID_RANGE);
351 QVERIFY(maxRange != INVALID_RANGE);
352
352
353 auto initialRangeStart
353 auto initialRangeStart
354 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
354 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
355 auto initialRangeEnd
355 auto initialRangeEnd
356 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
356 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
357 if (initialRangeStart > initialRangeEnd) {
357 if (initialRangeStart > initialRangeEnd) {
358 std::swap(initialRangeStart, initialRangeEnd);
358 std::swap(initialRangeStart, initialRangeEnd);
359 }
359 }
360
360
361 // Sets initial range on time controller
361 // Sets initial range on time controller
362 SqpRange initialRange{initialRangeStart, initialRangeEnd};
362 SqpRange initialRange{initialRangeStart, initialRangeEnd};
363 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Setting initial range to" << initialRange << "...";
363 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Setting initial range to" << initialRange << "...";
364 timeController.onTimeToUpdate(initialRange);
364 timeController.setDateTimeRange(initialRange);
365 properties.insert(INITIAL_RANGE_PROPERTY, QVariant::fromValue(initialRange));
365 properties.insert(INITIAL_RANGE_PROPERTY, QVariant::fromValue(initialRange));
366
366
367 FuzzingTest test{variableController, properties};
367 FuzzingTest test{variableController, properties};
368 test.execute();
368 test.execute();
369 }
369 }
370
370
371 int main(int argc, char *argv[])
371 int main(int argc, char *argv[])
372 {
372 {
373 // Increases the test function timeout (which is 5 minutes by default) to 12 hours
373 // Increases the test function timeout (which is 5 minutes by default) to 12 hours
374 // https://stackoverflow.com/questions/42655932/setting-timeout-to-qt-test
374 // https://stackoverflow.com/questions/42655932/setting-timeout-to-qt-test
375 qputenv("QTEST_FUNCTION_TIMEOUT", QByteArray::number(12*60*60*1000));
375 qputenv("QTEST_FUNCTION_TIMEOUT", QByteArray::number(12*60*60*1000));
376
376
377 QLoggingCategory::setFilterRules(
377 QLoggingCategory::setFilterRules(
378 "*.warning=false\n"
378 "*.warning=false\n"
379 "*.info=false\n"
379 "*.info=false\n"
380 "*.debug=false\n"
380 "*.debug=false\n"
381 "FuzzingOperations.info=true\n"
381 "FuzzingOperations.info=true\n"
382 "FuzzingValidators.info=true\n"
382 "FuzzingValidators.info=true\n"
383 "TestAmdaFuzzing.info=true\n");
383 "TestAmdaFuzzing.info=true\n");
384
384
385 SqpApplication app{argc, argv};
385 SqpApplication app{argc, argv};
386 SqpApplication::setOrganizationName("LPP");
386 SqpApplication::setOrganizationName("LPP");
387 SqpApplication::setOrganizationDomain("lpp.fr");
387 SqpApplication::setOrganizationDomain("lpp.fr");
388 SqpApplication::setApplicationName("SciQLop-TestFuzzing");
388 SqpApplication::setApplicationName("SciQLop-TestFuzzing");
389 app.setAttribute(Qt::AA_Use96Dpi, true);
389 app.setAttribute(Qt::AA_Use96Dpi, true);
390 TestAmdaFuzzing testObject{};
390 TestAmdaFuzzing testObject{};
391 QTEST_SET_MAIN_SOURCE_PATH
391 QTEST_SET_MAIN_SOURCE_PATH
392 return QTest::qExec(&testObject, argc, argv);
392 return QTest::qExec(&testObject, argc, argv);
393 }
393 }
394
394
395 #include "TestAmdaFuzzing.moc"
395 #include "TestAmdaFuzzing.moc"
@@ -1,119 +1,119
1 #include "MockPlugin.h"
1 #include "MockPlugin.h"
2 #include "CosinusProvider.h"
2 #include "CosinusProvider.h"
3 #include "MockDefs.h"
3 #include "MockDefs.h"
4
4
5 #include <DataSource/DataSourceController.h>
5 #include <DataSource/DataSourceController.h>
6 #include <DataSource/DataSourceItem.h>
6 #include <DataSource/DataSourceItem.h>
7 #include <DataSource/DataSourceItemAction.h>
7 #include <DataSource/DataSourceItemAction.h>
8
8
9 #include <SqpApplication.h>
9 #include <SqpApplication.h>
10
10
11 Q_LOGGING_CATEGORY(LOG_MockPlugin, "MockPlugin")
11 Q_LOGGING_CATEGORY(LOG_MockPlugin, "MockPlugin")
12
12
13 namespace {
13 namespace {
14
14
15 /// Name of the data source
15 /// Name of the data source
16 const auto DATA_SOURCE_NAME = QStringLiteral("MMS");
16 const auto DATA_SOURCE_NAME = QStringLiteral("MMS");
17
17
18 /// Creates the data provider relative to the plugin
18 /// Creates the data provider relative to the plugin
19 std::unique_ptr<IDataProvider> createDataProvider() noexcept
19 std::unique_ptr<IDataProvider> createDataProvider() noexcept
20 {
20 {
21 return std::make_unique<CosinusProvider>();
21 return std::make_unique<CosinusProvider>();
22 }
22 }
23
23
24 std::unique_ptr<DataSourceItem> createProductItem(const QVariantHash &data,
24 std::unique_ptr<DataSourceItem> createProductItem(const QVariantHash &metaData,
25 const QUuid &dataSourceUid)
25 const QUuid &dataSourceUid)
26 {
26 {
27 auto result = std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, data);
27 auto result = std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, metaData);
28
28
29 // Adds plugin name to product metadata
29 // Adds plugin name to product metadata
30 result->setData(DataSourceItem::PLUGIN_DATA_KEY, DATA_SOURCE_NAME);
30 result->setData(DataSourceItem::PLUGIN_DATA_KEY, DATA_SOURCE_NAME);
31 result->setData(DataSourceItem::ID_DATA_KEY, data.value(DataSourceItem::NAME_DATA_KEY));
31 result->setData(DataSourceItem::ID_DATA_KEY, metaData.value(DataSourceItem::NAME_DATA_KEY));
32
32
33 auto productName = data.value(DataSourceItem::NAME_DATA_KEY).toString();
33 auto productName = metaData.value(DataSourceItem::NAME_DATA_KEY).toString();
34
34
35 // Add action to load product from DataSourceController
35 // Add action to load product from DataSourceController
36 result->addAction(std::make_unique<DataSourceItemAction>(
36 result->addAction(std::make_unique<DataSourceItemAction>(
37 QObject::tr("Load %1 product").arg(productName),
37 QObject::tr("Load %1 product").arg(productName),
38 [productName, dataSourceUid](DataSourceItem &item) {
38 [productName, dataSourceUid](DataSourceItem &item) {
39 if (auto app = sqpApp) {
39 if (auto app = sqpApp) {
40 app->dataSourceController().loadProductItem(dataSourceUid, item);
40 app->dataSourceController().loadProductItem(dataSourceUid, item);
41 }
41 }
42 }));
42 }));
43
43
44 return result;
44 return result;
45 }
45 }
46
46
47 /// Creates the data source item relative to the plugin
47 /// Creates the data source item relative to the plugin
48 std::unique_ptr<DataSourceItem> createDataSourceItem(const QUuid &dataSourceUid) noexcept
48 std::unique_ptr<DataSourceItem> createDataSourceItem(const QUuid &dataSourceUid) noexcept
49 {
49 {
50 // Magnetic field products
50 // Magnetic field products
51 auto magneticFieldFolder = std::make_unique<DataSourceItem>(DataSourceItemType::NODE,
51 auto magneticFieldFolder = std::make_unique<DataSourceItem>(DataSourceItemType::NODE,
52 QStringLiteral("_Magnetic field"));
52 QStringLiteral("_Magnetic field"));
53 magneticFieldFolder->appendChild(
53 magneticFieldFolder->appendChild(
54 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Scalar 10 Hz")},
54 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Scalar 10 Hz")},
55 {COSINUS_TYPE_KEY, "scalar"},
55 {COSINUS_TYPE_KEY, "scalar"},
56 {COSINUS_FREQUENCY_KEY, 10.}},
56 {COSINUS_FREQUENCY_KEY, 10.}},
57 dataSourceUid));
57 dataSourceUid));
58 magneticFieldFolder->appendChild(
58 magneticFieldFolder->appendChild(
59 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Scalar 60 Hz")},
59 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Scalar 60 Hz")},
60 {COSINUS_TYPE_KEY, "scalar"},
60 {COSINUS_TYPE_KEY, "scalar"},
61 {COSINUS_FREQUENCY_KEY, 60.}},
61 {COSINUS_FREQUENCY_KEY, 60.}},
62 dataSourceUid));
62 dataSourceUid));
63 magneticFieldFolder->appendChild(
63 magneticFieldFolder->appendChild(
64 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Scalar 100 Hz")},
64 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Scalar 100 Hz")},
65 {COSINUS_TYPE_KEY, "scalar"},
65 {COSINUS_TYPE_KEY, "scalar"},
66 {COSINUS_FREQUENCY_KEY, 100.}},
66 {COSINUS_FREQUENCY_KEY, 100.}},
67 dataSourceUid));
67 dataSourceUid));
68 magneticFieldFolder->appendChild(
68 magneticFieldFolder->appendChild(
69 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Vector 10 Hz")},
69 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Vector 10 Hz")},
70 {COSINUS_TYPE_KEY, "vector"},
70 {COSINUS_TYPE_KEY, "vector"},
71 {COSINUS_FREQUENCY_KEY, 10.}},
71 {COSINUS_FREQUENCY_KEY, 10.}},
72 dataSourceUid));
72 dataSourceUid));
73 magneticFieldFolder->appendChild(
73 magneticFieldFolder->appendChild(
74 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Vector 60 Hz")},
74 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Vector 60 Hz")},
75 {COSINUS_TYPE_KEY, "vector"},
75 {COSINUS_TYPE_KEY, "vector"},
76 {COSINUS_FREQUENCY_KEY, 60.}},
76 {COSINUS_FREQUENCY_KEY, 60.}},
77 dataSourceUid));
77 dataSourceUid));
78 magneticFieldFolder->appendChild(
78 magneticFieldFolder->appendChild(
79 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Vector 100 Hz")},
79 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Vector 100 Hz")},
80 {COSINUS_TYPE_KEY, "vector"},
80 {COSINUS_TYPE_KEY, "vector"},
81 {COSINUS_FREQUENCY_KEY, 100.}},
81 {COSINUS_FREQUENCY_KEY, 100.}},
82 dataSourceUid));
82 dataSourceUid));
83 magneticFieldFolder->appendChild(
83 magneticFieldFolder->appendChild(
84 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Spectrogram 1 Hz")},
84 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Spectrogram 1 Hz")},
85 {COSINUS_TYPE_KEY, "spectrogram"},
85 {COSINUS_TYPE_KEY, "spectrogram"},
86 {COSINUS_FREQUENCY_KEY, 1.}},
86 {COSINUS_FREQUENCY_KEY, 1.}},
87 dataSourceUid));
87 dataSourceUid));
88
88
89 // Electric field products
89 // Electric field products
90 auto electricFieldFolder = std::make_unique<DataSourceItem>(DataSourceItemType::NODE,
90 auto electricFieldFolder = std::make_unique<DataSourceItem>(DataSourceItemType::NODE,
91 QStringLiteral("_Electric field"));
91 QStringLiteral("_Electric field"));
92
92
93 // Root
93 // Root
94 auto root = std::make_unique<DataSourceItem>(DataSourceItemType::NODE, DATA_SOURCE_NAME);
94 auto root = std::make_unique<DataSourceItem>(DataSourceItemType::NODE, DATA_SOURCE_NAME);
95 root->appendChild(std::move(magneticFieldFolder));
95 root->appendChild(std::move(magneticFieldFolder));
96 root->appendChild(std::move(electricFieldFolder));
96 root->appendChild(std::move(electricFieldFolder));
97
97
98 return root;
98 return root;
99 }
99 }
100
100
101 } // namespace
101 } // namespace
102
102
103 void MockPlugin::initialize()
103 void MockPlugin::initialize()
104 {
104 {
105 if (auto app = sqpApp) {
105 if (auto app = sqpApp) {
106 // Registers to the data source controller
106 // Registers to the data source controller
107 auto &dataSourceController = app->dataSourceController();
107 auto &dataSourceController = app->dataSourceController();
108 auto dataSourceUid = dataSourceController.registerDataSource(DATA_SOURCE_NAME);
108 auto dataSourceUid = dataSourceController.registerDataSource(DATA_SOURCE_NAME);
109
109
110 // Sets data source tree
110 // Sets data source tree
111 dataSourceController.setDataSourceItem(dataSourceUid, createDataSourceItem(dataSourceUid));
111 dataSourceController.setDataSourceItem(dataSourceUid, createDataSourceItem(dataSourceUid));
112
112
113 // Sets data provider
113 // Sets data provider
114 dataSourceController.setDataProvider(dataSourceUid, createDataProvider());
114 dataSourceController.setDataProvider(dataSourceUid, createDataProvider());
115 }
115 }
116 else {
116 else {
117 qCWarning(LOG_MockPlugin()) << tr("Can't access to SciQlop application");
117 qCWarning(LOG_MockPlugin()) << tr("Can't access to SciQlop application");
118 }
118 }
119 }
119 }
@@ -1,195 +1,195
1 #include "CosinusProvider.h"
1 #include "CosinusProvider.h"
2 #include "MockDefs.h"
2 #include "MockDefs.h"
3
3
4 #include <Data/DataProviderParameters.h>
4 #include <Data/DataProviderParameters.h>
5 #include <Data/ScalarSeries.h>
5 #include <Data/ScalarSeries.h>
6 #include <SqpApplication.h>
6 #include <SqpApplication.h>
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
10
11 #include <QObject>
11 #include <QObject>
12 #include <QtTest>
12 #include <QtTest>
13
13
14 #include <cmath>
14 #include <cmath>
15 #include <memory>
15 #include <memory>
16
16
17 namespace {
17 namespace {
18
18
19 /// Path for the tests
19 /// Path for the tests
20 const auto TESTS_RESOURCES_PATH = QFileInfo{
20 const auto TESTS_RESOURCES_PATH = QFileInfo{
21 QString{MOCKPLUGIN_TESTS_RESOURCES_DIR},
21 QString{MOCKPLUGIN_TESTS_RESOURCES_DIR},
22 "TestCosinusAcquisition"}.absoluteFilePath();
22 "TestCosinusAcquisition"}.absoluteFilePath();
23
23
24 /// Format of dates in data files
24 /// Format of dates in data files
25 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
25 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
26
26
27 /**
27 /**
28 * Verifies that the data in the candidate series are identical to the data in the reference series
28 * Verifies that the data in the candidate series are identical to the data in the reference series
29 * in a specific range
29 * in a specific range
30 * @param candidate the candidate data series
30 * @param candidate the candidate data series
31 * @param range the range to check
31 * @param range the range to check
32 * @param reference the reference data series
32 * @param reference the reference data series
33 * @return true if the data of the candidate series and the reference series are identical in the
33 * @return true if the data of the candidate series and the reference series are identical in the
34 * range, false otherwise
34 * range, false otherwise
35 */
35 */
36 bool checkDataSeries(std::shared_ptr<IDataSeries> candidate, const SqpRange &range,
36 bool checkDataSeries(std::shared_ptr<IDataSeries> candidate, const SqpRange &range,
37 std::shared_ptr<IDataSeries> reference)
37 std::shared_ptr<IDataSeries> reference)
38 {
38 {
39 if (candidate == nullptr || reference == nullptr) {
39 if (candidate == nullptr || reference == nullptr) {
40 return candidate == reference;
40 return candidate == reference;
41 }
41 }
42
42
43 auto referenceIt = reference->xAxisRange(range.m_TStart, range.m_TEnd);
43 auto referenceIt = reference->xAxisRange(range.m_TStart, range.m_TEnd);
44
44
45 qInfo() << "candidateSize" << std::distance(candidate->cbegin(), candidate->cend());
45 qInfo() << "candidateSize" << std::distance(candidate->cbegin(), candidate->cend());
46 qInfo() << "refSize" << std::distance(referenceIt.first, referenceIt.second);
46 qInfo() << "refSize" << std::distance(referenceIt.first, referenceIt.second);
47
47
48 return std::equal(candidate->cbegin(), candidate->cend(), referenceIt.first, referenceIt.second,
48 return std::equal(candidate->cbegin(), candidate->cend(), referenceIt.first, referenceIt.second,
49 [](const auto &it1, const auto &it2) {
49 [](const auto &it1, const auto &it2) {
50 // - milliseconds precision for time
50 // - milliseconds precision for time
51 // - 1e-6 precision for value
51 // - 1e-6 precision for value
52 return std::abs(it1.x() - it2.x()) < 1e-3
52 return std::abs(it1.x() - it2.x()) < 1e-3
53 && std::abs(it1.value() - it2.value()) < 1e-6;
53 && std::abs(it1.value() - it2.value()) < 1e-6;
54 });
54 });
55 }
55 }
56
56
57 } // namespace
57 } // namespace
58
58
59 /**
59 /**
60 * @brief The TestCosinusAcquisition class tests acquisition in SciQlop (operations like zooms in,
60 * @brief The TestCosinusAcquisition class tests acquisition in SciQlop (operations like zooms in,
61 * zooms out, pans) of data from CosinusProvider
61 * zooms out, pans) of data from CosinusProvider
62 * @sa CosinusProvider
62 * @sa CosinusProvider
63 */
63 */
64 class TestCosinusAcquisition : public QObject {
64 class TestCosinusAcquisition : public QObject {
65 Q_OBJECT
65 Q_OBJECT
66
66
67 private slots:
67 private slots:
68 /// Input data for @sa testAcquisition()
68 /// Input data for @sa testAcquisition()
69 void testAcquisition_data();
69 void testAcquisition_data();
70 void testAcquisition();
70 void testAcquisition();
71 };
71 };
72
72
73 void TestCosinusAcquisition::testAcquisition_data()
73 void TestCosinusAcquisition::testAcquisition_data()
74 {
74 {
75 // ////////////// //
75 // ////////////// //
76 // Test structure //
76 // Test structure //
77 // ////////////// //
77 // ////////////// //
78
78
79 QTest::addColumn<SqpRange>("referenceRange"); // Range for generating reference series
79 QTest::addColumn<SqpRange>("referenceRange"); // Range for generating reference series
80 QTest::addColumn<SqpRange>("initialRange"); // First acquisition
80 QTest::addColumn<SqpRange>("initialRange"); // First acquisition
81 QTest::addColumn<int>("operationDelay"); // Acquisitions to make
81 QTest::addColumn<int>("operationDelay"); // Acquisitions to make
82 QTest::addColumn<std::vector<SqpRange> >("operations"); // Acquisitions to make
82 QTest::addColumn<std::vector<SqpRange> >("operations"); // Acquisitions to make
83
83
84 // ////////// //
84 // ////////// //
85 // Test cases //
85 // Test cases //
86 // ////////// //
86 // ////////// //
87
87
88 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
88 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
89 return DateUtils::secondsSinceEpoch(
89 return DateUtils::secondsSinceEpoch(
90 QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC});
90 QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC});
91 };
91 };
92
92
93 QTest::newRow("cosinus")
93 QTest::newRow("cosinus")
94 << SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)}
94 << SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)}
95 << SqpRange{dateTime(2017, 1, 1, 12, 30, 0), dateTime(2017, 1, 1, 12, 35, 1)} << 250
95 << SqpRange{dateTime(2017, 1, 1, 12, 30, 0), dateTime(2017, 1, 1, 12, 35, 1)} << 250
96 << std::vector<SqpRange>{
96 << std::vector<SqpRange>{
97 // Pan (jump) left
97 // Pan (jump) left
98 SqpRange{dateTime(2017, 1, 1, 12, 45, 0), dateTime(2017, 1, 1, 12, 50, 0)},
98 SqpRange{dateTime(2017, 1, 1, 12, 45, 0), dateTime(2017, 1, 1, 12, 50, 0)},
99 // Pan (jump) right
99 // Pan (jump) right
100 SqpRange{dateTime(2017, 1, 1, 12, 15, 0), dateTime(2017, 1, 1, 12, 20, 0)},
100 SqpRange{dateTime(2017, 1, 1, 12, 15, 0), dateTime(2017, 1, 1, 12, 20, 0)},
101 // Pan (overlay) right
101 // Pan (overlay) right
102 SqpRange{dateTime(2017, 1, 1, 12, 14, 0), dateTime(2017, 1, 1, 12, 19, 0)},
102 SqpRange{dateTime(2017, 1, 1, 12, 14, 0), dateTime(2017, 1, 1, 12, 19, 0)},
103 // Pan (overlay) left
103 // Pan (overlay) left
104 SqpRange{dateTime(2017, 1, 1, 12, 15, 0), dateTime(2017, 1, 1, 12, 20, 0)},
104 SqpRange{dateTime(2017, 1, 1, 12, 15, 0), dateTime(2017, 1, 1, 12, 20, 0)},
105 // Pan (overlay) left
105 // Pan (overlay) left
106 SqpRange{dateTime(2017, 1, 1, 12, 16, 0), dateTime(2017, 1, 1, 12, 21, 0)},
106 SqpRange{dateTime(2017, 1, 1, 12, 16, 0), dateTime(2017, 1, 1, 12, 21, 0)},
107 // Zoom in
107 // Zoom in
108 SqpRange{dateTime(2017, 1, 1, 12, 17, 30), dateTime(2017, 1, 1, 12, 19, 30)},
108 SqpRange{dateTime(2017, 1, 1, 12, 17, 30), dateTime(2017, 1, 1, 12, 19, 30)},
109 // Zoom out
109 // Zoom out
110 SqpRange{dateTime(2017, 1, 1, 12, 12, 30), dateTime(2017, 1, 1, 12, 24, 30)}};
110 SqpRange{dateTime(2017, 1, 1, 12, 12, 30), dateTime(2017, 1, 1, 12, 24, 30)}};
111
111
112 QTest::newRow("cosinus_big")
112 QTest::newRow("cosinus_big")
113 << SqpRange{dateTime(2017, 1, 1, 1, 0, 0), dateTime(2017, 1, 5, 13, 0, 0)}
113 << SqpRange{dateTime(2017, 1, 1, 1, 0, 0), dateTime(2017, 1, 5, 13, 0, 0)}
114 << SqpRange{dateTime(2017, 1, 2, 6, 30, 0), dateTime(2017, 1, 2, 18, 30, 0)} << 5000
114 << SqpRange{dateTime(2017, 1, 2, 6, 30, 0), dateTime(2017, 1, 2, 18, 30, 0)} << 5000
115 << std::vector<SqpRange>{
115 << std::vector<SqpRange>{
116 // Pan (jump) left
116 // Pan (jump) left
117 SqpRange{dateTime(2017, 1, 1, 13, 30, 0), dateTime(2017, 1, 1, 18, 30, 0)},
117 SqpRange{dateTime(2017, 1, 1, 13, 30, 0), dateTime(2017, 1, 1, 18, 30, 0)},
118 // Pan (jump) right
118 // Pan (jump) right
119 SqpRange{dateTime(2017, 1, 3, 4, 30, 0), dateTime(2017, 1, 3, 10, 30, 0)},
119 SqpRange{dateTime(2017, 1, 3, 4, 30, 0), dateTime(2017, 1, 3, 10, 30, 0)},
120 // Pan (overlay) right
120 // Pan (overlay) right
121 SqpRange{dateTime(2017, 1, 3, 8, 30, 0), dateTime(2017, 1, 3, 12, 30, 0)},
121 SqpRange{dateTime(2017, 1, 3, 8, 30, 0), dateTime(2017, 1, 3, 12, 30, 0)},
122 // Pan (overlay) left
122 // Pan (overlay) left
123 SqpRange{dateTime(2017, 1, 2, 8, 30, 0), dateTime(2017, 1, 3, 10, 30, 0)},
123 SqpRange{dateTime(2017, 1, 2, 8, 30, 0), dateTime(2017, 1, 3, 10, 30, 0)},
124 // Pan (overlay) left
124 // Pan (overlay) left
125 SqpRange{dateTime(2017, 1, 1, 12, 30, 0), dateTime(2017, 1, 3, 5, 30, 0)},
125 SqpRange{dateTime(2017, 1, 1, 12, 30, 0), dateTime(2017, 1, 3, 5, 30, 0)},
126 // Zoom in
126 // Zoom in
127 SqpRange{dateTime(2017, 1, 2, 2, 30, 0), dateTime(2017, 1, 2, 8, 30, 0)},
127 SqpRange{dateTime(2017, 1, 2, 2, 30, 0), dateTime(2017, 1, 2, 8, 30, 0)},
128 // Zoom out
128 // Zoom out
129 SqpRange{dateTime(2017, 1, 1, 14, 30, 0), dateTime(2017, 1, 3, 12, 30, 0)}};
129 SqpRange{dateTime(2017, 1, 1, 14, 30, 0), dateTime(2017, 1, 3, 12, 30, 0)}};
130 }
130 }
131
131
132 void TestCosinusAcquisition::testAcquisition()
132 void TestCosinusAcquisition::testAcquisition()
133 {
133 {
134 // Retrieves reference range
134 // Retrieves reference range
135 QFETCH(SqpRange, referenceRange);
135 QFETCH(SqpRange, referenceRange);
136 CosinusProvider referenceProvider{};
136 CosinusProvider referenceProvider{};
137 auto dataSeries = referenceProvider.provideDataSeries(
137 auto dataSeries = referenceProvider.provideDataSeries(
138 referenceRange, {{COSINUS_TYPE_KEY, "scalar"}, {COSINUS_FREQUENCY_KEY, 10.}});
138 referenceRange, {{COSINUS_TYPE_KEY, "scalar"}, {COSINUS_FREQUENCY_KEY, 10.}});
139
139
140 auto end = dataSeries->cend() - 1;
140 auto end = dataSeries->cend() - 1;
141 qInfo() << dataSeries->nbPoints() << dataSeries->cbegin()->x() << end->x();
141 qInfo() << dataSeries->nbPoints() << dataSeries->cbegin()->x() << end->x();
142
142
143 /// Lambda used to validate a variable at each step
143 /// Lambda used to validate a variable at each step
144 auto validateVariable
144 auto validateVariable
145 = [dataSeries](std::shared_ptr<Variable> variable, const SqpRange &range) {
145 = [dataSeries](std::shared_ptr<Variable> variable, const SqpRange &range) {
146 // Checks that the variable's range has changed
146 // Checks that the variable's range has changed
147 qInfo() << "range vs expected range" << variable->range() << range;
147 qInfo() << "range vs expected range" << variable->range() << range;
148 QCOMPARE(variable->range(), range);
148 QCOMPARE(variable->range(), range);
149
149
150 // Checks the variable's data series
150 // Checks the variable's data series
151 QVERIFY(checkDataSeries(variable->dataSeries(), variable->cacheRange(), dataSeries));
151 QVERIFY(checkDataSeries(variable->dataSeries(), variable->cacheRange(), dataSeries));
152 };
152 };
153
153
154 // Creates variable
154 // Creates variable
155 QFETCH(SqpRange, initialRange);
155 QFETCH(SqpRange, initialRange);
156 sqpApp->timeController().onTimeToUpdate(initialRange);
156 sqpApp->timeController().setDateTimeRange(initialRange);
157 auto provider = std::make_shared<CosinusProvider>();
157 auto provider = std::make_shared<CosinusProvider>();
158 auto variable = sqpApp->variableController().createVariable(
158 auto variable = sqpApp->variableController().createVariable(
159 "MMS", {{COSINUS_TYPE_KEY, "scalar"}, {COSINUS_FREQUENCY_KEY, 10.}}, provider);
159 "MMS", {{COSINUS_TYPE_KEY, "scalar"}, {COSINUS_FREQUENCY_KEY, 10.}}, provider, initialRange);
160
160
161
161
162 QFETCH(int, operationDelay);
162 QFETCH(int, operationDelay);
163 QTest::qWait(operationDelay);
163 QTest::qWait(operationDelay);
164 validateVariable(variable, initialRange);
164 validateVariable(variable, initialRange);
165
165
166 QTest::qWait(operationDelay);
166 QTest::qWait(operationDelay);
167 // Makes operations on the variable
167 // Makes operations on the variable
168 QFETCH(std::vector<SqpRange>, operations);
168 QFETCH(std::vector<SqpRange>, operations);
169 for (const auto &operation : operations) {
169 for (const auto &operation : operations) {
170 // Asks request on the variable and waits during its execution
170 // Asks request on the variable and waits during its execution
171 sqpApp->variableController().onRequestDataLoading({variable}, operation, false);
171 sqpApp->variableController().onRequestDataLoading({variable}, operation, false);
172
172
173 QTest::qWait(operationDelay);
173 QTest::qWait(operationDelay);
174 validateVariable(variable, operation);
174 validateVariable(variable, operation);
175 }
175 }
176
176
177
177
178 for (const auto &operation : operations) {
178 for (const auto &operation : operations) {
179 // Asks request on the variable and waits during its execution
179 // Asks request on the variable and waits during its execution
180 sqpApp->variableController().onRequestDataLoading({variable}, operation, false);
180 sqpApp->variableController().onRequestDataLoading({variable}, operation, false);
181 }
181 }
182 QTest::qWait(operationDelay);
182 QTest::qWait(operationDelay);
183 validateVariable(variable, operations.back());
183 validateVariable(variable, operations.back());
184 }
184 }
185
185
186 int main(int argc, char *argv[])
186 int main(int argc, char *argv[])
187 {
187 {
188 SqpApplication app{argc, argv};
188 SqpApplication app{argc, argv};
189 app.setAttribute(Qt::AA_Use96Dpi, true);
189 app.setAttribute(Qt::AA_Use96Dpi, true);
190 TestCosinusAcquisition testObject{};
190 TestCosinusAcquisition testObject{};
191 QTEST_SET_MAIN_SOURCE_PATH
191 QTEST_SET_MAIN_SOURCE_PATH
192 return QTest::qExec(&testObject, argc, argv);
192 return QTest::qExec(&testObject, argc, argv);
193 }
193 }
194
194
195 #include "TestCosinusAcquisition.moc"
195 #include "TestCosinusAcquisition.moc"
General Comments 0
You need to be logged in to leave comments. Login now