##// END OF EJS Templates
Merge branch 'feature/DragVariables' into develop
trabillard -
r854:552d1389af00 merge
parent child
Show More
@@ -0,0 +1,18
1 #ifndef SCIQLOP_MIMETYPESDEF_H
2 #define SCIQLOP_MIMETYPESDEF_H
3
4 #include "CoreGlobal.h"
5
6 #include <QString>
7
8 // ////////////////// //
9 // SciQlop Mime Types //
10 // ////////////////// //
11
12 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_GRAPH;
13 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_ZONE;
14 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_VARIABLE_LIST;
15 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_TIME_RANGE;
16
17
18 #endif // SCIQLOP_MIMETYPESDEF_H
@@ -0,0 +1,6
1 #include "Common/MimeTypesDef.h"
2
3 const QString MIME_TYPE_GRAPH = QStringLiteral("scqlop/graph");
4 const QString MIME_TYPE_ZONE = QStringLiteral("scqlop/zone");
5 const QString MIME_TYPE_VARIABLE_LIST = QStringLiteral("scqlop/var-list");
6 const QString MIME_TYPE_TIME_RANGE = QStringLiteral("scqlop/time-range");
@@ -0,0 +1,7
1 #ifndef SCIQLOP_VISUALIZATIONDEF_H
2 #define SCIQLOP_VISUALIZATIONDEF_H
3
4 /// Minimum height for graph added in zones (in pixels)
5 extern const int GRAPH_MINIMUM_HEIGHT;
6
7 #endif // SCIQLOP_VISUALIZATIONDEF_H
@@ -0,0 +1,3
1 #include "Common/VisualizationDef.h"
2
3 const int GRAPH_MINIMUM_HEIGHT = 300;
@@ -1,130 +1,132
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/AcquisitionDataPacket.h>
6 #include <Data/AcquisitionDataPacket.h>
7 #include <Data/SqpRange.h>
7 #include <Data/SqpRange.h>
8
8
9 #include <QLoggingCategory>
9 #include <QLoggingCategory>
10 #include <QObject>
10 #include <QObject>
11 #include <QUuid>
11 #include <QUuid>
12
12
13 #include <Common/spimpl.h>
13 #include <Common/spimpl.h>
14
14
15 class IDataProvider;
15 class IDataProvider;
16 class QItemSelectionModel;
16 class QItemSelectionModel;
17 class TimeController;
17 class TimeController;
18 class Variable;
18 class Variable;
19 class VariableModel;
19 class VariableModel;
20
20
21 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
21 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
22
22
23
23
24 /**
24 /**
25 * Possible types of zoom operation
25 * Possible types of zoom operation
26 */
26 */
27 enum class AcquisitionZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
27 enum class AcquisitionZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
28
28
29
29
30 /**
30 /**
31 * @brief The VariableController class aims to handle the variables in SciQlop.
31 * @brief The VariableController class aims to handle the variables in SciQlop.
32 */
32 */
33 class SCIQLOP_CORE_EXPORT VariableController : public QObject {
33 class SCIQLOP_CORE_EXPORT VariableController : public QObject {
34 Q_OBJECT
34 Q_OBJECT
35 public:
35 public:
36 explicit VariableController(QObject *parent = 0);
36 explicit VariableController(QObject *parent = 0);
37 virtual ~VariableController();
37 virtual ~VariableController();
38
38
39 VariableModel *variableModel() noexcept;
39 VariableModel *variableModel() noexcept;
40 QItemSelectionModel *variableSelectionModel() noexcept;
40 QItemSelectionModel *variableSelectionModel() noexcept;
41
41
42 void setTimeController(TimeController *timeController) noexcept;
42 void setTimeController(TimeController *timeController) noexcept;
43
43
44 /**
44 /**
45 * Clones the variable passed in parameter and adds the duplicate to the controller
45 * Clones the variable passed in parameter and adds the duplicate to the controller
46 * @param variable the variable to duplicate
46 * @param variable the variable to duplicate
47 * @return the duplicate created, nullptr if the variable couldn't be created
47 * @return the duplicate created, nullptr if the variable couldn't be created
48 */
48 */
49 std::shared_ptr<Variable> cloneVariable(std::shared_ptr<Variable> variable) noexcept;
49 std::shared_ptr<Variable> cloneVariable(std::shared_ptr<Variable> variable) noexcept;
50
50
51 /**
51 /**
52 * Deletes from the controller the variable passed in parameter.
52 * Deletes from the controller the variable passed in parameter.
53 *
53 *
54 * Delete a variable includes:
54 * Delete a variable includes:
55 * - the deletion of the various references to the variable in SciQlop
55 * - the deletion of the various references to the variable in SciQlop
56 * - the deletion of the model variable
56 * - the deletion of the model variable
57 * - the deletion of the provider associated with the variable
57 * - the deletion of the provider associated with the variable
58 * - removing the cache associated with the variable
58 * - removing the cache associated with the variable
59 *
59 *
60 * @param variable the variable to delete from the controller.
60 * @param variable the variable to delete from the controller.
61 */
61 */
62 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
62 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
63
63
64 /**
64 /**
65 * Deletes from the controller the variables passed in parameter.
65 * Deletes from the controller the variables passed in parameter.
66 * @param variables the variables to delete from the controller.
66 * @param variables the variables to delete from the controller.
67 * @sa deleteVariable()
67 * @sa deleteVariable()
68 */
68 */
69 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
69 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
70
70
71 QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const;
72 QList<std::shared_ptr<Variable> > variablesForMimeData(const QByteArray &mimeData) const;
71
73
72 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
74 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
73 signals:
75 signals:
74 /// Signal emitted when a variable is about to be deleted from the controller
76 /// Signal emitted when a variable is about to be deleted from the controller
75 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
77 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
76
78
77 /// Signal emitted when a data acquisition is requested on a range for a variable
79 /// Signal emitted when a data acquisition is requested on a range for a variable
78 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
80 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
79
81
80 /// Signal emitted when a sub range of the cacheRange of the variable can be displayed
82 /// Signal emitted when a sub range of the cacheRange of the variable can be displayed
81 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
83 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
82
84
83 public slots:
85 public slots:
84 /// Request the data loading of the variable whithin range
86 /// Request the data loading of the variable whithin range
85 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
87 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
86 bool synchronise);
88 bool synchronise);
87 /**
89 /**
88 * Creates a new variable and adds it to the model
90 * Creates a new variable and adds it to the model
89 * @param name the name of the new variable
91 * @param name the name of the new variable
90 * @param metadata the metadata of the new variable
92 * @param metadata the metadata of the new variable
91 * @param provider the data provider for the new variable
93 * @param provider the data provider for the new variable
92 * @return the pointer to the new variable or nullptr if the creation failed
94 * @return the pointer to the new variable or nullptr if the creation failed
93 */
95 */
94 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
96 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
95 std::shared_ptr<IDataProvider> provider) noexcept;
97 std::shared_ptr<IDataProvider> provider) noexcept;
96
98
97 /// Update the temporal parameters of every selected variable to dateTime
99 /// Update the temporal parameters of every selected variable to dateTime
98 void onDateTimeOnSelection(const SqpRange &dateTime);
100 void onDateTimeOnSelection(const SqpRange &dateTime);
99
101
100
102
101 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
103 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
102 const SqpRange &cacheRangeRequested,
104 const SqpRange &cacheRangeRequested,
103 QVector<AcquisitionDataPacket> dataAcquired);
105 QVector<AcquisitionDataPacket> dataAcquired);
104
106
105 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
107 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
106
108
107 /// Cancel the current request for the variable
109 /// Cancel the current request for the variable
108 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
110 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
109 void onAbortAcquisitionRequested(QUuid vIdentifier);
111 void onAbortAcquisitionRequested(QUuid vIdentifier);
110
112
111 // synchronization group methods
113 // synchronization group methods
112 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
114 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
113 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
115 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
114 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
116 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
115
117
116 /// Desynchronizes the variable of the group whose identifier is passed in parameter
118 /// Desynchronizes the variable of the group whose identifier is passed in parameter
117 /// @remarks the method does nothing if the variable is not part of the group
119 /// @remarks the method does nothing if the variable is not part of the group
118 void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
120 void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
119
121
120 void initialize();
122 void initialize();
121 void finalize();
123 void finalize();
122
124
123 private:
125 private:
124 void waitForFinish();
126 void waitForFinish();
125
127
126 class VariableControllerPrivate;
128 class VariableControllerPrivate;
127 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
129 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
128 };
130 };
129
131
130 #endif // SCIQLOP_VARIABLECONTROLLER_H
132 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,95 +1,109
1 #ifndef SCIQLOP_VARIABLEMODEL_H
1 #ifndef SCIQLOP_VARIABLEMODEL_H
2 #define SCIQLOP_VARIABLEMODEL_H
2 #define SCIQLOP_VARIABLEMODEL_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 #include <QAbstractTableModel>
8 #include <QAbstractTableModel>
9 #include <QLoggingCategory>
9 #include <QLoggingCategory>
10
10
11 #include <Common/MetaTypes.h>
11 #include <Common/MetaTypes.h>
12 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
15
15
16 enum VariableRoles { ProgressRole = Qt::UserRole };
16 enum VariableRoles { ProgressRole = Qt::UserRole };
17
17
18
18
19 class IDataSeries;
19 class IDataSeries;
20 class Variable;
20 class Variable;
21 class VariableController;
21
22
22 /**
23 /**
23 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
24 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
24 */
25 */
25 class SCIQLOP_CORE_EXPORT VariableModel : public QAbstractTableModel {
26 class SCIQLOP_CORE_EXPORT VariableModel : public QAbstractTableModel {
26 Q_OBJECT
27 Q_OBJECT
27 public:
28 public:
28 explicit VariableModel(QObject *parent = nullptr);
29 explicit VariableModel(VariableController *parent = nullptr);
29
30
30 /**
31 /**
31 * Adds an existing variable in the model.
32 * Adds an existing variable in the model.
32 * @param variable the variable to add.
33 * @param variable the variable to add.
33 * @remarks the variable's name is modified to avoid name duplicates
34 * @remarks the variable's name is modified to avoid name duplicates
34 * @remarks this method does nothing if the variable already exists in the model
35 * @remarks this method does nothing if the variable already exists in the model
35 */
36 */
36 void addVariable(std::shared_ptr<Variable> variable) noexcept;
37 void addVariable(std::shared_ptr<Variable> variable) noexcept;
37
38
38 /**
39 /**
39 * Checks that a variable is contained in the model
40 * Checks that a variable is contained in the model
40 * @param variable the variable to check
41 * @param variable the variable to check
41 * @return true if the variable is in the model, false otherwise
42 * @return true if the variable is in the model, false otherwise
42 */
43 */
43 bool containsVariable(std::shared_ptr<Variable> variable) const noexcept;
44 bool containsVariable(std::shared_ptr<Variable> variable) const noexcept;
44
45
45 /**
46 /**
46 * Creates a new variable in the model
47 * Creates a new variable in the model
47 * @param name the name of the new variable
48 * @param name the name of the new variable
48 * @param metadata the metadata associated to the new variable
49 * @param metadata the metadata associated to the new variable
49 * @return the pointer to the new variable
50 * @return the pointer to the new variable
50 */
51 */
51 std::shared_ptr<Variable> createVariable(const QString &name,
52 std::shared_ptr<Variable> createVariable(const QString &name,
52 const QVariantHash &metadata) noexcept;
53 const QVariantHash &metadata) noexcept;
53
54
54 /**
55 /**
55 * Deletes a variable from the model, if it exists
56 * Deletes a variable from the model, if it exists
56 * @param variable the variable to delete
57 * @param variable the variable to delete
57 */
58 */
58 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
59 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
59
60
60
61
61 std::shared_ptr<Variable> variable(int index) const;
62 std::shared_ptr<Variable> variable(int index) const;
62 std::vector<std::shared_ptr<Variable> > variables() const;
63 std::vector<std::shared_ptr<Variable> > variables() const;
63
64
64 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
65 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
65
66
66
67
67 // /////////////////////////// //
68 // /////////////////////////// //
68 // QAbstractTableModel methods //
69 // QAbstractTableModel methods //
69 // /////////////////////////// //
70 // /////////////////////////// //
70
71
71 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
72 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
72 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
73 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
73 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
74 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
74 virtual QVariant headerData(int section, Qt::Orientation orientation,
75 virtual QVariant headerData(int section, Qt::Orientation orientation,
75 int role = Qt::DisplayRole) const override;
76 int role = Qt::DisplayRole) const override;
76
77 virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
78
79 // ///////////////// //
80 // Drag&Drop methods //
81 // ///////////////// //
82
83 virtual Qt::DropActions supportedDropActions() const override;
84 virtual Qt::DropActions supportedDragActions() const override;
85 virtual QStringList mimeTypes() const override;
86 virtual QMimeData *mimeData(const QModelIndexList &indexes) const override;
87 virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
88 const QModelIndex &parent) const override;
89 virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
90 const QModelIndex &parent) override;
77
91
78 void abortProgress(const QModelIndex &index);
92 void abortProgress(const QModelIndex &index);
79
93
80 signals:
94 signals:
81 void abortProgessRequested(std::shared_ptr<Variable> variable);
95 void abortProgessRequested(std::shared_ptr<Variable> variable);
82
96
83 private:
97 private:
84 class VariableModelPrivate;
98 class VariableModelPrivate;
85 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
99 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
86
100
87 private slots:
101 private slots:
88 /// Slot called when data of a variable has been updated
102 /// Slot called when data of a variable has been updated
89 void onVariableUpdated() noexcept;
103 void onVariableUpdated() noexcept;
90 };
104 };
91
105
92 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
106 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
93 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
107 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
94
108
95 #endif // SCIQLOP_VARIABLEMODEL_H
109 #endif // SCIQLOP_VARIABLEMODEL_H
@@ -1,1012 +1,1053
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 <QMutex>
16 #include <QMutex>
16 #include <QThread>
17 #include <QThread>
17 #include <QUuid>
18 #include <QUuid>
18 #include <QtCore/QItemSelectionModel>
19 #include <QtCore/QItemSelectionModel>
19
20
20 #include <deque>
21 #include <deque>
21 #include <set>
22 #include <set>
22 #include <unordered_map>
23 #include <unordered_map>
23
24
24 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
25 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
25
26
26 namespace {
27 namespace {
27
28
28 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
29 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
29 const SqpRange &oldGraphRange)
30 const SqpRange &oldGraphRange)
30 {
31 {
31 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
32 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
32
33
33 auto varRangeRequested = varRange;
34 auto varRangeRequested = varRange;
34 switch (zoomType) {
35 switch (zoomType) {
35 case AcquisitionZoomType::ZoomIn: {
36 case AcquisitionZoomType::ZoomIn: {
36 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
37 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
37 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
38 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
38 varRangeRequested.m_TStart += deltaLeft;
39 varRangeRequested.m_TStart += deltaLeft;
39 varRangeRequested.m_TEnd -= deltaRight;
40 varRangeRequested.m_TEnd -= deltaRight;
40 break;
41 break;
41 }
42 }
42
43
43 case AcquisitionZoomType::ZoomOut: {
44 case AcquisitionZoomType::ZoomOut: {
44 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
45 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
45 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
46 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
46 varRangeRequested.m_TStart -= deltaLeft;
47 varRangeRequested.m_TStart -= deltaLeft;
47 varRangeRequested.m_TEnd += deltaRight;
48 varRangeRequested.m_TEnd += deltaRight;
48 break;
49 break;
49 }
50 }
50 case AcquisitionZoomType::PanRight: {
51 case AcquisitionZoomType::PanRight: {
51 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
52 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
52 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
53 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
53 varRangeRequested.m_TStart += deltaLeft;
54 varRangeRequested.m_TStart += deltaLeft;
54 varRangeRequested.m_TEnd += deltaRight;
55 varRangeRequested.m_TEnd += deltaRight;
55 break;
56 break;
56 }
57 }
57 case AcquisitionZoomType::PanLeft: {
58 case AcquisitionZoomType::PanLeft: {
58 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
59 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
59 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
60 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
60 varRangeRequested.m_TStart -= deltaLeft;
61 varRangeRequested.m_TStart -= deltaLeft;
61 varRangeRequested.m_TEnd -= deltaRight;
62 varRangeRequested.m_TEnd -= deltaRight;
62 break;
63 break;
63 }
64 }
64 case AcquisitionZoomType::Unknown: {
65 case AcquisitionZoomType::Unknown: {
65 qCCritical(LOG_VariableController())
66 qCCritical(LOG_VariableController())
66 << VariableController::tr("Impossible to synchronize: zoom type unknown");
67 << VariableController::tr("Impossible to synchronize: zoom type unknown");
67 break;
68 break;
68 }
69 }
69 default:
70 default:
70 qCCritical(LOG_VariableController()) << VariableController::tr(
71 qCCritical(LOG_VariableController()) << VariableController::tr(
71 "Impossible to synchronize: zoom type not take into account");
72 "Impossible to synchronize: zoom type not take into account");
72 // No action
73 // No action
73 break;
74 break;
74 }
75 }
75
76
76 return varRangeRequested;
77 return varRangeRequested;
77 }
78 }
78 }
79 }
79
80
80 enum class VariableRequestHandlerState { OFF, RUNNING, PENDING };
81 enum class VariableRequestHandlerState { OFF, RUNNING, PENDING };
81
82
82 struct VariableRequestHandler {
83 struct VariableRequestHandler {
83
84
84 VariableRequestHandler()
85 VariableRequestHandler()
85 {
86 {
86 m_CanUpdate = false;
87 m_CanUpdate = false;
87 m_State = VariableRequestHandlerState::OFF;
88 m_State = VariableRequestHandlerState::OFF;
88 }
89 }
89
90
90 QUuid m_VarId;
91 QUuid m_VarId;
91 VariableRequest m_RunningVarRequest;
92 VariableRequest m_RunningVarRequest;
92 VariableRequest m_PendingVarRequest;
93 VariableRequest m_PendingVarRequest;
93 VariableRequestHandlerState m_State;
94 VariableRequestHandlerState m_State;
94 bool m_CanUpdate;
95 bool m_CanUpdate;
95 };
96 };
96
97
97 struct VariableController::VariableControllerPrivate {
98 struct VariableController::VariableControllerPrivate {
98 explicit VariableControllerPrivate(VariableController *parent)
99 explicit VariableControllerPrivate(VariableController *parent)
99 : m_WorkingMutex{},
100 : m_WorkingMutex{},
100 m_VariableModel{new VariableModel{parent}},
101 m_VariableModel{new VariableModel{parent}},
101 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
102 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
102 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
103 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
103 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
104 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
104 CacheStrategy::SingleThreshold)},
105 CacheStrategy::SingleThreshold)},
105 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
106 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
106 q{parent}
107 q{parent}
107 {
108 {
108
109
109 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
110 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
110 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
111 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
111 }
112 }
112
113
113
114
114 virtual ~VariableControllerPrivate()
115 virtual ~VariableControllerPrivate()
115 {
116 {
116 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
117 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
117 m_VariableAcquisitionWorkerThread.quit();
118 m_VariableAcquisitionWorkerThread.quit();
118 m_VariableAcquisitionWorkerThread.wait();
119 m_VariableAcquisitionWorkerThread.wait();
119 }
120 }
120
121
121
122
122 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
123 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
123 QUuid varRequestId);
124 QUuid varRequestId);
124
125
125 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
126 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
126 std::shared_ptr<IDataSeries>
127 std::shared_ptr<IDataSeries>
127 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
128 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
128
129
129 void registerProvider(std::shared_ptr<IDataProvider> provider);
130 void registerProvider(std::shared_ptr<IDataProvider> provider);
130
131
131 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
132 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
132 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
133 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
133 void updateVariables(QUuid varRequestId);
134 void updateVariables(QUuid varRequestId);
134 void updateVariableRequest(QUuid varRequestId);
135 void updateVariableRequest(QUuid varRequestId);
135 void cancelVariableRequest(QUuid varRequestId);
136 void cancelVariableRequest(QUuid varRequestId);
136 void executeVarRequest(std::shared_ptr<Variable> var, VariableRequest &varRequest);
137 void executeVarRequest(std::shared_ptr<Variable> var, VariableRequest &varRequest);
137
138
138 QMutex m_WorkingMutex;
139 QMutex m_WorkingMutex;
139 /// Variable model. The VariableController has the ownership
140 /// Variable model. The VariableController has the ownership
140 VariableModel *m_VariableModel;
141 VariableModel *m_VariableModel;
141 QItemSelectionModel *m_VariableSelectionModel;
142 QItemSelectionModel *m_VariableSelectionModel;
142
143
143
144
144 TimeController *m_TimeController{nullptr};
145 TimeController *m_TimeController{nullptr};
145 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
146 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
146 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
147 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
147 QThread m_VariableAcquisitionWorkerThread;
148 QThread m_VariableAcquisitionWorkerThread;
148
149
149 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
150 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
150 m_VariableToProviderMap;
151 m_VariableToProviderMap;
151 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
152 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
152 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
153 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
153 m_GroupIdToVariableSynchronizationGroupMap;
154 m_GroupIdToVariableSynchronizationGroupMap;
154 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
155 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
155 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
156 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
156
157
157 std::map<QUuid, std::list<QUuid> > m_VarGroupIdToVarIds;
158 std::map<QUuid, std::list<QUuid> > m_VarGroupIdToVarIds;
158 std::map<QUuid, std::unique_ptr<VariableRequestHandler> > m_VarIdToVarRequestHandler;
159 std::map<QUuid, std::unique_ptr<VariableRequestHandler> > m_VarIdToVarRequestHandler;
159
160
160 VariableController *q;
161 VariableController *q;
161 };
162 };
162
163
163
164
164 VariableController::VariableController(QObject *parent)
165 VariableController::VariableController(QObject *parent)
165 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
166 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
166 {
167 {
167 qCDebug(LOG_VariableController()) << tr("VariableController construction")
168 qCDebug(LOG_VariableController()) << tr("VariableController construction")
168 << QThread::currentThread();
169 << QThread::currentThread();
169
170
170 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
171 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
171 &VariableController::onAbortProgressRequested);
172 &VariableController::onAbortProgressRequested);
172
173
173 connect(impl->m_VariableAcquisitionWorker.get(),
174 connect(impl->m_VariableAcquisitionWorker.get(),
174 &VariableAcquisitionWorker::variableCanceledRequested, this,
175 &VariableAcquisitionWorker::variableCanceledRequested, this,
175 &VariableController::onAbortAcquisitionRequested);
176 &VariableController::onAbortAcquisitionRequested);
176
177
177 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
178 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
178 &VariableController::onDataProvided);
179 &VariableController::onDataProvided);
179 connect(impl->m_VariableAcquisitionWorker.get(),
180 connect(impl->m_VariableAcquisitionWorker.get(),
180 &VariableAcquisitionWorker::variableRequestInProgress, this,
181 &VariableAcquisitionWorker::variableRequestInProgress, this,
181 &VariableController::onVariableRetrieveDataInProgress);
182 &VariableController::onVariableRetrieveDataInProgress);
182
183
183
184
184 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
185 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
185 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
186 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
186 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
187 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
187 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
188 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
188
189
189
190
190 impl->m_VariableAcquisitionWorkerThread.start();
191 impl->m_VariableAcquisitionWorkerThread.start();
191 }
192 }
192
193
193 VariableController::~VariableController()
194 VariableController::~VariableController()
194 {
195 {
195 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
196 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
196 << QThread::currentThread();
197 << QThread::currentThread();
197 this->waitForFinish();
198 this->waitForFinish();
198 }
199 }
199
200
200 VariableModel *VariableController::variableModel() noexcept
201 VariableModel *VariableController::variableModel() noexcept
201 {
202 {
202 return impl->m_VariableModel;
203 return impl->m_VariableModel;
203 }
204 }
204
205
205 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
206 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
206 {
207 {
207 return impl->m_VariableSelectionModel;
208 return impl->m_VariableSelectionModel;
208 }
209 }
209
210
210 void VariableController::setTimeController(TimeController *timeController) noexcept
211 void VariableController::setTimeController(TimeController *timeController) noexcept
211 {
212 {
212 impl->m_TimeController = timeController;
213 impl->m_TimeController = timeController;
213 }
214 }
214
215
215 std::shared_ptr<Variable>
216 std::shared_ptr<Variable>
216 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
217 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
217 {
218 {
218 if (impl->m_VariableModel->containsVariable(variable)) {
219 if (impl->m_VariableModel->containsVariable(variable)) {
219 // Clones variable
220 // Clones variable
220 auto duplicate = variable->clone();
221 auto duplicate = variable->clone();
221
222
222 // Adds clone to model
223 // Adds clone to model
223 impl->m_VariableModel->addVariable(duplicate);
224 impl->m_VariableModel->addVariable(duplicate);
224
225
225 // Generates clone identifier
226 // Generates clone identifier
226 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
227 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
227
228
228 // Registers provider
229 // Registers provider
229 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
230 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
230 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
231 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
231
232
232 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
233 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
233 if (duplicateProvider) {
234 if (duplicateProvider) {
234 impl->registerProvider(duplicateProvider);
235 impl->registerProvider(duplicateProvider);
235 }
236 }
236
237
237 return duplicate;
238 return duplicate;
238 }
239 }
239 else {
240 else {
240 qCCritical(LOG_VariableController())
241 qCCritical(LOG_VariableController())
241 << tr("Can't create duplicate of variable %1: variable not registered in the model")
242 << tr("Can't create duplicate of variable %1: variable not registered in the model")
242 .arg(variable->name());
243 .arg(variable->name());
243 return nullptr;
244 return nullptr;
244 }
245 }
245 }
246 }
246
247
247 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
248 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
248 {
249 {
249 if (!variable) {
250 if (!variable) {
250 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
251 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
251 return;
252 return;
252 }
253 }
253
254
254 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
255 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
255 // make some treatments before the deletion
256 // make some treatments before the deletion
256 emit variableAboutToBeDeleted(variable);
257 emit variableAboutToBeDeleted(variable);
257
258
258 // Deletes identifier
259 // Deletes identifier
259 impl->m_VariableToIdentifierMap.erase(variable);
260 impl->m_VariableToIdentifierMap.erase(variable);
260
261
261 // Deletes provider
262 // Deletes provider
262 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
263 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
263 qCDebug(LOG_VariableController())
264 qCDebug(LOG_VariableController())
264 << tr("Number of providers deleted for variable %1: %2")
265 << tr("Number of providers deleted for variable %1: %2")
265 .arg(variable->name(), QString::number(nbProvidersDeleted));
266 .arg(variable->name(), QString::number(nbProvidersDeleted));
266
267
267
268
268 // Deletes from model
269 // Deletes from model
269 impl->m_VariableModel->deleteVariable(variable);
270 impl->m_VariableModel->deleteVariable(variable);
270 }
271 }
271
272
272 void VariableController::deleteVariables(
273 void VariableController::deleteVariables(
273 const QVector<std::shared_ptr<Variable> > &variables) noexcept
274 const QVector<std::shared_ptr<Variable> > &variables) noexcept
274 {
275 {
275 for (auto variable : qAsConst(variables)) {
276 for (auto variable : qAsConst(variables)) {
276 deleteVariable(variable);
277 deleteVariable(variable);
277 }
278 }
278 }
279 }
279
280
281 QByteArray
282 VariableController::mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const
283 {
284 auto encodedData = QByteArray{};
285
286 QVariantList ids;
287 for (auto &var : variables) {
288 auto itVar = impl->m_VariableToIdentifierMap.find(var);
289 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
290 qCCritical(LOG_VariableController())
291 << tr("Impossible to find the data for an unknown variable.");
292 }
293
294 ids << itVar->second.toByteArray();
295 }
296
297 QDataStream stream{&encodedData, QIODevice::WriteOnly};
298 stream << ids;
299
300 return encodedData;
301 }
302
303 QList<std::shared_ptr<Variable> >
304 VariableController::variablesForMimeData(const QByteArray &mimeData) const
305 {
306 auto variables = QList<std::shared_ptr<Variable> >{};
307 QDataStream stream{mimeData};
308
309 QVariantList ids;
310 stream >> ids;
311
312 for (auto id : ids) {
313 auto uuid = QUuid(id.toByteArray());
314 auto var = impl->findVariable(uuid);
315 variables << var;
316 }
317
318 return variables;
319 }
320
280 std::shared_ptr<Variable>
321 std::shared_ptr<Variable>
281 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
322 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
282 std::shared_ptr<IDataProvider> provider) noexcept
323 std::shared_ptr<IDataProvider> provider) noexcept
283 {
324 {
284 if (!impl->m_TimeController) {
325 if (!impl->m_TimeController) {
285 qCCritical(LOG_VariableController())
326 qCCritical(LOG_VariableController())
286 << tr("Impossible to create variable: The time controller is null");
327 << tr("Impossible to create variable: The time controller is null");
287 return nullptr;
328 return nullptr;
288 }
329 }
289
330
290 auto range = impl->m_TimeController->dateTime();
331 auto range = impl->m_TimeController->dateTime();
291
332
292 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
333 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
293 auto varId = QUuid::createUuid();
334 auto varId = QUuid::createUuid();
294
335
295 // Create the handler
336 // Create the handler
296 auto varRequestHandler = std::make_unique<VariableRequestHandler>();
337 auto varRequestHandler = std::make_unique<VariableRequestHandler>();
297 varRequestHandler->m_VarId = varId;
338 varRequestHandler->m_VarId = varId;
298
339
299 impl->m_VarIdToVarRequestHandler.insert(
340 impl->m_VarIdToVarRequestHandler.insert(
300 std::make_pair(varId, std::move(varRequestHandler)));
341 std::make_pair(varId, std::move(varRequestHandler)));
301
342
302 // store the provider
343 // store the provider
303 impl->registerProvider(provider);
344 impl->registerProvider(provider);
304
345
305 // Associate the provider
346 // Associate the provider
306 impl->m_VariableToProviderMap[newVariable] = provider;
347 impl->m_VariableToProviderMap[newVariable] = provider;
307 impl->m_VariableToIdentifierMap[newVariable] = varId;
348 impl->m_VariableToIdentifierMap[newVariable] = varId;
308
349
309 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{newVariable}, range, false);
350 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{newVariable}, range, false);
310
351
311 // auto varRequestId = QUuid::createUuid();
352 // auto varRequestId = QUuid::createUuid();
312 // qCInfo(LOG_VariableController()) << "createVariable: " << varId << varRequestId;
353 // qCInfo(LOG_VariableController()) << "createVariable: " << varId << varRequestId;
313 // impl->processRequest(newVariable, range, varRequestId);
354 // impl->processRequest(newVariable, range, varRequestId);
314 // impl->updateVariableRequest(varRequestId);
355 // impl->updateVariableRequest(varRequestId);
315
356
316 return newVariable;
357 return newVariable;
317 }
358 }
318 }
359 }
319
360
320 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
361 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
321 {
362 {
322 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
363 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
323 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
364 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
324 << QThread::currentThread()->objectName();
365 << QThread::currentThread()->objectName();
325 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
366 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
326
367
327 // NOTE we only permit the time modification for one variable
368 // NOTE we only permit the time modification for one variable
328 // DEPRECATED
369 // DEPRECATED
329 // auto variables = QVector<std::shared_ptr<Variable> >{};
370 // auto variables = QVector<std::shared_ptr<Variable> >{};
330 // for (const auto &selectedRow : qAsConst(selectedRows)) {
371 // for (const auto &selectedRow : qAsConst(selectedRows)) {
331 // if (auto selectedVariable =
372 // if (auto selectedVariable =
332 // impl->m_VariableModel->variable(selectedRow.row())) {
373 // impl->m_VariableModel->variable(selectedRow.row())) {
333 // variables << selectedVariable;
374 // variables << selectedVariable;
334
375
335 // // notify that rescale operation has to be done
376 // // notify that rescale operation has to be done
336 // emit rangeChanged(selectedVariable, dateTime);
377 // emit rangeChanged(selectedVariable, dateTime);
337 // }
378 // }
338 // }
379 // }
339 // if (!variables.isEmpty()) {
380 // if (!variables.isEmpty()) {
340 // this->onRequestDataLoading(variables, dateTime, synchro);
381 // this->onRequestDataLoading(variables, dateTime, synchro);
341 // }
382 // }
342 if (selectedRows.size() == 1) {
383 if (selectedRows.size() == 1) {
343
384
344 if (auto selectedVariable
385 if (auto selectedVariable
345 = impl->m_VariableModel->variable(qAsConst(selectedRows).first().row())) {
386 = impl->m_VariableModel->variable(qAsConst(selectedRows).first().row())) {
346
387
347 auto itVar = impl->m_VariableToIdentifierMap.find(selectedVariable);
388 auto itVar = impl->m_VariableToIdentifierMap.find(selectedVariable);
348 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
389 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
349 qCCritical(LOG_VariableController())
390 qCCritical(LOG_VariableController())
350 << tr("Impossible to onDateTimeOnSelection request for unknown variable");
391 << tr("Impossible to onDateTimeOnSelection request for unknown variable");
351 return;
392 return;
352 }
393 }
353
394
354 // notify that rescale operation has to be done
395 // notify that rescale operation has to be done
355 emit rangeChanged(selectedVariable, dateTime);
396 emit rangeChanged(selectedVariable, dateTime);
356
397
357 auto synchro = impl->m_VariableIdGroupIdMap.find(itVar->second)
398 auto synchro = impl->m_VariableIdGroupIdMap.find(itVar->second)
358 != impl->m_VariableIdGroupIdMap.cend();
399 != impl->m_VariableIdGroupIdMap.cend();
359
400
360 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{selectedVariable},
401 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{selectedVariable},
361 dateTime, synchro);
402 dateTime, synchro);
362 }
403 }
363 }
404 }
364 else if (selectedRows.size() > 1) {
405 else if (selectedRows.size() > 1) {
365 qCCritical(LOG_VariableController())
406 qCCritical(LOG_VariableController())
366 << tr("Impossible to set time for more than 1 variable in the same time");
407 << tr("Impossible to set time for more than 1 variable in the same time");
367 }
408 }
368 else {
409 else {
369 qCWarning(LOG_VariableController())
410 qCWarning(LOG_VariableController())
370 << tr("There is no variable selected to set the time one");
411 << tr("There is no variable selected to set the time one");
371 }
412 }
372 }
413 }
373
414
374 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
415 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
375 const SqpRange &cacheRangeRequested,
416 const SqpRange &cacheRangeRequested,
376 QVector<AcquisitionDataPacket> dataAcquired)
417 QVector<AcquisitionDataPacket> dataAcquired)
377 {
418 {
378 qCDebug(LOG_VariableController()) << tr("onDataProvided") << QThread::currentThread();
419 qCDebug(LOG_VariableController()) << tr("onDataProvided") << QThread::currentThread();
379 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
420 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
380 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
421 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
381 if (!varRequestId.isNull()) {
422 if (!varRequestId.isNull()) {
382 impl->updateVariables(varRequestId);
423 impl->updateVariables(varRequestId);
383 }
424 }
384 }
425 }
385
426
386 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
427 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
387 {
428 {
388 qCDebug(LOG_VariableController())
429 qCDebug(LOG_VariableController())
389 << "TORM: variableController::onVariableRetrieveDataInProgress"
430 << "TORM: variableController::onVariableRetrieveDataInProgress"
390 << QThread::currentThread()->objectName() << progress;
431 << QThread::currentThread()->objectName() << progress;
391 if (auto var = impl->findVariable(identifier)) {
432 if (auto var = impl->findVariable(identifier)) {
392 impl->m_VariableModel->setDataProgress(var, progress);
433 impl->m_VariableModel->setDataProgress(var, progress);
393 }
434 }
394 else {
435 else {
395 qCCritical(LOG_VariableController())
436 qCCritical(LOG_VariableController())
396 << tr("Impossible to notify progression of a null variable");
437 << tr("Impossible to notify progression of a null variable");
397 }
438 }
398 }
439 }
399
440
400 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
441 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
401 {
442 {
402 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortProgressRequested"
443 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortProgressRequested"
403 << QThread::currentThread()->objectName() << variable->name();
444 << QThread::currentThread()->objectName() << variable->name();
404
445
405 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
446 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
406 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
447 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
407 qCCritical(LOG_VariableController())
448 qCCritical(LOG_VariableController())
408 << tr("Impossible to onAbortProgressRequested request for unknown variable");
449 << tr("Impossible to onAbortProgressRequested request for unknown variable");
409 return;
450 return;
410 }
451 }
411
452
412 auto varId = itVar->second;
453 auto varId = itVar->second;
413
454
414 auto itVarHandler = impl->m_VarIdToVarRequestHandler.find(varId);
455 auto itVarHandler = impl->m_VarIdToVarRequestHandler.find(varId);
415 if (itVarHandler == impl->m_VarIdToVarRequestHandler.cend()) {
456 if (itVarHandler == impl->m_VarIdToVarRequestHandler.cend()) {
416 qCCritical(LOG_VariableController())
457 qCCritical(LOG_VariableController())
417 << tr("Impossible to onAbortProgressRequested for variable with unknown handler");
458 << tr("Impossible to onAbortProgressRequested for variable with unknown handler");
418 return;
459 return;
419 }
460 }
420
461
421 auto varHandler = itVarHandler->second.get();
462 auto varHandler = itVarHandler->second.get();
422
463
423 // case where a variable has a running request
464 // case where a variable has a running request
424 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
465 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
425 impl->cancelVariableRequest(varHandler->m_RunningVarRequest.m_VariableGroupId);
466 impl->cancelVariableRequest(varHandler->m_RunningVarRequest.m_VariableGroupId);
426 }
467 }
427 }
468 }
428
469
429 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
470 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
430 {
471 {
431 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
472 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
432 << QThread::currentThread()->objectName() << vIdentifier;
473 << QThread::currentThread()->objectName() << vIdentifier;
433
474
434 if (auto var = impl->findVariable(vIdentifier)) {
475 if (auto var = impl->findVariable(vIdentifier)) {
435 this->onAbortProgressRequested(var);
476 this->onAbortProgressRequested(var);
436 }
477 }
437 else {
478 else {
438 qCCritical(LOG_VariableController())
479 qCCritical(LOG_VariableController())
439 << tr("Impossible to abort Acquisition Requestof a null variable");
480 << tr("Impossible to abort Acquisition Requestof a null variable");
440 }
481 }
441 }
482 }
442
483
443 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
484 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
444 {
485 {
445 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
486 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
446 << QThread::currentThread()->objectName()
487 << QThread::currentThread()->objectName()
447 << synchronizationGroupId;
488 << synchronizationGroupId;
448 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
489 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
449 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
490 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
450 std::make_pair(synchronizationGroupId, vSynchroGroup));
491 std::make_pair(synchronizationGroupId, vSynchroGroup));
451 }
492 }
452
493
453 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
494 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
454 {
495 {
455 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
496 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
456 }
497 }
457
498
458 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
499 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
459 QUuid synchronizationGroupId)
500 QUuid synchronizationGroupId)
460
501
461 {
502 {
462 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
503 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
463 << synchronizationGroupId;
504 << synchronizationGroupId;
464 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
505 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
465 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
506 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
466 auto groupIdToVSGIt
507 auto groupIdToVSGIt
467 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
508 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
468 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
509 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
469 impl->m_VariableIdGroupIdMap.insert(
510 impl->m_VariableIdGroupIdMap.insert(
470 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
511 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
471 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
512 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
472 }
513 }
473 else {
514 else {
474 qCCritical(LOG_VariableController())
515 qCCritical(LOG_VariableController())
475 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
516 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
476 << variable->name();
517 << variable->name();
477 }
518 }
478 }
519 }
479 else {
520 else {
480 qCCritical(LOG_VariableController())
521 qCCritical(LOG_VariableController())
481 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
522 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
482 }
523 }
483 }
524 }
484
525
485 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
526 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
486 QUuid synchronizationGroupId)
527 QUuid synchronizationGroupId)
487 {
528 {
488 // Gets variable id
529 // Gets variable id
489 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
530 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
490 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
531 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
491 qCCritical(LOG_VariableController())
532 qCCritical(LOG_VariableController())
492 << tr("Can't desynchronize variable %1: variable identifier not found")
533 << tr("Can't desynchronize variable %1: variable identifier not found")
493 .arg(variable->name());
534 .arg(variable->name());
494 return;
535 return;
495 }
536 }
496
537
497 // Gets synchronization group
538 // Gets synchronization group
498 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
539 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
499 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
540 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
500 qCCritical(LOG_VariableController())
541 qCCritical(LOG_VariableController())
501 << tr("Can't desynchronize variable %1: unknown synchronization group")
542 << tr("Can't desynchronize variable %1: unknown synchronization group")
502 .arg(variable->name());
543 .arg(variable->name());
503 return;
544 return;
504 }
545 }
505
546
506 auto variableId = variableIt->second;
547 auto variableId = variableIt->second;
507
548
508 // Removes variable from synchronization group
549 // Removes variable from synchronization group
509 auto synchronizationGroup = groupIt->second;
550 auto synchronizationGroup = groupIt->second;
510 synchronizationGroup->removeVariableId(variableId);
551 synchronizationGroup->removeVariableId(variableId);
511
552
512 // Removes link between variable and synchronization group
553 // Removes link between variable and synchronization group
513 impl->m_VariableIdGroupIdMap.erase(variableId);
554 impl->m_VariableIdGroupIdMap.erase(variableId);
514 }
555 }
515
556
516 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
557 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
517 const SqpRange &range, bool synchronise)
558 const SqpRange &range, bool synchronise)
518 {
559 {
519 // variables is assumed synchronized
560 // variables is assumed synchronized
520 // TODO: Asser variables synchronization
561 // TODO: Asser variables synchronization
521 // we want to load data of the variable for the dateTime.
562 // we want to load data of the variable for the dateTime.
522 if (variables.isEmpty()) {
563 if (variables.isEmpty()) {
523 return;
564 return;
524 }
565 }
525
566
526 auto varRequestId = QUuid::createUuid();
567 auto varRequestId = QUuid::createUuid();
527 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
568 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
528 << QThread::currentThread()->objectName() << varRequestId
569 << QThread::currentThread()->objectName() << varRequestId
529 << range << synchronise;
570 << range << synchronise;
530
571
531 if (!synchronise) {
572 if (!synchronise) {
532 auto varIds = std::list<QUuid>{};
573 auto varIds = std::list<QUuid>{};
533 for (const auto &var : variables) {
574 for (const auto &var : variables) {
534 auto vId = impl->m_VariableToIdentifierMap.at(var);
575 auto vId = impl->m_VariableToIdentifierMap.at(var);
535 varIds.push_back(vId);
576 varIds.push_back(vId);
536 }
577 }
537 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
578 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
538 for (const auto &var : variables) {
579 for (const auto &var : variables) {
539 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId
580 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId
540 << varIds.size();
581 << varIds.size();
541 impl->processRequest(var, range, varRequestId);
582 impl->processRequest(var, range, varRequestId);
542 }
583 }
543 }
584 }
544 else {
585 else {
545 auto vId = impl->m_VariableToIdentifierMap.at(variables.first());
586 auto vId = impl->m_VariableToIdentifierMap.at(variables.first());
546 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
587 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
547 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
588 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
548 auto groupId = varIdToGroupIdIt->second;
589 auto groupId = varIdToGroupIdIt->second;
549
590
550 auto vSynchronizationGroup
591 auto vSynchronizationGroup
551 = impl->m_GroupIdToVariableSynchronizationGroupMap.at(groupId);
592 = impl->m_GroupIdToVariableSynchronizationGroupMap.at(groupId);
552 auto vSyncIds = vSynchronizationGroup->getIds();
593 auto vSyncIds = vSynchronizationGroup->getIds();
553
594
554 auto varIds = std::list<QUuid>{};
595 auto varIds = std::list<QUuid>{};
555 for (auto vId : vSyncIds) {
596 for (auto vId : vSyncIds) {
556 varIds.push_back(vId);
597 varIds.push_back(vId);
557 }
598 }
558 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
599 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
559
600
560 for (auto vId : vSyncIds) {
601 for (auto vId : vSyncIds) {
561 auto var = impl->findVariable(vId);
602 auto var = impl->findVariable(vId);
562
603
563 // Don't process already processed var
604 // Don't process already processed var
564 if (var != nullptr) {
605 if (var != nullptr) {
565 qCDebug(LOG_VariableController()) << "processRequest synchro for" << var->name()
606 qCDebug(LOG_VariableController()) << "processRequest synchro for" << var->name()
566 << varRequestId;
607 << varRequestId;
567 auto vSyncRangeRequested
608 auto vSyncRangeRequested
568 = variables.contains(var)
609 = variables.contains(var)
569 ? range
610 ? range
570 : computeSynchroRangeRequested(var->range(), range,
611 : computeSynchroRangeRequested(var->range(), range,
571 variables.first()->range());
612 variables.first()->range());
572 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
613 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
573 impl->processRequest(var, vSyncRangeRequested, varRequestId);
614 impl->processRequest(var, vSyncRangeRequested, varRequestId);
574 }
615 }
575 else {
616 else {
576 qCCritical(LOG_VariableController())
617 qCCritical(LOG_VariableController())
577
618
578 << tr("Impossible to synchronize a null variable");
619 << tr("Impossible to synchronize a null variable");
579 }
620 }
580 }
621 }
581 }
622 }
582 }
623 }
583
624
584 impl->updateVariables(varRequestId);
625 impl->updateVariables(varRequestId);
585 }
626 }
586
627
587
628
588 void VariableController::initialize()
629 void VariableController::initialize()
589 {
630 {
590 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
631 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
591 impl->m_WorkingMutex.lock();
632 impl->m_WorkingMutex.lock();
592 qCDebug(LOG_VariableController()) << tr("VariableController init END");
633 qCDebug(LOG_VariableController()) << tr("VariableController init END");
593 }
634 }
594
635
595 void VariableController::finalize()
636 void VariableController::finalize()
596 {
637 {
597 impl->m_WorkingMutex.unlock();
638 impl->m_WorkingMutex.unlock();
598 }
639 }
599
640
600 void VariableController::waitForFinish()
641 void VariableController::waitForFinish()
601 {
642 {
602 QMutexLocker locker{&impl->m_WorkingMutex};
643 QMutexLocker locker{&impl->m_WorkingMutex};
603 }
644 }
604
645
605 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
646 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
606 {
647 {
607 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
648 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
608 auto zoomType = AcquisitionZoomType::Unknown;
649 auto zoomType = AcquisitionZoomType::Unknown;
609 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
650 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
610 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
651 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
611 zoomType = AcquisitionZoomType::ZoomOut;
652 zoomType = AcquisitionZoomType::ZoomOut;
612 }
653 }
613 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
654 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
614 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
655 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
615 zoomType = AcquisitionZoomType::PanRight;
656 zoomType = AcquisitionZoomType::PanRight;
616 }
657 }
617 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
658 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
618 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
659 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
619 zoomType = AcquisitionZoomType::PanLeft;
660 zoomType = AcquisitionZoomType::PanLeft;
620 }
661 }
621 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
662 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
622 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
663 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
623 zoomType = AcquisitionZoomType::ZoomIn;
664 zoomType = AcquisitionZoomType::ZoomIn;
624 }
665 }
625 else {
666 else {
626 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
667 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
627 }
668 }
628 return zoomType;
669 return zoomType;
629 }
670 }
630
671
631 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
672 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
632 const SqpRange &rangeRequested,
673 const SqpRange &rangeRequested,
633 QUuid varRequestId)
674 QUuid varRequestId)
634 {
675 {
635 auto itVar = m_VariableToIdentifierMap.find(var);
676 auto itVar = m_VariableToIdentifierMap.find(var);
636 if (itVar == m_VariableToIdentifierMap.cend()) {
677 if (itVar == m_VariableToIdentifierMap.cend()) {
637 qCCritical(LOG_VariableController())
678 qCCritical(LOG_VariableController())
638 << tr("Impossible to process request for unknown variable");
679 << tr("Impossible to process request for unknown variable");
639 return;
680 return;
640 }
681 }
641
682
642 auto varId = itVar->second;
683 auto varId = itVar->second;
643
684
644 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
685 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
645 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
686 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
646 qCCritical(LOG_VariableController())
687 qCCritical(LOG_VariableController())
647 << tr("Impossible to process request for variable with unknown handler");
688 << tr("Impossible to process request for variable with unknown handler");
648 return;
689 return;
649 }
690 }
650
691
651 auto oldRange = var->range();
692 auto oldRange = var->range();
652
693
653 auto varHandler = itVarHandler->second.get();
694 auto varHandler = itVarHandler->second.get();
654
695
655 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
696 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
656 oldRange = varHandler->m_RunningVarRequest.m_RangeRequested;
697 oldRange = varHandler->m_RunningVarRequest.m_RangeRequested;
657 }
698 }
658
699
659 auto varRequest = VariableRequest{};
700 auto varRequest = VariableRequest{};
660 varRequest.m_VariableGroupId = varRequestId;
701 varRequest.m_VariableGroupId = varRequestId;
661 auto varStrategyRangesRequested
702 auto varStrategyRangesRequested
662 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
703 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
663 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
704 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
664 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
705 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
665
706
666 switch (varHandler->m_State) {
707 switch (varHandler->m_State) {
667 case VariableRequestHandlerState::OFF: {
708 case VariableRequestHandlerState::OFF: {
668 qCDebug(LOG_VariableController()) << tr("Process Request OFF")
709 qCDebug(LOG_VariableController()) << tr("Process Request OFF")
669 << varRequest.m_RangeRequested
710 << varRequest.m_RangeRequested
670 << varRequest.m_CacheRangeRequested;
711 << varRequest.m_CacheRangeRequested;
671 varHandler->m_RunningVarRequest = varRequest;
712 varHandler->m_RunningVarRequest = varRequest;
672 varHandler->m_State = VariableRequestHandlerState::RUNNING;
713 varHandler->m_State = VariableRequestHandlerState::RUNNING;
673 executeVarRequest(var, varRequest);
714 executeVarRequest(var, varRequest);
674 break;
715 break;
675 }
716 }
676 case VariableRequestHandlerState::RUNNING: {
717 case VariableRequestHandlerState::RUNNING: {
677 qCDebug(LOG_VariableController()) << tr("Process Request RUNNING")
718 qCDebug(LOG_VariableController()) << tr("Process Request RUNNING")
678 << varRequest.m_RangeRequested
719 << varRequest.m_RangeRequested
679 << varRequest.m_CacheRangeRequested;
720 << varRequest.m_CacheRangeRequested;
680 varHandler->m_State = VariableRequestHandlerState::PENDING;
721 varHandler->m_State = VariableRequestHandlerState::PENDING;
681 varHandler->m_PendingVarRequest = varRequest;
722 varHandler->m_PendingVarRequest = varRequest;
682 break;
723 break;
683 }
724 }
684 case VariableRequestHandlerState::PENDING: {
725 case VariableRequestHandlerState::PENDING: {
685 qCDebug(LOG_VariableController()) << tr("Process Request PENDING")
726 qCDebug(LOG_VariableController()) << tr("Process Request PENDING")
686 << varRequest.m_RangeRequested
727 << varRequest.m_RangeRequested
687 << varRequest.m_CacheRangeRequested;
728 << varRequest.m_CacheRangeRequested;
688 auto variableGroupIdToCancel = varHandler->m_PendingVarRequest.m_VariableGroupId;
729 auto variableGroupIdToCancel = varHandler->m_PendingVarRequest.m_VariableGroupId;
689 cancelVariableRequest(variableGroupIdToCancel);
730 cancelVariableRequest(variableGroupIdToCancel);
690 // Cancel variable can make state downgrade
731 // Cancel variable can make state downgrade
691 varHandler->m_State = VariableRequestHandlerState::PENDING;
732 varHandler->m_State = VariableRequestHandlerState::PENDING;
692 varHandler->m_PendingVarRequest = varRequest;
733 varHandler->m_PendingVarRequest = varRequest;
693
734
694 break;
735 break;
695 }
736 }
696 default:
737 default:
697 qCCritical(LOG_VariableController())
738 qCCritical(LOG_VariableController())
698 << QObject::tr("Unknown VariableRequestHandlerState");
739 << QObject::tr("Unknown VariableRequestHandlerState");
699 }
740 }
700 }
741 }
701
742
702 std::shared_ptr<Variable>
743 std::shared_ptr<Variable>
703 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
744 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
704 {
745 {
705 std::shared_ptr<Variable> var;
746 std::shared_ptr<Variable> var;
706 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
747 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
707
748
708 auto end = m_VariableToIdentifierMap.cend();
749 auto end = m_VariableToIdentifierMap.cend();
709 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
750 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
710 if (it != end) {
751 if (it != end) {
711 var = it->first;
752 var = it->first;
712 }
753 }
713 else {
754 else {
714 qCCritical(LOG_VariableController())
755 qCCritical(LOG_VariableController())
715 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
756 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
716 }
757 }
717
758
718 return var;
759 return var;
719 }
760 }
720
761
721 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
762 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
722 const QVector<AcquisitionDataPacket> acqDataPacketVector)
763 const QVector<AcquisitionDataPacket> acqDataPacketVector)
723 {
764 {
724 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
765 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
725 << acqDataPacketVector.size();
766 << acqDataPacketVector.size();
726 std::shared_ptr<IDataSeries> dataSeries;
767 std::shared_ptr<IDataSeries> dataSeries;
727 if (!acqDataPacketVector.isEmpty()) {
768 if (!acqDataPacketVector.isEmpty()) {
728 dataSeries = acqDataPacketVector[0].m_DateSeries;
769 dataSeries = acqDataPacketVector[0].m_DateSeries;
729 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
770 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
730 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
771 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
731 }
772 }
732 }
773 }
733 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
774 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
734 << acqDataPacketVector.size();
775 << acqDataPacketVector.size();
735 return dataSeries;
776 return dataSeries;
736 }
777 }
737
778
738 void VariableController::VariableControllerPrivate::registerProvider(
779 void VariableController::VariableControllerPrivate::registerProvider(
739 std::shared_ptr<IDataProvider> provider)
780 std::shared_ptr<IDataProvider> provider)
740 {
781 {
741 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
782 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
742 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
783 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
743 << provider->objectName();
784 << provider->objectName();
744 m_ProviderSet.insert(provider);
785 m_ProviderSet.insert(provider);
745 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
786 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
746 &VariableAcquisitionWorker::onVariableDataAcquired);
787 &VariableAcquisitionWorker::onVariableDataAcquired);
747 connect(provider.get(), &IDataProvider::dataProvidedProgress,
788 connect(provider.get(), &IDataProvider::dataProvidedProgress,
748 m_VariableAcquisitionWorker.get(),
789 m_VariableAcquisitionWorker.get(),
749 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
790 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
750 connect(provider.get(), &IDataProvider::dataProvidedFailed,
791 connect(provider.get(), &IDataProvider::dataProvidedFailed,
751 m_VariableAcquisitionWorker.get(),
792 m_VariableAcquisitionWorker.get(),
752 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
793 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
753 }
794 }
754 else {
795 else {
755 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
796 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
756 }
797 }
757 }
798 }
758
799
759 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
800 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
760 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
801 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
761 {
802 {
762 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
803 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
763 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
804 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
764 return QUuid();
805 return QUuid();
765 }
806 }
766
807
767 auto varHandler = itVarHandler->second.get();
808 auto varHandler = itVarHandler->second.get();
768 if (varHandler->m_State == VariableRequestHandlerState::OFF) {
809 if (varHandler->m_State == VariableRequestHandlerState::OFF) {
769 qCCritical(LOG_VariableController())
810 qCCritical(LOG_VariableController())
770 << tr("acceptVariableRequest impossible on a variable with OFF state");
811 << tr("acceptVariableRequest impossible on a variable with OFF state");
771 }
812 }
772
813
773 varHandler->m_RunningVarRequest.m_DataSeries = dataSeries;
814 varHandler->m_RunningVarRequest.m_DataSeries = dataSeries;
774 varHandler->m_CanUpdate = true;
815 varHandler->m_CanUpdate = true;
775
816
776 // Element traitΓ©, on a dΓ©jΓ  toutes les donnΓ©es necessaires
817 // Element traitΓ©, on a dΓ©jΓ  toutes les donnΓ©es necessaires
777 auto varGroupId = varHandler->m_RunningVarRequest.m_VariableGroupId;
818 auto varGroupId = varHandler->m_RunningVarRequest.m_VariableGroupId;
778 qCDebug(LOG_VariableController()) << "Variable::acceptVariableRequest" << varGroupId
819 qCDebug(LOG_VariableController()) << "Variable::acceptVariableRequest" << varGroupId
779 << m_VarGroupIdToVarIds.size();
820 << m_VarGroupIdToVarIds.size();
780
821
781 return varHandler->m_RunningVarRequest.m_VariableGroupId;
822 return varHandler->m_RunningVarRequest.m_VariableGroupId;
782 }
823 }
783
824
784 void VariableController::VariableControllerPrivate::updateVariables(QUuid varRequestId)
825 void VariableController::VariableControllerPrivate::updateVariables(QUuid varRequestId)
785 {
826 {
786 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
827 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
787 << QThread::currentThread()->objectName() << varRequestId;
828 << QThread::currentThread()->objectName() << varRequestId;
788
829
789 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
830 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
790 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
831 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
791 qCWarning(LOG_VariableController())
832 qCWarning(LOG_VariableController())
792 << tr("Impossible to updateVariables of unknown variables") << varRequestId;
833 << tr("Impossible to updateVariables of unknown variables") << varRequestId;
793 return;
834 return;
794 }
835 }
795
836
796 auto &varIds = varGroupIdToVarIdsIt->second;
837 auto &varIds = varGroupIdToVarIdsIt->second;
797 auto varIdsEnd = varIds.end();
838 auto varIdsEnd = varIds.end();
798 bool processVariableUpdate = true;
839 bool processVariableUpdate = true;
799 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
840 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
800 << varRequestId << varIds.size();
841 << varRequestId << varIds.size();
801 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd) && processVariableUpdate;
842 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd) && processVariableUpdate;
802 ++varIdsIt) {
843 ++varIdsIt) {
803 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
844 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
804 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
845 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
805 processVariableUpdate &= itVarHandler->second->m_CanUpdate;
846 processVariableUpdate &= itVarHandler->second->m_CanUpdate;
806 }
847 }
807 }
848 }
808
849
809 if (processVariableUpdate) {
850 if (processVariableUpdate) {
810 qCDebug(LOG_VariableController()) << "Final update OK for the var request" << varIds.size();
851 qCDebug(LOG_VariableController()) << "Final update OK for the var request" << varIds.size();
811 for (auto varIdsIt = varIds.begin(); varIdsIt != varIdsEnd; ++varIdsIt) {
852 for (auto varIdsIt = varIds.begin(); varIdsIt != varIdsEnd; ++varIdsIt) {
812 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
853 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
813 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
854 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
814 if (auto var = findVariable(*varIdsIt)) {
855 if (auto var = findVariable(*varIdsIt)) {
815 auto &varRequest = itVarHandler->second->m_RunningVarRequest;
856 auto &varRequest = itVarHandler->second->m_RunningVarRequest;
816 var->setRange(varRequest.m_RangeRequested);
857 var->setRange(varRequest.m_RangeRequested);
817 var->setCacheRange(varRequest.m_CacheRangeRequested);
858 var->setCacheRange(varRequest.m_CacheRangeRequested);
818 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
859 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
819 << varRequest.m_RangeRequested
860 << varRequest.m_RangeRequested
820 << varRequest.m_CacheRangeRequested;
861 << varRequest.m_CacheRangeRequested;
821 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
862 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
822 << var->nbPoints()
863 << var->nbPoints()
823 << varRequest.m_DataSeries->nbPoints();
864 << varRequest.m_DataSeries->nbPoints();
824 var->mergeDataSeries(varRequest.m_DataSeries);
865 var->mergeDataSeries(varRequest.m_DataSeries);
825 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
866 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
826 << var->nbPoints();
867 << var->nbPoints();
827
868
828 emit var->updated();
869 emit var->updated();
829 qCDebug(LOG_VariableController()) << tr("Update OK");
870 qCDebug(LOG_VariableController()) << tr("Update OK");
830 }
871 }
831 else {
872 else {
832 qCCritical(LOG_VariableController())
873 qCCritical(LOG_VariableController())
833 << tr("Impossible to update data to a null variable");
874 << tr("Impossible to update data to a null variable");
834 }
875 }
835 }
876 }
836 }
877 }
837 updateVariableRequest(varRequestId);
878 updateVariableRequest(varRequestId);
838
879
839 // cleaning varRequestId
880 // cleaning varRequestId
840 qCDebug(LOG_VariableController()) << tr("m_VarGroupIdToVarIds erase") << varRequestId;
881 qCDebug(LOG_VariableController()) << tr("m_VarGroupIdToVarIds erase") << varRequestId;
841 m_VarGroupIdToVarIds.erase(varRequestId);
882 m_VarGroupIdToVarIds.erase(varRequestId);
842 }
883 }
843 }
884 }
844
885
845
886
846 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
887 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
847 {
888 {
848 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
889 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
849 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
890 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
850 qCCritical(LOG_VariableController()) << QObject::tr(
891 qCCritical(LOG_VariableController()) << QObject::tr(
851 "Impossible to updateVariableRequest since varGroupdId isn't here anymore");
892 "Impossible to updateVariableRequest since varGroupdId isn't here anymore");
852
893
853 return;
894 return;
854 }
895 }
855
896
856 auto &varIds = varGroupIdToVarIdsIt->second;
897 auto &varIds = varGroupIdToVarIdsIt->second;
857 auto varIdsEnd = varIds.end();
898 auto varIdsEnd = varIds.end();
858 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
899 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
859 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
900 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
860 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
901 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
861
902
862 auto varHandler = itVarHandler->second.get();
903 auto varHandler = itVarHandler->second.get();
863 varHandler->m_CanUpdate = false;
904 varHandler->m_CanUpdate = false;
864
905
865
906
866 switch (varHandler->m_State) {
907 switch (varHandler->m_State) {
867 case VariableRequestHandlerState::OFF: {
908 case VariableRequestHandlerState::OFF: {
868 qCCritical(LOG_VariableController())
909 qCCritical(LOG_VariableController())
869 << QObject::tr("Impossible to update a variable with handler in OFF state");
910 << QObject::tr("Impossible to update a variable with handler in OFF state");
870 } break;
911 } break;
871 case VariableRequestHandlerState::RUNNING: {
912 case VariableRequestHandlerState::RUNNING: {
872 varHandler->m_State = VariableRequestHandlerState::OFF;
913 varHandler->m_State = VariableRequestHandlerState::OFF;
873 varHandler->m_RunningVarRequest = VariableRequest{};
914 varHandler->m_RunningVarRequest = VariableRequest{};
874 break;
915 break;
875 }
916 }
876 case VariableRequestHandlerState::PENDING: {
917 case VariableRequestHandlerState::PENDING: {
877 varHandler->m_State = VariableRequestHandlerState::RUNNING;
918 varHandler->m_State = VariableRequestHandlerState::RUNNING;
878 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
919 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
879 varHandler->m_PendingVarRequest = VariableRequest{};
920 varHandler->m_PendingVarRequest = VariableRequest{};
880 auto var = findVariable(itVarHandler->first);
921 auto var = findVariable(itVarHandler->first);
881 executeVarRequest(var, varHandler->m_RunningVarRequest);
922 executeVarRequest(var, varHandler->m_RunningVarRequest);
882 break;
923 break;
883 }
924 }
884 default:
925 default:
885 qCCritical(LOG_VariableController())
926 qCCritical(LOG_VariableController())
886 << QObject::tr("Unknown VariableRequestHandlerState");
927 << QObject::tr("Unknown VariableRequestHandlerState");
887 }
928 }
888 }
929 }
889 }
930 }
890 }
931 }
891
932
892
933
893 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
934 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
894 {
935 {
895 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest") << varRequestId;
936 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest") << varRequestId;
896
937
897 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
938 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
898 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
939 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
899 qCCritical(LOG_VariableController())
940 qCCritical(LOG_VariableController())
900 << tr("Impossible to cancelVariableRequest for unknown varGroupdId") << varRequestId;
941 << tr("Impossible to cancelVariableRequest for unknown varGroupdId") << varRequestId;
901 return;
942 return;
902 }
943 }
903
944
904 auto &varIds = varGroupIdToVarIdsIt->second;
945 auto &varIds = varGroupIdToVarIdsIt->second;
905 auto varIdsEnd = varIds.end();
946 auto varIdsEnd = varIds.end();
906 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
947 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
907 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
948 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
908 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
949 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
909
950
910 auto varHandler = itVarHandler->second.get();
951 auto varHandler = itVarHandler->second.get();
911 varHandler->m_VarId = QUuid{};
952 varHandler->m_VarId = QUuid{};
912 switch (varHandler->m_State) {
953 switch (varHandler->m_State) {
913 case VariableRequestHandlerState::OFF: {
954 case VariableRequestHandlerState::OFF: {
914 qCWarning(LOG_VariableController())
955 qCWarning(LOG_VariableController())
915 << QObject::tr("Impossible to cancel a variable with no running request");
956 << QObject::tr("Impossible to cancel a variable with no running request");
916 break;
957 break;
917 }
958 }
918 case VariableRequestHandlerState::RUNNING: {
959 case VariableRequestHandlerState::RUNNING: {
919
960
920 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
961 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
921 auto var = findVariable(itVarHandler->first);
962 auto var = findVariable(itVarHandler->first);
922 auto varProvider = m_VariableToProviderMap.at(var);
963 auto varProvider = m_VariableToProviderMap.at(var);
923 if (varProvider != nullptr) {
964 if (varProvider != nullptr) {
924 m_VariableAcquisitionWorker->abortProgressRequested(
965 m_VariableAcquisitionWorker->abortProgressRequested(
925 itVarHandler->first);
966 itVarHandler->first);
926 }
967 }
927 m_VariableModel->setDataProgress(var, 0.0);
968 m_VariableModel->setDataProgress(var, 0.0);
928 varHandler->m_CanUpdate = false;
969 varHandler->m_CanUpdate = false;
929 varHandler->m_State = VariableRequestHandlerState::OFF;
970 varHandler->m_State = VariableRequestHandlerState::OFF;
930 varHandler->m_RunningVarRequest = VariableRequest{};
971 varHandler->m_RunningVarRequest = VariableRequest{};
931 }
972 }
932 else {
973 else {
933 // TODO: log Impossible to cancel the running variable request beacause its
974 // TODO: log Impossible to cancel the running variable request beacause its
934 // varRequestId isn't not the canceled one
975 // varRequestId isn't not the canceled one
935 }
976 }
936 break;
977 break;
937 }
978 }
938 case VariableRequestHandlerState::PENDING: {
979 case VariableRequestHandlerState::PENDING: {
939 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
980 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
940 auto var = findVariable(itVarHandler->first);
981 auto var = findVariable(itVarHandler->first);
941 auto varProvider = m_VariableToProviderMap.at(var);
982 auto varProvider = m_VariableToProviderMap.at(var);
942 if (varProvider != nullptr) {
983 if (varProvider != nullptr) {
943 m_VariableAcquisitionWorker->abortProgressRequested(
984 m_VariableAcquisitionWorker->abortProgressRequested(
944 itVarHandler->first);
985 itVarHandler->first);
945 }
986 }
946 m_VariableModel->setDataProgress(var, 0.0);
987 m_VariableModel->setDataProgress(var, 0.0);
947 varHandler->m_CanUpdate = false;
988 varHandler->m_CanUpdate = false;
948 varHandler->m_State = VariableRequestHandlerState::RUNNING;
989 varHandler->m_State = VariableRequestHandlerState::RUNNING;
949 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
990 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
950 varHandler->m_PendingVarRequest = VariableRequest{};
991 varHandler->m_PendingVarRequest = VariableRequest{};
951 executeVarRequest(var, varHandler->m_RunningVarRequest);
992 executeVarRequest(var, varHandler->m_RunningVarRequest);
952 }
993 }
953 else if (varHandler->m_PendingVarRequest.m_VariableGroupId == varRequestId) {
994 else if (varHandler->m_PendingVarRequest.m_VariableGroupId == varRequestId) {
954 varHandler->m_State = VariableRequestHandlerState::RUNNING;
995 varHandler->m_State = VariableRequestHandlerState::RUNNING;
955 varHandler->m_PendingVarRequest = VariableRequest{};
996 varHandler->m_PendingVarRequest = VariableRequest{};
956 }
997 }
957 else {
998 else {
958 // TODO: log Impossible to cancel the variable request beacause its
999 // TODO: log Impossible to cancel the variable request beacause its
959 // varRequestId isn't not the canceled one
1000 // varRequestId isn't not the canceled one
960 }
1001 }
961 break;
1002 break;
962 }
1003 }
963 default:
1004 default:
964 qCCritical(LOG_VariableController())
1005 qCCritical(LOG_VariableController())
965 << QObject::tr("Unknown VariableRequestHandlerState");
1006 << QObject::tr("Unknown VariableRequestHandlerState");
966 }
1007 }
967 }
1008 }
968 }
1009 }
969 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest: erase") << varRequestId;
1010 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest: erase") << varRequestId;
970 m_VarGroupIdToVarIds.erase(varRequestId);
1011 m_VarGroupIdToVarIds.erase(varRequestId);
971 }
1012 }
972
1013
973 void VariableController::VariableControllerPrivate::executeVarRequest(std::shared_ptr<Variable> var,
1014 void VariableController::VariableControllerPrivate::executeVarRequest(std::shared_ptr<Variable> var,
974 VariableRequest &varRequest)
1015 VariableRequest &varRequest)
975 {
1016 {
976 qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest");
1017 qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest");
977
1018
978 auto varId = m_VariableToIdentifierMap.at(var);
1019 auto varId = m_VariableToIdentifierMap.at(var);
979
1020
980 auto varCacheRange = var->cacheRange();
1021 auto varCacheRange = var->cacheRange();
981 auto varCacheRangeRequested = varRequest.m_CacheRangeRequested;
1022 auto varCacheRangeRequested = varRequest.m_CacheRangeRequested;
982 auto notInCacheRangeList
1023 auto notInCacheRangeList
983 = Variable::provideNotInCacheRangeList(varCacheRange, varCacheRangeRequested);
1024 = Variable::provideNotInCacheRangeList(varCacheRange, varCacheRangeRequested);
984 auto inCacheRangeList
1025 auto inCacheRangeList
985 = Variable::provideInCacheRangeList(varCacheRange, varCacheRangeRequested);
1026 = Variable::provideInCacheRangeList(varCacheRange, varCacheRangeRequested);
986
1027
987 if (!notInCacheRangeList.empty()) {
1028 if (!notInCacheRangeList.empty()) {
988
1029
989 auto varProvider = m_VariableToProviderMap.at(var);
1030 auto varProvider = m_VariableToProviderMap.at(var);
990 if (varProvider != nullptr) {
1031 if (varProvider != nullptr) {
991 qCDebug(LOG_VariableController()) << "executeVarRequest " << varRequest.m_RangeRequested
1032 qCDebug(LOG_VariableController()) << "executeVarRequest " << varRequest.m_RangeRequested
992 << varRequest.m_CacheRangeRequested;
1033 << varRequest.m_CacheRangeRequested;
993 m_VariableAcquisitionWorker->pushVariableRequest(
1034 m_VariableAcquisitionWorker->pushVariableRequest(
994 varRequest.m_VariableGroupId, varId, varRequest.m_RangeRequested,
1035 varRequest.m_VariableGroupId, varId, varRequest.m_RangeRequested,
995 varRequest.m_CacheRangeRequested,
1036 varRequest.m_CacheRangeRequested,
996 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
1037 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
997 varProvider);
1038 varProvider);
998 }
1039 }
999 else {
1040 else {
1000 qCCritical(LOG_VariableController())
1041 qCCritical(LOG_VariableController())
1001 << "Impossible to provide data with a null provider";
1042 << "Impossible to provide data with a null provider";
1002 }
1043 }
1003
1044
1004 if (!inCacheRangeList.empty()) {
1045 if (!inCacheRangeList.empty()) {
1005 emit q->updateVarDisplaying(var, inCacheRangeList.first());
1046 emit q->updateVarDisplaying(var, inCacheRangeList.first());
1006 }
1047 }
1007 }
1048 }
1008 else {
1049 else {
1009 acceptVariableRequest(varId,
1050 acceptVariableRequest(varId,
1010 var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested));
1051 var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested));
1011 }
1052 }
1012 }
1053 }
@@ -1,293 +1,351
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableController.h>
2 #include <Variable/VariableModel.h>
3 #include <Variable/VariableModel.h>
3
4
4 #include <Common/DateUtils.h>
5 #include <Common/DateUtils.h>
6 #include <Common/MimeTypesDef.h>
5 #include <Common/StringUtils.h>
7 #include <Common/StringUtils.h>
6
8
7 #include <Data/IDataSeries.h>
9 #include <Data/IDataSeries.h>
8
10
11 #include <QMimeData>
9 #include <QSize>
12 #include <QSize>
10 #include <unordered_map>
13 #include <unordered_map>
11
14
12 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
15 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
13
16
14 namespace {
17 namespace {
15
18
16 // Column indexes
19 // Column indexes
17 const auto NAME_COLUMN = 0;
20 const auto NAME_COLUMN = 0;
18 const auto TSTART_COLUMN = 1;
21 const auto TSTART_COLUMN = 1;
19 const auto TEND_COLUMN = 2;
22 const auto TEND_COLUMN = 2;
20 const auto NBPOINTS_COLUMN = 3;
23 const auto NBPOINTS_COLUMN = 3;
21 const auto UNIT_COLUMN = 4;
24 const auto UNIT_COLUMN = 4;
22 const auto MISSION_COLUMN = 5;
25 const auto MISSION_COLUMN = 5;
23 const auto PLUGIN_COLUMN = 6;
26 const auto PLUGIN_COLUMN = 6;
24 const auto NB_COLUMNS = 7;
27 const auto NB_COLUMNS = 7;
25
28
26 // Column properties
29 // Column properties
27 const auto DEFAULT_HEIGHT = 25;
30 const auto DEFAULT_HEIGHT = 25;
28 const auto DEFAULT_WIDTH = 100;
31 const auto DEFAULT_WIDTH = 100;
29
32
30 struct ColumnProperties {
33 struct ColumnProperties {
31 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
34 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
32 int height = DEFAULT_HEIGHT)
35 int height = DEFAULT_HEIGHT)
33 : m_Name{name}, m_Width{width}, m_Height{height}
36 : m_Name{name}, m_Width{width}, m_Height{height}
34 {
37 {
35 }
38 }
36
39
37 QString m_Name;
40 QString m_Name;
38 int m_Width;
41 int m_Width;
39 int m_Height;
42 int m_Height;
40 };
43 };
41
44
42 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
45 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
43 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
46 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
44 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
47 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
45 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
48 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
46 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
49 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
47
50
48 /// Format for datetimes
51 /// Format for datetimes
49 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
52 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
50
53
51 QString uniqueName(const QString &defaultName,
54 QString uniqueName(const QString &defaultName,
52 const std::vector<std::shared_ptr<Variable> > &variables)
55 const std::vector<std::shared_ptr<Variable> > &variables)
53 {
56 {
54 auto forbiddenNames = std::vector<QString>(variables.size());
57 auto forbiddenNames = std::vector<QString>(variables.size());
55 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
58 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
56 [](const auto &variable) { return variable->name(); });
59 [](const auto &variable) { return variable->name(); });
57 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
60 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
58 Q_ASSERT(!uniqueName.isEmpty());
61 Q_ASSERT(!uniqueName.isEmpty());
59
62
60 return uniqueName;
63 return uniqueName;
61 }
64 }
62
65
63 } // namespace
66 } // namespace
64
67
65 struct VariableModel::VariableModelPrivate {
68 struct VariableModel::VariableModelPrivate {
66 /// Variables created in SciQlop
69 /// Variables created in SciQlop
67 std::vector<std::shared_ptr<Variable> > m_Variables;
70 std::vector<std::shared_ptr<Variable> > m_Variables;
68 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
71 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
72 VariableController *m_VariableController;
69
73
70 /// Return the row index of the variable. -1 if it's not found
74 /// Return the row index of the variable. -1 if it's not found
71 int indexOfVariable(Variable *variable) const noexcept;
75 int indexOfVariable(Variable *variable) const noexcept;
72 };
76 };
73
77
74 VariableModel::VariableModel(QObject *parent)
78 VariableModel::VariableModel(VariableController *parent)
75 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
79 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
76 {
80 {
81 impl->m_VariableController = parent;
77 }
82 }
78
83
79 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
84 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
80 {
85 {
81 auto insertIndex = rowCount();
86 auto insertIndex = rowCount();
82 beginInsertRows({}, insertIndex, insertIndex);
87 beginInsertRows({}, insertIndex, insertIndex);
83
88
84 // Generates unique name for the variable
89 // Generates unique name for the variable
85 variable->setName(uniqueName(variable->name(), impl->m_Variables));
90 variable->setName(uniqueName(variable->name(), impl->m_Variables));
86
91
87 impl->m_Variables.push_back(variable);
92 impl->m_Variables.push_back(variable);
88 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
93 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
89
94
90 endInsertRows();
95 endInsertRows();
91 }
96 }
92
97
93 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
98 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
94 {
99 {
95 auto end = impl->m_Variables.cend();
100 auto end = impl->m_Variables.cend();
96 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
101 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
97 }
102 }
98
103
99 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
104 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
100 const QVariantHash &metadata) noexcept
105 const QVariantHash &metadata) noexcept
101 {
106 {
102 auto variable = std::make_shared<Variable>(name, metadata);
107 auto variable = std::make_shared<Variable>(name, metadata);
103 addVariable(variable);
108 addVariable(variable);
104
109
105 return variable;
110 return variable;
106 }
111 }
107
112
108 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
113 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
109 {
114 {
110 if (!variable) {
115 if (!variable) {
111 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
116 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
112 return;
117 return;
113 }
118 }
114
119
115 // Finds variable in the model
120 // Finds variable in the model
116 auto begin = impl->m_Variables.cbegin();
121 auto begin = impl->m_Variables.cbegin();
117 auto end = impl->m_Variables.cend();
122 auto end = impl->m_Variables.cend();
118 auto it = std::find(begin, end, variable);
123 auto it = std::find(begin, end, variable);
119 if (it != end) {
124 if (it != end) {
120 auto removeIndex = std::distance(begin, it);
125 auto removeIndex = std::distance(begin, it);
121
126
122 // Deletes variable
127 // Deletes variable
123 beginRemoveRows({}, removeIndex, removeIndex);
128 beginRemoveRows({}, removeIndex, removeIndex);
124 impl->m_Variables.erase(it);
129 impl->m_Variables.erase(it);
125 endRemoveRows();
130 endRemoveRows();
126 }
131 }
127 else {
132 else {
128 qCritical(LOG_VariableModel())
133 qCritical(LOG_VariableModel())
129 << tr("Can't delete variable %1 from the model: the variable is not in the model")
134 << tr("Can't delete variable %1 from the model: the variable is not in the model")
130 .arg(variable->name());
135 .arg(variable->name());
131 }
136 }
132
137
133 // Removes variable from progress map
138 // Removes variable from progress map
134 impl->m_VariableToProgress.erase(variable);
139 impl->m_VariableToProgress.erase(variable);
135 }
140 }
136
141
137
142
138 std::shared_ptr<Variable> VariableModel::variable(int index) const
143 std::shared_ptr<Variable> VariableModel::variable(int index) const
139 {
144 {
140 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
145 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
141 }
146 }
142
147
143 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
148 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
144 {
149 {
145 return impl->m_Variables;
150 return impl->m_Variables;
146 }
151 }
147
152
148 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
153 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
149 {
154 {
150 if (progress > 0.0) {
155 if (progress > 0.0) {
151 impl->m_VariableToProgress[variable] = progress;
156 impl->m_VariableToProgress[variable] = progress;
152 }
157 }
153 else {
158 else {
154 impl->m_VariableToProgress.erase(variable);
159 impl->m_VariableToProgress.erase(variable);
155 }
160 }
156 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
161 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
157
162
158 emit dataChanged(modelIndex, modelIndex);
163 emit dataChanged(modelIndex, modelIndex);
159 }
164 }
160
165
161 int VariableModel::columnCount(const QModelIndex &parent) const
166 int VariableModel::columnCount(const QModelIndex &parent) const
162 {
167 {
163 Q_UNUSED(parent);
168 Q_UNUSED(parent);
164
169
165 return NB_COLUMNS;
170 return NB_COLUMNS;
166 }
171 }
167
172
168 int VariableModel::rowCount(const QModelIndex &parent) const
173 int VariableModel::rowCount(const QModelIndex &parent) const
169 {
174 {
170 Q_UNUSED(parent);
175 Q_UNUSED(parent);
171
176
172 return impl->m_Variables.size();
177 return impl->m_Variables.size();
173 }
178 }
174
179
175 QVariant VariableModel::data(const QModelIndex &index, int role) const
180 QVariant VariableModel::data(const QModelIndex &index, int role) const
176 {
181 {
177 if (!index.isValid()) {
182 if (!index.isValid()) {
178 return QVariant{};
183 return QVariant{};
179 }
184 }
180
185
181 if (index.row() < 0 || index.row() >= rowCount()) {
186 if (index.row() < 0 || index.row() >= rowCount()) {
182 return QVariant{};
187 return QVariant{};
183 }
188 }
184
189
185 if (role == Qt::DisplayRole) {
190 if (role == Qt::DisplayRole) {
186 if (auto variable = impl->m_Variables.at(index.row()).get()) {
191 if (auto variable = impl->m_Variables.at(index.row()).get()) {
187 switch (index.column()) {
192 switch (index.column()) {
188 case NAME_COLUMN:
193 case NAME_COLUMN:
189 return variable->name();
194 return variable->name();
190 case TSTART_COLUMN: {
195 case TSTART_COLUMN: {
191 auto range = variable->realRange();
196 auto range = variable->realRange();
192 return range != INVALID_RANGE
197 return range != INVALID_RANGE
193 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
198 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
194 : QVariant{};
199 : QVariant{};
195 }
200 }
196 case TEND_COLUMN: {
201 case TEND_COLUMN: {
197 auto range = variable->realRange();
202 auto range = variable->realRange();
198 return range != INVALID_RANGE
203 return range != INVALID_RANGE
199 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
204 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
200 : QVariant{};
205 : QVariant{};
201 }
206 }
202 case NBPOINTS_COLUMN:
207 case NBPOINTS_COLUMN:
203 return variable->nbPoints();
208 return variable->nbPoints();
204 case UNIT_COLUMN:
209 case UNIT_COLUMN:
205 return variable->metadata().value(QStringLiteral("units"));
210 return variable->metadata().value(QStringLiteral("units"));
206 case MISSION_COLUMN:
211 case MISSION_COLUMN:
207 return variable->metadata().value(QStringLiteral("mission"));
212 return variable->metadata().value(QStringLiteral("mission"));
208 case PLUGIN_COLUMN:
213 case PLUGIN_COLUMN:
209 return variable->metadata().value(QStringLiteral("plugin"));
214 return variable->metadata().value(QStringLiteral("plugin"));
210 default:
215 default:
211 // No action
216 // No action
212 break;
217 break;
213 }
218 }
214
219
215 qWarning(LOG_VariableModel())
220 qWarning(LOG_VariableModel())
216 << tr("Can't get data (unknown column %1)").arg(index.column());
221 << tr("Can't get data (unknown column %1)").arg(index.column());
217 }
222 }
218 else {
223 else {
219 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
224 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
220 }
225 }
221 }
226 }
222 else if (role == VariableRoles::ProgressRole) {
227 else if (role == VariableRoles::ProgressRole) {
223 if (auto variable = impl->m_Variables.at(index.row())) {
228 if (auto variable = impl->m_Variables.at(index.row())) {
224
229
225 auto it = impl->m_VariableToProgress.find(variable);
230 auto it = impl->m_VariableToProgress.find(variable);
226 if (it != impl->m_VariableToProgress.cend()) {
231 if (it != impl->m_VariableToProgress.cend()) {
227 return it->second;
232 return it->second;
228 }
233 }
229 }
234 }
230 }
235 }
231
236
232 return QVariant{};
237 return QVariant{};
233 }
238 }
234
239
235 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
240 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
236 {
241 {
237 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
242 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
238 return QVariant{};
243 return QVariant{};
239 }
244 }
240
245
241 if (orientation == Qt::Horizontal) {
246 if (orientation == Qt::Horizontal) {
242 auto propertiesIt = COLUMN_PROPERTIES.find(section);
247 auto propertiesIt = COLUMN_PROPERTIES.find(section);
243 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
248 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
244 // Role is either DisplayRole or SizeHintRole
249 // Role is either DisplayRole or SizeHintRole
245 return (role == Qt::DisplayRole)
250 return (role == Qt::DisplayRole)
246 ? QVariant{propertiesIt->m_Name}
251 ? QVariant{propertiesIt->m_Name}
247 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
252 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
248 }
253 }
249 else {
254 else {
250 qWarning(LOG_VariableModel())
255 qWarning(LOG_VariableModel())
251 << tr("Can't get header data (unknown column %1)").arg(section);
256 << tr("Can't get header data (unknown column %1)").arg(section);
252 }
257 }
253 }
258 }
254
259
255 return QVariant{};
260 return QVariant{};
256 }
261 }
257
262
263 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
264 {
265 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
266 }
267
268 Qt::DropActions VariableModel::supportedDropActions() const
269 {
270 return Qt::MoveAction;
271 }
272
273 Qt::DropActions VariableModel::supportedDragActions() const
274 {
275 return Qt::CopyAction | Qt::MoveAction;
276 }
277
278 QStringList VariableModel::mimeTypes() const
279 {
280 return {MIME_TYPE_VARIABLE_LIST};
281 }
282
283 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
284 {
285 auto mimeData = new QMimeData;
286
287 QList<std::shared_ptr<Variable> > variableList;
288
289 for (const auto &index : indexes) {
290 if (index.column() == 0) { // only the first column
291 auto variable = impl->m_Variables.at(index.row());
292 if (variable.get() && index.isValid()) {
293 variableList << variable;
294 }
295 }
296 }
297
298 auto encodedData = impl->m_VariableController->mimeDataForVariables(variableList);
299 mimeData->setData(MIME_TYPE_VARIABLE_LIST, encodedData);
300
301 return mimeData;
302 }
303
304 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
305 int column, const QModelIndex &parent) const
306 {
307 return false;
308 }
309
310 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
311 const QModelIndex &parent)
312 {
313 return false;
314 }
315
258 void VariableModel::abortProgress(const QModelIndex &index)
316 void VariableModel::abortProgress(const QModelIndex &index)
259 {
317 {
260 if (auto variable = impl->m_Variables.at(index.row())) {
318 if (auto variable = impl->m_Variables.at(index.row())) {
261 emit abortProgessRequested(variable);
319 emit abortProgessRequested(variable);
262 }
320 }
263 }
321 }
264
322
265 void VariableModel::onVariableUpdated() noexcept
323 void VariableModel::onVariableUpdated() noexcept
266 {
324 {
267 // Finds variable that has been updated in the model
325 // Finds variable that has been updated in the model
268 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
326 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
269 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
327 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
270
328
271 if (updatedVariableIndex > -1) {
329 if (updatedVariableIndex > -1) {
272 emit dataChanged(createIndex(updatedVariableIndex, 0),
330 emit dataChanged(createIndex(updatedVariableIndex, 0),
273 createIndex(updatedVariableIndex, columnCount() - 1));
331 createIndex(updatedVariableIndex, columnCount() - 1));
274 }
332 }
275 }
333 }
276 }
334 }
277
335
278 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
336 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
279 {
337 {
280 auto begin = std::cbegin(m_Variables);
338 auto begin = std::cbegin(m_Variables);
281 auto end = std::cend(m_Variables);
339 auto end = std::cend(m_Variables);
282 auto it
340 auto it
283 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
341 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
284
342
285 if (it != end) {
343 if (it != end) {
286 // Gets the index of the variable in the model: we assume here that views have the same
344 // Gets the index of the variable in the model: we assume here that views have the same
287 // order as the model
345 // order as the model
288 return std::distance(begin, it);
346 return std::distance(begin, it);
289 }
347 }
290 else {
348 else {
291 return -1;
349 return -1;
292 }
350 }
293 }
351 }
@@ -1,65 +1,85
1 #ifndef SCIQLOP_DRAGDROPHELPER_H
1 #ifndef SCIQLOP_DRAGDROPHELPER_H
2 #define SCIQLOP_DRAGDROPHELPER_H
2 #define SCIQLOP_DRAGDROPHELPER_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 #include <QWidget>
6 #include <QWidget>
6
7
7 class QVBoxLayout;
8 class QVBoxLayout;
8 class QScrollArea;
9 class QScrollArea;
9 class VisualizationDragWidget;
10 class VisualizationDragWidget;
11 class VisualizationDragDropContainer;
10 class QMimeData;
12 class QMimeData;
11
13
12 /**
14 Q_DECLARE_LOGGING_CATEGORY(LOG_DragDropHelper)
13 * @brief Event filter class which manage the scroll of QScrollArea during a drag&drop operation.
14 * @note A QScrollArea inside an other QScrollArea is not fully supported.
15 */
16 class DragDropScroller : public QObject {
17 Q_OBJECT
18
19 public:
20 DragDropScroller(QObject *parent = nullptr);
21
22 void addScrollArea(QScrollArea *scrollArea);
23 void removeScrollArea(QScrollArea *scrollArea);
24
25 protected:
26 bool eventFilter(QObject *obj, QEvent *event);
27
28 private:
29 class DragDropScrollerPrivate;
30 spimpl::unique_impl_ptr<DragDropScrollerPrivate> impl;
31
32 private slots:
33 void onTimer();
34 };
35
15
36 /**
16 /**
37 * @brief Helper class for drag&drop operations.
17 * @brief Helper class for drag&drop operations.
18 * @note The helper is accessible from the sqpApp singleton and has the same life as the whole
19 * application (like a controller). But contrary to a controller, it doesn't live in a thread and
20 * can interect with the gui.
21 * @see SqpApplication
38 */
22 */
39 class DragDropHelper {
23 class DragDropHelper {
40 public:
24 public:
41 static const QString MIME_TYPE_GRAPH;
25 static const QString MIME_TYPE_GRAPH;
42 static const QString MIME_TYPE_ZONE;
26 static const QString MIME_TYPE_ZONE;
43
27
44 DragDropHelper();
28 DragDropHelper();
45 virtual ~DragDropHelper();
29 virtual ~DragDropHelper();
46
30
31 /// Resets some internal variables. Must be called before any new drag&drop operation.
32 void resetDragAndDrop();
33
34 /// Sets the visualization widget currently being drag on the visualization.
47 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
35 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
36
37 /// Returns the visualization widget currently being drag on the visualization.
38 /// Can be null if a new visualization widget is intended to be created by the drag&drop
39 /// operation.
48 VisualizationDragWidget *getCurrentDragWidget() const;
40 VisualizationDragWidget *getCurrentDragWidget() const;
49
41
50 QWidget &placeHolder() const;
42 QWidget &placeHolder() const;
51 void insertPlaceHolder(QVBoxLayout *layout, int index);
43 void insertPlaceHolder(QVBoxLayout *layout, int index);
52 void removePlaceHolder();
44 void removePlaceHolder();
53 bool isPlaceHolderSet() const;
45 bool isPlaceHolderSet() const;
54
46
47 /// Checks if the specified mime data is valid for a drop in the visualization
48 bool checkMimeDataForVisualization(const QMimeData *mimeData,
49 VisualizationDragDropContainer *dropContainer);
50
55 void addDragDropScrollArea(QScrollArea *scrollArea);
51 void addDragDropScrollArea(QScrollArea *scrollArea);
56 void removeDragDropScrollArea(QScrollArea *scrollArea);
52 void removeDragDropScrollArea(QScrollArea *scrollArea);
57
53
58 QUrl imageTemporaryUrl(const QImage &image) const;
54 QUrl imageTemporaryUrl(const QImage &image) const;
59
55
60 private:
56 private:
61 class DragDropHelperPrivate;
57 class DragDropHelperPrivate;
62 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
58 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
63 };
59 };
64
60
61 /**
62 * @brief Event filter class which manage the scroll of QScrollArea during a drag&drop operation.
63 * @note A QScrollArea inside an other QScrollArea is not fully supported.
64 */
65 class DragDropScroller : public QObject {
66 Q_OBJECT
67
68 public:
69 DragDropScroller(QObject *parent = nullptr);
70
71 void addScrollArea(QScrollArea *scrollArea);
72 void removeScrollArea(QScrollArea *scrollArea);
73
74 protected:
75 bool eventFilter(QObject *obj, QEvent *event);
76
77 private:
78 class DragDropScrollerPrivate;
79 spimpl::unique_impl_ptr<DragDropScrollerPrivate> impl;
80
81 private slots:
82 void onTimer();
83 };
84
65 #endif // SCIQLOP_DRAGDROPHELPER_H
85 #endif // SCIQLOP_DRAGDROPHELPER_H
@@ -1,56 +1,57
1 #ifndef SCIQLOP_SQPAPPLICATION_H
1 #ifndef SCIQLOP_SQPAPPLICATION_H
2 #define SCIQLOP_SQPAPPLICATION_H
2 #define SCIQLOP_SQPAPPLICATION_H
3
3
4 #include "SqpApplication.h"
4 #include "SqpApplication.h"
5
5
6 #include <QApplication>
6 #include <QApplication>
7 #include <QLoggingCategory>
7 #include <QLoggingCategory>
8
8
9 #include <Common/spimpl.h>
9 #include <Common/spimpl.h>
10
10
11 Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication)
11 Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication)
12
12
13 #if defined(sqpApp)
13 #if defined(sqpApp)
14 #undef sqpApp
14 #undef sqpApp
15 #endif
15 #endif
16 #define sqpApp (static_cast<SqpApplication *>(QCoreApplication::instance()))
16 #define sqpApp (static_cast<SqpApplication *>(QCoreApplication::instance()))
17
17
18 class DataSourceController;
18 class DataSourceController;
19 class NetworkController;
19 class NetworkController;
20 class TimeController;
20 class TimeController;
21 class VariableController;
21 class VariableController;
22 class VisualizationController;
22 class VisualizationController;
23 class DragDropHelper;
23 class DragDropHelper;
24
24
25 /**
25 /**
26 * @brief The SqpApplication class aims to make the link between SciQlop
26 * @brief The SqpApplication class aims to make the link between SciQlop
27 * and its plugins. This is the intermediate class that SciQlop has to use
27 * and its plugins. This is the intermediate class that SciQlop has to use
28 * in the way to connect a data source. Please first use load method to initialize
28 * in the way to connect a data source. Please first use load method to initialize
29 * a plugin specified by its metadata name (JSON plugin source) then others specifics
29 * a plugin specified by its metadata name (JSON plugin source) then others specifics
30 * method will be able to access it.
30 * method will be able to access it.
31 * You can load a data source driver plugin then create a data source.
31 * You can load a data source driver plugin then create a data source.
32 */
32 */
33
33
34 class SqpApplication : public QApplication {
34 class SqpApplication : public QApplication {
35 Q_OBJECT
35 Q_OBJECT
36 public:
36 public:
37 explicit SqpApplication(int &argc, char **argv);
37 explicit SqpApplication(int &argc, char **argv);
38 virtual ~SqpApplication();
38 virtual ~SqpApplication();
39 void initialize();
39 void initialize();
40
40
41 /// Accessors for the differents sciqlop controllers
41 /// Accessors for the differents sciqlop controllers
42 DataSourceController &dataSourceController() noexcept;
42 DataSourceController &dataSourceController() noexcept;
43 NetworkController &networkController() noexcept;
43 NetworkController &networkController() noexcept;
44 TimeController &timeController() noexcept;
44 TimeController &timeController() noexcept;
45 VariableController &variableController() noexcept;
45 VariableController &variableController() noexcept;
46 VisualizationController &visualizationController() noexcept;
46 VisualizationController &visualizationController() noexcept;
47
47
48 /// Accessors for the differents sciqlop helpers
48 /// Accessors for the differents sciqlop helpers, these helpers classes are like controllers but
49 /// doesn't live in a thread and access gui
49 DragDropHelper &dragDropHelper() noexcept;
50 DragDropHelper &dragDropHelper() noexcept;
50
51
51 private:
52 private:
52 class SqpApplicationPrivate;
53 class SqpApplicationPrivate;
53 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
54 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
54 };
55 };
55
56
56 #endif // SCIQLOP_SQPAPPLICATION_H
57 #endif // SCIQLOP_SQPAPPLICATION_H
@@ -1,42 +1,51
1 #ifndef SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
1 #ifndef SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 #include <QMimeData>
6 #include <QMimeData>
6 #include <QVBoxLayout>
7 #include <QVBoxLayout>
7 #include <QWidget>
8 #include <QWidget>
8
9
10 #include <functional>
11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
13
9 class VisualizationDragWidget;
14 class VisualizationDragWidget;
10
15
11 class VisualizationDragDropContainer : public QWidget {
16 class VisualizationDragDropContainer : public QWidget {
12 Q_OBJECT
17 Q_OBJECT
13
18
14 signals:
19 signals:
15 void dropOccured(int dropIndex, const QMimeData *mimeData);
20 void dropOccured(int dropIndex, const QMimeData *mimeData);
16
21
17 public:
22 public:
23 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
24
18 VisualizationDragDropContainer(QWidget *parent = nullptr);
25 VisualizationDragDropContainer(QWidget *parent = nullptr);
19
26
20 void addDragWidget(VisualizationDragWidget *dragWidget);
27 void addDragWidget(VisualizationDragWidget *dragWidget);
21 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
28 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
22
29
23 void setAcceptedMimeTypes(const QStringList &mimeTypes);
30 void setAcceptedMimeTypes(const QStringList &mimeTypes);
24 void setMergeAllowedMimeTypes(const QStringList &mimeTypes);
31 void setMergeAllowedMimeTypes(const QStringList &mimeTypes);
25
32
26 int countDragWidget() const;
33 int countDragWidget() const;
27
34
35 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
36
28 protected:
37 protected:
29 void dragEnterEvent(QDragEnterEvent *event);
38 void dragEnterEvent(QDragEnterEvent *event);
30 void dragLeaveEvent(QDragLeaveEvent *event);
39 void dragLeaveEvent(QDragLeaveEvent *event);
31 void dragMoveEvent(QDragMoveEvent *event);
40 void dragMoveEvent(QDragMoveEvent *event);
32 void dropEvent(QDropEvent *event);
41 void dropEvent(QDropEvent *event);
33
42
34 private:
43 private:
35 class VisualizationDragDropContainerPrivate;
44 class VisualizationDragDropContainerPrivate;
36 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
45 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
37
46
38 private slots:
47 private slots:
39 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
48 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
40 };
49 };
41
50
42 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
51 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
@@ -1,230 +1,289
1 #include "DragDropHelper.h"
1 #include "DragDropHelper.h"
2 #include "SqpApplication.h"
2 #include "SqpApplication.h"
3 #include "Visualization/VisualizationDragDropContainer.h"
3 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/operations/FindVariableOperation.h"
7
8 #include "Variable/VariableController.h"
9
10 #include "Common/MimeTypesDef.h"
11 #include "Common/VisualizationDef.h"
4
12
5 #include <QDir>
13 #include <QDir>
6 #include <QDragEnterEvent>
14 #include <QDragEnterEvent>
7 #include <QDragMoveEvent>
15 #include <QDragMoveEvent>
8 #include <QScrollArea>
16 #include <QScrollArea>
9 #include <QScrollBar>
17 #include <QScrollBar>
10 #include <QTimer>
18 #include <QTimer>
11 #include <QVBoxLayout>
19 #include <QVBoxLayout>
12
20
13 const QString DragDropHelper::MIME_TYPE_GRAPH = "scqlop/graph";
14 const QString DragDropHelper::MIME_TYPE_ZONE = "scqlop/zone";
15
16 const int SCROLL_SPEED = 5;
21 const int SCROLL_SPEED = 5;
17 const int SCROLL_ZONE_SIZE = 50;
22 const int SCROLL_ZONE_SIZE = 50;
18
23
24 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDrophelper")
25
19 struct DragDropScroller::DragDropScrollerPrivate {
26 struct DragDropScroller::DragDropScrollerPrivate {
20
27
21 QList<QScrollArea *> m_ScrollAreas;
28 QList<QScrollArea *> m_ScrollAreas;
22 QScrollArea *m_CurrentScrollArea = nullptr;
29 QScrollArea *m_CurrentScrollArea = nullptr;
23 std::unique_ptr<QTimer> m_Timer = nullptr;
30 std::unique_ptr<QTimer> m_Timer = nullptr;
24
31
25
32
26 enum class ScrollDirection { up, down, unknown };
33 enum class ScrollDirection { up, down, unknown };
27 ScrollDirection m_Direction = ScrollDirection::unknown;
34 ScrollDirection m_Direction = ScrollDirection::unknown;
28
35
29 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
36 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
30 {
37 {
31 m_Timer->setInterval(0);
38 m_Timer->setInterval(0);
32 }
39 }
33 };
40 };
34
41
35 DragDropScroller::DragDropScroller(QObject *parent)
42 DragDropScroller::DragDropScroller(QObject *parent)
36 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
43 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
37 {
44 {
38 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
45 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
39 }
46 }
40
47
41 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
48 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
42 {
49 {
43 impl->m_ScrollAreas << scrollArea;
50 impl->m_ScrollAreas << scrollArea;
44 scrollArea->viewport()->setAcceptDrops(true);
51 scrollArea->viewport()->setAcceptDrops(true);
45 }
52 }
46
53
47 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
54 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
48 {
55 {
49 impl->m_ScrollAreas.removeAll(scrollArea);
56 impl->m_ScrollAreas.removeAll(scrollArea);
50 scrollArea->viewport()->setAcceptDrops(false);
57 scrollArea->viewport()->setAcceptDrops(false);
51 }
58 }
52
59
53 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
60 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
54 {
61 {
55 if (event->type() == QEvent::DragMove) {
62 if (event->type() == QEvent::DragMove) {
56 auto w = static_cast<QWidget *>(obj);
63 auto w = static_cast<QWidget *>(obj);
57
64
58 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
65 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
59 auto moveEvent = static_cast<QDragMoveEvent *>(event);
66 auto moveEvent = static_cast<QDragMoveEvent *>(event);
60
67
61 auto pos = moveEvent->pos();
68 auto pos = moveEvent->pos();
62 if (impl->m_CurrentScrollArea->viewport() != w) {
69 if (impl->m_CurrentScrollArea->viewport() != w) {
63 auto globalPos = w->mapToGlobal(moveEvent->pos());
70 auto globalPos = w->mapToGlobal(moveEvent->pos());
64 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
71 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
65 }
72 }
66
73
67 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
74 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
68 - SCROLL_ZONE_SIZE;
75 - SCROLL_ZONE_SIZE;
69 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
76 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
70
77
71 if (!isInTopZone && !isInBottomZone) {
78 if (!isInTopZone && !isInBottomZone) {
72 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
79 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
73 impl->m_Timer->stop();
80 impl->m_Timer->stop();
74 }
81 }
75 else if (!impl->m_Timer->isActive()) {
82 else if (!impl->m_Timer->isActive()) {
76 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
83 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
77 : DragDropScrollerPrivate::ScrollDirection::down;
84 : DragDropScrollerPrivate::ScrollDirection::down;
78 impl->m_Timer->start();
85 impl->m_Timer->start();
79 }
86 }
80 }
87 }
81 }
88 }
82 else if (event->type() == QEvent::DragEnter) {
89 else if (event->type() == QEvent::DragEnter) {
83 auto w = static_cast<QWidget *>(obj);
90 auto w = static_cast<QWidget *>(obj);
84
91
85 for (auto scrollArea : impl->m_ScrollAreas) {
92 for (auto scrollArea : impl->m_ScrollAreas) {
86 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
93 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
87 auto enterEvent = static_cast<QDragEnterEvent *>(event);
94 auto enterEvent = static_cast<QDragEnterEvent *>(event);
88 enterEvent->acceptProposedAction();
95 enterEvent->acceptProposedAction();
89 enterEvent->setDropAction(Qt::IgnoreAction);
96 enterEvent->setDropAction(Qt::IgnoreAction);
90 impl->m_CurrentScrollArea = scrollArea;
97 impl->m_CurrentScrollArea = scrollArea;
91 break;
98 break;
92 }
99 }
93 }
100 }
94 }
101 }
95 else if (event->type() == QEvent::DragLeave) {
102 else if (event->type() == QEvent::DragLeave) {
96 if (impl->m_CurrentScrollArea) {
103 if (impl->m_CurrentScrollArea) {
97 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
104 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
98 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
105 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
99 impl->m_CurrentScrollArea = nullptr;
106 impl->m_CurrentScrollArea = nullptr;
100 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
107 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
101 impl->m_Timer->stop();
108 impl->m_Timer->stop();
102 }
109 }
103 }
110 }
104 }
111 }
105 else if (event->type() == QEvent::Drop) {
112 else if (event->type() == QEvent::Drop) {
106 if (impl->m_CurrentScrollArea) {
113 if (impl->m_CurrentScrollArea) {
107 impl->m_CurrentScrollArea = nullptr;
114 impl->m_CurrentScrollArea = nullptr;
108 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
115 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
109 impl->m_Timer->stop();
116 impl->m_Timer->stop();
110 }
117 }
111 }
118 }
112
119
113 return false;
120 return false;
114 }
121 }
115
122
116 void DragDropScroller::onTimer()
123 void DragDropScroller::onTimer()
117 {
124 {
118 if (impl->m_CurrentScrollArea) {
125 if (impl->m_CurrentScrollArea) {
119 auto mvt = 0;
126 auto mvt = 0;
120 switch (impl->m_Direction) {
127 switch (impl->m_Direction) {
121 case DragDropScrollerPrivate::ScrollDirection::up:
128 case DragDropScrollerPrivate::ScrollDirection::up:
122 mvt = SCROLL_SPEED;
129 mvt = SCROLL_SPEED;
123 break;
130 break;
124 case DragDropScrollerPrivate::ScrollDirection::down:
131 case DragDropScrollerPrivate::ScrollDirection::down:
125 mvt = -SCROLL_SPEED;
132 mvt = -SCROLL_SPEED;
126 break;
133 break;
127 default:
134 default:
128 break;
135 break;
129 }
136 }
130
137
131 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
138 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
132 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
139 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
133 }
140 }
134 }
141 }
135
142
136 struct DragDropHelper::DragDropHelperPrivate {
143 struct DragDropHelper::DragDropHelperPrivate {
137
144
138 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
145 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
139 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
146 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
140 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
147 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
141 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
148 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
142 // QTemporaryFile to have a name which is not generated.
149 // QTemporaryFile to have a name which is not generated.
143
150
144 explicit DragDropHelperPrivate()
151 explicit DragDropHelperPrivate()
145 : m_PlaceHolder{std::make_unique<QWidget>()},
152 : m_PlaceHolder{std::make_unique<QWidget>()},
146 m_DragDropScroller{std::make_unique<DragDropScroller>()}
153 m_DragDropScroller{std::make_unique<DragDropScroller>()}
147 {
154 {
148 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
155 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
149 sqpApp->installEventFilter(m_DragDropScroller.get());
156 sqpApp->installEventFilter(m_DragDropScroller.get());
150
157
151
158
152 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
159 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
153 }
160 }
154
161
155 void preparePlaceHolder() const
162 void preparePlaceHolder() const
156 {
163 {
157 if (m_CurrentDragWidget) {
164 if (m_CurrentDragWidget) {
158 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
165 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
159 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
166 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
160 }
167 }
161 else {
168 else {
162 m_PlaceHolder->setMinimumSize(200, 200);
169 // Configuration of the placeHolder when there is no dragWidget
170 // (for instance with a drag from a variable)
171
172 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
173 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
163 }
174 }
164 }
175 }
165 };
176 };
166
177
167
178
168 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
179 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
169 {
180 {
170 }
181 }
171
182
172 DragDropHelper::~DragDropHelper()
183 DragDropHelper::~DragDropHelper()
173 {
184 {
174 QFile::remove(impl->m_ImageTempUrl);
185 QFile::remove(impl->m_ImageTempUrl);
175 }
186 }
176
187
188 void DragDropHelper::resetDragAndDrop()
189 {
190 setCurrentDragWidget(nullptr);
191 }
192
177 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
193 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
178 {
194 {
179 impl->m_CurrentDragWidget = dragWidget;
195 impl->m_CurrentDragWidget = dragWidget;
180 }
196 }
181
197
182 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
198 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
183 {
199 {
184 return impl->m_CurrentDragWidget;
200 return impl->m_CurrentDragWidget;
185 }
201 }
186
202
187
203
188 QWidget &DragDropHelper::placeHolder() const
204 QWidget &DragDropHelper::placeHolder() const
189 {
205 {
190 return *impl->m_PlaceHolder;
206 return *impl->m_PlaceHolder;
191 }
207 }
192
208
193 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
209 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
194 {
210 {
195 removePlaceHolder();
211 removePlaceHolder();
196 impl->preparePlaceHolder();
212 impl->preparePlaceHolder();
197 layout->insertWidget(index, impl->m_PlaceHolder.get());
213 layout->insertWidget(index, impl->m_PlaceHolder.get());
198 impl->m_PlaceHolder->show();
214 impl->m_PlaceHolder->show();
199 }
215 }
200
216
201 void DragDropHelper::removePlaceHolder()
217 void DragDropHelper::removePlaceHolder()
202 {
218 {
203 auto parentWidget = impl->m_PlaceHolder->parentWidget();
219 auto parentWidget = impl->m_PlaceHolder->parentWidget();
204 if (parentWidget) {
220 if (parentWidget) {
205 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
221 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
206 impl->m_PlaceHolder->setParent(nullptr);
222 impl->m_PlaceHolder->setParent(nullptr);
207 impl->m_PlaceHolder->hide();
223 impl->m_PlaceHolder->hide();
208 }
224 }
209 }
225 }
210
226
211 bool DragDropHelper::isPlaceHolderSet() const
227 bool DragDropHelper::isPlaceHolderSet() const
212 {
228 {
213 return impl->m_PlaceHolder->parentWidget();
229 return impl->m_PlaceHolder->parentWidget();
214 }
230 }
215
231
216 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
232 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
217 {
233 {
218 impl->m_DragDropScroller->addScrollArea(scrollArea);
234 impl->m_DragDropScroller->addScrollArea(scrollArea);
219 }
235 }
220
236
221 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
237 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
222 {
238 {
223 impl->m_DragDropScroller->removeScrollArea(scrollArea);
239 impl->m_DragDropScroller->removeScrollArea(scrollArea);
224 }
240 }
225
241
226 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
242 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
227 {
243 {
228 image.save(impl->m_ImageTempUrl);
244 image.save(impl->m_ImageTempUrl);
229 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
245 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
230 }
246 }
247
248 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
249 VisualizationDragDropContainer *dropContainer)
250 {
251 auto result = true;
252
253 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
254 auto variables = sqpApp->variableController().variablesForMimeData(
255 mimeData->data(MIME_TYPE_VARIABLE_LIST));
256
257 if (variables.count() == 1) {
258 // Check that the viariable is not already in a graph
259
260 // Search for the top level VisualizationWidget
261 auto parent = dropContainer->parentWidget();
262 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
263 parent = parent->parentWidget();
264 }
265
266 if (parent) {
267 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
268
269 FindVariableOperation findVariableOperation{variables.first()};
270 visualizationWidget->accept(&findVariableOperation);
271 auto variableContainers = findVariableOperation.result();
272 if (!variableContainers.empty()) {
273 result = false;
274 }
275 }
276 else {
277 qCWarning(LOG_DragDropHelper()) << QObject::tr(
278 "DragDropHelper::checkMimeDataForVisualization, the parent "
279 "VisualizationWidget cannot be found.");
280 result = false;
281 }
282 }
283 else {
284 result = false;
285 }
286 }
287
288 return result;
289 }
@@ -1,239 +1,245
1 #include <Variable/RenameVariableDialog.h>
1 #include <Variable/RenameVariableDialog.h>
2 #include <Variable/Variable.h>
2 #include <Variable/Variable.h>
3 #include <Variable/VariableController.h>
3 #include <Variable/VariableController.h>
4 #include <Variable/VariableInspectorWidget.h>
4 #include <Variable/VariableInspectorWidget.h>
5 #include <Variable/VariableMenuHeaderWidget.h>
5 #include <Variable/VariableMenuHeaderWidget.h>
6 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
7
7
8 #include <ui_VariableInspectorWidget.h>
8 #include <ui_VariableInspectorWidget.h>
9
9
10 #include <QMouseEvent>
10 #include <QMouseEvent>
11 #include <QSortFilterProxyModel>
11 #include <QSortFilterProxyModel>
12 #include <QStyledItemDelegate>
12 #include <QStyledItemDelegate>
13 #include <QWidgetAction>
13 #include <QWidgetAction>
14
14
15 #include <DragDropHelper.h>
15 #include <SqpApplication.h>
16 #include <SqpApplication.h>
16
17
17 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
18 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
18
19
19
20
20 class QProgressBarItemDelegate : public QStyledItemDelegate {
21 class QProgressBarItemDelegate : public QStyledItemDelegate {
21
22
22 public:
23 public:
23 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
24 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
24
25
25 void paint(QPainter *painter, const QStyleOptionViewItem &option,
26 void paint(QPainter *painter, const QStyleOptionViewItem &option,
26 const QModelIndex &index) const
27 const QModelIndex &index) const
27 {
28 {
28 auto data = index.data(Qt::DisplayRole);
29 auto data = index.data(Qt::DisplayRole);
29 auto progressData = index.data(VariableRoles::ProgressRole);
30 auto progressData = index.data(VariableRoles::ProgressRole);
30 if (data.isValid() && progressData.isValid()) {
31 if (data.isValid() && progressData.isValid()) {
31 auto name = data.value<QString>();
32 auto name = data.value<QString>();
32 auto progress = progressData.value<double>();
33 auto progress = progressData.value<double>();
33 if (progress > 0) {
34 if (progress > 0) {
34 auto cancelButtonWidth = 20;
35 auto cancelButtonWidth = 20;
35 auto progressBarOption = QStyleOptionProgressBar{};
36 auto progressBarOption = QStyleOptionProgressBar{};
36 auto progressRect = option.rect;
37 auto progressRect = option.rect;
37 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
38 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
38 progressBarOption.rect = progressRect;
39 progressBarOption.rect = progressRect;
39 progressBarOption.minimum = 0;
40 progressBarOption.minimum = 0;
40 progressBarOption.maximum = 100;
41 progressBarOption.maximum = 100;
41 progressBarOption.progress = progress;
42 progressBarOption.progress = progress;
42 progressBarOption.text
43 progressBarOption.text
43 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
44 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
44 progressBarOption.textVisible = true;
45 progressBarOption.textVisible = true;
45 progressBarOption.textAlignment = Qt::AlignCenter;
46 progressBarOption.textAlignment = Qt::AlignCenter;
46
47
47
48
48 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
49 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
49 painter);
50 painter);
50
51
51 // Cancel button
52 // Cancel button
52 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
53 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
53 option.rect.height());
54 option.rect.height());
54 auto buttonOption = QStyleOptionButton{};
55 auto buttonOption = QStyleOptionButton{};
55 buttonOption.rect = buttonRect;
56 buttonOption.rect = buttonRect;
56 buttonOption.text = "X";
57 buttonOption.text = "X";
57
58
58 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
59 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
59 }
60 }
60 else {
61 else {
61 QStyledItemDelegate::paint(painter, option, index);
62 QStyledItemDelegate::paint(painter, option, index);
62 }
63 }
63 }
64 }
64 else {
65 else {
65 QStyledItemDelegate::paint(painter, option, index);
66 QStyledItemDelegate::paint(painter, option, index);
66 }
67 }
67 }
68 }
68
69
69 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
70 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
70 const QModelIndex &index)
71 const QModelIndex &index)
71 {
72 {
72 if (event->type() == QEvent::MouseButtonRelease) {
73 if (event->type() == QEvent::MouseButtonRelease) {
73 auto data = index.data(Qt::DisplayRole);
74 auto data = index.data(Qt::DisplayRole);
74 auto progressData = index.data(VariableRoles::ProgressRole);
75 auto progressData = index.data(VariableRoles::ProgressRole);
75 if (data.isValid() && progressData.isValid()) {
76 if (data.isValid() && progressData.isValid()) {
76 auto cancelButtonWidth = 20;
77 auto cancelButtonWidth = 20;
77 auto progressRect = option.rect;
78 auto progressRect = option.rect;
78 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
79 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
79 // Cancel button
80 // Cancel button
80 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
81 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
81 option.rect.height());
82 option.rect.height());
82
83
83 auto e = (QMouseEvent *)event;
84 auto e = (QMouseEvent *)event;
84 auto clickX = e->x();
85 auto clickX = e->x();
85 auto clickY = e->y();
86 auto clickY = e->y();
86
87
87 auto x = buttonRect.left(); // the X coordinate
88 auto x = buttonRect.left(); // the X coordinate
88 auto y = buttonRect.top(); // the Y coordinate
89 auto y = buttonRect.top(); // the Y coordinate
89 auto w = buttonRect.width(); // button width
90 auto w = buttonRect.width(); // button width
90 auto h = buttonRect.height(); // button height
91 auto h = buttonRect.height(); // button height
91
92
92 if (clickX > x && clickX < x + w) {
93 if (clickX > x && clickX < x + w) {
93 if (clickY > y && clickY < y + h) {
94 if (clickY > y && clickY < y + h) {
94 auto variableModel = sqpApp->variableController().variableModel();
95 auto variableModel = sqpApp->variableController().variableModel();
95 variableModel->abortProgress(index);
96 variableModel->abortProgress(index);
96 }
97 }
97 return true;
98 return true;
98 }
99 }
99 else {
100 else {
100 return QStyledItemDelegate::editorEvent(event, model, option, index);
101 return QStyledItemDelegate::editorEvent(event, model, option, index);
101 }
102 }
102 }
103 }
103 else {
104 else {
104 return QStyledItemDelegate::editorEvent(event, model, option, index);
105 return QStyledItemDelegate::editorEvent(event, model, option, index);
105 }
106 }
106 }
107 }
107 else {
108 else {
108 return QStyledItemDelegate::editorEvent(event, model, option, index);
109 return QStyledItemDelegate::editorEvent(event, model, option, index);
109 }
110 }
110
111
111
112
112 return QStyledItemDelegate::editorEvent(event, model, option, index);
113 return QStyledItemDelegate::editorEvent(event, model, option, index);
113 }
114 }
114 };
115 };
115
116
116 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
117 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
117 : QWidget{parent},
118 : QWidget{parent},
118 ui{new Ui::VariableInspectorWidget},
119 ui{new Ui::VariableInspectorWidget},
119 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
120 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
120 {
121 {
121 ui->setupUi(this);
122 ui->setupUi(this);
122
123
123 // Sets model for table
124 // Sets model for table
124 // auto sortFilterModel = new QSortFilterProxyModel{this};
125 // auto sortFilterModel = new QSortFilterProxyModel{this};
125 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
126 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
126
127
127 auto variableModel = sqpApp->variableController().variableModel();
128 auto variableModel = sqpApp->variableController().variableModel();
128 ui->tableView->setModel(variableModel);
129 ui->tableView->setModel(variableModel);
129
130
130 // Adds extra signal/slot between view and model, so the view can be updated instantly when
131 // Adds extra signal/slot between view and model, so the view can be updated instantly when
131 // there is a change of data in the model
132 // there is a change of data in the model
132 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
133 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
133 SLOT(refresh()));
134 SLOT(refresh()));
134
135
135 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
136 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
136 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
137 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
137
138
138 // Fixes column sizes
139 // Fixes column sizes
139 auto model = ui->tableView->model();
140 auto model = ui->tableView->model();
140 const auto count = model->columnCount();
141 const auto count = model->columnCount();
141 for (auto i = 0; i < count; ++i) {
142 for (auto i = 0; i < count; ++i) {
142 ui->tableView->setColumnWidth(
143 ui->tableView->setColumnWidth(
143 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
144 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
144 }
145 }
145
146
146 // Sets selection options
147 // Sets selection options
147 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
148 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
148 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
149 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
149
150
150 // Connection to show a menu when right clicking on the tree
151 // Connection to show a menu when right clicking on the tree
151 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
152 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
152 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
153 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
153 &VariableInspectorWidget::onTableMenuRequested);
154 &VariableInspectorWidget::onTableMenuRequested);
155
156 // Resets the drag&drop operation on a left-click (the drag&drop is also started by a left
157 // click).
158 connect(ui->tableView, &QTableView::clicked,
159 [](const auto &modelIndex) { sqpApp->dragDropHelper().resetDragAndDrop(); });
154 }
160 }
155
161
156 VariableInspectorWidget::~VariableInspectorWidget()
162 VariableInspectorWidget::~VariableInspectorWidget()
157 {
163 {
158 delete ui;
164 delete ui;
159 }
165 }
160
166
161 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
167 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
162 {
168 {
163 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
169 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
164
170
165 // Gets the model to retrieve the underlying selected variables
171 // Gets the model to retrieve the underlying selected variables
166 auto model = sqpApp->variableController().variableModel();
172 auto model = sqpApp->variableController().variableModel();
167 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
173 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
168 for (const auto &selectedRow : qAsConst(selectedRows)) {
174 for (const auto &selectedRow : qAsConst(selectedRows)) {
169 if (auto selectedVariable = model->variable(selectedRow.row())) {
175 if (auto selectedVariable = model->variable(selectedRow.row())) {
170 selectedVariables.push_back(selectedVariable);
176 selectedVariables.push_back(selectedVariable);
171 }
177 }
172 }
178 }
173
179
174 QMenu tableMenu{};
180 QMenu tableMenu{};
175
181
176 // Emits a signal so that potential receivers can populate the menu before displaying it
182 // Emits a signal so that potential receivers can populate the menu before displaying it
177 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
183 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
178
184
179 // Adds menu-specific actions
185 // Adds menu-specific actions
180 if (!selectedVariables.isEmpty()) {
186 if (!selectedVariables.isEmpty()) {
181 tableMenu.addSeparator();
187 tableMenu.addSeparator();
182
188
183 // 'Rename' and 'Duplicate' actions (only if one variable selected)
189 // 'Rename' and 'Duplicate' actions (only if one variable selected)
184 if (selectedVariables.size() == 1) {
190 if (selectedVariables.size() == 1) {
185 auto selectedVariable = selectedVariables.front();
191 auto selectedVariable = selectedVariables.front();
186
192
187 auto duplicateFun = [varW = std::weak_ptr<Variable>(selectedVariable)]()
193 auto duplicateFun = [varW = std::weak_ptr<Variable>(selectedVariable)]()
188 {
194 {
189 if (auto var = varW.lock()) {
195 if (auto var = varW.lock()) {
190 sqpApp->variableController().cloneVariable(var);
196 sqpApp->variableController().cloneVariable(var);
191 }
197 }
192 };
198 };
193
199
194 tableMenu.addAction(tr("Duplicate"), duplicateFun);
200 tableMenu.addAction(tr("Duplicate"), duplicateFun);
195
201
196 auto renameFun = [ varW = std::weak_ptr<Variable>(selectedVariable), &model, this ]()
202 auto renameFun = [ varW = std::weak_ptr<Variable>(selectedVariable), &model, this ]()
197 {
203 {
198 if (auto var = varW.lock()) {
204 if (auto var = varW.lock()) {
199 // Generates forbidden names (names associated to existing variables)
205 // Generates forbidden names (names associated to existing variables)
200 auto allVariables = model->variables();
206 auto allVariables = model->variables();
201 auto forbiddenNames = QVector<QString>(allVariables.size());
207 auto forbiddenNames = QVector<QString>(allVariables.size());
202 std::transform(allVariables.cbegin(), allVariables.cend(),
208 std::transform(allVariables.cbegin(), allVariables.cend(),
203 forbiddenNames.begin(),
209 forbiddenNames.begin(),
204 [](const auto &variable) { return variable->name(); });
210 [](const auto &variable) { return variable->name(); });
205
211
206 RenameVariableDialog dialog{var->name(), forbiddenNames, this};
212 RenameVariableDialog dialog{var->name(), forbiddenNames, this};
207 if (dialog.exec() == QDialog::Accepted) {
213 if (dialog.exec() == QDialog::Accepted) {
208 var->setName(dialog.name());
214 var->setName(dialog.name());
209 }
215 }
210 }
216 }
211 };
217 };
212
218
213 tableMenu.addAction(tr("Rename..."), renameFun);
219 tableMenu.addAction(tr("Rename..."), renameFun);
214 }
220 }
215
221
216 // 'Delete' action
222 // 'Delete' action
217 auto deleteFun = [&selectedVariables]() {
223 auto deleteFun = [&selectedVariables]() {
218 sqpApp->variableController().deleteVariables(selectedVariables);
224 sqpApp->variableController().deleteVariables(selectedVariables);
219 };
225 };
220
226
221 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
227 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
222 }
228 }
223
229
224 if (!tableMenu.isEmpty()) {
230 if (!tableMenu.isEmpty()) {
225 // Generates menu header (inserted before first action)
231 // Generates menu header (inserted before first action)
226 auto firstAction = tableMenu.actions().first();
232 auto firstAction = tableMenu.actions().first();
227 auto headerAction = new QWidgetAction{&tableMenu};
233 auto headerAction = new QWidgetAction{&tableMenu};
228 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
234 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
229 tableMenu.insertAction(firstAction, headerAction);
235 tableMenu.insertAction(firstAction, headerAction);
230
236
231 // Displays menu
237 // Displays menu
232 tableMenu.exec(QCursor::pos());
238 tableMenu.exec(QCursor::pos());
233 }
239 }
234 }
240 }
235
241
236 void VariableInspectorWidget::refresh() noexcept
242 void VariableInspectorWidget::refresh() noexcept
237 {
243 {
238 ui->tableView->viewport()->update();
244 ui->tableView->viewport()->update();
239 }
245 }
@@ -1,302 +1,362
1 #include "Visualization/VisualizationDragDropContainer.h"
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragDropHelper.h"
2 #include "DragDropHelper.h"
3 #include "SqpApplication.h"
3 #include "SqpApplication.h"
4 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5
5
6 #include "Common/VisualizationDef.h"
7
6 #include <QDrag>
8 #include <QDrag>
7 #include <QDragEnterEvent>
9 #include <QDragEnterEvent>
8 #include <QVBoxLayout>
10 #include <QVBoxLayout>
9
11
10 #include <cmath>
12 #include <cmath>
11 #include <memory>
13 #include <memory>
12
14
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
16
13 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
17 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
14
18
15 QVBoxLayout *m_Layout;
19 QVBoxLayout *m_Layout;
16 QStringList m_AcceptedMimeTypes;
20 QStringList m_AcceptedMimeTypes;
17 QStringList m_MergeAllowedMimeTypes;
21 QStringList m_MergeAllowedMimeTypes;
22 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
23 = [](auto mimeData) { return true; };
18
24
19 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
25 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
20 {
26 {
21 m_Layout = new QVBoxLayout(widget);
27 m_Layout = new QVBoxLayout(widget);
22 m_Layout->setContentsMargins(0, 0, 0, 0);
28 m_Layout->setContentsMargins(0, 0, 0, 0);
23 }
29 }
24
30
25 bool acceptMimeData(const QMimeData *data) const
31 bool acceptMimeData(const QMimeData *data) const
26 {
32 {
27 for (const auto &type : m_AcceptedMimeTypes) {
33 for (const auto &type : m_AcceptedMimeTypes) {
28 if (data->hasFormat(type)) {
34 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
29 return true;
35 return true;
30 }
36 }
31 }
37 }
32
38
33 return false;
39 return false;
34 }
40 }
35
41
36 bool allowMergeMimeData(const QMimeData *data) const
42 bool allowMergeMimeData(const QMimeData *data) const
37 {
43 {
38 for (const auto &type : m_MergeAllowedMimeTypes) {
44 for (const auto &type : m_MergeAllowedMimeTypes) {
39 if (data->hasFormat(type)) {
45 if (data->hasFormat(type)) {
40 return true;
46 return true;
41 }
47 }
42 }
48 }
43
49
44 return false;
50 return false;
45 }
51 }
46
52
47 bool hasPlaceHolder() const
53 bool hasPlaceHolder() const
48 {
54 {
49 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
55 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
50 }
56 }
51
57
52 VisualizationDragWidget *getChildDragWidgetAt(QWidget *parent, const QPoint &pos) const
58 VisualizationDragWidget *getChildDragWidgetAt(QWidget *parent, const QPoint &pos) const
53 {
59 {
54 VisualizationDragWidget *dragWidget = nullptr;
60 VisualizationDragWidget *dragWidget = nullptr;
55
61
56 for (auto child : parent->children()) {
62 for (auto child : parent->children()) {
57 auto widget = qobject_cast<VisualizationDragWidget *>(child);
63 auto widget = qobject_cast<VisualizationDragWidget *>(child);
58 if (widget && widget->isVisible()) {
64 if (widget && widget->isVisible()) {
59 if (widget->frameGeometry().contains(pos)) {
65 if (widget->frameGeometry().contains(pos)) {
60 dragWidget = widget;
66 dragWidget = widget;
61 break;
67 break;
62 }
68 }
63 }
69 }
64 }
70 }
65
71
66 return dragWidget;
72 return dragWidget;
67 }
73 }
68
74
69 bool cursorIsInContainer(QWidget *container) const
75 bool cursorIsInContainer(QWidget *container) const
70 {
76 {
71 auto adustNum = 18; // to be safe, in case of scrollbar on the side
77 auto adustNum = 18; // to be safe, in case of scrollbar on the side
72 auto containerRect = QRect(QPoint(), container->contentsRect().size())
78 auto containerRect = QRect(QPoint(), container->contentsRect().size())
73 .adjusted(adustNum, adustNum, -adustNum, -adustNum);
79 .adjusted(adustNum, adustNum, -adustNum, -adustNum);
74 return containerRect.contains(container->mapFromGlobal(QCursor::pos()));
80 return containerRect.contains(container->mapFromGlobal(QCursor::pos()));
75 }
81 }
76 };
82 };
77
83
78 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
84 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
79 : QWidget{parent},
85 : QWidget{parent},
80 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
86 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
81 {
87 {
82 setAcceptDrops(true);
88 setAcceptDrops(true);
83 }
89 }
84
90
85 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
91 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
86 {
92 {
87 impl->m_Layout->addWidget(dragWidget);
93 impl->m_Layout->addWidget(dragWidget);
88 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
94 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
89 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
95 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
90 &VisualizationDragDropContainer::startDrag);
96 &VisualizationDragDropContainer::startDrag);
91 }
97 }
92
98
93 void VisualizationDragDropContainer::insertDragWidget(int index,
99 void VisualizationDragDropContainer::insertDragWidget(int index,
94 VisualizationDragWidget *dragWidget)
100 VisualizationDragWidget *dragWidget)
95 {
101 {
96 impl->m_Layout->insertWidget(index, dragWidget);
102 impl->m_Layout->insertWidget(index, dragWidget);
97 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
103 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
98 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
104 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
99 &VisualizationDragDropContainer::startDrag);
105 &VisualizationDragDropContainer::startDrag);
100 }
106 }
101
107
102 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
108 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
103 {
109 {
104 impl->m_AcceptedMimeTypes = mimeTypes;
110 impl->m_AcceptedMimeTypes = mimeTypes;
105 }
111 }
106
112
107 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
113 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
108 {
114 {
109 impl->m_MergeAllowedMimeTypes = mimeTypes;
115 impl->m_MergeAllowedMimeTypes = mimeTypes;
110 }
116 }
111
117
112 int VisualizationDragDropContainer::countDragWidget() const
118 int VisualizationDragDropContainer::countDragWidget() const
113 {
119 {
114 auto nbGraph = 0;
120 auto nbGraph = 0;
115 for (auto child : children()) {
121 for (auto child : children()) {
116 if (qobject_cast<VisualizationDragWidget *>(child)) {
122 if (qobject_cast<VisualizationDragWidget *>(child)) {
117 nbGraph += 1;
123 nbGraph += 1;
118 }
124 }
119 }
125 }
120
126
121 return nbGraph;
127 return nbGraph;
122 }
128 }
123
129
130 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
131 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
132 {
133 impl->m_AcceptMimeDataFun = fun;
134 }
135
124 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
136 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
125 const QPoint &dragPosition)
137 const QPoint &dragPosition)
126 {
138 {
127 auto &helper = sqpApp->dragDropHelper();
139 auto &helper = sqpApp->dragDropHelper();
140 helper.resetDragAndDrop();
128
141
129 // Note: The management of the drag object is done by Qt
142 // Note: The management of the drag object is done by Qt
130 auto drag = new QDrag{dragWidget};
143 auto drag = new QDrag{dragWidget};
131 drag->setHotSpot(dragPosition);
144 drag->setHotSpot(dragPosition);
132
145
133 auto mimeData = dragWidget->mimeData();
146 auto mimeData = dragWidget->mimeData();
134 drag->setMimeData(mimeData);
147 drag->setMimeData(mimeData);
135
148
136 auto pixmap = QPixmap(dragWidget->size());
149 auto pixmap = QPixmap(dragWidget->size());
137 dragWidget->render(&pixmap);
150 dragWidget->render(&pixmap);
138 drag->setPixmap(pixmap);
151 drag->setPixmap(pixmap);
139
152
140 auto image = pixmap.toImage();
153 auto image = pixmap.toImage();
141 mimeData->setImageData(image);
154 mimeData->setImageData(image);
142 mimeData->setUrls({helper.imageTemporaryUrl(image)});
155 mimeData->setUrls({helper.imageTemporaryUrl(image)});
143
156
144 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
157 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
145 helper.setCurrentDragWidget(dragWidget);
158 helper.setCurrentDragWidget(dragWidget);
146
159
147 if (impl->cursorIsInContainer(this)) {
160 if (impl->cursorIsInContainer(this)) {
148 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
161 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
149 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
162 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
150 dragWidget->setVisible(false);
163 dragWidget->setVisible(false);
151 }
164 }
152 }
153
165
154 // Note: The exec() is blocking on windows but not on linux and macOS
166 // Note: The exec() is blocking on windows but not on linux and macOS
155 drag->exec(Qt::MoveAction | Qt::CopyAction);
167 drag->exec(Qt::MoveAction | Qt::CopyAction);
168 }
169 else {
170 qCWarning(LOG_VisualizationDragDropContainer())
171 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
172 "VisualizationDragWidget is not found in this container.");
173 }
156 }
174 }
157
175
158 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
176 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
159 {
177 {
160 if (impl->acceptMimeData(event->mimeData())) {
178 if (impl->acceptMimeData(event->mimeData())) {
161 event->acceptProposedAction();
179 event->acceptProposedAction();
162
180
163 auto &helper = sqpApp->dragDropHelper();
181 auto &helper = sqpApp->dragDropHelper();
164
182
165 if (!impl->hasPlaceHolder()) {
183 if (!impl->hasPlaceHolder()) {
166 auto dragWidget = helper.getCurrentDragWidget();
184 auto dragWidget = helper.getCurrentDragWidget();
167 auto parentWidget
185
168 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
186 if (dragWidget) {
169 if (parentWidget) {
187 // If the drag&drop is internal to the visualization, entering the container hide
170 dragWidget->setVisible(false);
188 // the dragWidget which was hidden by the dragLeaveEvent
189 auto parentWidget
190 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
191 if (parentWidget) {
192 dragWidget->setVisible(false);
193 }
171 }
194 }
172
195
173 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
196 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
174
197
175 if (dragWidgetHovered) {
198 if (dragWidgetHovered) {
176 auto hoveredWidgetIndex = impl->m_Layout->indexOf(dragWidgetHovered);
199 auto hoveredWidgetIndex = impl->m_Layout->indexOf(dragWidgetHovered);
177 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
200
178 if (dragWidgetIndex >= 0 && dragWidgetIndex <= hoveredWidgetIndex) {
201 if (dragWidget) {
179 hoveredWidgetIndex
202 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
180 += 1; // Correction of the index if the drop occurs in the same container
203 if (dragWidgetIndex >= 0 && dragWidgetIndex <= hoveredWidgetIndex) {
204 // Correction of the index if the drop occurs in the same container
205 // and if the drag is started from the visualization (in that case, the
206 // dragWidget is hidden)
207 hoveredWidgetIndex += 1;
208 }
181 }
209 }
182
210
183 helper.insertPlaceHolder(impl->m_Layout, hoveredWidgetIndex);
211 helper.insertPlaceHolder(impl->m_Layout, hoveredWidgetIndex);
184 }
212 }
185 else {
213 else {
186 helper.insertPlaceHolder(impl->m_Layout, 0);
214 helper.insertPlaceHolder(impl->m_Layout, 0);
187 }
215 }
188 }
216 }
217 else {
218 // do nothing
219 }
189 }
220 }
190 else {
221 else {
191 event->ignore();
222 event->ignore();
192 }
223 }
193
224
194 QWidget::dragEnterEvent(event);
225 QWidget::dragEnterEvent(event);
195 }
226 }
196
227
197 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
228 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
198 {
229 {
199 Q_UNUSED(event);
230 Q_UNUSED(event);
200
231
201 auto &helper = sqpApp->dragDropHelper();
232 auto &helper = sqpApp->dragDropHelper();
202
233
203 if (!impl->cursorIsInContainer(this)) {
234 if (!impl->cursorIsInContainer(this)) {
204 helper.removePlaceHolder();
235 helper.removePlaceHolder();
205
236
206 bool isInternal = true;
237 auto dragWidget = helper.getCurrentDragWidget();
207 if (isInternal) {
238 if (dragWidget) {
208 // Only if the drag is started from the visualization
239 // dragWidget has a value only if the drag is started from the visualization
209 // Show the drag widget at its original place
240 // In that case, shows the drag widget at its original place
210 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
241 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
211 // drop zone (It is not possible to catch a drop event outside of the application)
242 // drop zone (It is not possible to catch a drop event outside of the application)
212
243
213 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
214 if (dragWidget) {
244 if (dragWidget) {
215 dragWidget->setVisible(true);
245 dragWidget->setVisible(true);
216 }
246 }
217 }
247 }
218 }
248 }
249 else {
250 // Leave event probably received for a child widget.
251 // Do nothing.
252 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
253 }
219
254
220 QWidget::dragLeaveEvent(event);
255 QWidget::dragLeaveEvent(event);
221 }
256 }
222
257
223 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
258 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
224 {
259 {
225 if (impl->acceptMimeData(event->mimeData())) {
260 if (impl->acceptMimeData(event->mimeData())) {
226 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
261 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
227 if (dragWidgetHovered) {
262 if (dragWidgetHovered) {
228 auto canMerge = impl->allowMergeMimeData(event->mimeData());
263 auto canMerge = impl->allowMergeMimeData(event->mimeData());
229
264
230 auto nbDragWidget = countDragWidget();
265 auto nbDragWidget = countDragWidget();
231 if (nbDragWidget > 0) {
266 if (nbDragWidget > 0) {
232 auto graphHeight = size().height() / nbDragWidget;
267 auto graphHeight = qMax(size().height() / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
268
233 auto dropIndex = floor(event->pos().y() / graphHeight);
269 auto dropIndex = floor(event->pos().y() / graphHeight);
234 auto zoneSize = qMin(graphHeight / 3.0, 150.0);
270 auto zoneSize = qMin(graphHeight / 3.0, 150.0);
235
271
236 auto isOnTop = event->pos().y() < dropIndex * graphHeight + zoneSize;
272 auto isOnTop = event->pos().y() < dropIndex * graphHeight + zoneSize;
237 auto isOnBottom = event->pos().y() > (dropIndex + 1) * graphHeight - zoneSize;
273 auto isOnBottom = event->pos().y() > (dropIndex + 1) * graphHeight - zoneSize;
238
274
239 auto &helper = sqpApp->dragDropHelper();
275 auto &helper = sqpApp->dragDropHelper();
240 auto placeHolderIndex = impl->m_Layout->indexOf(&(helper.placeHolder()));
276 auto placeHolderIndex = impl->m_Layout->indexOf(&(helper.placeHolder()));
241
277
242 if (isOnTop || isOnBottom) {
278 if (isOnTop || isOnBottom) {
243 if (isOnBottom) {
279 if (isOnBottom) {
244 dropIndex += 1;
280 dropIndex += 1;
245 }
281 }
246
282
247 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
283 if (helper.getCurrentDragWidget()) {
248 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
284 auto dragWidgetIndex
249 dropIndex += 1; // Correction of the index if the drop occurs in the same
285 = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
250 // container
286 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
287 // Correction of the index if the drop occurs in the same container
288 // and if the drag is started from the visualization (in that case, the
289 // dragWidget is hidden)
290 dropIndex += 1;
291 }
251 }
292 }
252
293
253 if (dropIndex != placeHolderIndex) {
294 if (dropIndex != placeHolderIndex) {
254 helper.insertPlaceHolder(impl->m_Layout, dropIndex);
295 helper.insertPlaceHolder(impl->m_Layout, dropIndex);
255 }
296 }
256 }
297 }
257 else if (canMerge) {
298 else if (canMerge) {
258 // drop on the middle -> merge
299 // drop on the middle -> merge
259 if (impl->hasPlaceHolder()) {
300 if (impl->hasPlaceHolder()) {
260 helper.removePlaceHolder();
301 helper.removePlaceHolder();
261 }
302 }
262 }
303 }
263 }
304 }
305 else {
306 qCWarning(LOG_VisualizationDragDropContainer())
307 << tr("VisualizationDragDropContainer::dragMoveEvent, no widget found in the "
308 "container");
309 }
310 }
311 else {
312 // No hovered drag widget, the mouse is probably hover the placeHolder
313 // Do nothing
264 }
314 }
265 }
315 }
266 else {
316 else {
267 event->ignore();
317 event->ignore();
268 }
318 }
269
319
270 QWidget::dragMoveEvent(event);
320 QWidget::dragMoveEvent(event);
271 }
321 }
272
322
273 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
323 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
274 {
324 {
275 if (impl->acceptMimeData(event->mimeData())) {
325 if (impl->acceptMimeData(event->mimeData())) {
276 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
326 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
277 if (impl->hasPlaceHolder() && dragWidget) {
327 if (impl->hasPlaceHolder()) {
278 auto &helper = sqpApp->dragDropHelper();
328 auto &helper = sqpApp->dragDropHelper();
279
329
280 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
330 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
281
331
282 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
332 if (dragWidget) {
283 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
333 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
284 droppedIndex
334 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
285 -= 1; // Correction of the index if the drop occurs in the same container
335 // Correction of the index if the drop occurs in the same container
286 }
336 // and if the drag is started from the visualization (in that case, the
337 // dragWidget is hidden)
338 droppedIndex -= 1;
339 }
287
340
288 dragWidget->setVisible(true);
341 dragWidget->setVisible(true);
342 }
289
343
290 event->acceptProposedAction();
344 event->acceptProposedAction();
291
345
292 helper.removePlaceHolder();
346 helper.removePlaceHolder();
293
347
294 emit dropOccured(droppedIndex, event->mimeData());
348 emit dropOccured(droppedIndex, event->mimeData());
295 }
349 }
350 else {
351 qCWarning(LOG_VisualizationDragDropContainer())
352 << tr("VisualizationDragDropContainer::dropEvent, couldn't drop because the "
353 "placeHolder is not found.");
354 Q_ASSERT(false);
355 }
296 }
356 }
297 else {
357 else {
298 event->ignore();
358 event->ignore();
299 }
359 }
300
360
301 QWidget::dropEvent(event);
361 QWidget::dropEvent(event);
302 }
362 }
@@ -1,384 +1,385
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationDefs.h"
3 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationGraphHelper.h"
4 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
8
8
9 #include <Common/MimeTypesDef.h>
9 #include <Data/ArrayData.h>
10 #include <Data/ArrayData.h>
10 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
11 #include <DragDropHelper.h>
12 #include <DragDropHelper.h>
12 #include <Settings/SqpSettingsDefs.h>
13 #include <Settings/SqpSettingsDefs.h>
13 #include <SqpApplication.h>
14 #include <SqpApplication.h>
14 #include <Variable/Variable.h>
15 #include <Variable/Variable.h>
15 #include <Variable/VariableController.h>
16 #include <Variable/VariableController.h>
16
17
17 #include <unordered_map>
18 #include <unordered_map>
18
19
19 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
20 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
20
21
21 namespace {
22 namespace {
22
23
23 /// Key pressed to enable zoom on horizontal axis
24 /// Key pressed to enable zoom on horizontal axis
24 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
25 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
25
26
26 /// Key pressed to enable zoom on vertical axis
27 /// Key pressed to enable zoom on vertical axis
27 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
28 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
28
29
29 } // namespace
30 } // namespace
30
31
31 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
32 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
32
33
33 explicit VisualizationGraphWidgetPrivate(const QString &name)
34 explicit VisualizationGraphWidgetPrivate(const QString &name)
34 : m_Name{name},
35 : m_Name{name},
35 m_DoAcquisition{true},
36 m_DoAcquisition{true},
36 m_IsCalibration{false},
37 m_IsCalibration{false},
37 m_RenderingDelegate{nullptr}
38 m_RenderingDelegate{nullptr}
38 {
39 {
39 }
40 }
40
41
41 QString m_Name;
42 QString m_Name;
42 // 1 variable -> n qcpplot
43 // 1 variable -> n qcpplot
43 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
44 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
44 bool m_DoAcquisition;
45 bool m_DoAcquisition;
45 bool m_IsCalibration;
46 bool m_IsCalibration;
46 QCPItemTracer *m_TextTracer;
47 QCPItemTracer *m_TextTracer;
47 /// Delegate used to attach rendering features to the plot
48 /// Delegate used to attach rendering features to the plot
48 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
49 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
49 };
50 };
50
51
51 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
52 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
52 : VisualizationDragWidget{parent},
53 : VisualizationDragWidget{parent},
53 ui{new Ui::VisualizationGraphWidget},
54 ui{new Ui::VisualizationGraphWidget},
54 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
55 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
55 {
56 {
56 ui->setupUi(this);
57 ui->setupUi(this);
57
58
58 // 'Close' options : widget is deleted when closed
59 // 'Close' options : widget is deleted when closed
59 setAttribute(Qt::WA_DeleteOnClose);
60 setAttribute(Qt::WA_DeleteOnClose);
60
61
61 // Set qcpplot properties :
62 // Set qcpplot properties :
62 // - Drag (on x-axis) and zoom are enabled
63 // - Drag (on x-axis) and zoom are enabled
63 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
64 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
64 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
65 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
65 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
66 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
66
67
67 // The delegate must be initialized after the ui as it uses the plot
68 // The delegate must be initialized after the ui as it uses the plot
68 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
69 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
69
70
70 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
71 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
71 connect(ui->widget, &QCustomPlot::mouseRelease, this,
72 connect(ui->widget, &QCustomPlot::mouseRelease, this,
72 &VisualizationGraphWidget::onMouseRelease);
73 &VisualizationGraphWidget::onMouseRelease);
73 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
74 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
74 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
75 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
75 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
76 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
76 &QCPAxis::rangeChanged),
77 &QCPAxis::rangeChanged),
77 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
78 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
78
79
79 // Activates menu when right clicking on the graph
80 // Activates menu when right clicking on the graph
80 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
81 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
81 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
82 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
82 &VisualizationGraphWidget::onGraphMenuRequested);
83 &VisualizationGraphWidget::onGraphMenuRequested);
83
84
84 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
85 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
85 &VariableController::onRequestDataLoading);
86 &VariableController::onRequestDataLoading);
86
87
87 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
88 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
88 &VisualizationGraphWidget::onUpdateVarDisplaying);
89 &VisualizationGraphWidget::onUpdateVarDisplaying);
89 }
90 }
90
91
91
92
92 VisualizationGraphWidget::~VisualizationGraphWidget()
93 VisualizationGraphWidget::~VisualizationGraphWidget()
93 {
94 {
94 delete ui;
95 delete ui;
95 }
96 }
96
97
97 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
98 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
98 {
99 {
99 auto parent = parentWidget();
100 auto parent = parentWidget();
100 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
101 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
101 parent = parent->parentWidget();
102 parent = parent->parentWidget();
102 }
103 }
103
104
104 return qobject_cast<VisualizationZoneWidget *>(parent);
105 return qobject_cast<VisualizationZoneWidget *>(parent);
105 }
106 }
106
107
107 void VisualizationGraphWidget::enableAcquisition(bool enable)
108 void VisualizationGraphWidget::enableAcquisition(bool enable)
108 {
109 {
109 impl->m_DoAcquisition = enable;
110 impl->m_DoAcquisition = enable;
110 }
111 }
111
112
112 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
113 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
113 {
114 {
114 // Uses delegate to create the qcpplot components according to the variable
115 // Uses delegate to create the qcpplot components according to the variable
115 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
116 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
116 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
117 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
117
118
118 // Set axes properties according to the units of the data series
119 // Set axes properties according to the units of the data series
119 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
120 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
120 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
121 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
121 auto xAxisUnit = Unit{};
122 auto xAxisUnit = Unit{};
122 auto valuesUnit = Unit{};
123 auto valuesUnit = Unit{};
123
124
124 if (auto dataSeries = variable->dataSeries()) {
125 if (auto dataSeries = variable->dataSeries()) {
125 dataSeries->lockRead();
126 dataSeries->lockRead();
126 xAxisUnit = dataSeries->xAxisUnit();
127 xAxisUnit = dataSeries->xAxisUnit();
127 valuesUnit = dataSeries->valuesUnit();
128 valuesUnit = dataSeries->valuesUnit();
128 dataSeries->unlock();
129 dataSeries->unlock();
129 }
130 }
130 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
131 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
131
132
132 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
133 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
133
134
134 this->enableAcquisition(false);
135 this->enableAcquisition(false);
135 this->setGraphRange(range);
136 this->setGraphRange(range);
136 this->enableAcquisition(true);
137 this->enableAcquisition(true);
137
138
138 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
139 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
139
140
140 emit variableAdded(variable);
141 emit variableAdded(variable);
141 }
142 }
142
143
143 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
144 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
144 {
145 {
145 // Each component associated to the variable :
146 // Each component associated to the variable :
146 // - is removed from qcpplot (which deletes it)
147 // - is removed from qcpplot (which deletes it)
147 // - is no longer referenced in the map
148 // - is no longer referenced in the map
148 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
149 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
149 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
150 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
150 emit variableAboutToBeRemoved(variable);
151 emit variableAboutToBeRemoved(variable);
151
152
152 auto &plottablesMap = variableIt->second;
153 auto &plottablesMap = variableIt->second;
153
154
154 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
155 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
155 plottableIt != plottableEnd;) {
156 plottableIt != plottableEnd;) {
156 ui->widget->removePlottable(plottableIt->second);
157 ui->widget->removePlottable(plottableIt->second);
157 plottableIt = plottablesMap.erase(plottableIt);
158 plottableIt = plottablesMap.erase(plottableIt);
158 }
159 }
159
160
160 impl->m_VariableToPlotMultiMap.erase(variableIt);
161 impl->m_VariableToPlotMultiMap.erase(variableIt);
161 }
162 }
162
163
163 // Updates graph
164 // Updates graph
164 ui->widget->replot();
165 ui->widget->replot();
165 }
166 }
166
167
167 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
168 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
168 {
169 {
169 auto variables = QList<std::shared_ptr<Variable> >{};
170 auto variables = QList<std::shared_ptr<Variable> >{};
170 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
171 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
171 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
172 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
172 variables << it->first;
173 variables << it->first;
173 }
174 }
174
175
175 return variables;
176 return variables;
176 }
177 }
177
178
178 void VisualizationGraphWidget::setYRange(const SqpRange &range)
179 void VisualizationGraphWidget::setYRange(const SqpRange &range)
179 {
180 {
180 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
181 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
181 }
182 }
182
183
183 SqpRange VisualizationGraphWidget::graphRange() const noexcept
184 SqpRange VisualizationGraphWidget::graphRange() const noexcept
184 {
185 {
185 auto graphRange = ui->widget->xAxis->range();
186 auto graphRange = ui->widget->xAxis->range();
186 return SqpRange{graphRange.lower, graphRange.upper};
187 return SqpRange{graphRange.lower, graphRange.upper};
187 }
188 }
188
189
189 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
190 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
190 {
191 {
191 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
192 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
192 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
193 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
193 ui->widget->replot();
194 ui->widget->replot();
194 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
195 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
195 }
196 }
196
197
197 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
198 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
198 {
199 {
199 if (visitor) {
200 if (visitor) {
200 visitor->visit(this);
201 visitor->visit(this);
201 }
202 }
202 else {
203 else {
203 qCCritical(LOG_VisualizationGraphWidget())
204 qCCritical(LOG_VisualizationGraphWidget())
204 << tr("Can't visit widget : the visitor is null");
205 << tr("Can't visit widget : the visitor is null");
205 }
206 }
206 }
207 }
207
208
208 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
209 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
209 {
210 {
210 /// @todo : for the moment, a graph can always accomodate a variable
211 /// @todo : for the moment, a graph can always accomodate a variable
211 Q_UNUSED(variable);
212 Q_UNUSED(variable);
212 return true;
213 return true;
213 }
214 }
214
215
215 bool VisualizationGraphWidget::contains(const Variable &variable) const
216 bool VisualizationGraphWidget::contains(const Variable &variable) const
216 {
217 {
217 // Finds the variable among the keys of the map
218 // Finds the variable among the keys of the map
218 auto variablePtr = &variable;
219 auto variablePtr = &variable;
219 auto findVariable
220 auto findVariable
220 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
221 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
221
222
222 auto end = impl->m_VariableToPlotMultiMap.cend();
223 auto end = impl->m_VariableToPlotMultiMap.cend();
223 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
224 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
224 return it != end;
225 return it != end;
225 }
226 }
226
227
227 QString VisualizationGraphWidget::name() const
228 QString VisualizationGraphWidget::name() const
228 {
229 {
229 return impl->m_Name;
230 return impl->m_Name;
230 }
231 }
231
232
232 QMimeData *VisualizationGraphWidget::mimeData() const
233 QMimeData *VisualizationGraphWidget::mimeData() const
233 {
234 {
234 auto mimeData = new QMimeData;
235 auto mimeData = new QMimeData;
235 mimeData->setData(DragDropHelper::MIME_TYPE_GRAPH, QByteArray());
236 mimeData->setData(MIME_TYPE_GRAPH, QByteArray());
236
237
237 return mimeData;
238 return mimeData;
238 }
239 }
239
240
240 bool VisualizationGraphWidget::isDragAllowed() const
241 bool VisualizationGraphWidget::isDragAllowed() const
241 {
242 {
242 return true;
243 return true;
243 }
244 }
244
245
245 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
246 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
246 {
247 {
247 Q_UNUSED(event);
248 Q_UNUSED(event);
248
249
249 // Prevents that all variables will be removed from graph when it will be closed
250 // Prevents that all variables will be removed from graph when it will be closed
250 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
251 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
251 emit variableAboutToBeRemoved(variableEntry.first);
252 emit variableAboutToBeRemoved(variableEntry.first);
252 }
253 }
253 }
254 }
254
255
255 void VisualizationGraphWidget::enterEvent(QEvent *event)
256 void VisualizationGraphWidget::enterEvent(QEvent *event)
256 {
257 {
257 Q_UNUSED(event);
258 Q_UNUSED(event);
258 impl->m_RenderingDelegate->showGraphOverlay(true);
259 impl->m_RenderingDelegate->showGraphOverlay(true);
259 }
260 }
260
261
261 void VisualizationGraphWidget::leaveEvent(QEvent *event)
262 void VisualizationGraphWidget::leaveEvent(QEvent *event)
262 {
263 {
263 Q_UNUSED(event);
264 Q_UNUSED(event);
264 impl->m_RenderingDelegate->showGraphOverlay(false);
265 impl->m_RenderingDelegate->showGraphOverlay(false);
265 }
266 }
266
267
267 QCustomPlot &VisualizationGraphWidget::plot() noexcept
268 QCustomPlot &VisualizationGraphWidget::plot() noexcept
268 {
269 {
269 return *ui->widget;
270 return *ui->widget;
270 }
271 }
271
272
272 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
273 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
273 {
274 {
274 QMenu graphMenu{};
275 QMenu graphMenu{};
275
276
276 // Iterates on variables (unique keys)
277 // Iterates on variables (unique keys)
277 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
278 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
278 end = impl->m_VariableToPlotMultiMap.cend();
279 end = impl->m_VariableToPlotMultiMap.cend();
279 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
280 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
280 // 'Remove variable' action
281 // 'Remove variable' action
281 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
282 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
282 [ this, var = it->first ]() { removeVariable(var); });
283 [ this, var = it->first ]() { removeVariable(var); });
283 }
284 }
284
285
285 if (!graphMenu.isEmpty()) {
286 if (!graphMenu.isEmpty()) {
286 graphMenu.exec(QCursor::pos());
287 graphMenu.exec(QCursor::pos());
287 }
288 }
288 }
289 }
289
290
290 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
291 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
291 {
292 {
292 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
293 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
293 << QThread::currentThread()->objectName() << "DoAcqui"
294 << QThread::currentThread()->objectName() << "DoAcqui"
294 << impl->m_DoAcquisition;
295 << impl->m_DoAcquisition;
295
296
296 auto graphRange = SqpRange{t1.lower, t1.upper};
297 auto graphRange = SqpRange{t1.lower, t1.upper};
297 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
298 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
298
299
299 if (impl->m_DoAcquisition) {
300 if (impl->m_DoAcquisition) {
300 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
301 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
301
302
302 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
303 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
303 end = impl->m_VariableToPlotMultiMap.end();
304 end = impl->m_VariableToPlotMultiMap.end();
304 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
305 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
305 variableUnderGraphVector.push_back(it->first);
306 variableUnderGraphVector.push_back(it->first);
306 }
307 }
307 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
308 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
308 !impl->m_IsCalibration);
309 !impl->m_IsCalibration);
309
310
310 if (!impl->m_IsCalibration) {
311 if (!impl->m_IsCalibration) {
311 qCDebug(LOG_VisualizationGraphWidget())
312 qCDebug(LOG_VisualizationGraphWidget())
312 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
313 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
313 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
314 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
314 emit synchronize(graphRange, oldGraphRange);
315 emit synchronize(graphRange, oldGraphRange);
315 }
316 }
316 }
317 }
317 }
318 }
318
319
319 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
320 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
320 {
321 {
321 // Handles plot rendering when mouse is moving
322 // Handles plot rendering when mouse is moving
322 impl->m_RenderingDelegate->onMouseMove(event);
323 impl->m_RenderingDelegate->onMouseMove(event);
323
324
324 VisualizationDragWidget::mouseMoveEvent(event);
325 VisualizationDragWidget::mouseMoveEvent(event);
325 }
326 }
326
327
327 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
328 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
328 {
329 {
329 auto zoomOrientations = QFlags<Qt::Orientation>{};
330 auto zoomOrientations = QFlags<Qt::Orientation>{};
330
331
331 // Lambda that enables a zoom orientation if the key modifier related to this orientation
332 // Lambda that enables a zoom orientation if the key modifier related to this orientation
332 // has
333 // has
333 // been pressed
334 // been pressed
334 auto enableOrientation
335 auto enableOrientation
335 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
336 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
336 auto orientationEnabled = event->modifiers().testFlag(modifier);
337 auto orientationEnabled = event->modifiers().testFlag(modifier);
337 zoomOrientations.setFlag(orientation, orientationEnabled);
338 zoomOrientations.setFlag(orientation, orientationEnabled);
338 };
339 };
339 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
340 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
340 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
341 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
341
342
342 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
343 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
343 }
344 }
344
345
345 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
346 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
346 {
347 {
347 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
348 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
348
349
349 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
350 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
350
351
351 VisualizationDragWidget::mousePressEvent(event);
352 VisualizationDragWidget::mousePressEvent(event);
352 }
353 }
353
354
354 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
355 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
355 {
356 {
356 impl->m_IsCalibration = false;
357 impl->m_IsCalibration = false;
357 }
358 }
358
359
359 void VisualizationGraphWidget::onDataCacheVariableUpdated()
360 void VisualizationGraphWidget::onDataCacheVariableUpdated()
360 {
361 {
361 auto graphRange = ui->widget->xAxis->range();
362 auto graphRange = ui->widget->xAxis->range();
362 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
363 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
363
364
364 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
365 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
365 auto variable = variableEntry.first;
366 auto variable = variableEntry.first;
366 qCDebug(LOG_VisualizationGraphWidget())
367 qCDebug(LOG_VisualizationGraphWidget())
367 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
368 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
368 qCDebug(LOG_VisualizationGraphWidget())
369 qCDebug(LOG_VisualizationGraphWidget())
369 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
370 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
370 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
371 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
371 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
372 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
372 variable->range());
373 variable->range());
373 }
374 }
374 }
375 }
375 }
376 }
376
377
377 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
378 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
378 const SqpRange &range)
379 const SqpRange &range)
379 {
380 {
380 auto it = impl->m_VariableToPlotMultiMap.find(variable);
381 auto it = impl->m_VariableToPlotMultiMap.find(variable);
381 if (it != impl->m_VariableToPlotMultiMap.end()) {
382 if (it != impl->m_VariableToPlotMultiMap.end()) {
382 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
383 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
383 }
384 }
384 }
385 }
@@ -1,219 +1,294
1 #include "Visualization/VisualizationTabWidget.h"
1 #include "Visualization/VisualizationTabWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "ui_VisualizationTabWidget.h"
3 #include "ui_VisualizationTabWidget.h"
4
4
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7
7
8 #include "Variable/VariableController.h"
8 #include "Variable/VariableController.h"
9
9
10 #include "Common/MimeTypesDef.h"
11
10 #include "DragDropHelper.h"
12 #include "DragDropHelper.h"
11 #include "SqpApplication.h"
13 #include "SqpApplication.h"
12
14
13 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
15 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
14
16
15 namespace {
17 namespace {
16
18
17 /// Generates a default name for a new zone, according to the number of zones already displayed in
19 /// Generates a default name for a new zone, according to the number of zones already displayed in
18 /// the tab
20 /// the tab
19 QString defaultZoneName(const QLayout &layout)
21 QString defaultZoneName(const QLayout &layout)
20 {
22 {
21 auto count = 0;
23 auto count = 0;
22 for (auto i = 0; i < layout.count(); ++i) {
24 for (auto i = 0; i < layout.count(); ++i) {
23 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
25 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
24 count++;
26 count++;
25 }
27 }
26 }
28 }
27
29
28 return QObject::tr("Zone %1").arg(count + 1);
30 return QObject::tr("Zone %1").arg(count + 1);
29 }
31 }
30
32
31 /**
33 /**
32 * Applies a function to all zones of the tab represented by its layout
34 * Applies a function to all zones of the tab represented by its layout
33 * @param layout the layout that contains zones
35 * @param layout the layout that contains zones
34 * @param fun the function to apply to each zone
36 * @param fun the function to apply to each zone
35 */
37 */
36 template <typename Fun>
38 template <typename Fun>
37 void processZones(QLayout &layout, Fun fun)
39 void processZones(QLayout &layout, Fun fun)
38 {
40 {
39 for (auto i = 0; i < layout.count(); ++i) {
41 for (auto i = 0; i < layout.count(); ++i) {
40 if (auto item = layout.itemAt(i)) {
42 if (auto item = layout.itemAt(i)) {
41 if (auto visualizationZoneWidget
43 if (auto visualizationZoneWidget
42 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
44 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
43 fun(*visualizationZoneWidget);
45 fun(*visualizationZoneWidget);
44 }
46 }
45 }
47 }
46 }
48 }
47 }
49 }
48
50
49 } // namespace
51 } // namespace
50
52
51 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
53 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
52 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
54 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
53
55
54 QString m_Name;
56 QString m_Name;
57
58 void dropGraph(int index, VisualizationTabWidget *tabWidget);
59 void dropZone(int index, VisualizationTabWidget *tabWidget);
60 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
61 VisualizationTabWidget *tabWidget);
55 };
62 };
56
63
57 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
64 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
58 : QWidget{parent},
65 : QWidget{parent},
59 ui{new Ui::VisualizationTabWidget},
66 ui{new Ui::VisualizationTabWidget},
60 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
67 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
61 {
68 {
62 ui->setupUi(this);
69 ui->setupUi(this);
63
70
64 ui->dragDropContainer->setAcceptedMimeTypes(
71 ui->dragDropContainer->setAcceptedMimeTypes(
65 {DragDropHelper::MIME_TYPE_GRAPH, DragDropHelper::MIME_TYPE_ZONE});
72 {MIME_TYPE_GRAPH, MIME_TYPE_ZONE, MIME_TYPE_VARIABLE_LIST});
66 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
73 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
67 &VisualizationTabWidget::dropMimeData);
74 &VisualizationTabWidget::dropMimeData);
75 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
76 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
77 ui->dragDropContainer);
78 });
68 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
79 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
69
80
70 // Widget is deleted when closed
81 // Widget is deleted when closed
71 setAttribute(Qt::WA_DeleteOnClose);
82 setAttribute(Qt::WA_DeleteOnClose);
72 }
83 }
73
84
74 VisualizationTabWidget::~VisualizationTabWidget()
85 VisualizationTabWidget::~VisualizationTabWidget()
75 {
86 {
76 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
87 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
77 delete ui;
88 delete ui;
78 }
89 }
79
90
80 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
91 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
81 {
92 {
82 ui->dragDropContainer->addDragWidget(zoneWidget);
93 ui->dragDropContainer->addDragWidget(zoneWidget);
83 }
94 }
84
95
85 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
96 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
86 {
97 {
87 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
98 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
88 }
99 }
89
100
90 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
101 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
91 {
102 {
92 return createZone({variable}, -1);
103 return createZone({variable}, -1);
93 }
104 }
94
105
95 VisualizationZoneWidget *
106 VisualizationZoneWidget *
96 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
107 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
97 {
108 {
98 auto zoneWidget = createEmptyZone(index);
109 auto zoneWidget = createEmptyZone(index);
99
110
100 // Creates a new graph into the zone
111 // Creates a new graph into the zone
101 zoneWidget->createGraph(variables, index);
112 zoneWidget->createGraph(variables, index);
102
113
103 return zoneWidget;
114 return zoneWidget;
104 }
115 }
105
116
106 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
117 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
107 {
118 {
108 auto zoneWidget
119 auto zoneWidget
109 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
120 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
110 this->insertZone(index, zoneWidget);
121 this->insertZone(index, zoneWidget);
111
122
112 return zoneWidget;
123 return zoneWidget;
113 }
124 }
114
125
115 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
126 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
116 {
127 {
117 if (visitor) {
128 if (visitor) {
118 visitor->visitEnter(this);
129 visitor->visitEnter(this);
119
130
120 // Apply visitor to zone children: widgets different from zones are not visited (no action)
131 // Apply visitor to zone children: widgets different from zones are not visited (no action)
121 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
132 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
122 zoneWidget.accept(visitor);
133 zoneWidget.accept(visitor);
123 });
134 });
124
135
125 visitor->visitLeave(this);
136 visitor->visitLeave(this);
126 }
137 }
127 else {
138 else {
128 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
139 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
129 }
140 }
130 }
141 }
131
142
132 bool VisualizationTabWidget::canDrop(const Variable &variable) const
143 bool VisualizationTabWidget::canDrop(const Variable &variable) const
133 {
144 {
134 // A tab can always accomodate a variable
145 // A tab can always accomodate a variable
135 Q_UNUSED(variable);
146 Q_UNUSED(variable);
136 return true;
147 return true;
137 }
148 }
138
149
139 bool VisualizationTabWidget::contains(const Variable &variable) const
150 bool VisualizationTabWidget::contains(const Variable &variable) const
140 {
151 {
141 Q_UNUSED(variable);
152 Q_UNUSED(variable);
142 return false;
153 return false;
143 }
154 }
144
155
145 QString VisualizationTabWidget::name() const
156 QString VisualizationTabWidget::name() const
146 {
157 {
147 return impl->m_Name;
158 return impl->m_Name;
148 }
159 }
149
160
150 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
161 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
151 {
162 {
152 // Closes zones in the tab
163 // Closes zones in the tab
153 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
164 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
154
165
155 QWidget::closeEvent(event);
166 QWidget::closeEvent(event);
156 }
167 }
157
168
158 QLayout &VisualizationTabWidget::tabLayout() const noexcept
169 QLayout &VisualizationTabWidget::tabLayout() const noexcept
159 {
170 {
160 return *ui->dragDropContainer->layout();
171 return *ui->dragDropContainer->layout();
161 }
172 }
162
173
163 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
174 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
164 {
175 {
176 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
177 impl->dropGraph(index, this);
178 }
179 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
180 impl->dropZone(index, this);
181 }
182 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
183 auto variables = sqpApp->variableController().variablesForMimeData(
184 mimeData->data(MIME_TYPE_VARIABLE_LIST));
185 impl->dropVariables(variables, index, this);
186 }
187 else {
188 qCWarning(LOG_VisualizationZoneWidget())
189 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
190 }
191 }
192
193 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
194 int index, VisualizationTabWidget *tabWidget)
195 {
165 auto &helper = sqpApp->dragDropHelper();
196 auto &helper = sqpApp->dragDropHelper();
166 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH)) {
167 auto graphWidget = static_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
168 auto parentDragDropContainer
169 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
170 Q_ASSERT(parentDragDropContainer);
171
172 auto nbGraph = parentDragDropContainer->countDragWidget();
173
174 const auto &variables = graphWidget->variables();
175
176 if (!variables.isEmpty()) {
177 // Abort the requests for the variables (if any)
178 // Commented, because it's not sure if it's needed or not
179 // for (const auto& var : variables)
180 //{
181 // sqpApp->variableController().onAbortProgressRequested(var);
182 //}
183
184 if (nbGraph == 1) {
185 // This is the only graph in the previous zone, close the zone
186 graphWidget->parentZoneWidget()->close();
187 }
188 else {
189 // Close the graph
190 graphWidget->close();
191 }
192
197
193 createZone(variables, index);
198 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
199 if (!graphWidget) {
200 qCWarning(LOG_VisualizationZoneWidget())
201 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
202 "found or invalid.");
203 Q_ASSERT(false);
204 return;
205 }
206
207 auto parentDragDropContainer
208 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
209 if (!parentDragDropContainer) {
210 qCWarning(LOG_VisualizationZoneWidget())
211 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
212 "the dropped graph is not found.");
213 Q_ASSERT(false);
214 return;
215 }
216
217 auto nbGraph = parentDragDropContainer->countDragWidget();
218
219 const auto &variables = graphWidget->variables();
220
221 if (!variables.isEmpty()) {
222 // Abort the requests for the variables (if any)
223 // Commented, because it's not sure if it's needed or not
224 // for (const auto& var : variables)
225 //{
226 // sqpApp->variableController().onAbortProgressRequested(var);
227 //}
228
229 if (nbGraph == 1) {
230 // This is the only graph in the previous zone, close the zone
231 graphWidget->parentZoneWidget()->close();
194 }
232 }
195 else {
233 else {
196 // The graph is empty, create an empty zone and move the graph inside
234 // Close the graph
235 graphWidget->close();
236 }
197
237
198 auto parentZoneWidget = graphWidget->parentZoneWidget();
238 tabWidget->createZone(variables, index);
239 }
240 else {
241 // The graph is empty, create an empty zone and move the graph inside
199
242
200 parentDragDropContainer->layout()->removeWidget(graphWidget);
243 auto parentZoneWidget = graphWidget->parentZoneWidget();
201
244
202 auto zoneWidget = createEmptyZone(index);
245 parentDragDropContainer->layout()->removeWidget(graphWidget);
203 zoneWidget->addGraph(graphWidget);
204
246
205 // Close the old zone if it was the only graph inside
247 auto zoneWidget = tabWidget->createEmptyZone(index);
206 if (nbGraph == 1) {
248 zoneWidget->addGraph(graphWidget);
207 parentZoneWidget->close();
249
208 }
250 // Close the old zone if it was the only graph inside
251 if (nbGraph == 1) {
252 parentZoneWidget->close();
209 }
253 }
210 }
254 }
211 else if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_ZONE)) {
255 }
212 // Simple move of the zone, no variable operation associated
213 auto zoneWidget = static_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
214 auto parentDragDropContainer = zoneWidget->parentWidget();
215 parentDragDropContainer->layout()->removeWidget(zoneWidget);
216
256
217 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
257 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
258 int index, VisualizationTabWidget *tabWidget)
259 {
260 auto &helper = sqpApp->dragDropHelper();
261
262 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
263 if (!zoneWidget) {
264 qCWarning(LOG_VisualizationZoneWidget())
265 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
266 "found or invalid.");
267 Q_ASSERT(false);
268 return;
269 }
270
271 auto parentDragDropContainer
272 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
273 if (!parentDragDropContainer) {
274 qCWarning(LOG_VisualizationZoneWidget())
275 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
276 "the dropped zone is not found.");
277 Q_ASSERT(false);
278 return;
218 }
279 }
280
281 // Simple move of the zone, no variable operation associated
282 parentDragDropContainer->layout()->removeWidget(zoneWidget);
283 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
284 }
285
286 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
287 const QList<std::shared_ptr<Variable> > &variables, int index,
288 VisualizationTabWidget *tabWidget)
289 {
290 // Note: we are sure that there is a single and compatible variable here
291 // because the AcceptMimeDataFunction, set on the drop container, makes the check before the
292 // drop can occur.
293 tabWidget->createZone(variables, index);
219 }
294 }
@@ -1,410 +1,484
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationWidget.h"
6 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7
8
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
11
8 #include <Data/SqpRange.h>
12 #include <Data/SqpRange.h>
9 #include <Variable/Variable.h>
13 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
14 #include <Variable/VariableController.h>
11
15
16 #include <Visualization/operations/FindVariableOperation.h>
17
12 #include <DragDropHelper.h>
18 #include <DragDropHelper.h>
13 #include <QUuid>
19 #include <QUuid>
14 #include <SqpApplication.h>
20 #include <SqpApplication.h>
15 #include <cmath>
21 #include <cmath>
16
22
17 #include <QLayout>
23 #include <QLayout>
18
24
19 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
25 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
20
26
21 namespace {
27 namespace {
22
28
23 /// Minimum height for graph added in zones (in pixels)
24 const auto GRAPH_MINIMUM_HEIGHT = 300;
25
29
26 /// Generates a default name for a new graph, according to the number of graphs already displayed in
30 /// Generates a default name for a new graph, according to the number of graphs already displayed in
27 /// the zone
31 /// the zone
28 QString defaultGraphName(const QLayout &layout)
32 QString defaultGraphName(const QLayout &layout)
29 {
33 {
30 auto count = 0;
34 auto count = 0;
31 for (auto i = 0; i < layout.count(); ++i) {
35 for (auto i = 0; i < layout.count(); ++i) {
32 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
36 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
33 count++;
37 count++;
34 }
38 }
35 }
39 }
36
40
37 return QObject::tr("Graph %1").arg(count + 1);
41 return QObject::tr("Graph %1").arg(count + 1);
38 }
42 }
39
43
40 /**
44 /**
41 * Applies a function to all graphs of the zone represented by its layout
45 * Applies a function to all graphs of the zone represented by its layout
42 * @param layout the layout that contains graphs
46 * @param layout the layout that contains graphs
43 * @param fun the function to apply to each graph
47 * @param fun the function to apply to each graph
44 */
48 */
45 template <typename Fun>
49 template <typename Fun>
46 void processGraphs(QLayout &layout, Fun fun)
50 void processGraphs(QLayout &layout, Fun fun)
47 {
51 {
48 for (auto i = 0; i < layout.count(); ++i) {
52 for (auto i = 0; i < layout.count(); ++i) {
49 if (auto item = layout.itemAt(i)) {
53 if (auto item = layout.itemAt(i)) {
50 if (auto visualizationGraphWidget
54 if (auto visualizationGraphWidget
51 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
55 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
52 fun(*visualizationGraphWidget);
56 fun(*visualizationGraphWidget);
53 }
57 }
54 }
58 }
55 }
59 }
56 }
60 }
57
61
58 } // namespace
62 } // namespace
59
63
60 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
64 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
61
65
62 explicit VisualizationZoneWidgetPrivate()
66 explicit VisualizationZoneWidgetPrivate()
63 : m_SynchronisationGroupId{QUuid::createUuid()},
67 : m_SynchronisationGroupId{QUuid::createUuid()},
64 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
68 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
65 {
69 {
66 }
70 }
67 QUuid m_SynchronisationGroupId;
71 QUuid m_SynchronisationGroupId;
68 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
72 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73
74 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
75 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
76 VisualizationZoneWidget *zoneWidget);
69 };
77 };
70
78
71 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
79 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
72 : VisualizationDragWidget{parent},
80 : VisualizationDragWidget{parent},
73 ui{new Ui::VisualizationZoneWidget},
81 ui{new Ui::VisualizationZoneWidget},
74 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
82 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
75 {
83 {
76 ui->setupUi(this);
84 ui->setupUi(this);
77
85
78 ui->zoneNameLabel->setText(name);
86 ui->zoneNameLabel->setText(name);
79
87
80 ui->dragDropContainer->setAcceptedMimeTypes({DragDropHelper::MIME_TYPE_GRAPH});
88 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST});
89 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
90 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
91 ui->dragDropContainer);
92 });
81 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
93 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
82 &VisualizationZoneWidget::dropMimeData);
94 &VisualizationZoneWidget::dropMimeData);
83
95
84 // 'Close' options : widget is deleted when closed
96 // 'Close' options : widget is deleted when closed
85 setAttribute(Qt::WA_DeleteOnClose);
97 setAttribute(Qt::WA_DeleteOnClose);
86 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
98 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
87 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
99 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
88
100
89 // Synchronisation id
101 // Synchronisation id
90 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
102 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
91 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
103 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
92 }
104 }
93
105
94 VisualizationZoneWidget::~VisualizationZoneWidget()
106 VisualizationZoneWidget::~VisualizationZoneWidget()
95 {
107 {
96 delete ui;
108 delete ui;
97 }
109 }
98
110
99 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
111 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
100 {
112 {
101 // Synchronize new graph with others in the zone
113 // Synchronize new graph with others in the zone
102 impl->m_Synchronizer->addGraph(*graphWidget);
114 impl->m_Synchronizer->addGraph(*graphWidget);
103
115
104 ui->dragDropContainer->addDragWidget(graphWidget);
116 ui->dragDropContainer->addDragWidget(graphWidget);
105 }
117 }
106
118
107 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
119 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
108 {
120 {
109 // Synchronize new graph with others in the zone
121 // Synchronize new graph with others in the zone
110 impl->m_Synchronizer->addGraph(*graphWidget);
122 impl->m_Synchronizer->addGraph(*graphWidget);
111
123
112 ui->dragDropContainer->insertDragWidget(index, graphWidget);
124 ui->dragDropContainer->insertDragWidget(index, graphWidget);
113 }
125 }
114
126
115 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
127 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
116 {
128 {
117 return createGraph(variable, -1);
129 return createGraph(variable, -1);
118 }
130 }
119
131
120 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
132 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
121 int index)
133 int index)
122 {
134 {
123 auto graphWidget
135 auto graphWidget
124 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
136 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
125
137
126
138
127 // Set graph properties
139 // Set graph properties
128 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
140 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
129 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
141 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
130
142
131
143
132 // Lambda to synchronize zone widget
144 // Lambda to synchronize zone widget
133 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
145 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
134 const SqpRange &oldGraphRange) {
146 const SqpRange &oldGraphRange) {
135
147
136 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
148 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
137 auto frameLayout = ui->dragDropContainer->layout();
149 auto frameLayout = ui->dragDropContainer->layout();
138 for (auto i = 0; i < frameLayout->count(); ++i) {
150 for (auto i = 0; i < frameLayout->count(); ++i) {
139 auto graphChild
151 auto graphChild
140 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
152 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
141 if (graphChild && (graphChild != graphWidget)) {
153 if (graphChild && (graphChild != graphWidget)) {
142
154
143 auto graphChildRange = graphChild->graphRange();
155 auto graphChildRange = graphChild->graphRange();
144 switch (zoomType) {
156 switch (zoomType) {
145 case AcquisitionZoomType::ZoomIn: {
157 case AcquisitionZoomType::ZoomIn: {
146 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
158 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
147 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
159 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
148 graphChildRange.m_TStart += deltaLeft;
160 graphChildRange.m_TStart += deltaLeft;
149 graphChildRange.m_TEnd -= deltaRight;
161 graphChildRange.m_TEnd -= deltaRight;
150 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
162 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
151 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
163 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
152 << deltaLeft;
164 << deltaLeft;
153 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
165 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
154 << deltaRight;
166 << deltaRight;
155 qCDebug(LOG_VisualizationZoneWidget())
167 qCDebug(LOG_VisualizationZoneWidget())
156 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
168 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
157
169
158 break;
170 break;
159 }
171 }
160
172
161 case AcquisitionZoomType::ZoomOut: {
173 case AcquisitionZoomType::ZoomOut: {
162 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
174 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
163 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
175 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
164 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
176 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
165 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
177 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
166 << deltaLeft;
178 << deltaLeft;
167 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
179 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
168 << deltaRight;
180 << deltaRight;
169 qCDebug(LOG_VisualizationZoneWidget())
181 qCDebug(LOG_VisualizationZoneWidget())
170 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
182 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
171 graphChildRange.m_TStart -= deltaLeft;
183 graphChildRange.m_TStart -= deltaLeft;
172 graphChildRange.m_TEnd += deltaRight;
184 graphChildRange.m_TEnd += deltaRight;
173 break;
185 break;
174 }
186 }
175 case AcquisitionZoomType::PanRight: {
187 case AcquisitionZoomType::PanRight: {
176 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
188 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
177 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
189 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
178 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
190 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
179 graphChildRange.m_TStart += deltaLeft;
191 graphChildRange.m_TStart += deltaLeft;
180 graphChildRange.m_TEnd += deltaRight;
192 graphChildRange.m_TEnd += deltaRight;
181 qCDebug(LOG_VisualizationZoneWidget())
193 qCDebug(LOG_VisualizationZoneWidget())
182 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
194 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
183 break;
195 break;
184 }
196 }
185 case AcquisitionZoomType::PanLeft: {
197 case AcquisitionZoomType::PanLeft: {
186 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
198 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
187 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
199 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
188 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
200 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
189 graphChildRange.m_TStart -= deltaLeft;
201 graphChildRange.m_TStart -= deltaLeft;
190 graphChildRange.m_TEnd -= deltaRight;
202 graphChildRange.m_TEnd -= deltaRight;
191 break;
203 break;
192 }
204 }
193 case AcquisitionZoomType::Unknown: {
205 case AcquisitionZoomType::Unknown: {
194 qCDebug(LOG_VisualizationZoneWidget())
206 qCDebug(LOG_VisualizationZoneWidget())
195 << tr("Impossible to synchronize: zoom type unknown");
207 << tr("Impossible to synchronize: zoom type unknown");
196 break;
208 break;
197 }
209 }
198 default:
210 default:
199 qCCritical(LOG_VisualizationZoneWidget())
211 qCCritical(LOG_VisualizationZoneWidget())
200 << tr("Impossible to synchronize: zoom type not take into account");
212 << tr("Impossible to synchronize: zoom type not take into account");
201 // No action
213 // No action
202 break;
214 break;
203 }
215 }
204 graphChild->enableAcquisition(false);
216 graphChild->enableAcquisition(false);
205 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
217 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
206 << graphChild->graphRange();
218 << graphChild->graphRange();
207 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
219 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
208 << graphChildRange;
220 << graphChildRange;
209 qCDebug(LOG_VisualizationZoneWidget())
221 qCDebug(LOG_VisualizationZoneWidget())
210 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
222 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
211 graphChild->setGraphRange(graphChildRange);
223 graphChild->setGraphRange(graphChildRange);
212 graphChild->enableAcquisition(true);
224 graphChild->enableAcquisition(true);
213 }
225 }
214 }
226 }
215 };
227 };
216
228
217 // connection for synchronization
229 // connection for synchronization
218 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
230 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
219 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
231 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
220 &VisualizationZoneWidget::onVariableAdded);
232 &VisualizationZoneWidget::onVariableAdded);
221 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
233 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
222 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
234 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
223
235
224 auto range = SqpRange{};
236 auto range = SqpRange{};
225
237
226 // Apply visitor to graph children
238 // Apply visitor to graph children
227 auto layout = ui->dragDropContainer->layout();
239 auto layout = ui->dragDropContainer->layout();
228 if (layout->count() > 0) {
240 if (layout->count() > 0) {
229 // Case of a new graph in a existant zone
241 // Case of a new graph in a existant zone
230 if (auto visualizationGraphWidget
242 if (auto visualizationGraphWidget
231 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
243 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
232 range = visualizationGraphWidget->graphRange();
244 range = visualizationGraphWidget->graphRange();
233 }
245 }
234 }
246 }
235 else {
247 else {
236 // Case of a new graph as the first of the zone
248 // Case of a new graph as the first of the zone
237 range = variable->range();
249 range = variable->range();
238 }
250 }
239
251
240 this->insertGraph(index, graphWidget);
252 this->insertGraph(index, graphWidget);
241
253
242 graphWidget->addVariable(variable, range);
254 graphWidget->addVariable(variable, range);
243
255
244 // get y using variable range
256 // get y using variable range
245 if (auto dataSeries = variable->dataSeries()) {
257 if (auto dataSeries = variable->dataSeries()) {
246 dataSeries->lockRead();
258 dataSeries->lockRead();
247 auto valuesBounds
259 auto valuesBounds
248 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
260 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
249 auto end = dataSeries->cend();
261 auto end = dataSeries->cend();
250 if (valuesBounds.first != end && valuesBounds.second != end) {
262 if (valuesBounds.first != end && valuesBounds.second != end) {
251 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
263 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
252
264
253 auto minValue = rangeValue(valuesBounds.first->minValue());
265 auto minValue = rangeValue(valuesBounds.first->minValue());
254 auto maxValue = rangeValue(valuesBounds.second->maxValue());
266 auto maxValue = rangeValue(valuesBounds.second->maxValue());
255
267
256 graphWidget->setYRange(SqpRange{minValue, maxValue});
268 graphWidget->setYRange(SqpRange{minValue, maxValue});
257 }
269 }
258 dataSeries->unlock();
270 dataSeries->unlock();
259 }
271 }
260
272
261 return graphWidget;
273 return graphWidget;
262 }
274 }
263
275
264 VisualizationGraphWidget *
276 VisualizationGraphWidget *
265 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
277 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
266 {
278 {
267 if (variables.isEmpty()) {
279 if (variables.isEmpty()) {
268 return nullptr;
280 return nullptr;
269 }
281 }
270
282
271 auto graphWidget = createGraph(variables.first(), index);
283 auto graphWidget = createGraph(variables.first(), index);
272 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
284 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
273 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
285 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
274 }
286 }
275
287
276 return graphWidget;
288 return graphWidget;
277 }
289 }
278
290
279 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
291 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
280 {
292 {
281 if (visitor) {
293 if (visitor) {
282 visitor->visitEnter(this);
294 visitor->visitEnter(this);
283
295
284 // Apply visitor to graph children: widgets different from graphs are not visited (no
296 // Apply visitor to graph children: widgets different from graphs are not visited (no
285 // action)
297 // action)
286 processGraphs(
298 processGraphs(
287 *ui->dragDropContainer->layout(),
299 *ui->dragDropContainer->layout(),
288 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
300 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
289
301
290 visitor->visitLeave(this);
302 visitor->visitLeave(this);
291 }
303 }
292 else {
304 else {
293 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
305 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
294 }
306 }
295 }
307 }
296
308
297 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
309 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
298 {
310 {
299 // A tab can always accomodate a variable
311 // A tab can always accomodate a variable
300 Q_UNUSED(variable);
312 Q_UNUSED(variable);
301 return true;
313 return true;
302 }
314 }
303
315
304 bool VisualizationZoneWidget::contains(const Variable &variable) const
316 bool VisualizationZoneWidget::contains(const Variable &variable) const
305 {
317 {
306 Q_UNUSED(variable);
318 Q_UNUSED(variable);
307 return false;
319 return false;
308 }
320 }
309
321
310 QString VisualizationZoneWidget::name() const
322 QString VisualizationZoneWidget::name() const
311 {
323 {
312 return ui->zoneNameLabel->text();
324 return ui->zoneNameLabel->text();
313 }
325 }
314
326
315 QMimeData *VisualizationZoneWidget::mimeData() const
327 QMimeData *VisualizationZoneWidget::mimeData() const
316 {
328 {
317 auto mimeData = new QMimeData;
329 auto mimeData = new QMimeData;
318 mimeData->setData(DragDropHelper::MIME_TYPE_ZONE, QByteArray());
330 mimeData->setData(MIME_TYPE_ZONE, QByteArray());
319
331
320 return mimeData;
332 return mimeData;
321 }
333 }
322
334
323 bool VisualizationZoneWidget::isDragAllowed() const
335 bool VisualizationZoneWidget::isDragAllowed() const
324 {
336 {
325 return true;
337 return true;
326 }
338 }
327
339
328 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
340 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
329 {
341 {
330 // Closes graphs in the zone
342 // Closes graphs in the zone
331 processGraphs(*ui->dragDropContainer->layout(),
343 processGraphs(*ui->dragDropContainer->layout(),
332 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
344 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
333
345
334 // Delete synchronization group from variable controller
346 // Delete synchronization group from variable controller
335 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
347 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
336 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
348 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
337
349
338 QWidget::closeEvent(event);
350 QWidget::closeEvent(event);
339 }
351 }
340
352
341 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
353 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
342 {
354 {
343 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
355 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
344 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
356 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
345 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
357 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
346 }
358 }
347
359
348 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
360 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
349 {
361 {
350 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
362 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
351 Q_ARG(std::shared_ptr<Variable>, variable),
363 Q_ARG(std::shared_ptr<Variable>, variable),
352 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
364 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
353 }
365 }
354
366
355 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
367 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
356 {
368 {
369 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
370 impl->dropGraph(index, this);
371 }
372 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
373 auto variables = sqpApp->variableController().variablesForMimeData(
374 mimeData->data(MIME_TYPE_VARIABLE_LIST));
375 impl->dropVariables(variables, index, this);
376 }
377 else {
378 qCWarning(LOG_VisualizationZoneWidget())
379 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
380 }
381 }
382
383 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
384 int index, VisualizationZoneWidget *zoneWidget)
385 {
357 auto &helper = sqpApp->dragDropHelper();
386 auto &helper = sqpApp->dragDropHelper();
358 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH)) {
359 auto graphWidget = static_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
360 auto parentDragDropContainer
361 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
362 Q_ASSERT(parentDragDropContainer);
363
364 const auto &variables = graphWidget->variables();
365
366 if (parentDragDropContainer != ui->dragDropContainer && !variables.isEmpty()) {
367 // The drop didn't occur in the same zone
368
369 // Abort the requests for the variables (if any)
370 // Commented, because it's not sure if it's needed or not
371 // for (const auto& var : variables)
372 //{
373 // sqpApp->variableController().onAbortProgressRequested(var);
374 //}
375
376 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
377 auto nbGraph = parentDragDropContainer->countDragWidget();
378 if (nbGraph == 1) {
379 // This is the only graph in the previous zone, close the zone
380 previousParentZoneWidget->close();
381 }
382 else {
383 // Close the graph
384 graphWidget->close();
385 }
386
387
387 // Creates the new graph in the zone
388 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
388 createGraph(variables, index);
389 if (!graphWidget) {
390 qCWarning(LOG_VisualizationZoneWidget())
391 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
392 "found or invalid.");
393 Q_ASSERT(false);
394 return;
395 }
396
397 auto parentDragDropContainer
398 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
399 if (!parentDragDropContainer) {
400 qCWarning(LOG_VisualizationZoneWidget())
401 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
402 "the dropped graph is not found.");
403 Q_ASSERT(false);
404 return;
405 }
406
407 const auto &variables = graphWidget->variables();
408
409 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
410 // The drop didn't occur in the same zone
411
412 // Abort the requests for the variables (if any)
413 // Commented, because it's not sure if it's needed or not
414 // for (const auto& var : variables)
415 //{
416 // sqpApp->variableController().onAbortProgressRequested(var);
417 //}
418
419 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
420 auto nbGraph = parentDragDropContainer->countDragWidget();
421 if (nbGraph == 1) {
422 // This is the only graph in the previous zone, close the zone
423 previousParentZoneWidget->close();
389 }
424 }
390 else {
425 else {
391 // The drop occurred in the same zone or the graph is empty
426 // Close the graph
392 // Simple move of the graph, no variable operation associated
427 graphWidget->close();
393 parentDragDropContainer->layout()->removeWidget(graphWidget);
428 }
394
429
395 if (variables.isEmpty() && parentDragDropContainer != ui->dragDropContainer) {
430 // Creates the new graph in the zone
396 // The graph is empty and dropped in a different zone.
431 zoneWidget->createGraph(variables, index);
397 // Take the range of the first graph in the zone (if existing).
432 }
398 auto layout = ui->dragDropContainer->layout();
433 else {
399 if (layout->count() > 0) {
434 // The drop occurred in the same zone or the graph is empty
400 if (auto visualizationGraphWidget
435 // Simple move of the graph, no variable operation associated
401 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
436 parentDragDropContainer->layout()->removeWidget(graphWidget);
402 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
437
403 }
438 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
439 // The graph is empty and dropped in a different zone.
440 // Take the range of the first graph in the zone (if existing).
441 auto layout = zoneWidget->ui->dragDropContainer->layout();
442 if (layout->count() > 0) {
443 if (auto visualizationGraphWidget
444 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
445 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
404 }
446 }
405 }
447 }
448 }
449
450 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
451 }
452 }
453
454 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
455 const QList<std::shared_ptr<Variable> > &variables, int index,
456 VisualizationZoneWidget *zoneWidget)
457 {
458 // Search for the top level VisualizationWidget
459 auto parent = zoneWidget->parentWidget();
460 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
461 parent = parent->parentWidget();
462 }
463
464 if (!parent) {
465 qCWarning(LOG_VisualizationZoneWidget())
466 << tr("VisualizationZoneWidget::dropVariables, drop aborted, the parent "
467 "VisualizationWidget cannot be found.");
468 Q_ASSERT(false);
469 return;
470 }
471
472 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
406
473
407 ui->dragDropContainer->insertDragWidget(index, graphWidget);
474 // Search for the first variable which can be dropped
475 for (auto variable : variables) {
476 FindVariableOperation findVariableOperation{variable};
477 visualizationWidget->accept(&findVariableOperation);
478 auto variableContainers = findVariableOperation.result();
479 if (variableContainers.empty()) {
480 zoneWidget->createGraph(variable, index);
481 break;
408 }
482 }
409 }
483 }
410 }
484 }
General Comments 1
Under Review
author

Auto status change to "Under Review"

You need to be logged in to leave comments. Login now