##// END OF EJS Templates
Merge pull request 341 from SciQLop-fork develop...
leroux -
r941:baf8c7fca294 merge
parent child
Show More
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -1,135 +1,138
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 /// Returns the MIME data associated to a list of variables
71 /// Returns the MIME data associated to a list of variables
72 QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const;
72 QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const;
73
73
74 /// Returns the list of variables contained in a MIME data
74 /// Returns the list of variables contained in a MIME data
75 QList<std::shared_ptr<Variable> > variablesForMimeData(const QByteArray &mimeData) const;
75 QList<std::shared_ptr<Variable> > variablesForMimeData(const QByteArray &mimeData) const;
76
76
77 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
77 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
78 signals:
78 signals:
79 /// Signal emitted when a variable is about to be deleted from the controller
79 /// Signal emitted when a variable is about to be deleted from the controller
80 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
80 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
81
81
82 /// Signal emitted when a data acquisition is requested on a range for a variable
82 /// Signal emitted when a data acquisition is requested on a range for a variable
83 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
83 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
84
84
85 /// Signal emitted when a sub range of the cacheRange of the variable can be displayed
85 /// Signal emitted when a sub range of the cacheRange of the variable can be displayed
86 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
86 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
87
87
88 public slots:
88 public slots:
89 /// Request the data loading of the variable whithin range
89 /// Request the data loading of the variable whithin range
90 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
90 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
91 bool synchronise);
91 bool synchronise);
92 /**
92 /**
93 * Creates a new variable and adds it to the model
93 * Creates a new variable and adds it to the model
94 * @param name the name of the new variable
94 * @param name the name of the new variable
95 * @param metadata the metadata of the new variable
95 * @param metadata the metadata of the new variable
96 * @param provider the data provider for the new variable
96 * @param provider the data provider for the new variable
97 * @return the pointer to the new variable or nullptr if the creation failed
97 * @return the pointer to the new variable or nullptr if the creation failed
98 */
98 */
99 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
99 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
100 std::shared_ptr<IDataProvider> provider) noexcept;
100 std::shared_ptr<IDataProvider> provider) noexcept;
101
101
102 /// Update the temporal parameters of every selected variable to dateTime
102 /// Update the temporal parameters of every selected variable to dateTime
103 void onDateTimeOnSelection(const SqpRange &dateTime);
103 void onDateTimeOnSelection(const SqpRange &dateTime);
104
104
105 /// Update the temporal parameters of the specified variable
106 void onUpdateDateTime(std::shared_ptr<Variable> variable, const SqpRange &dateTime);
107
105
108
106 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
109 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
107 const SqpRange &cacheRangeRequested,
110 const SqpRange &cacheRangeRequested,
108 QVector<AcquisitionDataPacket> dataAcquired);
111 QVector<AcquisitionDataPacket> dataAcquired);
109
112
110 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
113 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
111
114
112 /// Cancel the current request for the variable
115 /// Cancel the current request for the variable
113 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
116 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
114 void onAbortAcquisitionRequested(QUuid vIdentifier);
117 void onAbortAcquisitionRequested(QUuid vIdentifier);
115
118
116 // synchronization group methods
119 // synchronization group methods
117 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
120 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
118 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
121 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
119 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
122 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
120
123
121 /// Desynchronizes the variable of the group whose identifier is passed in parameter
124 /// Desynchronizes the variable of the group whose identifier is passed in parameter
122 /// @remarks the method does nothing if the variable is not part of the group
125 /// @remarks the method does nothing if the variable is not part of the group
123 void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
126 void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
124
127
125 void initialize();
128 void initialize();
126 void finalize();
129 void finalize();
127
130
128 private:
131 private:
129 void waitForFinish();
132 void waitForFinish();
130
133
131 class VariableControllerPrivate;
134 class VariableControllerPrivate;
132 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
135 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
133 };
136 };
134
137
135 #endif // SCIQLOP_VARIABLECONTROLLER_H
138 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,110 +1,111
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 class VariableController;
22
22
23 /**
23 /**
24 * @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
25 */
25 */
26 class SCIQLOP_CORE_EXPORT VariableModel : public QAbstractTableModel {
26 class SCIQLOP_CORE_EXPORT VariableModel : public QAbstractTableModel {
27 Q_OBJECT
27 Q_OBJECT
28 public:
28 public:
29 explicit VariableModel(VariableController *parent = nullptr);
29 explicit VariableModel(VariableController *parent = nullptr);
30
30
31 /**
31 /**
32 * Adds an existing variable in the model.
32 * Adds an existing variable in the model.
33 * @param variable the variable to add.
33 * @param variable the variable to add.
34 * @remarks the variable's name is modified to avoid name duplicates
34 * @remarks the variable's name is modified to avoid name duplicates
35 * @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
36 */
36 */
37 void addVariable(std::shared_ptr<Variable> variable) noexcept;
37 void addVariable(std::shared_ptr<Variable> variable) noexcept;
38
38
39 /**
39 /**
40 * Checks that a variable is contained in the model
40 * Checks that a variable is contained in the model
41 * @param variable the variable to check
41 * @param variable the variable to check
42 * @return true if the variable is in the model, false otherwise
42 * @return true if the variable is in the model, false otherwise
43 */
43 */
44 bool containsVariable(std::shared_ptr<Variable> variable) const noexcept;
44 bool containsVariable(std::shared_ptr<Variable> variable) const noexcept;
45
45
46 /**
46 /**
47 * Creates a new variable in the model
47 * Creates a new variable in the model
48 * @param name the name of the new variable
48 * @param name the name of the new variable
49 * @param metadata the metadata associated to the new variable
49 * @param metadata the metadata associated to the new variable
50 * @return the pointer to the new variable
50 * @return the pointer to the new variable
51 */
51 */
52 std::shared_ptr<Variable> createVariable(const QString &name,
52 std::shared_ptr<Variable> createVariable(const QString &name,
53 const QVariantHash &metadata) noexcept;
53 const QVariantHash &metadata) noexcept;
54
54
55 /**
55 /**
56 * Deletes a variable from the model, if it exists
56 * Deletes a variable from the model, if it exists
57 * @param variable the variable to delete
57 * @param variable the variable to delete
58 */
58 */
59 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
59 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
60
60
61
61
62 std::shared_ptr<Variable> variable(int index) const;
62 std::shared_ptr<Variable> variable(int index) const;
63 std::vector<std::shared_ptr<Variable> > variables() const;
63 std::vector<std::shared_ptr<Variable> > variables() const;
64
64
65 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
65 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
66
66
67
67
68 // /////////////////////////// //
68 // /////////////////////////// //
69 // QAbstractTableModel methods //
69 // QAbstractTableModel methods //
70 // /////////////////////////// //
70 // /////////////////////////// //
71
71
72 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
72 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
73 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
73 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
74 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;
75 virtual QVariant headerData(int section, Qt::Orientation orientation,
75 virtual QVariant headerData(int section, Qt::Orientation orientation,
76 int role = Qt::DisplayRole) const override;
76 int role = Qt::DisplayRole) const override;
77 virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
77 virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
78
78
79 // ///////////////// //
79 // ///////////////// //
80 // Drag&Drop methods //
80 // Drag&Drop methods //
81 // ///////////////// //
81 // ///////////////// //
82
82
83 virtual Qt::DropActions supportedDropActions() const override;
83 virtual Qt::DropActions supportedDropActions() const override;
84 virtual Qt::DropActions supportedDragActions() const override;
84 virtual Qt::DropActions supportedDragActions() const override;
85 virtual QStringList mimeTypes() const override;
85 virtual QStringList mimeTypes() const override;
86 virtual QMimeData *mimeData(const QModelIndexList &indexes) 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,
87 virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
88 const QModelIndex &parent) const override;
88 const QModelIndex &parent) const override;
89 virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
89 virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
90 const QModelIndex &parent) override;
90 const QModelIndex &parent) override;
91
91
92 void abortProgress(const QModelIndex &index);
92 void abortProgress(const QModelIndex &index);
93
93
94 signals:
94 signals:
95 void abortProgessRequested(std::shared_ptr<Variable> variable);
95 void abortProgessRequested(std::shared_ptr<Variable> variable);
96 void requestVariable(const QVariantHash &productData);
96 void requestVariable(const QVariantHash &productData);
97 void requestVariableRangeUpdate(std::shared_ptr<Variable> variable, const SqpRange &range);
97
98
98 private:
99 private:
99 class VariableModelPrivate;
100 class VariableModelPrivate;
100 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
101 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
101
102
102 private slots:
103 private slots:
103 /// Slot called when data of a variable has been updated
104 /// Slot called when data of a variable has been updated
104 void onVariableUpdated() noexcept;
105 void onVariableUpdated() noexcept;
105 };
106 };
106
107
107 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
108 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
108 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
109 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
109
110
110 #endif // SCIQLOP_VARIABLEMODEL_H
111 #endif // SCIQLOP_VARIABLEMODEL_H
@@ -1,1053 +1,1060
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableAcquisitionWorker.h>
2 #include <Variable/VariableAcquisitionWorker.h>
3 #include <Variable/VariableCacheStrategy.h>
3 #include <Variable/VariableCacheStrategy.h>
4 #include <Variable/VariableCacheStrategyFactory.h>
4 #include <Variable/VariableCacheStrategyFactory.h>
5 #include <Variable/VariableController.h>
5 #include <Variable/VariableController.h>
6 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
7 #include <Variable/VariableSynchronizationGroup.h>
7 #include <Variable/VariableSynchronizationGroup.h>
8
8
9 #include <Data/DataProviderParameters.h>
9 #include <Data/DataProviderParameters.h>
10 #include <Data/IDataProvider.h>
10 #include <Data/IDataProvider.h>
11 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
12 #include <Data/VariableRequest.h>
12 #include <Data/VariableRequest.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14
14
15 #include <QDataStream>
15 #include <QDataStream>
16 #include <QMutex>
16 #include <QMutex>
17 #include <QThread>
17 #include <QThread>
18 #include <QUuid>
18 #include <QUuid>
19 #include <QtCore/QItemSelectionModel>
19 #include <QtCore/QItemSelectionModel>
20
20
21 #include <deque>
21 #include <deque>
22 #include <set>
22 #include <set>
23 #include <unordered_map>
23 #include <unordered_map>
24
24
25 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
25 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
26
26
27 namespace {
27 namespace {
28
28
29 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
29 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
30 const SqpRange &oldGraphRange)
30 const SqpRange &oldGraphRange)
31 {
31 {
32 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
32 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
33
33
34 auto varRangeRequested = varRange;
34 auto varRangeRequested = varRange;
35 switch (zoomType) {
35 switch (zoomType) {
36 case AcquisitionZoomType::ZoomIn: {
36 case AcquisitionZoomType::ZoomIn: {
37 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
37 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
38 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
38 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
39 varRangeRequested.m_TStart += deltaLeft;
39 varRangeRequested.m_TStart += deltaLeft;
40 varRangeRequested.m_TEnd -= deltaRight;
40 varRangeRequested.m_TEnd -= deltaRight;
41 break;
41 break;
42 }
42 }
43
43
44 case AcquisitionZoomType::ZoomOut: {
44 case AcquisitionZoomType::ZoomOut: {
45 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
45 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
46 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
46 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
47 varRangeRequested.m_TStart -= deltaLeft;
47 varRangeRequested.m_TStart -= deltaLeft;
48 varRangeRequested.m_TEnd += deltaRight;
48 varRangeRequested.m_TEnd += deltaRight;
49 break;
49 break;
50 }
50 }
51 case AcquisitionZoomType::PanRight: {
51 case AcquisitionZoomType::PanRight: {
52 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
52 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
53 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
53 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
54 varRangeRequested.m_TStart += deltaLeft;
54 varRangeRequested.m_TStart += deltaLeft;
55 varRangeRequested.m_TEnd += deltaRight;
55 varRangeRequested.m_TEnd += deltaRight;
56 break;
56 break;
57 }
57 }
58 case AcquisitionZoomType::PanLeft: {
58 case AcquisitionZoomType::PanLeft: {
59 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
59 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
60 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
60 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
61 varRangeRequested.m_TStart -= deltaLeft;
61 varRangeRequested.m_TStart -= deltaLeft;
62 varRangeRequested.m_TEnd -= deltaRight;
62 varRangeRequested.m_TEnd -= deltaRight;
63 break;
63 break;
64 }
64 }
65 case AcquisitionZoomType::Unknown: {
65 case AcquisitionZoomType::Unknown: {
66 qCCritical(LOG_VariableController())
66 qCCritical(LOG_VariableController())
67 << VariableController::tr("Impossible to synchronize: zoom type unknown");
67 << VariableController::tr("Impossible to synchronize: zoom type unknown");
68 break;
68 break;
69 }
69 }
70 default:
70 default:
71 qCCritical(LOG_VariableController()) << VariableController::tr(
71 qCCritical(LOG_VariableController()) << VariableController::tr(
72 "Impossible to synchronize: zoom type not take into account");
72 "Impossible to synchronize: zoom type not take into account");
73 // No action
73 // No action
74 break;
74 break;
75 }
75 }
76
76
77 return varRangeRequested;
77 return varRangeRequested;
78 }
78 }
79 }
79 }
80
80
81 enum class VariableRequestHandlerState { OFF, RUNNING, PENDING };
81 enum class VariableRequestHandlerState { OFF, RUNNING, PENDING };
82
82
83 struct VariableRequestHandler {
83 struct VariableRequestHandler {
84
84
85 VariableRequestHandler()
85 VariableRequestHandler()
86 {
86 {
87 m_CanUpdate = false;
87 m_CanUpdate = false;
88 m_State = VariableRequestHandlerState::OFF;
88 m_State = VariableRequestHandlerState::OFF;
89 }
89 }
90
90
91 QUuid m_VarId;
91 QUuid m_VarId;
92 VariableRequest m_RunningVarRequest;
92 VariableRequest m_RunningVarRequest;
93 VariableRequest m_PendingVarRequest;
93 VariableRequest m_PendingVarRequest;
94 VariableRequestHandlerState m_State;
94 VariableRequestHandlerState m_State;
95 bool m_CanUpdate;
95 bool m_CanUpdate;
96 };
96 };
97
97
98 struct VariableController::VariableControllerPrivate {
98 struct VariableController::VariableControllerPrivate {
99 explicit VariableControllerPrivate(VariableController *parent)
99 explicit VariableControllerPrivate(VariableController *parent)
100 : m_WorkingMutex{},
100 : m_WorkingMutex{},
101 m_VariableModel{new VariableModel{parent}},
101 m_VariableModel{new VariableModel{parent}},
102 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
102 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
103 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
103 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
104 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
104 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
105 CacheStrategy::SingleThreshold)},
105 CacheStrategy::SingleThreshold)},
106 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
106 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
107 q{parent}
107 q{parent}
108 {
108 {
109
109
110 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
110 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
111 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
111 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
112 }
112 }
113
113
114
114
115 virtual ~VariableControllerPrivate()
115 virtual ~VariableControllerPrivate()
116 {
116 {
117 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
117 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
118 m_VariableAcquisitionWorkerThread.quit();
118 m_VariableAcquisitionWorkerThread.quit();
119 m_VariableAcquisitionWorkerThread.wait();
119 m_VariableAcquisitionWorkerThread.wait();
120 }
120 }
121
121
122
122
123 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
123 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
124 QUuid varRequestId);
124 QUuid varRequestId);
125
125
126 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
126 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
127 std::shared_ptr<IDataSeries>
127 std::shared_ptr<IDataSeries>
128 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
128 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
129
129
130 void registerProvider(std::shared_ptr<IDataProvider> provider);
130 void registerProvider(std::shared_ptr<IDataProvider> provider);
131
131
132 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
132 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
133 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
133 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
134 void updateVariables(QUuid varRequestId);
134 void updateVariables(QUuid varRequestId);
135 void updateVariableRequest(QUuid varRequestId);
135 void updateVariableRequest(QUuid varRequestId);
136 void cancelVariableRequest(QUuid varRequestId);
136 void cancelVariableRequest(QUuid varRequestId);
137 void executeVarRequest(std::shared_ptr<Variable> var, VariableRequest &varRequest);
137 void executeVarRequest(std::shared_ptr<Variable> var, VariableRequest &varRequest);
138
138
139 QMutex m_WorkingMutex;
139 QMutex m_WorkingMutex;
140 /// Variable model. The VariableController has the ownership
140 /// Variable model. The VariableController has the ownership
141 VariableModel *m_VariableModel;
141 VariableModel *m_VariableModel;
142 QItemSelectionModel *m_VariableSelectionModel;
142 QItemSelectionModel *m_VariableSelectionModel;
143
143
144
144
145 TimeController *m_TimeController{nullptr};
145 TimeController *m_TimeController{nullptr};
146 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
146 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
147 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
147 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
148 QThread m_VariableAcquisitionWorkerThread;
148 QThread m_VariableAcquisitionWorkerThread;
149
149
150 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
150 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
151 m_VariableToProviderMap;
151 m_VariableToProviderMap;
152 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
152 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
153 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
153 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
154 m_GroupIdToVariableSynchronizationGroupMap;
154 m_GroupIdToVariableSynchronizationGroupMap;
155 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
155 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
156 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
156 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
157
157
158 std::map<QUuid, std::list<QUuid> > m_VarGroupIdToVarIds;
158 std::map<QUuid, std::list<QUuid> > m_VarGroupIdToVarIds;
159 std::map<QUuid, std::unique_ptr<VariableRequestHandler> > m_VarIdToVarRequestHandler;
159 std::map<QUuid, std::unique_ptr<VariableRequestHandler> > m_VarIdToVarRequestHandler;
160
160
161 VariableController *q;
161 VariableController *q;
162 };
162 };
163
163
164
164
165 VariableController::VariableController(QObject *parent)
165 VariableController::VariableController(QObject *parent)
166 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
166 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
167 {
167 {
168 qCDebug(LOG_VariableController()) << tr("VariableController construction")
168 qCDebug(LOG_VariableController()) << tr("VariableController construction")
169 << QThread::currentThread();
169 << QThread::currentThread();
170
170
171 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
171 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
172 &VariableController::onAbortProgressRequested);
172 &VariableController::onAbortProgressRequested);
173
173
174 connect(impl->m_VariableAcquisitionWorker.get(),
174 connect(impl->m_VariableAcquisitionWorker.get(),
175 &VariableAcquisitionWorker::variableCanceledRequested, this,
175 &VariableAcquisitionWorker::variableCanceledRequested, this,
176 &VariableController::onAbortAcquisitionRequested);
176 &VariableController::onAbortAcquisitionRequested);
177
177
178 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
178 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
179 &VariableController::onDataProvided);
179 &VariableController::onDataProvided);
180 connect(impl->m_VariableAcquisitionWorker.get(),
180 connect(impl->m_VariableAcquisitionWorker.get(),
181 &VariableAcquisitionWorker::variableRequestInProgress, this,
181 &VariableAcquisitionWorker::variableRequestInProgress, this,
182 &VariableController::onVariableRetrieveDataInProgress);
182 &VariableController::onVariableRetrieveDataInProgress);
183
183
184
184
185 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
185 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
186 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
186 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
187 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
187 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
188 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
188 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
189
189
190 connect(impl->m_VariableModel, &VariableModel::requestVariableRangeUpdate, this,
191 &VariableController::onUpdateDateTime);
190
192
191 impl->m_VariableAcquisitionWorkerThread.start();
193 impl->m_VariableAcquisitionWorkerThread.start();
192 }
194 }
193
195
194 VariableController::~VariableController()
196 VariableController::~VariableController()
195 {
197 {
196 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
198 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
197 << QThread::currentThread();
199 << QThread::currentThread();
198 this->waitForFinish();
200 this->waitForFinish();
199 }
201 }
200
202
201 VariableModel *VariableController::variableModel() noexcept
203 VariableModel *VariableController::variableModel() noexcept
202 {
204 {
203 return impl->m_VariableModel;
205 return impl->m_VariableModel;
204 }
206 }
205
207
206 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
208 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
207 {
209 {
208 return impl->m_VariableSelectionModel;
210 return impl->m_VariableSelectionModel;
209 }
211 }
210
212
211 void VariableController::setTimeController(TimeController *timeController) noexcept
213 void VariableController::setTimeController(TimeController *timeController) noexcept
212 {
214 {
213 impl->m_TimeController = timeController;
215 impl->m_TimeController = timeController;
214 }
216 }
215
217
216 std::shared_ptr<Variable>
218 std::shared_ptr<Variable>
217 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
219 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
218 {
220 {
219 if (impl->m_VariableModel->containsVariable(variable)) {
221 if (impl->m_VariableModel->containsVariable(variable)) {
220 // Clones variable
222 // Clones variable
221 auto duplicate = variable->clone();
223 auto duplicate = variable->clone();
222
224
223 // Adds clone to model
225 // Adds clone to model
224 impl->m_VariableModel->addVariable(duplicate);
226 impl->m_VariableModel->addVariable(duplicate);
225
227
226 // Generates clone identifier
228 // Generates clone identifier
227 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
229 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
228
230
229 // Registers provider
231 // Registers provider
230 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
232 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
231 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
233 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
232
234
233 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
235 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
234 if (duplicateProvider) {
236 if (duplicateProvider) {
235 impl->registerProvider(duplicateProvider);
237 impl->registerProvider(duplicateProvider);
236 }
238 }
237
239
238 return duplicate;
240 return duplicate;
239 }
241 }
240 else {
242 else {
241 qCCritical(LOG_VariableController())
243 qCCritical(LOG_VariableController())
242 << tr("Can't create duplicate of variable %1: variable not registered in the model")
244 << tr("Can't create duplicate of variable %1: variable not registered in the model")
243 .arg(variable->name());
245 .arg(variable->name());
244 return nullptr;
246 return nullptr;
245 }
247 }
246 }
248 }
247
249
248 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
250 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
249 {
251 {
250 if (!variable) {
252 if (!variable) {
251 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
253 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
252 return;
254 return;
253 }
255 }
254
256
255 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
257 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
256 // make some treatments before the deletion
258 // make some treatments before the deletion
257 emit variableAboutToBeDeleted(variable);
259 emit variableAboutToBeDeleted(variable);
258
260
259 // Deletes identifier
261 // Deletes identifier
260 impl->m_VariableToIdentifierMap.erase(variable);
262 impl->m_VariableToIdentifierMap.erase(variable);
261
263
262 // Deletes provider
264 // Deletes provider
263 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
265 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
264 qCDebug(LOG_VariableController())
266 qCDebug(LOG_VariableController())
265 << tr("Number of providers deleted for variable %1: %2")
267 << tr("Number of providers deleted for variable %1: %2")
266 .arg(variable->name(), QString::number(nbProvidersDeleted));
268 .arg(variable->name(), QString::number(nbProvidersDeleted));
267
269
268
270
269 // Deletes from model
271 // Deletes from model
270 impl->m_VariableModel->deleteVariable(variable);
272 impl->m_VariableModel->deleteVariable(variable);
271 }
273 }
272
274
273 void VariableController::deleteVariables(
275 void VariableController::deleteVariables(
274 const QVector<std::shared_ptr<Variable> > &variables) noexcept
276 const QVector<std::shared_ptr<Variable> > &variables) noexcept
275 {
277 {
276 for (auto variable : qAsConst(variables)) {
278 for (auto variable : qAsConst(variables)) {
277 deleteVariable(variable);
279 deleteVariable(variable);
278 }
280 }
279 }
281 }
280
282
281 QByteArray
283 QByteArray
282 VariableController::mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const
284 VariableController::mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const
283 {
285 {
284 auto encodedData = QByteArray{};
286 auto encodedData = QByteArray{};
285
287
286 QVariantList ids;
288 QVariantList ids;
287 for (auto &var : variables) {
289 for (auto &var : variables) {
288 auto itVar = impl->m_VariableToIdentifierMap.find(var);
290 auto itVar = impl->m_VariableToIdentifierMap.find(var);
289 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
291 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
290 qCCritical(LOG_VariableController())
292 qCCritical(LOG_VariableController())
291 << tr("Impossible to find the data for an unknown variable.");
293 << tr("Impossible to find the data for an unknown variable.");
292 }
294 }
293
295
294 ids << itVar->second.toByteArray();
296 ids << itVar->second.toByteArray();
295 }
297 }
296
298
297 QDataStream stream{&encodedData, QIODevice::WriteOnly};
299 QDataStream stream{&encodedData, QIODevice::WriteOnly};
298 stream << ids;
300 stream << ids;
299
301
300 return encodedData;
302 return encodedData;
301 }
303 }
302
304
303 QList<std::shared_ptr<Variable> >
305 QList<std::shared_ptr<Variable> >
304 VariableController::variablesForMimeData(const QByteArray &mimeData) const
306 VariableController::variablesForMimeData(const QByteArray &mimeData) const
305 {
307 {
306 auto variables = QList<std::shared_ptr<Variable> >{};
308 auto variables = QList<std::shared_ptr<Variable> >{};
307 QDataStream stream{mimeData};
309 QDataStream stream{mimeData};
308
310
309 QVariantList ids;
311 QVariantList ids;
310 stream >> ids;
312 stream >> ids;
311
313
312 for (auto id : ids) {
314 for (auto id : ids) {
313 auto uuid = QUuid{id.toByteArray()};
315 auto uuid = QUuid{id.toByteArray()};
314 auto var = impl->findVariable(uuid);
316 auto var = impl->findVariable(uuid);
315 variables << var;
317 variables << var;
316 }
318 }
317
319
318 return variables;
320 return variables;
319 }
321 }
320
322
321 std::shared_ptr<Variable>
323 std::shared_ptr<Variable>
322 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
324 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
323 std::shared_ptr<IDataProvider> provider) noexcept
325 std::shared_ptr<IDataProvider> provider) noexcept
324 {
326 {
325 if (!impl->m_TimeController) {
327 if (!impl->m_TimeController) {
326 qCCritical(LOG_VariableController())
328 qCCritical(LOG_VariableController())
327 << tr("Impossible to create variable: The time controller is null");
329 << tr("Impossible to create variable: The time controller is null");
328 return nullptr;
330 return nullptr;
329 }
331 }
330
332
331 auto range = impl->m_TimeController->dateTime();
333 auto range = impl->m_TimeController->dateTime();
332
334
333 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
335 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
334 auto varId = QUuid::createUuid();
336 auto varId = QUuid::createUuid();
335
337
336 // Create the handler
338 // Create the handler
337 auto varRequestHandler = std::make_unique<VariableRequestHandler>();
339 auto varRequestHandler = std::make_unique<VariableRequestHandler>();
338 varRequestHandler->m_VarId = varId;
340 varRequestHandler->m_VarId = varId;
339
341
340 impl->m_VarIdToVarRequestHandler.insert(
342 impl->m_VarIdToVarRequestHandler.insert(
341 std::make_pair(varId, std::move(varRequestHandler)));
343 std::make_pair(varId, std::move(varRequestHandler)));
342
344
343 // store the provider
345 // store the provider
344 impl->registerProvider(provider);
346 impl->registerProvider(provider);
345
347
346 // Associate the provider
348 // Associate the provider
347 impl->m_VariableToProviderMap[newVariable] = provider;
349 impl->m_VariableToProviderMap[newVariable] = provider;
348 impl->m_VariableToIdentifierMap[newVariable] = varId;
350 impl->m_VariableToIdentifierMap[newVariable] = varId;
349
351
350 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{newVariable}, range, false);
352 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{newVariable}, range, false);
351
353
352 // auto varRequestId = QUuid::createUuid();
354 // auto varRequestId = QUuid::createUuid();
353 // qCInfo(LOG_VariableController()) << "createVariable: " << varId << varRequestId;
355 // qCInfo(LOG_VariableController()) << "createVariable: " << varId << varRequestId;
354 // impl->processRequest(newVariable, range, varRequestId);
356 // impl->processRequest(newVariable, range, varRequestId);
355 // impl->updateVariableRequest(varRequestId);
357 // impl->updateVariableRequest(varRequestId);
356
358
357 return newVariable;
359 return newVariable;
358 }
360 }
359 }
361 }
360
362
361 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
363 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
362 {
364 {
363 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
365 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
364 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
366 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
365 << QThread::currentThread()->objectName();
367 << QThread::currentThread()->objectName();
366 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
368 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
367
369
368 // NOTE we only permit the time modification for one variable
370 // NOTE we only permit the time modification for one variable
369 // DEPRECATED
371 // DEPRECATED
370 // auto variables = QVector<std::shared_ptr<Variable> >{};
372 // auto variables = QVector<std::shared_ptr<Variable> >{};
371 // for (const auto &selectedRow : qAsConst(selectedRows)) {
373 // for (const auto &selectedRow : qAsConst(selectedRows)) {
372 // if (auto selectedVariable =
374 // if (auto selectedVariable =
373 // impl->m_VariableModel->variable(selectedRow.row())) {
375 // impl->m_VariableModel->variable(selectedRow.row())) {
374 // variables << selectedVariable;
376 // variables << selectedVariable;
375
377
376 // // notify that rescale operation has to be done
378 // // notify that rescale operation has to be done
377 // emit rangeChanged(selectedVariable, dateTime);
379 // emit rangeChanged(selectedVariable, dateTime);
378 // }
380 // }
379 // }
381 // }
380 // if (!variables.isEmpty()) {
382 // if (!variables.isEmpty()) {
381 // this->onRequestDataLoading(variables, dateTime, synchro);
383 // this->onRequestDataLoading(variables, dateTime, synchro);
382 // }
384 // }
383 if (selectedRows.size() == 1) {
385 if (selectedRows.size() == 1) {
384
386
385 if (auto selectedVariable
387 if (auto selectedVariable
386 = impl->m_VariableModel->variable(qAsConst(selectedRows).first().row())) {
388 = impl->m_VariableModel->variable(qAsConst(selectedRows).first().row())) {
387
389
388 auto itVar = impl->m_VariableToIdentifierMap.find(selectedVariable);
390 onUpdateDateTime(selectedVariable, dateTime);
389 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
390 qCCritical(LOG_VariableController())
391 << tr("Impossible to onDateTimeOnSelection request for unknown variable");
392 return;
393 }
394
395 // notify that rescale operation has to be done
396 emit rangeChanged(selectedVariable, dateTime);
397
398 auto synchro = impl->m_VariableIdGroupIdMap.find(itVar->second)
399 != impl->m_VariableIdGroupIdMap.cend();
400
401 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{selectedVariable},
402 dateTime, synchro);
403 }
391 }
404 }
392 }
405 else if (selectedRows.size() > 1) {
393 else if (selectedRows.size() > 1) {
406 qCCritical(LOG_VariableController())
394 qCCritical(LOG_VariableController())
407 << tr("Impossible to set time for more than 1 variable in the same time");
395 << tr("Impossible to set time for more than 1 variable in the same time");
408 }
396 }
409 else {
397 else {
410 qCWarning(LOG_VariableController())
398 qCWarning(LOG_VariableController())
411 << tr("There is no variable selected to set the time one");
399 << tr("There is no variable selected to set the time one");
412 }
400 }
413 }
401 }
414
402
403 void VariableController::onUpdateDateTime(std::shared_ptr<Variable> variable,
404 const SqpRange &dateTime)
405 {
406 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
407 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
408 qCCritical(LOG_VariableController())
409 << tr("Impossible to onDateTimeOnSelection request for unknown variable");
410 return;
411 }
412
413 // notify that rescale operation has to be done
414 emit rangeChanged(variable, dateTime);
415
416 auto synchro
417 = impl->m_VariableIdGroupIdMap.find(itVar->second) != impl->m_VariableIdGroupIdMap.cend();
418
419 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{variable}, dateTime, synchro);
420 }
421
415 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
422 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
416 const SqpRange &cacheRangeRequested,
423 const SqpRange &cacheRangeRequested,
417 QVector<AcquisitionDataPacket> dataAcquired)
424 QVector<AcquisitionDataPacket> dataAcquired)
418 {
425 {
419 qCDebug(LOG_VariableController()) << tr("onDataProvided") << QThread::currentThread();
426 qCDebug(LOG_VariableController()) << tr("onDataProvided") << QThread::currentThread();
420 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
427 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
421 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
428 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
422 if (!varRequestId.isNull()) {
429 if (!varRequestId.isNull()) {
423 impl->updateVariables(varRequestId);
430 impl->updateVariables(varRequestId);
424 }
431 }
425 }
432 }
426
433
427 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
434 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
428 {
435 {
429 qCDebug(LOG_VariableController())
436 qCDebug(LOG_VariableController())
430 << "TORM: variableController::onVariableRetrieveDataInProgress"
437 << "TORM: variableController::onVariableRetrieveDataInProgress"
431 << QThread::currentThread()->objectName() << progress;
438 << QThread::currentThread()->objectName() << progress;
432 if (auto var = impl->findVariable(identifier)) {
439 if (auto var = impl->findVariable(identifier)) {
433 impl->m_VariableModel->setDataProgress(var, progress);
440 impl->m_VariableModel->setDataProgress(var, progress);
434 }
441 }
435 else {
442 else {
436 qCCritical(LOG_VariableController())
443 qCCritical(LOG_VariableController())
437 << tr("Impossible to notify progression of a null variable");
444 << tr("Impossible to notify progression of a null variable");
438 }
445 }
439 }
446 }
440
447
441 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
448 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
442 {
449 {
443 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortProgressRequested"
450 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortProgressRequested"
444 << QThread::currentThread()->objectName() << variable->name();
451 << QThread::currentThread()->objectName() << variable->name();
445
452
446 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
453 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
447 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
454 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
448 qCCritical(LOG_VariableController())
455 qCCritical(LOG_VariableController())
449 << tr("Impossible to onAbortProgressRequested request for unknown variable");
456 << tr("Impossible to onAbortProgressRequested request for unknown variable");
450 return;
457 return;
451 }
458 }
452
459
453 auto varId = itVar->second;
460 auto varId = itVar->second;
454
461
455 auto itVarHandler = impl->m_VarIdToVarRequestHandler.find(varId);
462 auto itVarHandler = impl->m_VarIdToVarRequestHandler.find(varId);
456 if (itVarHandler == impl->m_VarIdToVarRequestHandler.cend()) {
463 if (itVarHandler == impl->m_VarIdToVarRequestHandler.cend()) {
457 qCCritical(LOG_VariableController())
464 qCCritical(LOG_VariableController())
458 << tr("Impossible to onAbortProgressRequested for variable with unknown handler");
465 << tr("Impossible to onAbortProgressRequested for variable with unknown handler");
459 return;
466 return;
460 }
467 }
461
468
462 auto varHandler = itVarHandler->second.get();
469 auto varHandler = itVarHandler->second.get();
463
470
464 // case where a variable has a running request
471 // case where a variable has a running request
465 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
472 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
466 impl->cancelVariableRequest(varHandler->m_RunningVarRequest.m_VariableGroupId);
473 impl->cancelVariableRequest(varHandler->m_RunningVarRequest.m_VariableGroupId);
467 }
474 }
468 }
475 }
469
476
470 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
477 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
471 {
478 {
472 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
479 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
473 << QThread::currentThread()->objectName() << vIdentifier;
480 << QThread::currentThread()->objectName() << vIdentifier;
474
481
475 if (auto var = impl->findVariable(vIdentifier)) {
482 if (auto var = impl->findVariable(vIdentifier)) {
476 this->onAbortProgressRequested(var);
483 this->onAbortProgressRequested(var);
477 }
484 }
478 else {
485 else {
479 qCCritical(LOG_VariableController())
486 qCCritical(LOG_VariableController())
480 << tr("Impossible to abort Acquisition Requestof a null variable");
487 << tr("Impossible to abort Acquisition Requestof a null variable");
481 }
488 }
482 }
489 }
483
490
484 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
491 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
485 {
492 {
486 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
493 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
487 << QThread::currentThread()->objectName()
494 << QThread::currentThread()->objectName()
488 << synchronizationGroupId;
495 << synchronizationGroupId;
489 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
496 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
490 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
497 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
491 std::make_pair(synchronizationGroupId, vSynchroGroup));
498 std::make_pair(synchronizationGroupId, vSynchroGroup));
492 }
499 }
493
500
494 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
501 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
495 {
502 {
496 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
503 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
497 }
504 }
498
505
499 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
506 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
500 QUuid synchronizationGroupId)
507 QUuid synchronizationGroupId)
501
508
502 {
509 {
503 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
510 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
504 << synchronizationGroupId;
511 << synchronizationGroupId;
505 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
512 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
506 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
513 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
507 auto groupIdToVSGIt
514 auto groupIdToVSGIt
508 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
515 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
509 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
516 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
510 impl->m_VariableIdGroupIdMap.insert(
517 impl->m_VariableIdGroupIdMap.insert(
511 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
518 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
512 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
519 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
513 }
520 }
514 else {
521 else {
515 qCCritical(LOG_VariableController())
522 qCCritical(LOG_VariableController())
516 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
523 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
517 << variable->name();
524 << variable->name();
518 }
525 }
519 }
526 }
520 else {
527 else {
521 qCCritical(LOG_VariableController())
528 qCCritical(LOG_VariableController())
522 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
529 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
523 }
530 }
524 }
531 }
525
532
526 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
533 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
527 QUuid synchronizationGroupId)
534 QUuid synchronizationGroupId)
528 {
535 {
529 // Gets variable id
536 // Gets variable id
530 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
537 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
531 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
538 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
532 qCCritical(LOG_VariableController())
539 qCCritical(LOG_VariableController())
533 << tr("Can't desynchronize variable %1: variable identifier not found")
540 << tr("Can't desynchronize variable %1: variable identifier not found")
534 .arg(variable->name());
541 .arg(variable->name());
535 return;
542 return;
536 }
543 }
537
544
538 // Gets synchronization group
545 // Gets synchronization group
539 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
546 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
540 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
547 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
541 qCCritical(LOG_VariableController())
548 qCCritical(LOG_VariableController())
542 << tr("Can't desynchronize variable %1: unknown synchronization group")
549 << tr("Can't desynchronize variable %1: unknown synchronization group")
543 .arg(variable->name());
550 .arg(variable->name());
544 return;
551 return;
545 }
552 }
546
553
547 auto variableId = variableIt->second;
554 auto variableId = variableIt->second;
548
555
549 // Removes variable from synchronization group
556 // Removes variable from synchronization group
550 auto synchronizationGroup = groupIt->second;
557 auto synchronizationGroup = groupIt->second;
551 synchronizationGroup->removeVariableId(variableId);
558 synchronizationGroup->removeVariableId(variableId);
552
559
553 // Removes link between variable and synchronization group
560 // Removes link between variable and synchronization group
554 impl->m_VariableIdGroupIdMap.erase(variableId);
561 impl->m_VariableIdGroupIdMap.erase(variableId);
555 }
562 }
556
563
557 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
564 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
558 const SqpRange &range, bool synchronise)
565 const SqpRange &range, bool synchronise)
559 {
566 {
560 // variables is assumed synchronized
567 // variables is assumed synchronized
561 // TODO: Asser variables synchronization
568 // TODO: Asser variables synchronization
562 // we want to load data of the variable for the dateTime.
569 // we want to load data of the variable for the dateTime.
563 if (variables.isEmpty()) {
570 if (variables.isEmpty()) {
564 return;
571 return;
565 }
572 }
566
573
567 auto varRequestId = QUuid::createUuid();
574 auto varRequestId = QUuid::createUuid();
568 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
575 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
569 << QThread::currentThread()->objectName() << varRequestId
576 << QThread::currentThread()->objectName() << varRequestId
570 << range << synchronise;
577 << range << synchronise;
571
578
572 if (!synchronise) {
579 if (!synchronise) {
573 auto varIds = std::list<QUuid>{};
580 auto varIds = std::list<QUuid>{};
574 for (const auto &var : variables) {
581 for (const auto &var : variables) {
575 auto vId = impl->m_VariableToIdentifierMap.at(var);
582 auto vId = impl->m_VariableToIdentifierMap.at(var);
576 varIds.push_back(vId);
583 varIds.push_back(vId);
577 }
584 }
578 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
585 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
579 for (const auto &var : variables) {
586 for (const auto &var : variables) {
580 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId
587 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId
581 << varIds.size();
588 << varIds.size();
582 impl->processRequest(var, range, varRequestId);
589 impl->processRequest(var, range, varRequestId);
583 }
590 }
584 }
591 }
585 else {
592 else {
586 auto vId = impl->m_VariableToIdentifierMap.at(variables.first());
593 auto vId = impl->m_VariableToIdentifierMap.at(variables.first());
587 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
594 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
588 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
595 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
589 auto groupId = varIdToGroupIdIt->second;
596 auto groupId = varIdToGroupIdIt->second;
590
597
591 auto vSynchronizationGroup
598 auto vSynchronizationGroup
592 = impl->m_GroupIdToVariableSynchronizationGroupMap.at(groupId);
599 = impl->m_GroupIdToVariableSynchronizationGroupMap.at(groupId);
593 auto vSyncIds = vSynchronizationGroup->getIds();
600 auto vSyncIds = vSynchronizationGroup->getIds();
594
601
595 auto varIds = std::list<QUuid>{};
602 auto varIds = std::list<QUuid>{};
596 for (auto vId : vSyncIds) {
603 for (auto vId : vSyncIds) {
597 varIds.push_back(vId);
604 varIds.push_back(vId);
598 }
605 }
599 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
606 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
600
607
601 for (auto vId : vSyncIds) {
608 for (auto vId : vSyncIds) {
602 auto var = impl->findVariable(vId);
609 auto var = impl->findVariable(vId);
603
610
604 // Don't process already processed var
611 // Don't process already processed var
605 if (var != nullptr) {
612 if (var != nullptr) {
606 qCDebug(LOG_VariableController()) << "processRequest synchro for" << var->name()
613 qCDebug(LOG_VariableController()) << "processRequest synchro for" << var->name()
607 << varRequestId;
614 << varRequestId;
608 auto vSyncRangeRequested
615 auto vSyncRangeRequested
609 = variables.contains(var)
616 = variables.contains(var)
610 ? range
617 ? range
611 : computeSynchroRangeRequested(var->range(), range,
618 : computeSynchroRangeRequested(var->range(), range,
612 variables.first()->range());
619 variables.first()->range());
613 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
620 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
614 impl->processRequest(var, vSyncRangeRequested, varRequestId);
621 impl->processRequest(var, vSyncRangeRequested, varRequestId);
615 }
622 }
616 else {
623 else {
617 qCCritical(LOG_VariableController())
624 qCCritical(LOG_VariableController())
618
625
619 << tr("Impossible to synchronize a null variable");
626 << tr("Impossible to synchronize a null variable");
620 }
627 }
621 }
628 }
622 }
629 }
623 }
630 }
624
631
625 impl->updateVariables(varRequestId);
632 impl->updateVariables(varRequestId);
626 }
633 }
627
634
628
635
629 void VariableController::initialize()
636 void VariableController::initialize()
630 {
637 {
631 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
638 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
632 impl->m_WorkingMutex.lock();
639 impl->m_WorkingMutex.lock();
633 qCDebug(LOG_VariableController()) << tr("VariableController init END");
640 qCDebug(LOG_VariableController()) << tr("VariableController init END");
634 }
641 }
635
642
636 void VariableController::finalize()
643 void VariableController::finalize()
637 {
644 {
638 impl->m_WorkingMutex.unlock();
645 impl->m_WorkingMutex.unlock();
639 }
646 }
640
647
641 void VariableController::waitForFinish()
648 void VariableController::waitForFinish()
642 {
649 {
643 QMutexLocker locker{&impl->m_WorkingMutex};
650 QMutexLocker locker{&impl->m_WorkingMutex};
644 }
651 }
645
652
646 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
653 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
647 {
654 {
648 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
655 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
649 auto zoomType = AcquisitionZoomType::Unknown;
656 auto zoomType = AcquisitionZoomType::Unknown;
650 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
657 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
651 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
658 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
652 zoomType = AcquisitionZoomType::ZoomOut;
659 zoomType = AcquisitionZoomType::ZoomOut;
653 }
660 }
654 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
661 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
655 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
662 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
656 zoomType = AcquisitionZoomType::PanRight;
663 zoomType = AcquisitionZoomType::PanRight;
657 }
664 }
658 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
665 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
659 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
666 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
660 zoomType = AcquisitionZoomType::PanLeft;
667 zoomType = AcquisitionZoomType::PanLeft;
661 }
668 }
662 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
669 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
663 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
670 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
664 zoomType = AcquisitionZoomType::ZoomIn;
671 zoomType = AcquisitionZoomType::ZoomIn;
665 }
672 }
666 else {
673 else {
667 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
674 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
668 }
675 }
669 return zoomType;
676 return zoomType;
670 }
677 }
671
678
672 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
679 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
673 const SqpRange &rangeRequested,
680 const SqpRange &rangeRequested,
674 QUuid varRequestId)
681 QUuid varRequestId)
675 {
682 {
676 auto itVar = m_VariableToIdentifierMap.find(var);
683 auto itVar = m_VariableToIdentifierMap.find(var);
677 if (itVar == m_VariableToIdentifierMap.cend()) {
684 if (itVar == m_VariableToIdentifierMap.cend()) {
678 qCCritical(LOG_VariableController())
685 qCCritical(LOG_VariableController())
679 << tr("Impossible to process request for unknown variable");
686 << tr("Impossible to process request for unknown variable");
680 return;
687 return;
681 }
688 }
682
689
683 auto varId = itVar->second;
690 auto varId = itVar->second;
684
691
685 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
692 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
686 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
693 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
687 qCCritical(LOG_VariableController())
694 qCCritical(LOG_VariableController())
688 << tr("Impossible to process request for variable with unknown handler");
695 << tr("Impossible to process request for variable with unknown handler");
689 return;
696 return;
690 }
697 }
691
698
692 auto oldRange = var->range();
699 auto oldRange = var->range();
693
700
694 auto varHandler = itVarHandler->second.get();
701 auto varHandler = itVarHandler->second.get();
695
702
696 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
703 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
697 oldRange = varHandler->m_RunningVarRequest.m_RangeRequested;
704 oldRange = varHandler->m_RunningVarRequest.m_RangeRequested;
698 }
705 }
699
706
700 auto varRequest = VariableRequest{};
707 auto varRequest = VariableRequest{};
701 varRequest.m_VariableGroupId = varRequestId;
708 varRequest.m_VariableGroupId = varRequestId;
702 auto varStrategyRangesRequested
709 auto varStrategyRangesRequested
703 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
710 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
704 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
711 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
705 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
712 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
706
713
707 switch (varHandler->m_State) {
714 switch (varHandler->m_State) {
708 case VariableRequestHandlerState::OFF: {
715 case VariableRequestHandlerState::OFF: {
709 qCDebug(LOG_VariableController()) << tr("Process Request OFF")
716 qCDebug(LOG_VariableController()) << tr("Process Request OFF")
710 << varRequest.m_RangeRequested
717 << varRequest.m_RangeRequested
711 << varRequest.m_CacheRangeRequested;
718 << varRequest.m_CacheRangeRequested;
712 varHandler->m_RunningVarRequest = varRequest;
719 varHandler->m_RunningVarRequest = varRequest;
713 varHandler->m_State = VariableRequestHandlerState::RUNNING;
720 varHandler->m_State = VariableRequestHandlerState::RUNNING;
714 executeVarRequest(var, varRequest);
721 executeVarRequest(var, varRequest);
715 break;
722 break;
716 }
723 }
717 case VariableRequestHandlerState::RUNNING: {
724 case VariableRequestHandlerState::RUNNING: {
718 qCDebug(LOG_VariableController()) << tr("Process Request RUNNING")
725 qCDebug(LOG_VariableController()) << tr("Process Request RUNNING")
719 << varRequest.m_RangeRequested
726 << varRequest.m_RangeRequested
720 << varRequest.m_CacheRangeRequested;
727 << varRequest.m_CacheRangeRequested;
721 varHandler->m_State = VariableRequestHandlerState::PENDING;
728 varHandler->m_State = VariableRequestHandlerState::PENDING;
722 varHandler->m_PendingVarRequest = varRequest;
729 varHandler->m_PendingVarRequest = varRequest;
723 break;
730 break;
724 }
731 }
725 case VariableRequestHandlerState::PENDING: {
732 case VariableRequestHandlerState::PENDING: {
726 qCDebug(LOG_VariableController()) << tr("Process Request PENDING")
733 qCDebug(LOG_VariableController()) << tr("Process Request PENDING")
727 << varRequest.m_RangeRequested
734 << varRequest.m_RangeRequested
728 << varRequest.m_CacheRangeRequested;
735 << varRequest.m_CacheRangeRequested;
729 auto variableGroupIdToCancel = varHandler->m_PendingVarRequest.m_VariableGroupId;
736 auto variableGroupIdToCancel = varHandler->m_PendingVarRequest.m_VariableGroupId;
730 cancelVariableRequest(variableGroupIdToCancel);
737 cancelVariableRequest(variableGroupIdToCancel);
731 // Cancel variable can make state downgrade
738 // Cancel variable can make state downgrade
732 varHandler->m_State = VariableRequestHandlerState::PENDING;
739 varHandler->m_State = VariableRequestHandlerState::PENDING;
733 varHandler->m_PendingVarRequest = varRequest;
740 varHandler->m_PendingVarRequest = varRequest;
734
741
735 break;
742 break;
736 }
743 }
737 default:
744 default:
738 qCCritical(LOG_VariableController())
745 qCCritical(LOG_VariableController())
739 << QObject::tr("Unknown VariableRequestHandlerState");
746 << QObject::tr("Unknown VariableRequestHandlerState");
740 }
747 }
741 }
748 }
742
749
743 std::shared_ptr<Variable>
750 std::shared_ptr<Variable>
744 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
751 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
745 {
752 {
746 std::shared_ptr<Variable> var;
753 std::shared_ptr<Variable> var;
747 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
754 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
748
755
749 auto end = m_VariableToIdentifierMap.cend();
756 auto end = m_VariableToIdentifierMap.cend();
750 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
757 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
751 if (it != end) {
758 if (it != end) {
752 var = it->first;
759 var = it->first;
753 }
760 }
754 else {
761 else {
755 qCCritical(LOG_VariableController())
762 qCCritical(LOG_VariableController())
756 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
763 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
757 }
764 }
758
765
759 return var;
766 return var;
760 }
767 }
761
768
762 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
769 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
763 const QVector<AcquisitionDataPacket> acqDataPacketVector)
770 const QVector<AcquisitionDataPacket> acqDataPacketVector)
764 {
771 {
765 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
772 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
766 << acqDataPacketVector.size();
773 << acqDataPacketVector.size();
767 std::shared_ptr<IDataSeries> dataSeries;
774 std::shared_ptr<IDataSeries> dataSeries;
768 if (!acqDataPacketVector.isEmpty()) {
775 if (!acqDataPacketVector.isEmpty()) {
769 dataSeries = acqDataPacketVector[0].m_DateSeries;
776 dataSeries = acqDataPacketVector[0].m_DateSeries;
770 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
777 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
771 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
778 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
772 }
779 }
773 }
780 }
774 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
781 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
775 << acqDataPacketVector.size();
782 << acqDataPacketVector.size();
776 return dataSeries;
783 return dataSeries;
777 }
784 }
778
785
779 void VariableController::VariableControllerPrivate::registerProvider(
786 void VariableController::VariableControllerPrivate::registerProvider(
780 std::shared_ptr<IDataProvider> provider)
787 std::shared_ptr<IDataProvider> provider)
781 {
788 {
782 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
789 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
783 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
790 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
784 << provider->objectName();
791 << provider->objectName();
785 m_ProviderSet.insert(provider);
792 m_ProviderSet.insert(provider);
786 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
793 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
787 &VariableAcquisitionWorker::onVariableDataAcquired);
794 &VariableAcquisitionWorker::onVariableDataAcquired);
788 connect(provider.get(), &IDataProvider::dataProvidedProgress,
795 connect(provider.get(), &IDataProvider::dataProvidedProgress,
789 m_VariableAcquisitionWorker.get(),
796 m_VariableAcquisitionWorker.get(),
790 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
797 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
791 connect(provider.get(), &IDataProvider::dataProvidedFailed,
798 connect(provider.get(), &IDataProvider::dataProvidedFailed,
792 m_VariableAcquisitionWorker.get(),
799 m_VariableAcquisitionWorker.get(),
793 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
800 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
794 }
801 }
795 else {
802 else {
796 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
803 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
797 }
804 }
798 }
805 }
799
806
800 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
807 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
801 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
808 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
802 {
809 {
803 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
810 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
804 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
811 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
805 return QUuid();
812 return QUuid();
806 }
813 }
807
814
808 auto varHandler = itVarHandler->second.get();
815 auto varHandler = itVarHandler->second.get();
809 if (varHandler->m_State == VariableRequestHandlerState::OFF) {
816 if (varHandler->m_State == VariableRequestHandlerState::OFF) {
810 qCCritical(LOG_VariableController())
817 qCCritical(LOG_VariableController())
811 << tr("acceptVariableRequest impossible on a variable with OFF state");
818 << tr("acceptVariableRequest impossible on a variable with OFF state");
812 }
819 }
813
820
814 varHandler->m_RunningVarRequest.m_DataSeries = dataSeries;
821 varHandler->m_RunningVarRequest.m_DataSeries = dataSeries;
815 varHandler->m_CanUpdate = true;
822 varHandler->m_CanUpdate = true;
816
823
817 // Element traité, on a déjà toutes les données necessaires
824 // Element traité, on a déjà toutes les données necessaires
818 auto varGroupId = varHandler->m_RunningVarRequest.m_VariableGroupId;
825 auto varGroupId = varHandler->m_RunningVarRequest.m_VariableGroupId;
819 qCDebug(LOG_VariableController()) << "Variable::acceptVariableRequest" << varGroupId
826 qCDebug(LOG_VariableController()) << "Variable::acceptVariableRequest" << varGroupId
820 << m_VarGroupIdToVarIds.size();
827 << m_VarGroupIdToVarIds.size();
821
828
822 return varHandler->m_RunningVarRequest.m_VariableGroupId;
829 return varHandler->m_RunningVarRequest.m_VariableGroupId;
823 }
830 }
824
831
825 void VariableController::VariableControllerPrivate::updateVariables(QUuid varRequestId)
832 void VariableController::VariableControllerPrivate::updateVariables(QUuid varRequestId)
826 {
833 {
827 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
834 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
828 << QThread::currentThread()->objectName() << varRequestId;
835 << QThread::currentThread()->objectName() << varRequestId;
829
836
830 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
837 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
831 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
838 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
832 qCWarning(LOG_VariableController())
839 qCWarning(LOG_VariableController())
833 << tr("Impossible to updateVariables of unknown variables") << varRequestId;
840 << tr("Impossible to updateVariables of unknown variables") << varRequestId;
834 return;
841 return;
835 }
842 }
836
843
837 auto &varIds = varGroupIdToVarIdsIt->second;
844 auto &varIds = varGroupIdToVarIdsIt->second;
838 auto varIdsEnd = varIds.end();
845 auto varIdsEnd = varIds.end();
839 bool processVariableUpdate = true;
846 bool processVariableUpdate = true;
840 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
847 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
841 << varRequestId << varIds.size();
848 << varRequestId << varIds.size();
842 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd) && processVariableUpdate;
849 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd) && processVariableUpdate;
843 ++varIdsIt) {
850 ++varIdsIt) {
844 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
851 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
845 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
852 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
846 processVariableUpdate &= itVarHandler->second->m_CanUpdate;
853 processVariableUpdate &= itVarHandler->second->m_CanUpdate;
847 }
854 }
848 }
855 }
849
856
850 if (processVariableUpdate) {
857 if (processVariableUpdate) {
851 qCDebug(LOG_VariableController()) << "Final update OK for the var request" << varIds.size();
858 qCDebug(LOG_VariableController()) << "Final update OK for the var request" << varIds.size();
852 for (auto varIdsIt = varIds.begin(); varIdsIt != varIdsEnd; ++varIdsIt) {
859 for (auto varIdsIt = varIds.begin(); varIdsIt != varIdsEnd; ++varIdsIt) {
853 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
860 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
854 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
861 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
855 if (auto var = findVariable(*varIdsIt)) {
862 if (auto var = findVariable(*varIdsIt)) {
856 auto &varRequest = itVarHandler->second->m_RunningVarRequest;
863 auto &varRequest = itVarHandler->second->m_RunningVarRequest;
857 var->setRange(varRequest.m_RangeRequested);
864 var->setRange(varRequest.m_RangeRequested);
858 var->setCacheRange(varRequest.m_CacheRangeRequested);
865 var->setCacheRange(varRequest.m_CacheRangeRequested);
859 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
866 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
860 << varRequest.m_RangeRequested
867 << varRequest.m_RangeRequested
861 << varRequest.m_CacheRangeRequested;
868 << varRequest.m_CacheRangeRequested;
862 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
869 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
863 << var->nbPoints()
870 << var->nbPoints()
864 << varRequest.m_DataSeries->nbPoints();
871 << varRequest.m_DataSeries->nbPoints();
865 var->mergeDataSeries(varRequest.m_DataSeries);
872 var->mergeDataSeries(varRequest.m_DataSeries);
866 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
873 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
867 << var->nbPoints();
874 << var->nbPoints();
868
875
869 emit var->updated();
876 emit var->updated();
870 qCDebug(LOG_VariableController()) << tr("Update OK");
877 qCDebug(LOG_VariableController()) << tr("Update OK");
871 }
878 }
872 else {
879 else {
873 qCCritical(LOG_VariableController())
880 qCCritical(LOG_VariableController())
874 << tr("Impossible to update data to a null variable");
881 << tr("Impossible to update data to a null variable");
875 }
882 }
876 }
883 }
877 }
884 }
878 updateVariableRequest(varRequestId);
885 updateVariableRequest(varRequestId);
879
886
880 // cleaning varRequestId
887 // cleaning varRequestId
881 qCDebug(LOG_VariableController()) << tr("m_VarGroupIdToVarIds erase") << varRequestId;
888 qCDebug(LOG_VariableController()) << tr("m_VarGroupIdToVarIds erase") << varRequestId;
882 m_VarGroupIdToVarIds.erase(varRequestId);
889 m_VarGroupIdToVarIds.erase(varRequestId);
883 }
890 }
884 }
891 }
885
892
886
893
887 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
894 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
888 {
895 {
889 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
896 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
890 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
897 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
891 qCCritical(LOG_VariableController()) << QObject::tr(
898 qCCritical(LOG_VariableController()) << QObject::tr(
892 "Impossible to updateVariableRequest since varGroupdId isn't here anymore");
899 "Impossible to updateVariableRequest since varGroupdId isn't here anymore");
893
900
894 return;
901 return;
895 }
902 }
896
903
897 auto &varIds = varGroupIdToVarIdsIt->second;
904 auto &varIds = varGroupIdToVarIdsIt->second;
898 auto varIdsEnd = varIds.end();
905 auto varIdsEnd = varIds.end();
899 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
906 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
900 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
907 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
901 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
908 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
902
909
903 auto varHandler = itVarHandler->second.get();
910 auto varHandler = itVarHandler->second.get();
904 varHandler->m_CanUpdate = false;
911 varHandler->m_CanUpdate = false;
905
912
906
913
907 switch (varHandler->m_State) {
914 switch (varHandler->m_State) {
908 case VariableRequestHandlerState::OFF: {
915 case VariableRequestHandlerState::OFF: {
909 qCCritical(LOG_VariableController())
916 qCCritical(LOG_VariableController())
910 << QObject::tr("Impossible to update a variable with handler in OFF state");
917 << QObject::tr("Impossible to update a variable with handler in OFF state");
911 } break;
918 } break;
912 case VariableRequestHandlerState::RUNNING: {
919 case VariableRequestHandlerState::RUNNING: {
913 varHandler->m_State = VariableRequestHandlerState::OFF;
920 varHandler->m_State = VariableRequestHandlerState::OFF;
914 varHandler->m_RunningVarRequest = VariableRequest{};
921 varHandler->m_RunningVarRequest = VariableRequest{};
915 break;
922 break;
916 }
923 }
917 case VariableRequestHandlerState::PENDING: {
924 case VariableRequestHandlerState::PENDING: {
918 varHandler->m_State = VariableRequestHandlerState::RUNNING;
925 varHandler->m_State = VariableRequestHandlerState::RUNNING;
919 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
926 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
920 varHandler->m_PendingVarRequest = VariableRequest{};
927 varHandler->m_PendingVarRequest = VariableRequest{};
921 auto var = findVariable(itVarHandler->first);
928 auto var = findVariable(itVarHandler->first);
922 executeVarRequest(var, varHandler->m_RunningVarRequest);
929 executeVarRequest(var, varHandler->m_RunningVarRequest);
923 break;
930 break;
924 }
931 }
925 default:
932 default:
926 qCCritical(LOG_VariableController())
933 qCCritical(LOG_VariableController())
927 << QObject::tr("Unknown VariableRequestHandlerState");
934 << QObject::tr("Unknown VariableRequestHandlerState");
928 }
935 }
929 }
936 }
930 }
937 }
931 }
938 }
932
939
933
940
934 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
941 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
935 {
942 {
936 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest") << varRequestId;
943 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest") << varRequestId;
937
944
938 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
945 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
939 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
946 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
940 qCCritical(LOG_VariableController())
947 qCCritical(LOG_VariableController())
941 << tr("Impossible to cancelVariableRequest for unknown varGroupdId") << varRequestId;
948 << tr("Impossible to cancelVariableRequest for unknown varGroupdId") << varRequestId;
942 return;
949 return;
943 }
950 }
944
951
945 auto &varIds = varGroupIdToVarIdsIt->second;
952 auto &varIds = varGroupIdToVarIdsIt->second;
946 auto varIdsEnd = varIds.end();
953 auto varIdsEnd = varIds.end();
947 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
954 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
948 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
955 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
949 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
956 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
950
957
951 auto varHandler = itVarHandler->second.get();
958 auto varHandler = itVarHandler->second.get();
952 varHandler->m_VarId = QUuid{};
959 varHandler->m_VarId = QUuid{};
953 switch (varHandler->m_State) {
960 switch (varHandler->m_State) {
954 case VariableRequestHandlerState::OFF: {
961 case VariableRequestHandlerState::OFF: {
955 qCWarning(LOG_VariableController())
962 qCWarning(LOG_VariableController())
956 << QObject::tr("Impossible to cancel a variable with no running request");
963 << QObject::tr("Impossible to cancel a variable with no running request");
957 break;
964 break;
958 }
965 }
959 case VariableRequestHandlerState::RUNNING: {
966 case VariableRequestHandlerState::RUNNING: {
960
967
961 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
968 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
962 auto var = findVariable(itVarHandler->first);
969 auto var = findVariable(itVarHandler->first);
963 auto varProvider = m_VariableToProviderMap.at(var);
970 auto varProvider = m_VariableToProviderMap.at(var);
964 if (varProvider != nullptr) {
971 if (varProvider != nullptr) {
965 m_VariableAcquisitionWorker->abortProgressRequested(
972 m_VariableAcquisitionWorker->abortProgressRequested(
966 itVarHandler->first);
973 itVarHandler->first);
967 }
974 }
968 m_VariableModel->setDataProgress(var, 0.0);
975 m_VariableModel->setDataProgress(var, 0.0);
969 varHandler->m_CanUpdate = false;
976 varHandler->m_CanUpdate = false;
970 varHandler->m_State = VariableRequestHandlerState::OFF;
977 varHandler->m_State = VariableRequestHandlerState::OFF;
971 varHandler->m_RunningVarRequest = VariableRequest{};
978 varHandler->m_RunningVarRequest = VariableRequest{};
972 }
979 }
973 else {
980 else {
974 // TODO: log Impossible to cancel the running variable request beacause its
981 // TODO: log Impossible to cancel the running variable request beacause its
975 // varRequestId isn't not the canceled one
982 // varRequestId isn't not the canceled one
976 }
983 }
977 break;
984 break;
978 }
985 }
979 case VariableRequestHandlerState::PENDING: {
986 case VariableRequestHandlerState::PENDING: {
980 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
987 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
981 auto var = findVariable(itVarHandler->first);
988 auto var = findVariable(itVarHandler->first);
982 auto varProvider = m_VariableToProviderMap.at(var);
989 auto varProvider = m_VariableToProviderMap.at(var);
983 if (varProvider != nullptr) {
990 if (varProvider != nullptr) {
984 m_VariableAcquisitionWorker->abortProgressRequested(
991 m_VariableAcquisitionWorker->abortProgressRequested(
985 itVarHandler->first);
992 itVarHandler->first);
986 }
993 }
987 m_VariableModel->setDataProgress(var, 0.0);
994 m_VariableModel->setDataProgress(var, 0.0);
988 varHandler->m_CanUpdate = false;
995 varHandler->m_CanUpdate = false;
989 varHandler->m_State = VariableRequestHandlerState::RUNNING;
996 varHandler->m_State = VariableRequestHandlerState::RUNNING;
990 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
997 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
991 varHandler->m_PendingVarRequest = VariableRequest{};
998 varHandler->m_PendingVarRequest = VariableRequest{};
992 executeVarRequest(var, varHandler->m_RunningVarRequest);
999 executeVarRequest(var, varHandler->m_RunningVarRequest);
993 }
1000 }
994 else if (varHandler->m_PendingVarRequest.m_VariableGroupId == varRequestId) {
1001 else if (varHandler->m_PendingVarRequest.m_VariableGroupId == varRequestId) {
995 varHandler->m_State = VariableRequestHandlerState::RUNNING;
1002 varHandler->m_State = VariableRequestHandlerState::RUNNING;
996 varHandler->m_PendingVarRequest = VariableRequest{};
1003 varHandler->m_PendingVarRequest = VariableRequest{};
997 }
1004 }
998 else {
1005 else {
999 // TODO: log Impossible to cancel the variable request beacause its
1006 // TODO: log Impossible to cancel the variable request beacause its
1000 // varRequestId isn't not the canceled one
1007 // varRequestId isn't not the canceled one
1001 }
1008 }
1002 break;
1009 break;
1003 }
1010 }
1004 default:
1011 default:
1005 qCCritical(LOG_VariableController())
1012 qCCritical(LOG_VariableController())
1006 << QObject::tr("Unknown VariableRequestHandlerState");
1013 << QObject::tr("Unknown VariableRequestHandlerState");
1007 }
1014 }
1008 }
1015 }
1009 }
1016 }
1010 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest: erase") << varRequestId;
1017 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest: erase") << varRequestId;
1011 m_VarGroupIdToVarIds.erase(varRequestId);
1018 m_VarGroupIdToVarIds.erase(varRequestId);
1012 }
1019 }
1013
1020
1014 void VariableController::VariableControllerPrivate::executeVarRequest(std::shared_ptr<Variable> var,
1021 void VariableController::VariableControllerPrivate::executeVarRequest(std::shared_ptr<Variable> var,
1015 VariableRequest &varRequest)
1022 VariableRequest &varRequest)
1016 {
1023 {
1017 qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest");
1024 qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest");
1018
1025
1019 auto varId = m_VariableToIdentifierMap.at(var);
1026 auto varId = m_VariableToIdentifierMap.at(var);
1020
1027
1021 auto varCacheRange = var->cacheRange();
1028 auto varCacheRange = var->cacheRange();
1022 auto varCacheRangeRequested = varRequest.m_CacheRangeRequested;
1029 auto varCacheRangeRequested = varRequest.m_CacheRangeRequested;
1023 auto notInCacheRangeList
1030 auto notInCacheRangeList
1024 = Variable::provideNotInCacheRangeList(varCacheRange, varCacheRangeRequested);
1031 = Variable::provideNotInCacheRangeList(varCacheRange, varCacheRangeRequested);
1025 auto inCacheRangeList
1032 auto inCacheRangeList
1026 = Variable::provideInCacheRangeList(varCacheRange, varCacheRangeRequested);
1033 = Variable::provideInCacheRangeList(varCacheRange, varCacheRangeRequested);
1027
1034
1028 if (!notInCacheRangeList.empty()) {
1035 if (!notInCacheRangeList.empty()) {
1029
1036
1030 auto varProvider = m_VariableToProviderMap.at(var);
1037 auto varProvider = m_VariableToProviderMap.at(var);
1031 if (varProvider != nullptr) {
1038 if (varProvider != nullptr) {
1032 qCDebug(LOG_VariableController()) << "executeVarRequest " << varRequest.m_RangeRequested
1039 qCDebug(LOG_VariableController()) << "executeVarRequest " << varRequest.m_RangeRequested
1033 << varRequest.m_CacheRangeRequested;
1040 << varRequest.m_CacheRangeRequested;
1034 m_VariableAcquisitionWorker->pushVariableRequest(
1041 m_VariableAcquisitionWorker->pushVariableRequest(
1035 varRequest.m_VariableGroupId, varId, varRequest.m_RangeRequested,
1042 varRequest.m_VariableGroupId, varId, varRequest.m_RangeRequested,
1036 varRequest.m_CacheRangeRequested,
1043 varRequest.m_CacheRangeRequested,
1037 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
1044 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
1038 varProvider);
1045 varProvider);
1039 }
1046 }
1040 else {
1047 else {
1041 qCCritical(LOG_VariableController())
1048 qCCritical(LOG_VariableController())
1042 << "Impossible to provide data with a null provider";
1049 << "Impossible to provide data with a null provider";
1043 }
1050 }
1044
1051
1045 if (!inCacheRangeList.empty()) {
1052 if (!inCacheRangeList.empty()) {
1046 emit q->updateVarDisplaying(var, inCacheRangeList.first());
1053 emit q->updateVarDisplaying(var, inCacheRangeList.first());
1047 }
1054 }
1048 }
1055 }
1049 else {
1056 else {
1050 acceptVariableRequest(varId,
1057 acceptVariableRequest(varId,
1051 var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested));
1058 var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested));
1052 }
1059 }
1053 }
1060 }
@@ -1,383 +1,394
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableController.h>
2 #include <Variable/VariableController.h>
3 #include <Variable/VariableModel.h>
3 #include <Variable/VariableModel.h>
4
4
5 #include <Common/DateUtils.h>
5 #include <Common/DateUtils.h>
6 #include <Common/MimeTypesDef.h>
6 #include <Common/MimeTypesDef.h>
7 #include <Common/StringUtils.h>
7 #include <Common/StringUtils.h>
8
8
9 #include <Data/IDataSeries.h>
9 #include <Data/IDataSeries.h>
10
10
11 #include <DataSource/DataSourceController.h>
11 #include <DataSource/DataSourceController.h>
12 #include <Time/TimeController.h>
12 #include <Time/TimeController.h>
13
13
14 #include <QMimeData>
14 #include <QMimeData>
15 #include <QSize>
15 #include <QSize>
16 #include <QTimer>
16 #include <unordered_map>
17 #include <unordered_map>
17
18
18 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
19 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
19
20
20 namespace {
21 namespace {
21
22
22 // Column indexes
23 // Column indexes
23 const auto NAME_COLUMN = 0;
24 const auto NAME_COLUMN = 0;
24 const auto TSTART_COLUMN = 1;
25 const auto TSTART_COLUMN = 1;
25 const auto TEND_COLUMN = 2;
26 const auto TEND_COLUMN = 2;
26 const auto NBPOINTS_COLUMN = 3;
27 const auto NBPOINTS_COLUMN = 3;
27 const auto UNIT_COLUMN = 4;
28 const auto UNIT_COLUMN = 4;
28 const auto MISSION_COLUMN = 5;
29 const auto MISSION_COLUMN = 5;
29 const auto PLUGIN_COLUMN = 6;
30 const auto PLUGIN_COLUMN = 6;
30 const auto NB_COLUMNS = 7;
31 const auto NB_COLUMNS = 7;
31
32
32 // Column properties
33 // Column properties
33 const auto DEFAULT_HEIGHT = 25;
34 const auto DEFAULT_HEIGHT = 25;
34 const auto DEFAULT_WIDTH = 100;
35 const auto DEFAULT_WIDTH = 100;
35
36
36 struct ColumnProperties {
37 struct ColumnProperties {
37 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
38 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
38 int height = DEFAULT_HEIGHT)
39 int height = DEFAULT_HEIGHT)
39 : m_Name{name}, m_Width{width}, m_Height{height}
40 : m_Name{name}, m_Width{width}, m_Height{height}
40 {
41 {
41 }
42 }
42
43
43 QString m_Name;
44 QString m_Name;
44 int m_Width;
45 int m_Width;
45 int m_Height;
46 int m_Height;
46 };
47 };
47
48
48 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
49 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
49 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
50 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
50 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
51 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
51 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
52 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
52 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
53 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
53
54
54 /// Format for datetimes
55 /// Format for datetimes
55 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
56 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
56
57
57 QString uniqueName(const QString &defaultName,
58 QString uniqueName(const QString &defaultName,
58 const std::vector<std::shared_ptr<Variable> > &variables)
59 const std::vector<std::shared_ptr<Variable> > &variables)
59 {
60 {
60 auto forbiddenNames = std::vector<QString>(variables.size());
61 auto forbiddenNames = std::vector<QString>(variables.size());
61 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
62 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
62 [](const auto &variable) { return variable->name(); });
63 [](const auto &variable) { return variable->name(); });
63 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
64 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
64 Q_ASSERT(!uniqueName.isEmpty());
65 Q_ASSERT(!uniqueName.isEmpty());
65
66
66 return uniqueName;
67 return uniqueName;
67 }
68 }
68
69
69 } // namespace
70 } // namespace
70
71
71 struct VariableModel::VariableModelPrivate {
72 struct VariableModel::VariableModelPrivate {
72 /// Variables created in SciQlop
73 /// Variables created in SciQlop
73 std::vector<std::shared_ptr<Variable> > m_Variables;
74 std::vector<std::shared_ptr<Variable> > m_Variables;
74 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
75 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
75 VariableController *m_VariableController;
76 VariableController *m_VariableController;
76
77
77 /// Return the row index of the variable. -1 if it's not found
78 /// Return the row index of the variable. -1 if it's not found
78 int indexOfVariable(Variable *variable) const noexcept;
79 int indexOfVariable(Variable *variable) const noexcept;
79 };
80 };
80
81
81 VariableModel::VariableModel(VariableController *parent)
82 VariableModel::VariableModel(VariableController *parent)
82 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
83 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
83 {
84 {
84 impl->m_VariableController = parent;
85 impl->m_VariableController = parent;
85 }
86 }
86
87
87 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
88 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
88 {
89 {
89 auto insertIndex = rowCount();
90 auto insertIndex = rowCount();
90 beginInsertRows({}, insertIndex, insertIndex);
91 beginInsertRows({}, insertIndex, insertIndex);
91
92
92 // Generates unique name for the variable
93 // Generates unique name for the variable
93 variable->setName(uniqueName(variable->name(), impl->m_Variables));
94 variable->setName(uniqueName(variable->name(), impl->m_Variables));
94
95
95 impl->m_Variables.push_back(variable);
96 impl->m_Variables.push_back(variable);
96 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
97 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
97
98
98 endInsertRows();
99 endInsertRows();
99 }
100 }
100
101
101 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
102 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
102 {
103 {
103 auto end = impl->m_Variables.cend();
104 auto end = impl->m_Variables.cend();
104 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
105 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
105 }
106 }
106
107
107 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
108 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
108 const QVariantHash &metadata) noexcept
109 const QVariantHash &metadata) noexcept
109 {
110 {
110 auto variable = std::make_shared<Variable>(name, metadata);
111 auto variable = std::make_shared<Variable>(name, metadata);
111 addVariable(variable);
112 addVariable(variable);
112
113
113 return variable;
114 return variable;
114 }
115 }
115
116
116 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
117 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
117 {
118 {
118 if (!variable) {
119 if (!variable) {
119 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
120 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
120 return;
121 return;
121 }
122 }
122
123
123 // Finds variable in the model
124 // Finds variable in the model
124 auto begin = impl->m_Variables.cbegin();
125 auto begin = impl->m_Variables.cbegin();
125 auto end = impl->m_Variables.cend();
126 auto end = impl->m_Variables.cend();
126 auto it = std::find(begin, end, variable);
127 auto it = std::find(begin, end, variable);
127 if (it != end) {
128 if (it != end) {
128 auto removeIndex = std::distance(begin, it);
129 auto removeIndex = std::distance(begin, it);
129
130
130 // Deletes variable
131 // Deletes variable
131 beginRemoveRows({}, removeIndex, removeIndex);
132 beginRemoveRows({}, removeIndex, removeIndex);
132 impl->m_Variables.erase(it);
133 impl->m_Variables.erase(it);
133 endRemoveRows();
134 endRemoveRows();
134 }
135 }
135 else {
136 else {
136 qCritical(LOG_VariableModel())
137 qCritical(LOG_VariableModel())
137 << tr("Can't delete variable %1 from the model: the variable is not in the model")
138 << tr("Can't delete variable %1 from the model: the variable is not in the model")
138 .arg(variable->name());
139 .arg(variable->name());
139 }
140 }
140
141
141 // Removes variable from progress map
142 // Removes variable from progress map
142 impl->m_VariableToProgress.erase(variable);
143 impl->m_VariableToProgress.erase(variable);
143 }
144 }
144
145
145
146
146 std::shared_ptr<Variable> VariableModel::variable(int index) const
147 std::shared_ptr<Variable> VariableModel::variable(int index) const
147 {
148 {
148 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
149 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
149 }
150 }
150
151
151 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
152 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
152 {
153 {
153 return impl->m_Variables;
154 return impl->m_Variables;
154 }
155 }
155
156
156 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
157 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
157 {
158 {
158 if (progress > 0.0) {
159 if (progress > 0.0) {
159 impl->m_VariableToProgress[variable] = progress;
160 impl->m_VariableToProgress[variable] = progress;
160 }
161 }
161 else {
162 else {
162 impl->m_VariableToProgress.erase(variable);
163 impl->m_VariableToProgress.erase(variable);
163 }
164 }
164 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
165 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
165
166
166 emit dataChanged(modelIndex, modelIndex);
167 emit dataChanged(modelIndex, modelIndex);
167 }
168 }
168
169
169 int VariableModel::columnCount(const QModelIndex &parent) const
170 int VariableModel::columnCount(const QModelIndex &parent) const
170 {
171 {
171 Q_UNUSED(parent);
172 Q_UNUSED(parent);
172
173
173 return NB_COLUMNS;
174 return NB_COLUMNS;
174 }
175 }
175
176
176 int VariableModel::rowCount(const QModelIndex &parent) const
177 int VariableModel::rowCount(const QModelIndex &parent) const
177 {
178 {
178 Q_UNUSED(parent);
179 Q_UNUSED(parent);
179
180
180 return impl->m_Variables.size();
181 return impl->m_Variables.size();
181 }
182 }
182
183
183 QVariant VariableModel::data(const QModelIndex &index, int role) const
184 QVariant VariableModel::data(const QModelIndex &index, int role) const
184 {
185 {
185 if (!index.isValid()) {
186 if (!index.isValid()) {
186 return QVariant{};
187 return QVariant{};
187 }
188 }
188
189
189 if (index.row() < 0 || index.row() >= rowCount()) {
190 if (index.row() < 0 || index.row() >= rowCount()) {
190 return QVariant{};
191 return QVariant{};
191 }
192 }
192
193
193 if (role == Qt::DisplayRole) {
194 if (role == Qt::DisplayRole) {
194 if (auto variable = impl->m_Variables.at(index.row()).get()) {
195 if (auto variable = impl->m_Variables.at(index.row()).get()) {
195 switch (index.column()) {
196 switch (index.column()) {
196 case NAME_COLUMN:
197 case NAME_COLUMN:
197 return variable->name();
198 return variable->name();
198 case TSTART_COLUMN: {
199 case TSTART_COLUMN: {
199 auto range = variable->realRange();
200 auto range = variable->realRange();
200 return range != INVALID_RANGE
201 return range != INVALID_RANGE
201 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
202 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
202 : QVariant{};
203 : QVariant{};
203 }
204 }
204 case TEND_COLUMN: {
205 case TEND_COLUMN: {
205 auto range = variable->realRange();
206 auto range = variable->realRange();
206 return range != INVALID_RANGE
207 return range != INVALID_RANGE
207 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
208 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
208 : QVariant{};
209 : QVariant{};
209 }
210 }
210 case NBPOINTS_COLUMN:
211 case NBPOINTS_COLUMN:
211 return variable->nbPoints();
212 return variable->nbPoints();
212 case UNIT_COLUMN:
213 case UNIT_COLUMN:
213 return variable->metadata().value(QStringLiteral("units"));
214 return variable->metadata().value(QStringLiteral("units"));
214 case MISSION_COLUMN:
215 case MISSION_COLUMN:
215 return variable->metadata().value(QStringLiteral("mission"));
216 return variable->metadata().value(QStringLiteral("mission"));
216 case PLUGIN_COLUMN:
217 case PLUGIN_COLUMN:
217 return variable->metadata().value(QStringLiteral("plugin"));
218 return variable->metadata().value(QStringLiteral("plugin"));
218 default:
219 default:
219 // No action
220 // No action
220 break;
221 break;
221 }
222 }
222
223
223 qWarning(LOG_VariableModel())
224 qWarning(LOG_VariableModel())
224 << tr("Can't get data (unknown column %1)").arg(index.column());
225 << tr("Can't get data (unknown column %1)").arg(index.column());
225 }
226 }
226 else {
227 else {
227 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
228 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
228 }
229 }
229 }
230 }
230 else if (role == VariableRoles::ProgressRole) {
231 else if (role == VariableRoles::ProgressRole) {
231 if (auto variable = impl->m_Variables.at(index.row())) {
232 if (auto variable = impl->m_Variables.at(index.row())) {
232
233
233 auto it = impl->m_VariableToProgress.find(variable);
234 auto it = impl->m_VariableToProgress.find(variable);
234 if (it != impl->m_VariableToProgress.cend()) {
235 if (it != impl->m_VariableToProgress.cend()) {
235 return it->second;
236 return it->second;
236 }
237 }
237 }
238 }
238 }
239 }
239
240
240 return QVariant{};
241 return QVariant{};
241 }
242 }
242
243
243 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
244 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
244 {
245 {
245 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
246 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
246 return QVariant{};
247 return QVariant{};
247 }
248 }
248
249
249 if (orientation == Qt::Horizontal) {
250 if (orientation == Qt::Horizontal) {
250 auto propertiesIt = COLUMN_PROPERTIES.find(section);
251 auto propertiesIt = COLUMN_PROPERTIES.find(section);
251 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
252 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
252 // Role is either DisplayRole or SizeHintRole
253 // Role is either DisplayRole or SizeHintRole
253 return (role == Qt::DisplayRole)
254 return (role == Qt::DisplayRole)
254 ? QVariant{propertiesIt->m_Name}
255 ? QVariant{propertiesIt->m_Name}
255 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
256 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
256 }
257 }
257 else {
258 else {
258 qWarning(LOG_VariableModel())
259 qWarning(LOG_VariableModel())
259 << tr("Can't get header data (unknown column %1)").arg(section);
260 << tr("Can't get header data (unknown column %1)").arg(section);
260 }
261 }
261 }
262 }
262
263
263 return QVariant{};
264 return QVariant{};
264 }
265 }
265
266
266 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
267 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
267 {
268 {
268 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
269 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
269 }
270 }
270
271
271 Qt::DropActions VariableModel::supportedDropActions() const
272 Qt::DropActions VariableModel::supportedDropActions() const
272 {
273 {
273 return Qt::CopyAction | Qt::MoveAction;
274 return Qt::CopyAction | Qt::MoveAction;
274 }
275 }
275
276
276 Qt::DropActions VariableModel::supportedDragActions() const
277 Qt::DropActions VariableModel::supportedDragActions() const
277 {
278 {
278 return Qt::CopyAction | Qt::MoveAction;
279 return Qt::CopyAction | Qt::MoveAction;
279 }
280 }
280
281
281 QStringList VariableModel::mimeTypes() const
282 QStringList VariableModel::mimeTypes() const
282 {
283 {
283 return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE};
284 return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE};
284 }
285 }
285
286
286 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
287 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
287 {
288 {
288 auto mimeData = new QMimeData;
289 auto mimeData = new QMimeData;
289
290
290 QList<std::shared_ptr<Variable> > variableList;
291 QList<std::shared_ptr<Variable> > variableList;
291
292
292
293
293 SqpRange firstTimeRange;
294 SqpRange firstTimeRange;
294 for (const auto &index : indexes) {
295 for (const auto &index : indexes) {
295 if (index.column() == 0) { // only the first column
296 if (index.column() == 0) { // only the first column
296 auto variable = impl->m_Variables.at(index.row());
297 auto variable = impl->m_Variables.at(index.row());
297 if (variable.get() && index.isValid()) {
298 if (variable.get() && index.isValid()) {
298
299
299 if (variableList.isEmpty()) {
300 if (variableList.isEmpty()) {
300 // Gets the range of the first variable
301 // Gets the range of the first variable
301 firstTimeRange = std::move(variable->range());
302 firstTimeRange = std::move(variable->range());
302 }
303 }
303
304
304 variableList << variable;
305 variableList << variable;
305 }
306 }
306 }
307 }
307 }
308 }
308
309
309 auto variablesEncodedData = impl->m_VariableController->mimeDataForVariables(variableList);
310 auto variablesEncodedData = impl->m_VariableController->mimeDataForVariables(variableList);
310 mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData);
311 mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData);
311
312
312 if (variableList.count() == 1) {
313 if (variableList.count() == 1) {
313 // No time range MIME data if multiple variables are dragged
314 // No time range MIME data if multiple variables are dragged
314 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
315 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
315 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
316 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
316 }
317 }
317
318
318 return mimeData;
319 return mimeData;
319 }
320 }
320
321
321 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
322 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
322 int column, const QModelIndex &parent) const
323 int column, const QModelIndex &parent) const
323 {
324 {
324 // drop of a product
325 // drop of a product
325 return data->hasFormat(MIME_TYPE_PRODUCT_LIST);
326 return data->hasFormat(MIME_TYPE_PRODUCT_LIST)
327 || (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()
328 && !data->hasFormat(MIME_TYPE_VARIABLE_LIST));
326 }
329 }
327
330
328 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
331 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
329 const QModelIndex &parent)
332 const QModelIndex &parent)
330 {
333 {
331 auto dropDone = false;
334 auto dropDone = false;
332
335
333 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
336 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
334
337
335 auto productList
338 auto productList
336 = DataSourceController::productsDataForMimeData(data->data(MIME_TYPE_PRODUCT_LIST));
339 = DataSourceController::productsDataForMimeData(data->data(MIME_TYPE_PRODUCT_LIST));
337
340
338 for (auto metaData : productList) {
341 for (auto metaData : productList) {
339 emit requestVariable(metaData.toHash());
342 emit requestVariable(metaData.toHash());
340 }
343 }
341
344
342 dropDone = true;
345 dropDone = true;
343 }
346 }
347 else if (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()) {
348 auto variable = this->variable(parent.row());
349 auto range = TimeController::timeRangeForMimeData(data->data(MIME_TYPE_TIME_RANGE));
350
351 emit requestVariableRangeUpdate(variable, range);
352
353 dropDone = true;
354 }
344
355
345 return dropDone;
356 return dropDone;
346 }
357 }
347
358
348 void VariableModel::abortProgress(const QModelIndex &index)
359 void VariableModel::abortProgress(const QModelIndex &index)
349 {
360 {
350 if (auto variable = impl->m_Variables.at(index.row())) {
361 if (auto variable = impl->m_Variables.at(index.row())) {
351 emit abortProgessRequested(variable);
362 emit abortProgessRequested(variable);
352 }
363 }
353 }
364 }
354
365
355 void VariableModel::onVariableUpdated() noexcept
366 void VariableModel::onVariableUpdated() noexcept
356 {
367 {
357 // Finds variable that has been updated in the model
368 // Finds variable that has been updated in the model
358 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
369 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
359 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
370 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
360
371
361 if (updatedVariableIndex > -1) {
372 if (updatedVariableIndex > -1) {
362 emit dataChanged(createIndex(updatedVariableIndex, 0),
373 emit dataChanged(createIndex(updatedVariableIndex, 0),
363 createIndex(updatedVariableIndex, columnCount() - 1));
374 createIndex(updatedVariableIndex, columnCount() - 1));
364 }
375 }
365 }
376 }
366 }
377 }
367
378
368 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
379 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
369 {
380 {
370 auto begin = std::cbegin(m_Variables);
381 auto begin = std::cbegin(m_Variables);
371 auto end = std::cend(m_Variables);
382 auto end = std::cend(m_Variables);
372 auto it
383 auto it
373 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
384 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
374
385
375 if (it != end) {
386 if (it != end) {
376 // Gets the index of the variable in the model: we assume here that views have the same
387 // Gets the index of the variable in the model: we assume here that views have the same
377 // order as the model
388 // order as the model
378 return std::distance(begin, it);
389 return std::distance(begin, it);
379 }
390 }
380 else {
391 else {
381 return -1;
392 return -1;
382 }
393 }
383 }
394 }
@@ -1,18 +1,18
1 #ifndef SCIQLOP_MACSCROLLBARSTYLE_H
1 #ifndef SCIQLOP_MACSCROLLBARSTYLE_H
2 #define SCIQLOP_MACSCROLLBARSTYLE_H
2 #define SCIQLOP_MACSCROLLBARSTYLE_H
3
3
4 #include <QProxyStyle>
4 #include <QProxyStyle>
5
5
6 /**
6 /**
7 * @brief Special style to always display the scrollbars on MAC.
7 * @brief Special style to always display the scrollbars on MAC.
8 */
8 */
9 class MacScrollBarStyle : public QProxyStyle {
9 class MacScrollBarStyle : public QProxyStyle {
10
10
11 public:
11 public:
12 int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
12 int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
13 QStyleHintReturn *returnData) const;
13 QStyleHintReturn *returnData) const override;
14
14
15 void selfInstallOn(QWidget *widget, bool installOnSubWidgets);
15 void selfInstallOn(QWidget *widget, bool installOnSubWidgets);
16 };
16 };
17
17
18 #endif // SCIQLOP_MACSCROLLBARSTYLE_H
18 #endif // SCIQLOP_MACSCROLLBARSTYLE_H
@@ -1,57 +1,57
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 <QFrame>
5 #include <QFrame>
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QMimeData>
7 #include <QMimeData>
8 #include <QVBoxLayout>
8 #include <QVBoxLayout>
9
9
10 #include <functional>
10 #include <functional>
11
11
12 #include <DragAndDrop/DragDropHelper.h>
12 #include <DragAndDrop/DragDropHelper.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
15
15
16 class VisualizationDragWidget;
16 class VisualizationDragWidget;
17
17
18 class VisualizationDragDropContainer : public QFrame {
18 class VisualizationDragDropContainer : public QFrame {
19 Q_OBJECT
19 Q_OBJECT
20
20
21 signals:
21 signals:
22 void dropOccuredInContainer(int dropIndex, const QMimeData *mimeData);
22 void dropOccuredInContainer(int dropIndex, const QMimeData *mimeData);
23 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
23 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
24
24
25 public:
25 public:
26 enum class DropBehavior { Inserted, Merged, InsertedAndMerged };
26 enum class DropBehavior { Inserted, Merged, InsertedAndMerged, Forbidden };
27 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
27 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
28
28
29 VisualizationDragDropContainer(QWidget *parent = nullptr);
29 VisualizationDragDropContainer(QWidget *parent = nullptr);
30
30
31 void addDragWidget(VisualizationDragWidget *dragWidget);
31 void addDragWidget(VisualizationDragWidget *dragWidget);
32 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
32 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
33
33
34 void addAcceptedMimeType(const QString &mimeType, DropBehavior behavior);
34 void setMimeType(const QString &mimeType, DropBehavior behavior);
35
35
36 int countDragWidget() const;
36 int countDragWidget() const;
37
37
38 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
38 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
39
39
40 void setPlaceHolderType(DragDropHelper::PlaceHolderType type,
40 void setPlaceHolderType(DragDropHelper::PlaceHolderType type,
41 const QString &placeHolderText = QString());
41 const QString &placeHolderText = QString());
42
42
43 protected:
43 protected:
44 void dragEnterEvent(QDragEnterEvent *event);
44 void dragEnterEvent(QDragEnterEvent *event);
45 void dragLeaveEvent(QDragLeaveEvent *event);
45 void dragLeaveEvent(QDragLeaveEvent *event);
46 void dragMoveEvent(QDragMoveEvent *event);
46 void dragMoveEvent(QDragMoveEvent *event);
47 void dropEvent(QDropEvent *event);
47 void dropEvent(QDropEvent *event);
48
48
49 private:
49 private:
50 class VisualizationDragDropContainerPrivate;
50 class VisualizationDragDropContainerPrivate;
51 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
51 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
52
52
53 private slots:
53 private slots:
54 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
54 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
55 };
55 };
56
56
57 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
57 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
@@ -1,16 +1,17
1 <RCC>
1 <RCC>
2 <qresource prefix="/">
2 <qresource prefix="/">
3 <file>icones/dataSourceComponent.png</file>
3 <file>icones/dataSourceComponent.png</file>
4 <file>icones/dataSourceNode.png</file>
4 <file>icones/dataSourceNode.png</file>
5 <file>icones/dataSourceProduct.png</file>
5 <file>icones/dataSourceProduct.png</file>
6 <file>icones/dataSourceRoot.png</file>
6 <file>icones/dataSourceRoot.png</file>
7 <file>icones/delete.png</file>
7 <file>icones/delete.png</file>
8 <file>icones/down.png</file>
8 <file>icones/down.png</file>
9 <file>icones/openInspector.png</file>
9 <file>icones/openInspector.png</file>
10 <file>icones/next.png</file>
10 <file>icones/next.png</file>
11 <file>icones/plot.png</file>
11 <file>icones/plot.png</file>
12 <file>icones/previous.png</file>
12 <file>icones/previous.png</file>
13 <file>icones/unplot.png</file>
13 <file>icones/unplot.png</file>
14 <file>icones/up.png</file>
14 <file>icones/up.png</file>
15 <file>icones/time.png</file>
15 </qresource>
16 </qresource>
16 </RCC>
17 </RCC>
@@ -1,156 +1,154
1 #include "TimeWidget/TimeWidget.h"
1 #include "TimeWidget/TimeWidget.h"
2 #include "ui_TimeWidget.h"
2 #include "ui_TimeWidget.h"
3
3
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5 #include <Common/MimeTypesDef.h>
5 #include <Common/MimeTypesDef.h>
6
6
7 #include <DragAndDrop/DragDropHelper.h>
7 #include <DragAndDrop/DragDropHelper.h>
8 #include <SqpApplication.h>
8 #include <SqpApplication.h>
9 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
10
10
11 #include <QDrag>
11 #include <QDrag>
12 #include <QDragEnterEvent>
12 #include <QDragEnterEvent>
13 #include <QDropEvent>
13 #include <QDropEvent>
14 #include <QMimeData>
14 #include <QMimeData>
15
15
16
16
17 struct TimeWidget::TimeWidgetPrivate {
17 struct TimeWidget::TimeWidgetPrivate {
18
18
19 explicit TimeWidgetPrivate() {}
19 explicit TimeWidgetPrivate() {}
20
20
21 QPoint m_DragStartPosition;
21 QPoint m_DragStartPosition;
22 };
22 };
23
23
24 TimeWidget::TimeWidget(QWidget *parent)
24 TimeWidget::TimeWidget(QWidget *parent)
25 : QWidget{parent},
25 : QWidget{parent},
26 ui{new Ui::TimeWidget},
26 ui{new Ui::TimeWidget},
27 impl{spimpl::make_unique_impl<TimeWidgetPrivate>()}
27 impl{spimpl::make_unique_impl<TimeWidgetPrivate>()}
28 {
28 {
29 ui->setupUi(this);
29 ui->setupUi(this);
30
30
31 ui->applyToolButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_DialogApplyButton));
31 ui->applyToolButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_DialogApplyButton));
32
32
33 // Connection
33 // Connection
34 connect(ui->startDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
34 connect(ui->startDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
35 &TimeWidget::onTimeUpdateRequested);
35 &TimeWidget::onTimeUpdateRequested);
36
36
37 connect(ui->endDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
37 connect(ui->endDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
38 &TimeWidget::onTimeUpdateRequested);
38 &TimeWidget::onTimeUpdateRequested);
39
39
40
40
41 connect(ui->applyToolButton, &QToolButton::clicked, &sqpApp->timeController(),
41 connect(ui->applyToolButton, &QToolButton::clicked, &sqpApp->timeController(),
42 &TimeController::onTimeNotify);
42 &TimeController::onTimeNotify);
43
43
44 // Initialisation
44 // Initialisation
45 auto endDateTime = QDateTime::currentDateTimeUtc();
45 auto endDateTime = QDateTime::currentDateTimeUtc();
46 auto startDateTime = endDateTime.addSecs(-3600); // one hour before
46 auto startDateTime = endDateTime.addSecs(-3600); // one hour before
47
47
48 ui->startDateTimeEdit->setDateTime(startDateTime);
48 ui->startDateTimeEdit->setDateTime(startDateTime);
49 ui->endDateTimeEdit->setDateTime(endDateTime);
49 ui->endDateTimeEdit->setDateTime(endDateTime);
50
50
51 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(startDateTime),
51 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(startDateTime),
52 DateUtils::secondsSinceEpoch(endDateTime)};
52 DateUtils::secondsSinceEpoch(endDateTime)};
53
53
54 sqpApp->timeController().onTimeToUpdate(dateTime);
54 sqpApp->timeController().onTimeToUpdate(dateTime);
55 }
55 }
56
56
57
57
58 TimeWidget::~TimeWidget()
58 TimeWidget::~TimeWidget()
59 {
59 {
60 delete ui;
60 delete ui;
61 }
61 }
62
62
63 void TimeWidget::setTimeRange(SqpRange time)
63 void TimeWidget::setTimeRange(SqpRange time)
64 {
64 {
65 auto startDateTime = DateUtils::dateTime(time.m_TStart);
65 auto startDateTime = DateUtils::dateTime(time.m_TStart);
66 auto endDateTime = DateUtils::dateTime(time.m_TEnd);
66 auto endDateTime = DateUtils::dateTime(time.m_TEnd);
67
67
68 ui->startDateTimeEdit->setDateTime(startDateTime);
68 ui->startDateTimeEdit->setDateTime(startDateTime);
69 ui->endDateTimeEdit->setDateTime(endDateTime);
69 ui->endDateTimeEdit->setDateTime(endDateTime);
70 }
70 }
71
71
72 SqpRange TimeWidget::timeRange() const
72 SqpRange TimeWidget::timeRange() const
73 {
73 {
74 return SqpRange{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
74 return SqpRange{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
75 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
75 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
76 }
76 }
77
77
78 void TimeWidget::onTimeUpdateRequested()
78 void TimeWidget::onTimeUpdateRequested()
79 {
79 {
80 auto dateTime = timeRange();
80 auto dateTime = timeRange();
81 emit timeUpdated(std::move(dateTime));
81 emit timeUpdated(std::move(dateTime));
82 }
82 }
83
83
84 void TimeWidget::dragEnterEvent(QDragEnterEvent *event)
84 void TimeWidget::dragEnterEvent(QDragEnterEvent *event)
85 {
85 {
86 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
86 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
87 event->acceptProposedAction();
87 event->acceptProposedAction();
88 setStyleSheet("QDateTimeEdit{background-color: #BBD5EE; border:2px solid #2A7FD4}");
88 setStyleSheet("QDateTimeEdit{background-color: #BBD5EE; border:2px solid #2A7FD4}");
89 }
89 }
90 else {
90 else {
91 event->ignore();
91 event->ignore();
92 }
92 }
93 }
93 }
94
94
95 void TimeWidget::dragLeaveEvent(QDragLeaveEvent *event)
95 void TimeWidget::dragLeaveEvent(QDragLeaveEvent *event)
96 {
96 {
97 setStyleSheet(QString());
97 setStyleSheet(QString{});
98 }
98 }
99
99
100 void TimeWidget::dropEvent(QDropEvent *event)
100 void TimeWidget::dropEvent(QDropEvent *event)
101 {
101 {
102 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
102 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
103 auto mimeData = event->mimeData()->data(MIME_TYPE_TIME_RANGE);
103 auto mimeData = event->mimeData()->data(MIME_TYPE_TIME_RANGE);
104 auto timeRange = TimeController::timeRangeForMimeData(mimeData);
104 auto timeRange = TimeController::timeRangeForMimeData(mimeData);
105
105
106 setTimeRange(timeRange);
106 setTimeRange(timeRange);
107 }
107 }
108 else {
108 else {
109 event->ignore();
109 event->ignore();
110 }
110 }
111
111
112 setStyleSheet(QString());
112 setStyleSheet(QString{});
113 }
113 }
114
114
115
115
116 void TimeWidget::mousePressEvent(QMouseEvent *event)
116 void TimeWidget::mousePressEvent(QMouseEvent *event)
117 {
117 {
118 if (event->button() == Qt::LeftButton) {
118 if (event->button() == Qt::LeftButton) {
119 impl->m_DragStartPosition = event->pos();
119 impl->m_DragStartPosition = event->pos();
120 }
120 }
121
121
122 QWidget::mousePressEvent(event);
122 QWidget::mousePressEvent(event);
123 }
123 }
124
124
125 void TimeWidget::mouseMoveEvent(QMouseEvent *event)
125 void TimeWidget::mouseMoveEvent(QMouseEvent *event)
126 {
126 {
127 if (!(event->buttons() & Qt::LeftButton)) {
127 if (!(event->buttons() & Qt::LeftButton)) {
128 return;
128 return;
129 }
129 }
130
130
131 if ((event->pos() - impl->m_DragStartPosition).manhattanLength()
131 if ((event->pos() - impl->m_DragStartPosition).manhattanLength()
132 < QApplication::startDragDistance()) {
132 < QApplication::startDragDistance()) {
133 return;
133 return;
134 }
134 }
135
135
136 // Note: The management of the drag object is done by Qt
136 // Note: The management of the drag object is done by Qt
137 auto drag = new QDrag{this};
137 auto drag = new QDrag{this};
138
138
139 auto mimeData = new QMimeData;
139 auto mimeData = new QMimeData;
140 auto timeData = TimeController::mimeDataForTimeRange(timeRange());
140 auto timeData = TimeController::mimeDataForTimeRange(timeRange());
141 mimeData->setData(MIME_TYPE_TIME_RANGE, timeData);
141 mimeData->setData(MIME_TYPE_TIME_RANGE, timeData);
142
142
143 drag->setMimeData(mimeData);
143 drag->setMimeData(mimeData);
144
144
145 auto pixmap = QPixmap(size());
145 auto pixmap = QPixmap{":/icones/time.png"};
146 render(&pixmap);
146 drag->setPixmap(pixmap.scaledToWidth(22));
147 drag->setPixmap(pixmap);
148 drag->setHotSpot(impl->m_DragStartPosition);
149
147
150 sqpApp->dragDropHelper().resetDragAndDrop();
148 sqpApp->dragDropHelper().resetDragAndDrop();
151
149
152 // Note: The exec() is blocking on windows but not on linux and macOS
150 // Note: The exec() is blocking on windows but not on linux and macOS
153 drag->exec(Qt::MoveAction | Qt::CopyAction);
151 drag->exec(Qt::MoveAction | Qt::CopyAction);
154
152
155 QWidget::mouseMoveEvent(event);
153 QWidget::mouseMoveEvent(event);
156 }
154 }
@@ -1,453 +1,472
1 #include "Visualization/VisualizationDragDropContainer.h"
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragAndDrop/DragDropHelper.h"
2 #include "DragAndDrop/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"
6 #include "Common/VisualizationDef.h"
7
7
8 #include <QDrag>
8 #include <QDrag>
9 #include <QDragEnterEvent>
9 #include <QDragEnterEvent>
10 #include <QVBoxLayout>
10 #include <QVBoxLayout>
11
11
12 #include <cmath>
12 #include <cmath>
13 #include <memory>
13 #include <memory>
14
14
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
16
16
17 auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels
18
17 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
19 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
18
20
19 QVBoxLayout *m_Layout;
21 QVBoxLayout *m_Layout;
20 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
22 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
21 QString m_PlaceHolderText;
23 QString m_PlaceHolderText;
22 DragDropHelper::PlaceHolderType m_PlaceHolderType = DragDropHelper::PlaceHolderType::Graph;
24 DragDropHelper::PlaceHolderType m_PlaceHolderType = DragDropHelper::PlaceHolderType::Graph;
23
25
24 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
26 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
25 = [](auto mimeData) { return true; };
27 = [](auto mimeData) { return true; };
26
28
27 int m_MinContainerHeight = 0;
29 int m_MinContainerHeight = 0;
28
30
29 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
31 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
30 {
32 {
31 m_Layout = new QVBoxLayout(widget);
33 m_Layout = new QVBoxLayout(widget);
32 m_Layout->setContentsMargins(0, 0, 0, 0);
34 m_Layout->setContentsMargins(0, 0, 0, 0);
33 }
35 }
34
36
35 bool acceptMimeData(const QMimeData *data) const
37 bool acceptMimeData(const QMimeData *data) const
36 {
38 {
37 for (const auto &type : m_AcceptedMimeTypes.keys()) {
39 auto accepted = false;
38 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
40 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
39 return true;
41 ++it) {
42 const auto &type = it.key();
43 const auto &behavior = it.value();
44
45 if (data->hasFormat(type)) {
46 if (behavior != DropBehavior::Forbidden) {
47 accepted = true;
48 }
49 else {
50 accepted = false;
51 break;
52 }
40 }
53 }
41 }
54 }
42
55
43 return false;
56 if (accepted) {
57 accepted = m_AcceptMimeDataFun(data);
58 }
59
60 return accepted;
44 }
61 }
45
62
46 bool allowMergeForMimeData(const QMimeData *data) const
63 bool allowMergeForMimeData(const QMimeData *data) const
47 {
64 {
48 bool result = false;
65 auto result = false;
49 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
66 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
50 ++it) {
67 ++it) {
51
68
52 if (data->hasFormat(it.key())
69 if (data->hasFormat(it.key())
53 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
70 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
54 || it.value()
71 || it.value()
55 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
72 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
56 result = true;
73 result = true;
57 }
74 }
58 else if (data->hasFormat(it.key())
75 else if (data->hasFormat(it.key())
59 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
76 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
60 // Merge is forbidden if the mime data contain an acceptable type which cannot be
77 // Merge is forbidden if the mime data contain an acceptable type which cannot be
61 // merged
78 // merged
62 result = false;
79 result = false;
63 break;
80 break;
64 }
81 }
65 }
82 }
66
83
67 return result;
84 return result;
68 }
85 }
69
86
70 bool allowInsertForMimeData(const QMimeData *data) const
87 bool allowInsertForMimeData(const QMimeData *data) const
71 {
88 {
72 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
89 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
73 ++it) {
90 ++it) {
74 if (data->hasFormat(it.key())
91 if (data->hasFormat(it.key())
75 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
92 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
76 || it.value()
93 || it.value()
77 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
94 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
78 return true;
95 return true;
79 }
96 }
80 }
97 }
81
98
82 return false;
99 return false;
83 }
100 }
84
101
85 bool hasPlaceHolder() const
102 bool hasPlaceHolder() const
86 {
103 {
87 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
104 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
88 }
105 }
89
106
90 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
107 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
91 {
108 {
92 VisualizationDragWidget *dragWidget = nullptr;
109 VisualizationDragWidget *dragWidget = nullptr;
93
110
94 for (auto child : parent->children()) {
111 for (auto child : parent->children()) {
95 auto widget = qobject_cast<VisualizationDragWidget *>(child);
112 auto widget = qobject_cast<VisualizationDragWidget *>(child);
96 if (widget && widget->isVisible()) {
113 if (widget && widget->isVisible()) {
97 if (widget->frameGeometry().contains(pos)) {
114 if (widget->frameGeometry().contains(pos)) {
98 dragWidget = widget;
115 dragWidget = widget;
99 break;
116 break;
100 }
117 }
101 }
118 }
102 }
119 }
103
120
104 return dragWidget;
121 return dragWidget;
105 }
122 }
106
123
107 bool cursorIsInContainer(QWidget *container) const
124 bool cursorIsInContainer(QWidget *container) const
108 {
125 {
109 return container->isAncestorOf(sqpApp->widgetAt(QCursor::pos()));
126 auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos());
127 return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container
128 && sqpApp->dragDropHelper().placeHolder().isAncestorOf(widgetUnderMouse);
110 }
129 }
111
130
112 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
131 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
113 {
132 {
114 auto nbGraph = 0;
133 auto nbGraph = 0;
115 for (auto child : parent->children()) {
134 for (auto child : parent->children()) {
116 if (qobject_cast<VisualizationDragWidget *>(child)) {
135 if (qobject_cast<VisualizationDragWidget *>(child)) {
117 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
136 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
118 nbGraph += 1;
137 nbGraph += 1;
119 }
138 }
120 }
139 }
121 }
140 }
122
141
123 return nbGraph;
142 return nbGraph;
124 }
143 }
125
144
126 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
145 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
127 const VisualizationDragDropContainer *container);
146 const VisualizationDragDropContainer *container);
128 };
147 };
129
148
130 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
149 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
131 : QFrame{parent},
150 : QFrame{parent},
132 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
151 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
133 {
152 {
134 setAcceptDrops(true);
153 setAcceptDrops(true);
135 }
154 }
136
155
137 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
156 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
138 {
157 {
139 impl->m_Layout->addWidget(dragWidget);
158 impl->m_Layout->addWidget(dragWidget);
140 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
159 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
141 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
160 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
142 &VisualizationDragDropContainer::startDrag);
161 &VisualizationDragDropContainer::startDrag);
143 }
162 }
144
163
145 void VisualizationDragDropContainer::insertDragWidget(int index,
164 void VisualizationDragDropContainer::insertDragWidget(int index,
146 VisualizationDragWidget *dragWidget)
165 VisualizationDragWidget *dragWidget)
147 {
166 {
148 impl->m_Layout->insertWidget(index, dragWidget);
167 impl->m_Layout->insertWidget(index, dragWidget);
149 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
168 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
150 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
169 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
151 &VisualizationDragDropContainer::startDrag);
170 &VisualizationDragDropContainer::startDrag);
152 }
171 }
153
172
154 void VisualizationDragDropContainer::addAcceptedMimeType(
173 void VisualizationDragDropContainer::setMimeType(
155 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
174 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
156 {
175 {
157 impl->m_AcceptedMimeTypes[mimeType] = behavior;
176 impl->m_AcceptedMimeTypes[mimeType] = behavior;
158 }
177 }
159
178
160 int VisualizationDragDropContainer::countDragWidget() const
179 int VisualizationDragDropContainer::countDragWidget() const
161 {
180 {
162 return impl->countDragWidget(this);
181 return impl->countDragWidget(this);
163 }
182 }
164
183
165 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
184 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
166 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
185 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
167 {
186 {
168 impl->m_AcceptMimeDataFun = fun;
187 impl->m_AcceptMimeDataFun = fun;
169 }
188 }
170
189
171 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
190 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
172 const QString &placeHolderText)
191 const QString &placeHolderText)
173 {
192 {
174 impl->m_PlaceHolderType = type;
193 impl->m_PlaceHolderType = type;
175 impl->m_PlaceHolderText = placeHolderText;
194 impl->m_PlaceHolderText = placeHolderText;
176 }
195 }
177
196
178 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
197 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
179 const QPoint &dragPosition)
198 const QPoint &dragPosition)
180 {
199 {
181 auto &helper = sqpApp->dragDropHelper();
200 auto &helper = sqpApp->dragDropHelper();
182 helper.resetDragAndDrop();
201 helper.resetDragAndDrop();
183
202
184 // Note: The management of the drag object is done by Qt
203 // Note: The management of the drag object is done by Qt
185 auto drag = new QDrag{dragWidget};
204 auto drag = new QDrag{dragWidget};
186 drag->setHotSpot(dragPosition);
187
205
188 auto mimeData = dragWidget->mimeData();
206 auto mimeData = dragWidget->mimeData();
189 drag->setMimeData(mimeData);
207 drag->setMimeData(mimeData);
190
208
191 auto pixmap = QPixmap(dragWidget->size());
209 auto pixmap = QPixmap(dragWidget->size());
192 dragWidget->render(&pixmap);
210 dragWidget->render(&pixmap);
193 drag->setPixmap(pixmap);
211 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
212 Qt::KeepAspectRatio, Qt::SmoothTransformation));
194
213
195 auto image = pixmap.toImage();
214 auto image = pixmap.toImage();
196 mimeData->setImageData(image);
215 mimeData->setImageData(image);
197 mimeData->setUrls({helper.imageTemporaryUrl(image)});
216 mimeData->setUrls({helper.imageTemporaryUrl(image)});
198
217
199 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
218 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
200 helper.setCurrentDragWidget(dragWidget);
219 helper.setCurrentDragWidget(dragWidget);
201
220
202 if (impl->cursorIsInContainer(this)) {
221 if (impl->cursorIsInContainer(this)) {
203 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
222 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
204 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
223 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
205 impl->m_PlaceHolderText);
224 impl->m_PlaceHolderText);
206 dragWidget->setVisible(false);
225 dragWidget->setVisible(false);
207 }
226 }
208 else {
227 else {
209 // The drag starts directly outside the drop zone
228 // The drag starts directly outside the drop zone
210 // do not add the placeHolder
229 // do not add the placeHolder
211 }
230 }
212
231
213 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
232 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
214
233
215 helper.doCloseWidgets();
234 helper.doCloseWidgets();
216 }
235 }
217 else {
236 else {
218 qCWarning(LOG_VisualizationDragDropContainer())
237 qCWarning(LOG_VisualizationDragDropContainer())
219 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
238 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
220 "VisualizationDragWidget is not found in this container.");
239 "VisualizationDragWidget is not found in this container.");
221 }
240 }
222 }
241 }
223
242
224 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
243 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
225 {
244 {
226 if (impl->acceptMimeData(event->mimeData())) {
245 if (impl->acceptMimeData(event->mimeData())) {
227 event->acceptProposedAction();
246 event->acceptProposedAction();
228
247
229 auto &helper = sqpApp->dragDropHelper();
248 auto &helper = sqpApp->dragDropHelper();
230
249
231 if (!impl->hasPlaceHolder()) {
250 if (!impl->hasPlaceHolder()) {
232 auto dragWidget = helper.getCurrentDragWidget();
251 auto dragWidget = helper.getCurrentDragWidget();
233
252
234 if (dragWidget) {
253 if (dragWidget) {
235 // If the drag&drop is internal to the visualization, entering the container hide
254 // If the drag&drop is internal to the visualization, entering the container hide
236 // the dragWidget which was made visible by the dragLeaveEvent
255 // the dragWidget which was made visible by the dragLeaveEvent
237 auto parentWidget
256 auto parentWidget
238 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
257 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
239 if (parentWidget) {
258 if (parentWidget) {
240 dragWidget->setVisible(false);
259 dragWidget->setVisible(false);
241 }
260 }
242 }
261 }
243
262
244 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
263 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
245 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
264 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
246 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
265 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
247 }
266 }
248 else {
267 else {
249 // do nothing
268 // do nothing
250 }
269 }
251 }
270 }
252 else {
271 else {
253 event->ignore();
272 event->ignore();
254 }
273 }
255
274
256 QWidget::dragEnterEvent(event);
275 QWidget::dragEnterEvent(event);
257 }
276 }
258
277
259 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
278 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
260 {
279 {
261 Q_UNUSED(event);
280 Q_UNUSED(event);
262
281
263 auto &helper = sqpApp->dragDropHelper();
282 auto &helper = sqpApp->dragDropHelper();
264
283
265 if (!impl->cursorIsInContainer(this)) {
284 if (!impl->cursorIsInContainer(this)) {
266 helper.removePlaceHolder();
285 helper.removePlaceHolder();
267 helper.setHightlightedDragWidget(nullptr);
286 helper.setHightlightedDragWidget(nullptr);
268 impl->m_MinContainerHeight = 0;
287 impl->m_MinContainerHeight = 0;
269
288
270 auto dragWidget = helper.getCurrentDragWidget();
289 auto dragWidget = helper.getCurrentDragWidget();
271 if (dragWidget) {
290 if (dragWidget) {
272 // dragWidget has a value only if the drag is started from the visualization
291 // dragWidget has a value only if the drag is started from the visualization
273 // In that case, shows the drag widget at its original place
292 // In that case, shows the drag widget at its original place
274 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
293 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
275 // drop zone (It is not possible to catch a drop event outside of the application)
294 // drop zone (It is not possible to catch a drop event outside of the application)
276
295
277 if (dragWidget) {
296 if (dragWidget) {
278 dragWidget->setVisible(true);
297 dragWidget->setVisible(true);
279 }
298 }
280 }
299 }
281 }
300 }
282 else {
301 else {
283 // Leave event probably received for a child widget.
302 // Leave event probably received for a child widget.
284 // Do nothing.
303 // Do nothing.
285 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
304 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
286 }
305 }
287
306
288 QWidget::dragLeaveEvent(event);
307 QWidget::dragLeaveEvent(event);
289 }
308 }
290
309
291 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
310 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
292 {
311 {
293 if (impl->acceptMimeData(event->mimeData())) {
312 if (impl->acceptMimeData(event->mimeData())) {
294 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
313 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
295 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
314 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
296 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
315 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
297 }
316 }
298 else {
317 else {
299 event->ignore();
318 event->ignore();
300 }
319 }
301
320
302 QWidget::dragMoveEvent(event);
321 QWidget::dragMoveEvent(event);
303 }
322 }
304
323
305 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
324 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
306 {
325 {
307 auto &helper = sqpApp->dragDropHelper();
326 auto &helper = sqpApp->dragDropHelper();
308
327
309 if (impl->acceptMimeData(event->mimeData())) {
328 if (impl->acceptMimeData(event->mimeData())) {
310 auto dragWidget = helper.getCurrentDragWidget();
329 auto dragWidget = helper.getCurrentDragWidget();
311 if (impl->hasPlaceHolder()) {
330 if (impl->hasPlaceHolder()) {
312 // drop where the placeHolder is located
331 // drop where the placeHolder is located
313
332
314 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
333 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
315 if (canInsert) {
334 if (canInsert) {
316 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
335 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
317
336
318 if (dragWidget) {
337 if (dragWidget) {
319 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
338 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
320 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
339 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
321 // Correction of the index if the drop occurs in the same container
340 // Correction of the index if the drop occurs in the same container
322 // and if the drag is started from the visualization (in that case, the
341 // and if the drag is started from the visualization (in that case, the
323 // dragWidget is hidden)
342 // dragWidget is hidden)
324 droppedIndex -= 1;
343 droppedIndex -= 1;
325 }
344 }
326
345
327 dragWidget->setVisible(true);
346 dragWidget->setVisible(true);
328 }
347 }
329
348
330 event->acceptProposedAction();
349 event->acceptProposedAction();
331
350
332 helper.removePlaceHolder();
351 helper.removePlaceHolder();
333
352
334 emit dropOccuredInContainer(droppedIndex, event->mimeData());
353 emit dropOccuredInContainer(droppedIndex, event->mimeData());
335 }
354 }
336 else {
355 else {
337 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
356 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
338 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
357 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
339 "the insertion is forbidden.");
358 "the insertion is forbidden.");
340 Q_ASSERT(false);
359 Q_ASSERT(false);
341 }
360 }
342 }
361 }
343 else if (helper.getHightlightedDragWidget()) {
362 else if (helper.getHightlightedDragWidget()) {
344 // drop on the highlighted widget
363 // drop on the highlighted widget
345
364
346 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
365 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
347 if (canMerge) {
366 if (canMerge) {
348 event->acceptProposedAction();
367 event->acceptProposedAction();
349 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
368 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
350 }
369 }
351 else {
370 else {
352 qCWarning(LOG_VisualizationDragDropContainer())
371 qCWarning(LOG_VisualizationDragDropContainer())
353 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
372 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
354 "the merge is forbidden.");
373 "the merge is forbidden.");
355 Q_ASSERT(false);
374 Q_ASSERT(false);
356 }
375 }
357 }
376 }
358 }
377 }
359 else {
378 else {
360 event->ignore();
379 event->ignore();
361 }
380 }
362
381
363 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
382 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
364 impl->m_MinContainerHeight = 0;
383 impl->m_MinContainerHeight = 0;
365
384
366 QWidget::dropEvent(event);
385 QWidget::dropEvent(event);
367 }
386 }
368
387
369
388
370 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
389 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
371 const QPoint &pos, bool canInsert, bool canMerge,
390 const QPoint &pos, bool canInsert, bool canMerge,
372 const VisualizationDragDropContainer *container)
391 const VisualizationDragDropContainer *container)
373 {
392 {
374 auto &helper = sqpApp->dragDropHelper();
393 auto &helper = sqpApp->dragDropHelper();
375
394
376 auto absPos = container->mapToGlobal(pos);
395 auto absPos = container->mapToGlobal(pos);
377 auto isOnPlaceHolder = sqpApp->widgetAt(absPos) == &(helper.placeHolder());
396 auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos));
378
397
379 if (countDragWidget(container, true) == 0) {
398 if (countDragWidget(container, true) == 0) {
380 // Drop on an empty container, just add the placeHolder at the top
399 // Drop on an empty container, just add the placeHolder at the top
381 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
400 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
382 }
401 }
383 else if (!isOnPlaceHolder) {
402 else if (!isOnPlaceHolder) {
384 auto nbDragWidget = countDragWidget(container);
403 auto nbDragWidget = countDragWidget(container);
385 if (nbDragWidget > 0) {
404 if (nbDragWidget > 0) {
386
405
387 if (m_MinContainerHeight == 0) {
406 if (m_MinContainerHeight == 0) {
388 m_MinContainerHeight = container->size().height();
407 m_MinContainerHeight = container->size().height();
389 }
408 }
390
409
391 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
410 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
392 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
411 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
393
412
394 auto posY = pos.y();
413 auto posY = pos.y();
395 auto dropIndex = floor(posY / graphHeight);
414 auto dropIndex = floor(posY / graphHeight);
396 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
415 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
397
416
398
417
399 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
418 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
400 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
419 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
401
420
402 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
421 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
403
422
404 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
423 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
405
424
406 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
425 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
407 if (isOnBottom) {
426 if (isOnBottom) {
408 dropIndex += 1;
427 dropIndex += 1;
409 }
428 }
410
429
411 if (helper.getCurrentDragWidget()) {
430 if (helper.getCurrentDragWidget()) {
412 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
431 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
413 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
432 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
414 // Correction of the index if the drop occurs in the same container
433 // Correction of the index if the drop occurs in the same container
415 // and if the drag is started from the visualization (in that case, the
434 // and if the drag is started from the visualization (in that case, the
416 // dragWidget is hidden)
435 // dragWidget is hidden)
417 dropIndex += 1;
436 dropIndex += 1;
418 }
437 }
419 }
438 }
420
439
421 if (dropIndex != placeHolderIndex) {
440 if (dropIndex != placeHolderIndex) {
422 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
441 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
423 m_PlaceHolderText);
442 m_PlaceHolderText);
424 }
443 }
425
444
426 helper.setHightlightedDragWidget(nullptr);
445 helper.setHightlightedDragWidget(nullptr);
427 }
446 }
428 else if (canMerge && dragWidgetHovered) {
447 else if (canMerge && dragWidgetHovered) {
429 // drop on the middle -> merge
448 // drop on the middle -> merge
430 if (hasPlaceHolder()) {
449 if (hasPlaceHolder()) {
431 helper.removePlaceHolder();
450 helper.removePlaceHolder();
432 }
451 }
433
452
434 helper.setHightlightedDragWidget(dragWidgetHovered);
453 helper.setHightlightedDragWidget(dragWidgetHovered);
435 }
454 }
436 else {
455 else {
437 qCWarning(LOG_VisualizationDragDropContainer())
456 qCWarning(LOG_VisualizationDragDropContainer())
438 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
457 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
439 "action.");
458 "action.");
440 }
459 }
441 }
460 }
442 else {
461 else {
443 qCWarning(LOG_VisualizationDragDropContainer())
462 qCWarning(LOG_VisualizationDragDropContainer())
444 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
463 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
445 "found in the "
464 "found in the "
446 "container");
465 "container");
447 }
466 }
448 }
467 }
449 else {
468 else {
450 // the mouse is hover the placeHolder
469 // the mouse is hover the placeHolder
451 // Do nothing
470 // Do nothing
452 }
471 }
453 }
472 }
@@ -1,319 +1,320
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 "Visualization/MacScrollBarStyle.h"
8 #include "Visualization/MacScrollBarStyle.h"
9
9
10 #include "Variable/VariableController.h"
10 #include "Variable/VariableController.h"
11
11
12 #include "Common/MimeTypesDef.h"
12 #include "Common/MimeTypesDef.h"
13
13
14 #include "DragAndDrop/DragDropHelper.h"
14 #include "DragAndDrop/DragDropHelper.h"
15 #include "SqpApplication.h"
15 #include "SqpApplication.h"
16
16
17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
18
18
19 namespace {
19 namespace {
20
20
21 /// Generates a default name for a new zone, according to the number of zones already displayed in
21 /// Generates a default name for a new zone, according to the number of zones already displayed in
22 /// the tab
22 /// the tab
23 QString defaultZoneName(const QLayout &layout)
23 QString defaultZoneName(const QLayout &layout)
24 {
24 {
25 auto count = 0;
25 auto count = 0;
26 for (auto i = 0; i < layout.count(); ++i) {
26 for (auto i = 0; i < layout.count(); ++i) {
27 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
27 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
28 count++;
28 count++;
29 }
29 }
30 }
30 }
31
31
32 return QObject::tr("Zone %1").arg(count + 1);
32 return QObject::tr("Zone %1").arg(count + 1);
33 }
33 }
34
34
35 /**
35 /**
36 * Applies a function to all zones of the tab represented by its layout
36 * Applies a function to all zones of the tab represented by its layout
37 * @param layout the layout that contains zones
37 * @param layout the layout that contains zones
38 * @param fun the function to apply to each zone
38 * @param fun the function to apply to each zone
39 */
39 */
40 template <typename Fun>
40 template <typename Fun>
41 void processZones(QLayout &layout, Fun fun)
41 void processZones(QLayout &layout, Fun fun)
42 {
42 {
43 for (auto i = 0; i < layout.count(); ++i) {
43 for (auto i = 0; i < layout.count(); ++i) {
44 if (auto item = layout.itemAt(i)) {
44 if (auto item = layout.itemAt(i)) {
45 if (auto visualizationZoneWidget
45 if (auto visualizationZoneWidget
46 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
46 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
47 fun(*visualizationZoneWidget);
47 fun(*visualizationZoneWidget);
48 }
48 }
49 }
49 }
50 }
50 }
51 }
51 }
52
52
53 } // namespace
53 } // namespace
54
54
55 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
55 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
56 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
56 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
57
57
58 QString m_Name;
58 QString m_Name;
59
59
60 #ifdef Q_OS_MAC
60 #ifdef Q_OS_MAC
61 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
61 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
62 #endif
62 #endif
63
63
64 void dropGraph(int index, VisualizationTabWidget *tabWidget);
64 void dropGraph(int index, VisualizationTabWidget *tabWidget);
65 void dropZone(int index, VisualizationTabWidget *tabWidget);
65 void dropZone(int index, VisualizationTabWidget *tabWidget);
66 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
66 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
67 VisualizationTabWidget *tabWidget);
67 VisualizationTabWidget *tabWidget);
68 };
68 };
69
69
70 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
70 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
71 : QWidget{parent},
71 : QWidget{parent},
72 ui{new Ui::VisualizationTabWidget},
72 ui{new Ui::VisualizationTabWidget},
73 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
73 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
74 {
74 {
75 ui->setupUi(this);
75 ui->setupUi(this);
76
76
77 #ifdef Q_OS_MAC
77 #ifdef Q_OS_MAC
78 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
78 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
79 #endif
79 #endif
80
80
81 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Zone, "Zone");
81 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Zone, "Zone");
82 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 5);
82 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
83 ui->dragDropContainer->addAcceptedMimeType(
83 ui->dragDropContainer->layout()->setSpacing(0);
84 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
84 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
85 ui->dragDropContainer->addAcceptedMimeType(
85 VisualizationDragDropContainer::DropBehavior::Inserted);
86 MIME_TYPE_ZONE, VisualizationDragDropContainer::DropBehavior::Inserted);
86 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
87 ui->dragDropContainer->addAcceptedMimeType(
87 VisualizationDragDropContainer::DropBehavior::Inserted);
88 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::Inserted);
88 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
89 VisualizationDragDropContainer::DropBehavior::Inserted);
89
90
90 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
91 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
91 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
92 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
92 ui->dragDropContainer);
93 ui->dragDropContainer);
93 });
94 });
94
95
95 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
96 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
96 &VisualizationTabWidget::dropMimeData);
97 &VisualizationTabWidget::dropMimeData);
97
98
98 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
99 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
99
100
100 // Widget is deleted when closed
101 // Widget is deleted when closed
101 setAttribute(Qt::WA_DeleteOnClose);
102 setAttribute(Qt::WA_DeleteOnClose);
102 }
103 }
103
104
104 VisualizationTabWidget::~VisualizationTabWidget()
105 VisualizationTabWidget::~VisualizationTabWidget()
105 {
106 {
106 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
107 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
107 delete ui;
108 delete ui;
108 }
109 }
109
110
110 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
111 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
111 {
112 {
112 ui->dragDropContainer->addDragWidget(zoneWidget);
113 ui->dragDropContainer->addDragWidget(zoneWidget);
113 }
114 }
114
115
115 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
116 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
116 {
117 {
117 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
118 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
118 }
119 }
119
120
120 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
121 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
121 {
122 {
122 return createZone({variable}, -1);
123 return createZone({variable}, -1);
123 }
124 }
124
125
125 VisualizationZoneWidget *
126 VisualizationZoneWidget *
126 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
127 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
127 {
128 {
128 auto zoneWidget = createEmptyZone(index);
129 auto zoneWidget = createEmptyZone(index);
129
130
130 // Creates a new graph into the zone
131 // Creates a new graph into the zone
131 zoneWidget->createGraph(variables, index);
132 zoneWidget->createGraph(variables, index);
132
133
133 return zoneWidget;
134 return zoneWidget;
134 }
135 }
135
136
136 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
137 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
137 {
138 {
138 auto zoneWidget
139 auto zoneWidget
139 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
140 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
140 this->insertZone(index, zoneWidget);
141 this->insertZone(index, zoneWidget);
141
142
142 return zoneWidget;
143 return zoneWidget;
143 }
144 }
144
145
145 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
146 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
146 {
147 {
147 if (visitor) {
148 if (visitor) {
148 visitor->visitEnter(this);
149 visitor->visitEnter(this);
149
150
150 // Apply visitor to zone children: widgets different from zones are not visited (no action)
151 // Apply visitor to zone children: widgets different from zones are not visited (no action)
151 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
152 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
152 zoneWidget.accept(visitor);
153 zoneWidget.accept(visitor);
153 });
154 });
154
155
155 visitor->visitLeave(this);
156 visitor->visitLeave(this);
156 }
157 }
157 else {
158 else {
158 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
159 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
159 }
160 }
160 }
161 }
161
162
162 bool VisualizationTabWidget::canDrop(const Variable &variable) const
163 bool VisualizationTabWidget::canDrop(const Variable &variable) const
163 {
164 {
164 // A tab can always accomodate a variable
165 // A tab can always accomodate a variable
165 Q_UNUSED(variable);
166 Q_UNUSED(variable);
166 return true;
167 return true;
167 }
168 }
168
169
169 bool VisualizationTabWidget::contains(const Variable &variable) const
170 bool VisualizationTabWidget::contains(const Variable &variable) const
170 {
171 {
171 Q_UNUSED(variable);
172 Q_UNUSED(variable);
172 return false;
173 return false;
173 }
174 }
174
175
175 QString VisualizationTabWidget::name() const
176 QString VisualizationTabWidget::name() const
176 {
177 {
177 return impl->m_Name;
178 return impl->m_Name;
178 }
179 }
179
180
180 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
181 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
181 {
182 {
182 // Closes zones in the tab
183 // Closes zones in the tab
183 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
184 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
184
185
185 QWidget::closeEvent(event);
186 QWidget::closeEvent(event);
186 }
187 }
187
188
188 QLayout &VisualizationTabWidget::tabLayout() const noexcept
189 QLayout &VisualizationTabWidget::tabLayout() const noexcept
189 {
190 {
190 return *ui->dragDropContainer->layout();
191 return *ui->dragDropContainer->layout();
191 }
192 }
192
193
193 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
194 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
194 {
195 {
195 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
196 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
196 impl->dropGraph(index, this);
197 impl->dropGraph(index, this);
197 }
198 }
198 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
199 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
199 impl->dropZone(index, this);
200 impl->dropZone(index, this);
200 }
201 }
201 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
202 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
202 auto variables = sqpApp->variableController().variablesForMimeData(
203 auto variables = sqpApp->variableController().variablesForMimeData(
203 mimeData->data(MIME_TYPE_VARIABLE_LIST));
204 mimeData->data(MIME_TYPE_VARIABLE_LIST));
204 impl->dropVariables(variables, index, this);
205 impl->dropVariables(variables, index, this);
205 }
206 }
206 else {
207 else {
207 qCWarning(LOG_VisualizationZoneWidget())
208 qCWarning(LOG_VisualizationZoneWidget())
208 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
209 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
209 }
210 }
210 }
211 }
211
212
212 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
213 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
213 int index, VisualizationTabWidget *tabWidget)
214 int index, VisualizationTabWidget *tabWidget)
214 {
215 {
215 auto &helper = sqpApp->dragDropHelper();
216 auto &helper = sqpApp->dragDropHelper();
216
217
217 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
218 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
218 if (!graphWidget) {
219 if (!graphWidget) {
219 qCWarning(LOG_VisualizationZoneWidget())
220 qCWarning(LOG_VisualizationZoneWidget())
220 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
221 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
221 "found or invalid.");
222 "found or invalid.");
222 Q_ASSERT(false);
223 Q_ASSERT(false);
223 return;
224 return;
224 }
225 }
225
226
226 auto parentDragDropContainer
227 auto parentDragDropContainer
227 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
228 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
228 if (!parentDragDropContainer) {
229 if (!parentDragDropContainer) {
229 qCWarning(LOG_VisualizationZoneWidget())
230 qCWarning(LOG_VisualizationZoneWidget())
230 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
231 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
231 "the dropped graph is not found.");
232 "the dropped graph is not found.");
232 Q_ASSERT(false);
233 Q_ASSERT(false);
233 return;
234 return;
234 }
235 }
235
236
236 auto nbGraph = parentDragDropContainer->countDragWidget();
237 auto nbGraph = parentDragDropContainer->countDragWidget();
237
238
238 const auto &variables = graphWidget->variables();
239 const auto &variables = graphWidget->variables();
239
240
240 if (!variables.isEmpty()) {
241 if (!variables.isEmpty()) {
241 // Abort the requests for the variables (if any)
242 // Abort the requests for the variables (if any)
242 // Commented, because it's not sure if it's needed or not
243 // Commented, because it's not sure if it's needed or not
243 // for (const auto& var : variables)
244 // for (const auto& var : variables)
244 //{
245 //{
245 // sqpApp->variableController().onAbortProgressRequested(var);
246 // sqpApp->variableController().onAbortProgressRequested(var);
246 //}
247 //}
247
248
248 if (nbGraph == 1) {
249 if (nbGraph == 1) {
249 // This is the only graph in the previous zone, close the zone
250 // This is the only graph in the previous zone, close the zone
250 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
251 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
251 }
252 }
252 else {
253 else {
253 // Close the graph
254 // Close the graph
254 helper.delayedCloseWidget(graphWidget);
255 helper.delayedCloseWidget(graphWidget);
255 }
256 }
256
257
257 tabWidget->createZone(variables, index);
258 tabWidget->createZone(variables, index);
258 }
259 }
259 else {
260 else {
260 // The graph is empty, create an empty zone and move the graph inside
261 // The graph is empty, create an empty zone and move the graph inside
261
262
262 auto parentZoneWidget = graphWidget->parentZoneWidget();
263 auto parentZoneWidget = graphWidget->parentZoneWidget();
263
264
264 parentDragDropContainer->layout()->removeWidget(graphWidget);
265 parentDragDropContainer->layout()->removeWidget(graphWidget);
265
266
266 auto zoneWidget = tabWidget->createEmptyZone(index);
267 auto zoneWidget = tabWidget->createEmptyZone(index);
267 zoneWidget->addGraph(graphWidget);
268 zoneWidget->addGraph(graphWidget);
268
269
269 // Close the old zone if it was the only graph inside
270 // Close the old zone if it was the only graph inside
270 if (nbGraph == 1) {
271 if (nbGraph == 1) {
271 helper.delayedCloseWidget(parentZoneWidget);
272 helper.delayedCloseWidget(parentZoneWidget);
272 }
273 }
273 }
274 }
274 }
275 }
275
276
276 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
277 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
277 int index, VisualizationTabWidget *tabWidget)
278 int index, VisualizationTabWidget *tabWidget)
278 {
279 {
279 auto &helper = sqpApp->dragDropHelper();
280 auto &helper = sqpApp->dragDropHelper();
280
281
281 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
282 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
282 if (!zoneWidget) {
283 if (!zoneWidget) {
283 qCWarning(LOG_VisualizationZoneWidget())
284 qCWarning(LOG_VisualizationZoneWidget())
284 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
285 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
285 "found or invalid.");
286 "found or invalid.");
286 Q_ASSERT(false);
287 Q_ASSERT(false);
287 return;
288 return;
288 }
289 }
289
290
290 auto parentDragDropContainer
291 auto parentDragDropContainer
291 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
292 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
292 if (!parentDragDropContainer) {
293 if (!parentDragDropContainer) {
293 qCWarning(LOG_VisualizationZoneWidget())
294 qCWarning(LOG_VisualizationZoneWidget())
294 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
295 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
295 "the dropped zone is not found.");
296 "the dropped zone is not found.");
296 Q_ASSERT(false);
297 Q_ASSERT(false);
297 return;
298 return;
298 }
299 }
299
300
300 // Simple move of the zone, no variable operation associated
301 // Simple move of the zone, no variable operation associated
301 parentDragDropContainer->layout()->removeWidget(zoneWidget);
302 parentDragDropContainer->layout()->removeWidget(zoneWidget);
302 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
303 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
303 }
304 }
304
305
305 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
306 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
306 const QList<std::shared_ptr<Variable> > &variables, int index,
307 const QList<std::shared_ptr<Variable> > &variables, int index,
307 VisualizationTabWidget *tabWidget)
308 VisualizationTabWidget *tabWidget)
308 {
309 {
309 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
310 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
310 // compatible variable here
311 // compatible variable here
311 if (variables.count() > 1) {
312 if (variables.count() > 1) {
312 qCWarning(LOG_VisualizationZoneWidget())
313 qCWarning(LOG_VisualizationZoneWidget())
313 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
314 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
314 "aborted.");
315 "aborted.");
315 return;
316 return;
316 }
317 }
317
318
318 tabWidget->createZone(variables, index);
319 tabWidget->createZone(variables, index);
319 }
320 }
@@ -1,500 +1,507
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 "Visualization/VisualizationWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
8
8
9 #include "Common/MimeTypesDef.h"
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
10 #include "Common/VisualizationDef.h"
11
11
12 #include <Data/SqpRange.h>
12 #include <Data/SqpRange.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14 #include <Variable/Variable.h>
14 #include <Variable/Variable.h>
15 #include <Variable/VariableController.h>
15 #include <Variable/VariableController.h>
16
16
17 #include <Visualization/operations/FindVariableOperation.h>
17 #include <Visualization/operations/FindVariableOperation.h>
18
18
19 #include <DragAndDrop/DragDropHelper.h>
19 #include <DragAndDrop/DragDropHelper.h>
20 #include <QUuid>
20 #include <QUuid>
21 #include <SqpApplication.h>
21 #include <SqpApplication.h>
22 #include <cmath>
22 #include <cmath>
23
23
24 #include <QLayout>
24 #include <QLayout>
25
25
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27
27
28 namespace {
28 namespace {
29
29
30
30
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
32 /// the zone
32 /// the zone
33 QString defaultGraphName(const QLayout &layout)
33 QString defaultGraphName(const QLayout &layout)
34 {
34 {
35 auto count = 0;
35 auto count = 0;
36 for (auto i = 0; i < layout.count(); ++i) {
36 for (auto i = 0; i < layout.count(); ++i) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
38 count++;
38 count++;
39 }
39 }
40 }
40 }
41
41
42 return QObject::tr("Graph %1").arg(count + 1);
42 return QObject::tr("Graph %1").arg(count + 1);
43 }
43 }
44
44
45 /**
45 /**
46 * Applies a function to all graphs of the zone represented by its layout
46 * Applies a function to all graphs of the zone represented by its layout
47 * @param layout the layout that contains graphs
47 * @param layout the layout that contains graphs
48 * @param fun the function to apply to each graph
48 * @param fun the function to apply to each graph
49 */
49 */
50 template <typename Fun>
50 template <typename Fun>
51 void processGraphs(QLayout &layout, Fun fun)
51 void processGraphs(QLayout &layout, Fun fun)
52 {
52 {
53 for (auto i = 0; i < layout.count(); ++i) {
53 for (auto i = 0; i < layout.count(); ++i) {
54 if (auto item = layout.itemAt(i)) {
54 if (auto item = layout.itemAt(i)) {
55 if (auto visualizationGraphWidget
55 if (auto visualizationGraphWidget
56 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
56 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
57 fun(*visualizationGraphWidget);
57 fun(*visualizationGraphWidget);
58 }
58 }
59 }
59 }
60 }
60 }
61 }
61 }
62
62
63 } // namespace
63 } // namespace
64
64
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
66
66
67 explicit VisualizationZoneWidgetPrivate()
67 explicit VisualizationZoneWidgetPrivate()
68 : m_SynchronisationGroupId{QUuid::createUuid()},
68 : m_SynchronisationGroupId{QUuid::createUuid()},
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
70 {
70 {
71 }
71 }
72 QUuid m_SynchronisationGroupId;
72 QUuid m_SynchronisationGroupId;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
74
74
75 // Returns the first graph in the zone or nullptr if there is no graph inside
75 // Returns the first graph in the zone or nullptr if there is no graph inside
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
77 {
77 {
78 VisualizationGraphWidget *firstGraph = nullptr;
78 VisualizationGraphWidget *firstGraph = nullptr;
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
80 if (layout->count() > 0) {
80 if (layout->count() > 0) {
81 if (auto visualizationGraphWidget
81 if (auto visualizationGraphWidget
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
83 firstGraph = visualizationGraphWidget;
83 firstGraph = visualizationGraphWidget;
84 }
84 }
85 }
85 }
86
86
87 return firstGraph;
87 return firstGraph;
88 }
88 }
89
89
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
92 VisualizationZoneWidget *zoneWidget);
92 VisualizationZoneWidget *zoneWidget);
93 };
93 };
94
94
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
96 : VisualizationDragWidget{parent},
96 : VisualizationDragWidget{parent},
97 ui{new Ui::VisualizationZoneWidget},
97 ui{new Ui::VisualizationZoneWidget},
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
99 {
99 {
100 ui->setupUi(this);
100 ui->setupUi(this);
101
101
102 ui->zoneNameLabel->setText(name);
102 ui->zoneNameLabel->setText(name);
103
103
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
105 ui->dragDropContainer->addAcceptedMimeType(
105 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
106 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
106 VisualizationDragDropContainer::DropBehavior::Inserted);
107 ui->dragDropContainer->addAcceptedMimeType(
107 ui->dragDropContainer->setMimeType(
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
109 ui->dragDropContainer->addAcceptedMimeType(
109 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
110 MIME_TYPE_TIME_RANGE, VisualizationDragDropContainer::DropBehavior::Merged);
110 VisualizationDragDropContainer::DropBehavior::Merged);
111 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
112 VisualizationDragDropContainer::DropBehavior::Forbidden);
111 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
113 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
112 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
114 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
113 ui->dragDropContainer);
115 ui->dragDropContainer);
114 });
116 });
115
117
116 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
117 &VisualizationZoneWidget::dropMimeData);
119 &VisualizationZoneWidget::dropMimeData);
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
120 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
119 &VisualizationZoneWidget::dropMimeDataOnGraph);
121 &VisualizationZoneWidget::dropMimeDataOnGraph);
120
122
121 // 'Close' options : widget is deleted when closed
123 // 'Close' options : widget is deleted when closed
122 setAttribute(Qt::WA_DeleteOnClose);
124 setAttribute(Qt::WA_DeleteOnClose);
123 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
125 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
124 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
126 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
125
127
126 // Synchronisation id
128 // Synchronisation id
127 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
129 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
128 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
130 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
129 }
131 }
130
132
131 VisualizationZoneWidget::~VisualizationZoneWidget()
133 VisualizationZoneWidget::~VisualizationZoneWidget()
132 {
134 {
133 delete ui;
135 delete ui;
134 }
136 }
135
137
136 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
138 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
137 {
139 {
138 // Synchronize new graph with others in the zone
140 // Synchronize new graph with others in the zone
139 impl->m_Synchronizer->addGraph(*graphWidget);
141 impl->m_Synchronizer->addGraph(*graphWidget);
140
142
141 ui->dragDropContainer->addDragWidget(graphWidget);
143 ui->dragDropContainer->addDragWidget(graphWidget);
142 }
144 }
143
145
144 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
146 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
145 {
147 {
146 // Synchronize new graph with others in the zone
148 // Synchronize new graph with others in the zone
147 impl->m_Synchronizer->addGraph(*graphWidget);
149 impl->m_Synchronizer->addGraph(*graphWidget);
148
150
149 ui->dragDropContainer->insertDragWidget(index, graphWidget);
151 ui->dragDropContainer->insertDragWidget(index, graphWidget);
150 }
152 }
151
153
152 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
154 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
153 {
155 {
154 return createGraph(variable, -1);
156 return createGraph(variable, -1);
155 }
157 }
156
158
157 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
159 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
158 int index)
160 int index)
159 {
161 {
160 auto graphWidget
162 auto graphWidget
161 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
163 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
162
164
163
165
164 // Set graph properties
166 // Set graph properties
165 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
167 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
166 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
168 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
167
169
168
170
169 // Lambda to synchronize zone widget
171 // Lambda to synchronize zone widget
170 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
172 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
171 const SqpRange &oldGraphRange) {
173 const SqpRange &oldGraphRange) {
172
174
173 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
175 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
174 auto frameLayout = ui->dragDropContainer->layout();
176 auto frameLayout = ui->dragDropContainer->layout();
175 for (auto i = 0; i < frameLayout->count(); ++i) {
177 for (auto i = 0; i < frameLayout->count(); ++i) {
176 auto graphChild
178 auto graphChild
177 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
179 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
178 if (graphChild && (graphChild != graphWidget)) {
180 if (graphChild && (graphChild != graphWidget)) {
179
181
180 auto graphChildRange = graphChild->graphRange();
182 auto graphChildRange = graphChild->graphRange();
181 switch (zoomType) {
183 switch (zoomType) {
182 case AcquisitionZoomType::ZoomIn: {
184 case AcquisitionZoomType::ZoomIn: {
183 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
185 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
184 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
186 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
185 graphChildRange.m_TStart += deltaLeft;
187 graphChildRange.m_TStart += deltaLeft;
186 graphChildRange.m_TEnd -= deltaRight;
188 graphChildRange.m_TEnd -= deltaRight;
187 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
189 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
188 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
189 << deltaLeft;
191 << deltaLeft;
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
192 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
191 << deltaRight;
193 << deltaRight;
192 qCDebug(LOG_VisualizationZoneWidget())
194 qCDebug(LOG_VisualizationZoneWidget())
193 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
195 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
194
196
195 break;
197 break;
196 }
198 }
197
199
198 case AcquisitionZoomType::ZoomOut: {
200 case AcquisitionZoomType::ZoomOut: {
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
201 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
200 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
202 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
201 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
203 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
203 << deltaLeft;
205 << deltaLeft;
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
206 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
205 << deltaRight;
207 << deltaRight;
206 qCDebug(LOG_VisualizationZoneWidget())
208 qCDebug(LOG_VisualizationZoneWidget())
207 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
209 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
208 graphChildRange.m_TStart -= deltaLeft;
210 graphChildRange.m_TStart -= deltaLeft;
209 graphChildRange.m_TEnd += deltaRight;
211 graphChildRange.m_TEnd += deltaRight;
210 break;
212 break;
211 }
213 }
212 case AcquisitionZoomType::PanRight: {
214 case AcquisitionZoomType::PanRight: {
213 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
215 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
214 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
216 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
215 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
217 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
216 graphChildRange.m_TStart += deltaLeft;
218 graphChildRange.m_TStart += deltaLeft;
217 graphChildRange.m_TEnd += deltaRight;
219 graphChildRange.m_TEnd += deltaRight;
218 qCDebug(LOG_VisualizationZoneWidget())
220 qCDebug(LOG_VisualizationZoneWidget())
219 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
221 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
220 break;
222 break;
221 }
223 }
222 case AcquisitionZoomType::PanLeft: {
224 case AcquisitionZoomType::PanLeft: {
223 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
225 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
224 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
226 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
225 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
227 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
226 graphChildRange.m_TStart -= deltaLeft;
228 graphChildRange.m_TStart -= deltaLeft;
227 graphChildRange.m_TEnd -= deltaRight;
229 graphChildRange.m_TEnd -= deltaRight;
228 break;
230 break;
229 }
231 }
230 case AcquisitionZoomType::Unknown: {
232 case AcquisitionZoomType::Unknown: {
231 qCDebug(LOG_VisualizationZoneWidget())
233 qCDebug(LOG_VisualizationZoneWidget())
232 << tr("Impossible to synchronize: zoom type unknown");
234 << tr("Impossible to synchronize: zoom type unknown");
233 break;
235 break;
234 }
236 }
235 default:
237 default:
236 qCCritical(LOG_VisualizationZoneWidget())
238 qCCritical(LOG_VisualizationZoneWidget())
237 << tr("Impossible to synchronize: zoom type not take into account");
239 << tr("Impossible to synchronize: zoom type not take into account");
238 // No action
240 // No action
239 break;
241 break;
240 }
242 }
241 graphChild->enableAcquisition(false);
243 graphChild->enableAcquisition(false);
242 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
243 << graphChild->graphRange();
245 << graphChild->graphRange();
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
246 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
245 << graphChildRange;
247 << graphChildRange;
246 qCDebug(LOG_VisualizationZoneWidget())
248 qCDebug(LOG_VisualizationZoneWidget())
247 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
249 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
248 graphChild->setGraphRange(graphChildRange);
250 graphChild->setGraphRange(graphChildRange);
249 graphChild->enableAcquisition(true);
251 graphChild->enableAcquisition(true);
250 }
252 }
251 }
253 }
252 };
254 };
253
255
254 // connection for synchronization
256 // connection for synchronization
255 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
257 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
256 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
258 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
257 &VisualizationZoneWidget::onVariableAdded);
259 &VisualizationZoneWidget::onVariableAdded);
258 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
260 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
259 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
261 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
260
262
261 auto range = SqpRange{};
263 auto range = SqpRange{};
262 if (auto firstGraph = impl->firstGraph(this)) {
264 if (auto firstGraph = impl->firstGraph(this)) {
263 // Case of a new graph in a existant zone
265 // Case of a new graph in a existant zone
264 range = firstGraph->graphRange();
266 range = firstGraph->graphRange();
265 }
267 }
266 else {
268 else {
267 // Case of a new graph as the first of the zone
269 // Case of a new graph as the first of the zone
268 range = variable->range();
270 range = variable->range();
269 }
271 }
270
272
271 this->insertGraph(index, graphWidget);
273 this->insertGraph(index, graphWidget);
272
274
273 graphWidget->addVariable(variable, range);
275 graphWidget->addVariable(variable, range);
274 graphWidget->setYRange(variable);
276 graphWidget->setYRange(variable);
275
277
276 return graphWidget;
278 return graphWidget;
277 }
279 }
278
280
279 VisualizationGraphWidget *
281 VisualizationGraphWidget *
280 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
282 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
281 {
283 {
282 if (variables.isEmpty()) {
284 if (variables.isEmpty()) {
283 return nullptr;
285 return nullptr;
284 }
286 }
285
287
286 auto graphWidget = createGraph(variables.first(), index);
288 auto graphWidget = createGraph(variables.first(), index);
287 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
289 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
288 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
290 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
289 }
291 }
290
292
291 return graphWidget;
293 return graphWidget;
292 }
294 }
293
295
294 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
296 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
295 {
297 {
296 if (visitor) {
298 if (visitor) {
297 visitor->visitEnter(this);
299 visitor->visitEnter(this);
298
300
299 // Apply visitor to graph children: widgets different from graphs are not visited (no
301 // Apply visitor to graph children: widgets different from graphs are not visited (no
300 // action)
302 // action)
301 processGraphs(
303 processGraphs(
302 *ui->dragDropContainer->layout(),
304 *ui->dragDropContainer->layout(),
303 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
305 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
304
306
305 visitor->visitLeave(this);
307 visitor->visitLeave(this);
306 }
308 }
307 else {
309 else {
308 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
310 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
309 }
311 }
310 }
312 }
311
313
312 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
314 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
313 {
315 {
314 // A tab can always accomodate a variable
316 // A tab can always accomodate a variable
315 Q_UNUSED(variable);
317 Q_UNUSED(variable);
316 return true;
318 return true;
317 }
319 }
318
320
319 bool VisualizationZoneWidget::contains(const Variable &variable) const
321 bool VisualizationZoneWidget::contains(const Variable &variable) const
320 {
322 {
321 Q_UNUSED(variable);
323 Q_UNUSED(variable);
322 return false;
324 return false;
323 }
325 }
324
326
325 QString VisualizationZoneWidget::name() const
327 QString VisualizationZoneWidget::name() const
326 {
328 {
327 return ui->zoneNameLabel->text();
329 return ui->zoneNameLabel->text();
328 }
330 }
329
331
330 QMimeData *VisualizationZoneWidget::mimeData() const
332 QMimeData *VisualizationZoneWidget::mimeData() const
331 {
333 {
332 auto mimeData = new QMimeData;
334 auto mimeData = new QMimeData;
333 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
335 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
334
336
337 if (auto firstGraph = impl->firstGraph(this)) {
338 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
339 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
340 }
341
335 return mimeData;
342 return mimeData;
336 }
343 }
337
344
338 bool VisualizationZoneWidget::isDragAllowed() const
345 bool VisualizationZoneWidget::isDragAllowed() const
339 {
346 {
340 return true;
347 return true;
341 }
348 }
342
349
343 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
350 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
344 {
351 {
345 // Closes graphs in the zone
352 // Closes graphs in the zone
346 processGraphs(*ui->dragDropContainer->layout(),
353 processGraphs(*ui->dragDropContainer->layout(),
347 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
354 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
348
355
349 // Delete synchronization group from variable controller
356 // Delete synchronization group from variable controller
350 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
357 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
351 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
358 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
352
359
353 QWidget::closeEvent(event);
360 QWidget::closeEvent(event);
354 }
361 }
355
362
356 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
363 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
357 {
364 {
358 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
365 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
359 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
366 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
360 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
367 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
361 }
368 }
362
369
363 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
370 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
364 {
371 {
365 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
372 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
366 Q_ARG(std::shared_ptr<Variable>, variable),
373 Q_ARG(std::shared_ptr<Variable>, variable),
367 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
374 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
368 }
375 }
369
376
370 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
377 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
371 {
378 {
372 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
379 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
373 impl->dropGraph(index, this);
380 impl->dropGraph(index, this);
374 }
381 }
375 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
382 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
376 auto variables = sqpApp->variableController().variablesForMimeData(
383 auto variables = sqpApp->variableController().variablesForMimeData(
377 mimeData->data(MIME_TYPE_VARIABLE_LIST));
384 mimeData->data(MIME_TYPE_VARIABLE_LIST));
378 impl->dropVariables(variables, index, this);
385 impl->dropVariables(variables, index, this);
379 }
386 }
380 else {
387 else {
381 qCWarning(LOG_VisualizationZoneWidget())
388 qCWarning(LOG_VisualizationZoneWidget())
382 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
389 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
383 }
390 }
384 }
391 }
385
392
386 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
393 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
387 const QMimeData *mimeData)
394 const QMimeData *mimeData)
388 {
395 {
389 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
396 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
390 if (!graphWidget) {
397 if (!graphWidget) {
391 qCWarning(LOG_VisualizationZoneWidget())
398 qCWarning(LOG_VisualizationZoneWidget())
392 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
399 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
393 "drop aborted");
400 "drop aborted");
394 Q_ASSERT(false);
401 Q_ASSERT(false);
395 return;
402 return;
396 }
403 }
397
404
398 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
405 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
399 auto variables = sqpApp->variableController().variablesForMimeData(
406 auto variables = sqpApp->variableController().variablesForMimeData(
400 mimeData->data(MIME_TYPE_VARIABLE_LIST));
407 mimeData->data(MIME_TYPE_VARIABLE_LIST));
401 for (const auto &var : variables) {
408 for (const auto &var : variables) {
402 graphWidget->addVariable(var, graphWidget->graphRange());
409 graphWidget->addVariable(var, graphWidget->graphRange());
403 }
410 }
404 }
411 }
405 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
412 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
406 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
413 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
407 graphWidget->setGraphRange(range);
414 graphWidget->setGraphRange(range);
408 }
415 }
409 else {
416 else {
410 qCWarning(LOG_VisualizationZoneWidget())
417 qCWarning(LOG_VisualizationZoneWidget())
411 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
418 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
412 }
419 }
413 }
420 }
414
421
415 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
422 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
416 int index, VisualizationZoneWidget *zoneWidget)
423 int index, VisualizationZoneWidget *zoneWidget)
417 {
424 {
418 auto &helper = sqpApp->dragDropHelper();
425 auto &helper = sqpApp->dragDropHelper();
419
426
420 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
427 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
421 if (!graphWidget) {
428 if (!graphWidget) {
422 qCWarning(LOG_VisualizationZoneWidget())
429 qCWarning(LOG_VisualizationZoneWidget())
423 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
430 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
424 "found or invalid.");
431 "found or invalid.");
425 Q_ASSERT(false);
432 Q_ASSERT(false);
426 return;
433 return;
427 }
434 }
428
435
429 auto parentDragDropContainer
436 auto parentDragDropContainer
430 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
437 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
431 if (!parentDragDropContainer) {
438 if (!parentDragDropContainer) {
432 qCWarning(LOG_VisualizationZoneWidget())
439 qCWarning(LOG_VisualizationZoneWidget())
433 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
440 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
434 "the dropped graph is not found.");
441 "the dropped graph is not found.");
435 Q_ASSERT(false);
442 Q_ASSERT(false);
436 return;
443 return;
437 }
444 }
438
445
439 const auto &variables = graphWidget->variables();
446 const auto &variables = graphWidget->variables();
440
447
441 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
448 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
442 // The drop didn't occur in the same zone
449 // The drop didn't occur in the same zone
443
450
444 // Abort the requests for the variables (if any)
451 // Abort the requests for the variables (if any)
445 // Commented, because it's not sure if it's needed or not
452 // Commented, because it's not sure if it's needed or not
446 // for (const auto& var : variables)
453 // for (const auto& var : variables)
447 //{
454 //{
448 // sqpApp->variableController().onAbortProgressRequested(var);
455 // sqpApp->variableController().onAbortProgressRequested(var);
449 //}
456 //}
450
457
451 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
458 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
452 auto nbGraph = parentDragDropContainer->countDragWidget();
459 auto nbGraph = parentDragDropContainer->countDragWidget();
453 if (nbGraph == 1) {
460 if (nbGraph == 1) {
454 // This is the only graph in the previous zone, close the zone
461 // This is the only graph in the previous zone, close the zone
455 helper.delayedCloseWidget(previousParentZoneWidget);
462 helper.delayedCloseWidget(previousParentZoneWidget);
456 }
463 }
457 else {
464 else {
458 // Close the graph
465 // Close the graph
459 helper.delayedCloseWidget(graphWidget);
466 helper.delayedCloseWidget(graphWidget);
460 }
467 }
461
468
462 // Creates the new graph in the zone
469 // Creates the new graph in the zone
463 zoneWidget->createGraph(variables, index);
470 zoneWidget->createGraph(variables, index);
464 }
471 }
465 else {
472 else {
466 // The drop occurred in the same zone or the graph is empty
473 // The drop occurred in the same zone or the graph is empty
467 // Simple move of the graph, no variable operation associated
474 // Simple move of the graph, no variable operation associated
468 parentDragDropContainer->layout()->removeWidget(graphWidget);
475 parentDragDropContainer->layout()->removeWidget(graphWidget);
469
476
470 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
477 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
471 // The graph is empty and dropped in a different zone.
478 // The graph is empty and dropped in a different zone.
472 // Take the range of the first graph in the zone (if existing).
479 // Take the range of the first graph in the zone (if existing).
473 auto layout = zoneWidget->ui->dragDropContainer->layout();
480 auto layout = zoneWidget->ui->dragDropContainer->layout();
474 if (layout->count() > 0) {
481 if (layout->count() > 0) {
475 if (auto visualizationGraphWidget
482 if (auto visualizationGraphWidget
476 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
483 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
477 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
484 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
478 }
485 }
479 }
486 }
480 }
487 }
481
488
482 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
489 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
483 }
490 }
484 }
491 }
485
492
486 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
493 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
487 const QList<std::shared_ptr<Variable> > &variables, int index,
494 const QList<std::shared_ptr<Variable> > &variables, int index,
488 VisualizationZoneWidget *zoneWidget)
495 VisualizationZoneWidget *zoneWidget)
489 {
496 {
490 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
497 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
491 // compatible variable here
498 // compatible variable here
492 if (variables.count() > 1) {
499 if (variables.count() > 1) {
493 qCWarning(LOG_VisualizationZoneWidget())
500 qCWarning(LOG_VisualizationZoneWidget())
494 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
501 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
495 "aborted.");
502 "aborted.");
496 return;
503 return;
497 }
504 }
498
505
499 zoneWidget->createGraph(variables, index);
506 zoneWidget->createGraph(variables, index);
500 }
507 }
@@ -1,125 +1,125
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>VisualizationZoneWidget</class>
3 <class>VisualizationZoneWidget</class>
4 <widget class="QWidget" name="VisualizationZoneWidget">
4 <widget class="QWidget" name="VisualizationZoneWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>400</width>
9 <width>400</width>
10 <height>300</height>
10 <height>300</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="windowTitle">
13 <property name="windowTitle">
14 <string>Form</string>
14 <string>Form</string>
15 </property>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout_2">
16 <layout class="QVBoxLayout" name="verticalLayout_2">
17 <property name="spacing">
17 <property name="spacing">
18 <number>0</number>
18 <number>0</number>
19 </property>
19 </property>
20 <property name="leftMargin">
20 <property name="leftMargin">
21 <number>0</number>
21 <number>0</number>
22 </property>
22 </property>
23 <property name="topMargin">
23 <property name="topMargin">
24 <number>0</number>
24 <number>0</number>
25 </property>
25 </property>
26 <property name="rightMargin">
26 <property name="rightMargin">
27 <number>0</number>
27 <number>0</number>
28 </property>
28 </property>
29 <property name="bottomMargin">
29 <property name="bottomMargin">
30 <number>0</number>
30 <number>6</number>
31 </property>
31 </property>
32 <item>
32 <item>
33 <widget class="QWidget" name="infobar" native="true">
33 <widget class="QWidget" name="infobar" native="true">
34 <property name="sizePolicy">
34 <property name="sizePolicy">
35 <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
35 <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
36 <horstretch>0</horstretch>
36 <horstretch>0</horstretch>
37 <verstretch>0</verstretch>
37 <verstretch>0</verstretch>
38 </sizepolicy>
38 </sizepolicy>
39 </property>
39 </property>
40 <layout class="QHBoxLayout" name="horizontalLayout">
40 <layout class="QHBoxLayout" name="horizontalLayout">
41 <property name="spacing">
41 <property name="spacing">
42 <number>0</number>
42 <number>0</number>
43 </property>
43 </property>
44 <property name="leftMargin">
44 <property name="leftMargin">
45 <number>0</number>
45 <number>0</number>
46 </property>
46 </property>
47 <property name="topMargin">
47 <property name="topMargin">
48 <number>0</number>
48 <number>0</number>
49 </property>
49 </property>
50 <property name="rightMargin">
50 <property name="rightMargin">
51 <number>0</number>
51 <number>0</number>
52 </property>
52 </property>
53 <property name="bottomMargin">
53 <property name="bottomMargin">
54 <number>0</number>
54 <number>0</number>
55 </property>
55 </property>
56 <item>
56 <item>
57 <widget class="QLabel" name="zoneNameLabel">
57 <widget class="QLabel" name="zoneNameLabel">
58 <property name="styleSheet">
58 <property name="styleSheet">
59 <string notr="true">color: rgb(127, 127, 127);
59 <string notr="true">color: rgb(127, 127, 127);
60 </string>
60 </string>
61 </property>
61 </property>
62 <property name="text">
62 <property name="text">
63 <string>TextLabel</string>
63 <string>TextLabel</string>
64 </property>
64 </property>
65 </widget>
65 </widget>
66 </item>
66 </item>
67 <item>
67 <item>
68 <widget class="QToolButton" name="closeButton">
68 <widget class="QToolButton" name="closeButton">
69 <property name="styleSheet">
69 <property name="styleSheet">
70 <string notr="true">background-color: transparent;</string>
70 <string notr="true">background-color: transparent;</string>
71 </property>
71 </property>
72 <property name="text">
72 <property name="text">
73 <string>Close</string>
73 <string>Close</string>
74 </property>
74 </property>
75 </widget>
75 </widget>
76 </item>
76 </item>
77 </layout>
77 </layout>
78 </widget>
78 </widget>
79 </item>
79 </item>
80 <item>
80 <item>
81 <widget class="VisualizationDragDropContainer" name="dragDropContainer">
81 <widget class="VisualizationDragDropContainer" name="dragDropContainer">
82 <property name="sizePolicy">
82 <property name="sizePolicy">
83 <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
83 <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
84 <horstretch>0</horstretch>
84 <horstretch>0</horstretch>
85 <verstretch>0</verstretch>
85 <verstretch>0</verstretch>
86 </sizepolicy>
86 </sizepolicy>
87 </property>
87 </property>
88 <property name="frameShape">
88 <property name="frameShape">
89 <enum>QFrame::Box</enum>
89 <enum>QFrame::Box</enum>
90 </property>
90 </property>
91 <property name="frameShadow">
91 <property name="frameShadow">
92 <enum>QFrame::Raised</enum>
92 <enum>QFrame::Raised</enum>
93 </property>
93 </property>
94 <property name="lineWidth">
94 <property name="lineWidth">
95 <number>1</number>
95 <number>1</number>
96 </property>
96 </property>
97 <layout class="QVBoxLayout" name="verticalLayout">
97 <layout class="QVBoxLayout" name="verticalLayout">
98 <property name="leftMargin">
98 <property name="leftMargin">
99 <number>0</number>
99 <number>0</number>
100 </property>
100 </property>
101 <property name="topMargin">
101 <property name="topMargin">
102 <number>0</number>
102 <number>0</number>
103 </property>
103 </property>
104 <property name="rightMargin">
104 <property name="rightMargin">
105 <number>0</number>
105 <number>0</number>
106 </property>
106 </property>
107 <property name="bottomMargin">
107 <property name="bottomMargin">
108 <number>0</number>
108 <number>0</number>
109 </property>
109 </property>
110 </layout>
110 </layout>
111 </widget>
111 </widget>
112 </item>
112 </item>
113 </layout>
113 </layout>
114 </widget>
114 </widget>
115 <customwidgets>
115 <customwidgets>
116 <customwidget>
116 <customwidget>
117 <class>VisualizationDragDropContainer</class>
117 <class>VisualizationDragDropContainer</class>
118 <extends>QFrame</extends>
118 <extends>QFrame</extends>
119 <header>Visualization/VisualizationDragDropContainer.h</header>
119 <header>Visualization/VisualizationDragDropContainer.h</header>
120 <container>1</container>
120 <container>1</container>
121 </customwidget>
121 </customwidget>
122 </customwidgets>
122 </customwidgets>
123 <resources/>
123 <resources/>
124 <connections/>
124 <connections/>
125 </ui>
125 </ui>
General Comments 0
You need to be logged in to leave comments. Login now