##// END OF EJS Templates
Drop of variable, graph and zones on the time widget
trabillard -
r878:e439cb403ff9
parent child
Show More
@@ -1,99 +1,102
1 #ifndef SCIQLOP_DATASOURCECONTROLLER_H
1 #ifndef SCIQLOP_DATASOURCECONTROLLER_H
2 #define SCIQLOP_DATASOURCECONTROLLER_H
2 #define SCIQLOP_DATASOURCECONTROLLER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QObject>
7 #include <QObject>
8 #include <QUuid>
8 #include <QUuid>
9
9
10 #include <Common/spimpl.h>
10 #include <Common/spimpl.h>
11
11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController)
13
13
14 class DataSourceItem;
14 class DataSourceItem;
15 class IDataProvider;
15 class IDataProvider;
16
16
17 /**
17 /**
18 * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This
18 * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This
19 * is the intermediate class that SciQlop has to use in the way to connect a data source. Please
19 * is the intermediate class that SciQlop has to use in the way to connect a data source. Please
20 * first use register method to initialize a plugin specified by its metadata name (JSON plugin
20 * first use register method to initialize a plugin specified by its metadata name (JSON plugin
21 * source) then others specifics method will be able to access it. You can load a data source driver
21 * source) then others specifics method will be able to access it. You can load a data source driver
22 * plugin then create a data source.
22 * plugin then create a data source.
23 */
23 */
24 class SCIQLOP_CORE_EXPORT DataSourceController : public QObject {
24 class SCIQLOP_CORE_EXPORT DataSourceController : public QObject {
25 Q_OBJECT
25 Q_OBJECT
26 public:
26 public:
27 explicit DataSourceController(QObject *parent = 0);
27 explicit DataSourceController(QObject *parent = 0);
28 virtual ~DataSourceController();
28 virtual ~DataSourceController();
29
29
30 /**
30 /**
31 * Registers a data source. The method delivers a unique id that can be used afterwards to
31 * Registers a data source. The method delivers a unique id that can be used afterwards to
32 * access to the data source properties (structure, connection parameters, data provider, etc.)
32 * access to the data source properties (structure, connection parameters, data provider, etc.)
33 * @param dataSourceName the name of the data source
33 * @param dataSourceName the name of the data source
34 * @return the unique id with which the data source has been registered
34 * @return the unique id with which the data source has been registered
35 */
35 */
36 QUuid registerDataSource(const QString &dataSourceName) noexcept;
36 QUuid registerDataSource(const QString &dataSourceName) noexcept;
37
37
38 /**
38 /**
39 * Sets the structure of a data source. The controller takes ownership of the structure.
39 * Sets the structure of a data source. The controller takes ownership of the structure.
40 * @param dataSourceUid the unique id with which the data source has been registered into the
40 * @param dataSourceUid the unique id with which the data source has been registered into the
41 * controller. If it is invalid, the method has no effect.
41 * controller. If it is invalid, the method has no effect.
42 * @param dataSourceItem the structure of the data source. It must be not null to be registered
42 * @param dataSourceItem the structure of the data source. It must be not null to be registered
43 * @sa registerDataSource()
43 * @sa registerDataSource()
44 */
44 */
45 void setDataSourceItem(const QUuid &dataSourceUid,
45 void setDataSourceItem(const QUuid &dataSourceUid,
46 std::unique_ptr<DataSourceItem> dataSourceItem) noexcept;
46 std::unique_ptr<DataSourceItem> dataSourceItem) noexcept;
47
47
48 /**
48 /**
49 * Sets the data provider used to retrieve data from of a data source. The controller takes
49 * Sets the data provider used to retrieve data from of a data source. The controller takes
50 * ownership of the provider.
50 * ownership of the provider.
51 * @param dataSourceUid the unique id with which the data source has been registered into the
51 * @param dataSourceUid the unique id with which the data source has been registered into the
52 * controller. If it is invalid, the method has no effect.
52 * controller. If it is invalid, the method has no effect.
53 * @param dataProvider the provider of the data source
53 * @param dataProvider the provider of the data source
54 * @sa registerDataSource()
54 * @sa registerDataSource()
55 */
55 */
56 void setDataProvider(const QUuid &dataSourceUid,
56 void setDataProvider(const QUuid &dataSourceUid,
57 std::unique_ptr<IDataProvider> dataProvider) noexcept;
57 std::unique_ptr<IDataProvider> dataProvider) noexcept;
58
58
59 /**
59 /**
60 * Loads an item (product) as a variable in SciQlop
60 * Loads an item (product) as a variable in SciQlop
61 * @param dataSourceUid the unique id of the data source containing the item. It is used to get
61 * @param dataSourceUid the unique id of the data source containing the item. It is used to get
62 * the data provider associated to the data source, and pass it to for the variable creation
62 * the data provider associated to the data source, and pass it to for the variable creation
63 * @param productItem the item to load
63 * @param productItem the item to load
64 */
64 */
65 void loadProductItem(const QUuid &dataSourceUid, const DataSourceItem &productItem) noexcept;
65 void loadProductItem(const QUuid &dataSourceUid, const DataSourceItem &productItem) noexcept;
66
66
67 QByteArray mimeDataForProductsData(const QVariantList &productsData) const;
67 /// Returns the MIME data associated to a list of product meta data
68 QVariantList productsDataForMimeData(const QByteArray &mimeData) const;
68 static QByteArray mimeDataForProductsData(const QVariantList &productsData);
69
70 /// Returns the list of meta data contained in a MIME data
71 static QVariantList productsDataForMimeData(const QByteArray &mimeData);
69
72
70 public slots:
73 public slots:
71 /// Manage init/end of the controller
74 /// Manage init/end of the controller
72 void initialize();
75 void initialize();
73 void finalize();
76 void finalize();
74
77
75 void requestVariable(const QVariantHash &productData);
78 void requestVariable(const QVariantHash &productData);
76
79
77 signals:
80 signals:
78 /// Signal emitted when a structure has been set for a data source
81 /// Signal emitted when a structure has been set for a data source
79 void dataSourceItemSet(DataSourceItem *dataSourceItem);
82 void dataSourceItemSet(DataSourceItem *dataSourceItem);
80
83
81 /**
84 /**
82 * Signal emitted when a variable creation is asked for a product
85 * Signal emitted when a variable creation is asked for a product
83 * @param variableName the name of the variable
86 * @param variableName the name of the variable
84 * @param variableMetadata the metadata of the variable
87 * @param variableMetadata the metadata of the variable
85 * @param variableProvider the provider that will be used to retrieve the data of the variable
88 * @param variableProvider the provider that will be used to retrieve the data of the variable
86 * (can be null)
89 * (can be null)
87 */
90 */
88 void variableCreationRequested(const QString &variableName,
91 void variableCreationRequested(const QString &variableName,
89 const QVariantHash &variableMetadata,
92 const QVariantHash &variableMetadata,
90 std::shared_ptr<IDataProvider> variableProvider);
93 std::shared_ptr<IDataProvider> variableProvider);
91
94
92 private:
95 private:
93 void waitForFinish();
96 void waitForFinish();
94
97
95 class DataSourceControllerPrivate;
98 class DataSourceControllerPrivate;
96 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
99 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
97 };
100 };
98
101
99 #endif // SCIQLOP_DATASOURCECONTROLLER_H
102 #endif // SCIQLOP_DATASOURCECONTROLLER_H
@@ -1,42 +1,48
1 #ifndef SCIQLOP_TIMECONTROLLER_H
1 #ifndef SCIQLOP_TIMECONTROLLER_H
2 #define SCIQLOP_TIMECONTROLLER_H
2 #define SCIQLOP_TIMECONTROLLER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QObject>
9 #include <QObject>
10
10
11 #include <Common/spimpl.h>
11 #include <Common/spimpl.h>
12
12
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_TimeController)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_TimeController)
15
15
16 /**
16 /**
17 * @brief The TimeController class aims to handle the Time parameters notification in SciQlop.
17 * @brief The TimeController class aims to handle the Time parameters notification in SciQlop.
18 */
18 */
19 class SCIQLOP_CORE_EXPORT TimeController : public QObject {
19 class SCIQLOP_CORE_EXPORT TimeController : public QObject {
20 Q_OBJECT
20 Q_OBJECT
21 public:
21 public:
22 explicit TimeController(QObject *parent = 0);
22 explicit TimeController(QObject *parent = 0);
23
23
24 SqpRange dateTime() const noexcept;
24 SqpRange dateTime() const noexcept;
25
25
26 /// Returns the MIME data associated to a time range
27 static QByteArray mimeDataForTimeRange(const SqpRange &timeRange);
28
29 /// Returns the time range contained in a MIME data
30 static SqpRange timeRangeForMimeData(const QByteArray &mimeData);
31
26 signals:
32 signals:
27 /// Signal emitted to notify that time parameters has beed updated
33 /// Signal emitted to notify that time parameters has beed updated
28 void timeUpdated(SqpRange time);
34 void timeUpdated(SqpRange time);
29
35
30 public slots:
36 public slots:
31 /// Slot called when a new dateTime has been defined.
37 /// Slot called when a new dateTime has been defined.
32 void onTimeToUpdate(SqpRange dateTime);
38 void onTimeToUpdate(SqpRange dateTime);
33
39
34 /// Slot called when the dateTime has to be notified. Call timeUpdated signal
40 /// Slot called when the dateTime has to be notified. Call timeUpdated signal
35 void onTimeNotify();
41 void onTimeNotify();
36
42
37 private:
43 private:
38 class TimeControllerPrivate;
44 class TimeControllerPrivate;
39 spimpl::unique_impl_ptr<TimeControllerPrivate> impl;
45 spimpl::unique_impl_ptr<TimeControllerPrivate> impl;
40 };
46 };
41
47
42 #endif // SCIQLOP_TIMECONTROLLER_H
48 #endif // SCIQLOP_TIMECONTROLLER_H
@@ -1,132 +1,135
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 QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const;
72 QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const;
73
74 /// Returns the list of variables contained in a MIME data
72 QList<std::shared_ptr<Variable> > variablesForMimeData(const QByteArray &mimeData) const;
75 QList<std::shared_ptr<Variable> > variablesForMimeData(const QByteArray &mimeData) const;
73
76
74 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
77 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
75 signals:
78 signals:
76 /// 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
77 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
80 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
78
81
79 /// 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
80 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
83 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
81
84
82 /// 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
83 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
86 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
84
87
85 public slots:
88 public slots:
86 /// Request the data loading of the variable whithin range
89 /// Request the data loading of the variable whithin range
87 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
90 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
88 bool synchronise);
91 bool synchronise);
89 /**
92 /**
90 * Creates a new variable and adds it to the model
93 * Creates a new variable and adds it to the model
91 * @param name the name of the new variable
94 * @param name the name of the new variable
92 * @param metadata the metadata of the new variable
95 * @param metadata the metadata of the new variable
93 * @param provider the data provider for the new variable
96 * @param provider the data provider for the new variable
94 * @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
95 */
98 */
96 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
99 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
97 std::shared_ptr<IDataProvider> provider) noexcept;
100 std::shared_ptr<IDataProvider> provider) noexcept;
98
101
99 /// Update the temporal parameters of every selected variable to dateTime
102 /// Update the temporal parameters of every selected variable to dateTime
100 void onDateTimeOnSelection(const SqpRange &dateTime);
103 void onDateTimeOnSelection(const SqpRange &dateTime);
101
104
102
105
103 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
106 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
104 const SqpRange &cacheRangeRequested,
107 const SqpRange &cacheRangeRequested,
105 QVector<AcquisitionDataPacket> dataAcquired);
108 QVector<AcquisitionDataPacket> dataAcquired);
106
109
107 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
110 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
108
111
109 /// Cancel the current request for the variable
112 /// Cancel the current request for the variable
110 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
113 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
111 void onAbortAcquisitionRequested(QUuid vIdentifier);
114 void onAbortAcquisitionRequested(QUuid vIdentifier);
112
115
113 // synchronization group methods
116 // synchronization group methods
114 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
117 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
115 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
118 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
116 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
119 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
117
120
118 /// Desynchronizes the variable of the group whose identifier is passed in parameter
121 /// Desynchronizes the variable of the group whose identifier is passed in parameter
119 /// @remarks the method does nothing if the variable is not part of the group
122 /// @remarks the method does nothing if the variable is not part of the group
120 void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
123 void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
121
124
122 void initialize();
125 void initialize();
123 void finalize();
126 void finalize();
124
127
125 private:
128 private:
126 void waitForFinish();
129 void waitForFinish();
127
130
128 class VariableControllerPrivate;
131 class VariableControllerPrivate;
129 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
132 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
130 };
133 };
131
134
132 #endif // SCIQLOP_VARIABLECONTROLLER_H
135 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,192 +1,192
1 #include "DataSource/DataSourceController.h"
1 #include "DataSource/DataSourceController.h"
2 #include "DataSource/DataSourceItem.h"
2 #include "DataSource/DataSourceItem.h"
3
3
4 #include <Data/IDataProvider.h>
4 #include <Data/IDataProvider.h>
5
5
6 #include <QMutex>
6 #include <QMutex>
7 #include <QThread>
7 #include <QThread>
8
8
9 #include <QDataStream>
9 #include <QDataStream>
10 #include <QDir>
10 #include <QDir>
11 #include <QStandardPaths>
11 #include <QStandardPaths>
12
12
13 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
13 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
14
14
15 namespace {
15 namespace {
16
16
17 /**
17 /**
18 * Builds the metadata of the variable that will be generated from the loading of an item
18 * Builds the metadata of the variable that will be generated from the loading of an item
19 * @param dataSourceItem the data source item from which to generate the metadata
19 * @param dataSourceItem the data source item from which to generate the metadata
20 * @return the metadata of the variable
20 * @return the metadata of the variable
21 */
21 */
22 QVariantHash variableMetadata(const DataSourceItem &dataSourceItem)
22 QVariantHash variableMetadata(const DataSourceItem &dataSourceItem)
23 {
23 {
24 // Variable metadata contains...
24 // Variable metadata contains...
25
25
26 // ... all metadata of the item
26 // ... all metadata of the item
27 auto result = dataSourceItem.data();
27 auto result = dataSourceItem.data();
28
28
29 // ... and the name of the plugin, recovered from root item
29 // ... and the name of the plugin, recovered from root item
30 result.insert(QStringLiteral("plugin"), dataSourceItem.rootItem().name());
30 result.insert(QStringLiteral("plugin"), dataSourceItem.rootItem().name());
31
31
32 return result;
32 return result;
33 }
33 }
34
34
35 } // namespace
35 } // namespace
36
36
37 class DataSourceController::DataSourceControllerPrivate {
37 class DataSourceController::DataSourceControllerPrivate {
38 public:
38 public:
39 QMutex m_WorkingMutex;
39 QMutex m_WorkingMutex;
40 /// Data sources registered
40 /// Data sources registered
41 QHash<QUuid, QString> m_DataSources;
41 QHash<QUuid, QString> m_DataSources;
42 /// Data sources structures
42 /// Data sources structures
43 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
43 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
44 /// Data providers registered
44 /// Data providers registered
45 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
45 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
46 /// continue to live without necessarily the data source controller
46 /// continue to live without necessarily the data source controller
47 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
47 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
48
48
49 // Search for the first datasource item matching the specified data
49 // Search for the first datasource item matching the specified data
50 DataSourceItem *findDataSourceItem(const QVariantHash &data)
50 DataSourceItem *findDataSourceItem(const QVariantHash &data)
51 {
51 {
52 DataSourceItem *sourceItem = nullptr;
52 DataSourceItem *sourceItem = nullptr;
53 for (const auto &item : m_DataSourceItems) {
53 for (const auto &item : m_DataSourceItems) {
54 sourceItem = item.second->findItem(data, true);
54 sourceItem = item.second->findItem(data, true);
55 if (sourceItem) {
55 if (sourceItem) {
56 break;
56 break;
57 }
57 }
58 }
58 }
59
59
60 return sourceItem;
60 return sourceItem;
61 }
61 }
62 };
62 };
63
63
64 DataSourceController::DataSourceController(QObject *parent)
64 DataSourceController::DataSourceController(QObject *parent)
65 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
65 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
66 {
66 {
67 qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction")
67 qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction")
68 << QThread::currentThread();
68 << QThread::currentThread();
69 }
69 }
70
70
71 DataSourceController::~DataSourceController()
71 DataSourceController::~DataSourceController()
72 {
72 {
73 qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction")
73 qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction")
74 << QThread::currentThread();
74 << QThread::currentThread();
75 this->waitForFinish();
75 this->waitForFinish();
76 }
76 }
77
77
78 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
78 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
79 {
79 {
80 auto dataSourceUid = QUuid::createUuid();
80 auto dataSourceUid = QUuid::createUuid();
81 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
81 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
82
82
83 return dataSourceUid;
83 return dataSourceUid;
84 }
84 }
85
85
86 void DataSourceController::setDataSourceItem(
86 void DataSourceController::setDataSourceItem(
87 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
87 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
88 {
88 {
89 if (!dataSourceItem) {
89 if (!dataSourceItem) {
90 qCWarning(LOG_DataSourceController())
90 qCWarning(LOG_DataSourceController())
91 << tr("Data source item can't be registered (null item)");
91 << tr("Data source item can't be registered (null item)");
92 return;
92 return;
93 }
93 }
94
94
95 if (impl->m_DataSources.contains(dataSourceUid)) {
95 if (impl->m_DataSources.contains(dataSourceUid)) {
96 // The data provider is implicitly converted to a shared_ptr
96 // The data provider is implicitly converted to a shared_ptr
97 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
97 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
98
98
99 // Retrieves the data source item to emit the signal with it
99 // Retrieves the data source item to emit the signal with it
100 auto it = impl->m_DataSourceItems.find(dataSourceUid);
100 auto it = impl->m_DataSourceItems.find(dataSourceUid);
101 if (it != impl->m_DataSourceItems.end()) {
101 if (it != impl->m_DataSourceItems.end()) {
102 emit dataSourceItemSet(it->second.get());
102 emit dataSourceItemSet(it->second.get());
103 }
103 }
104 }
104 }
105 else {
105 else {
106 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
106 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
107 "data source has been registered with the uid")
107 "data source has been registered with the uid")
108 .arg(dataSourceUid.toString());
108 .arg(dataSourceUid.toString());
109 }
109 }
110 }
110 }
111
111
112 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
112 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
113 std::unique_ptr<IDataProvider> dataProvider) noexcept
113 std::unique_ptr<IDataProvider> dataProvider) noexcept
114 {
114 {
115 if (impl->m_DataSources.contains(dataSourceUid)) {
115 if (impl->m_DataSources.contains(dataSourceUid)) {
116 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
116 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
117 }
117 }
118 else {
118 else {
119 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
119 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
120 "source has been registered with the uid")
120 "source has been registered with the uid")
121 .arg(dataSourceUid.toString());
121 .arg(dataSourceUid.toString());
122 }
122 }
123 }
123 }
124
124
125 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
125 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
126 const DataSourceItem &productItem) noexcept
126 const DataSourceItem &productItem) noexcept
127 {
127 {
128 if (productItem.type() == DataSourceItemType::PRODUCT
128 if (productItem.type() == DataSourceItemType::PRODUCT
129 || productItem.type() == DataSourceItemType::COMPONENT) {
129 || productItem.type() == DataSourceItemType::COMPONENT) {
130 /// Retrieves the data provider of the data source (if any)
130 /// Retrieves the data provider of the data source (if any)
131 auto it = impl->m_DataProviders.find(dataSourceUid);
131 auto it = impl->m_DataProviders.find(dataSourceUid);
132 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
132 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
133
133
134 emit variableCreationRequested(productItem.name(), variableMetadata(productItem),
134 emit variableCreationRequested(productItem.name(), variableMetadata(productItem),
135 dataProvider);
135 dataProvider);
136 }
136 }
137 else {
137 else {
138 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
138 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
139 }
139 }
140 }
140 }
141
141
142 QByteArray DataSourceController::mimeDataForProductsData(const QVariantList &productsData) const
142 QByteArray DataSourceController::mimeDataForProductsData(const QVariantList &productsData)
143 {
143 {
144 QByteArray encodedData;
144 QByteArray encodedData;
145 QDataStream stream{&encodedData, QIODevice::WriteOnly};
145 QDataStream stream{&encodedData, QIODevice::WriteOnly};
146
146
147 stream << productsData;
147 stream << productsData;
148
148
149 return encodedData;
149 return encodedData;
150 }
150 }
151
151
152 QVariantList DataSourceController::productsDataForMimeData(const QByteArray &mimeData) const
152 QVariantList DataSourceController::productsDataForMimeData(const QByteArray &mimeData)
153 {
153 {
154 QDataStream stream{mimeData};
154 QDataStream stream{mimeData};
155
155
156 QVariantList productList;
156 QVariantList productList;
157 stream >> productList;
157 stream >> productList;
158
158
159 return productList;
159 return productList;
160 }
160 }
161
161
162 void DataSourceController::initialize()
162 void DataSourceController::initialize()
163 {
163 {
164 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init")
164 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init")
165 << QThread::currentThread();
165 << QThread::currentThread();
166 impl->m_WorkingMutex.lock();
166 impl->m_WorkingMutex.lock();
167 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
167 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
168 }
168 }
169
169
170 void DataSourceController::finalize()
170 void DataSourceController::finalize()
171 {
171 {
172 impl->m_WorkingMutex.unlock();
172 impl->m_WorkingMutex.unlock();
173 }
173 }
174
174
175 void DataSourceController::requestVariable(const QVariantHash &productData)
175 void DataSourceController::requestVariable(const QVariantHash &productData)
176 {
176 {
177 auto sourceItem = impl->findDataSourceItem(productData);
177 auto sourceItem = impl->findDataSourceItem(productData);
178
178
179 if (sourceItem) {
179 if (sourceItem) {
180 auto sourceName = sourceItem->rootItem().name();
180 auto sourceName = sourceItem->rootItem().name();
181 auto sourceId = impl->m_DataSources.key(sourceName);
181 auto sourceId = impl->m_DataSources.key(sourceName);
182 loadProductItem(sourceId, *sourceItem);
182 loadProductItem(sourceId, *sourceItem);
183 }
183 }
184 else {
184 else {
185 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
185 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
186 }
186 }
187 }
187 }
188
188
189 void DataSourceController::waitForFinish()
189 void DataSourceController::waitForFinish()
190 {
190 {
191 QMutexLocker locker{&impl->m_WorkingMutex};
191 QMutexLocker locker{&impl->m_WorkingMutex};
192 }
192 }
@@ -1,29 +1,51
1 #include "Time/TimeController.h"
1 #include "Time/TimeController.h"
2
2
3 #include <QDataStream>
4
3 Q_LOGGING_CATEGORY(LOG_TimeController, "TimeController")
5 Q_LOGGING_CATEGORY(LOG_TimeController, "TimeController")
4
6
5 struct TimeController::TimeControllerPrivate {
7 struct TimeController::TimeControllerPrivate {
6
8
7 SqpRange m_DateTime;
9 SqpRange m_DateTime;
8 };
10 };
9
11
10 TimeController::TimeController(QObject *parent)
12 TimeController::TimeController(QObject *parent)
11 : QObject{parent}, impl{spimpl::make_unique_impl<TimeControllerPrivate>()}
13 : QObject{parent}, impl{spimpl::make_unique_impl<TimeControllerPrivate>()}
12 {
14 {
13 qCDebug(LOG_TimeController()) << tr("TimeController construction");
15 qCDebug(LOG_TimeController()) << tr("TimeController construction");
14 }
16 }
15
17
16 SqpRange TimeController::dateTime() const noexcept
18 SqpRange TimeController::dateTime() const noexcept
17 {
19 {
18 return impl->m_DateTime;
20 return impl->m_DateTime;
19 }
21 }
20
22
23 QByteArray TimeController::mimeDataForTimeRange(const SqpRange &timeRange)
24 {
25 QByteArray encodedData;
26 QDataStream stream{&encodedData, QIODevice::WriteOnly};
27
28 stream << timeRange.m_TStart << timeRange.m_TEnd;
29
30 return encodedData;
31 }
32
33 SqpRange TimeController::timeRangeForMimeData(const QByteArray &mimeData)
34 {
35 QDataStream stream{mimeData};
36
37 SqpRange timeRange;
38 stream >> timeRange.m_TStart >> timeRange.m_TEnd;
39
40 return timeRange;
41 }
42
21 void TimeController::onTimeToUpdate(SqpRange dateTime)
43 void TimeController::onTimeToUpdate(SqpRange dateTime)
22 {
44 {
23 impl->m_DateTime = dateTime;
45 impl->m_DateTime = dateTime;
24 }
46 }
25
47
26 void TimeController::onTimeNotify()
48 void TimeController::onTimeNotify()
27 {
49 {
28 emit timeUpdated(impl->m_DateTime);
50 emit timeUpdated(impl->m_DateTime);
29 }
51 }
@@ -1,368 +1,383
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 <QDataStream>
11 #include <DataSource/DataSourceController.h>
12 #include <Time/TimeController.h>
13
12 #include <QMimeData>
14 #include <QMimeData>
13 #include <QSize>
15 #include <QSize>
14 #include <unordered_map>
16 #include <unordered_map>
15
17
16 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
18 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
17
19
18 namespace {
20 namespace {
19
21
20 // Column indexes
22 // Column indexes
21 const auto NAME_COLUMN = 0;
23 const auto NAME_COLUMN = 0;
22 const auto TSTART_COLUMN = 1;
24 const auto TSTART_COLUMN = 1;
23 const auto TEND_COLUMN = 2;
25 const auto TEND_COLUMN = 2;
24 const auto NBPOINTS_COLUMN = 3;
26 const auto NBPOINTS_COLUMN = 3;
25 const auto UNIT_COLUMN = 4;
27 const auto UNIT_COLUMN = 4;
26 const auto MISSION_COLUMN = 5;
28 const auto MISSION_COLUMN = 5;
27 const auto PLUGIN_COLUMN = 6;
29 const auto PLUGIN_COLUMN = 6;
28 const auto NB_COLUMNS = 7;
30 const auto NB_COLUMNS = 7;
29
31
30 // Column properties
32 // Column properties
31 const auto DEFAULT_HEIGHT = 25;
33 const auto DEFAULT_HEIGHT = 25;
32 const auto DEFAULT_WIDTH = 100;
34 const auto DEFAULT_WIDTH = 100;
33
35
34 struct ColumnProperties {
36 struct ColumnProperties {
35 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
37 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
36 int height = DEFAULT_HEIGHT)
38 int height = DEFAULT_HEIGHT)
37 : m_Name{name}, m_Width{width}, m_Height{height}
39 : m_Name{name}, m_Width{width}, m_Height{height}
38 {
40 {
39 }
41 }
40
42
41 QString m_Name;
43 QString m_Name;
42 int m_Width;
44 int m_Width;
43 int m_Height;
45 int m_Height;
44 };
46 };
45
47
46 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
48 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
47 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
49 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
48 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
50 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
49 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
51 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
50 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
52 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
51
53
52 /// Format for datetimes
54 /// Format for datetimes
53 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
55 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
54
56
55 QString uniqueName(const QString &defaultName,
57 QString uniqueName(const QString &defaultName,
56 const std::vector<std::shared_ptr<Variable> > &variables)
58 const std::vector<std::shared_ptr<Variable> > &variables)
57 {
59 {
58 auto forbiddenNames = std::vector<QString>(variables.size());
60 auto forbiddenNames = std::vector<QString>(variables.size());
59 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
61 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
60 [](const auto &variable) { return variable->name(); });
62 [](const auto &variable) { return variable->name(); });
61 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
63 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
62 Q_ASSERT(!uniqueName.isEmpty());
64 Q_ASSERT(!uniqueName.isEmpty());
63
65
64 return uniqueName;
66 return uniqueName;
65 }
67 }
66
68
67 } // namespace
69 } // namespace
68
70
69 struct VariableModel::VariableModelPrivate {
71 struct VariableModel::VariableModelPrivate {
70 /// Variables created in SciQlop
72 /// Variables created in SciQlop
71 std::vector<std::shared_ptr<Variable> > m_Variables;
73 std::vector<std::shared_ptr<Variable> > m_Variables;
72 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
74 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
73 VariableController *m_VariableController;
75 VariableController *m_VariableController;
74
76
75 /// Return the row index of the variable. -1 if it's not found
77 /// Return the row index of the variable. -1 if it's not found
76 int indexOfVariable(Variable *variable) const noexcept;
78 int indexOfVariable(Variable *variable) const noexcept;
77 };
79 };
78
80
79 VariableModel::VariableModel(VariableController *parent)
81 VariableModel::VariableModel(VariableController *parent)
80 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
82 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
81 {
83 {
82 impl->m_VariableController = parent;
84 impl->m_VariableController = parent;
83 }
85 }
84
86
85 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
87 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
86 {
88 {
87 auto insertIndex = rowCount();
89 auto insertIndex = rowCount();
88 beginInsertRows({}, insertIndex, insertIndex);
90 beginInsertRows({}, insertIndex, insertIndex);
89
91
90 // Generates unique name for the variable
92 // Generates unique name for the variable
91 variable->setName(uniqueName(variable->name(), impl->m_Variables));
93 variable->setName(uniqueName(variable->name(), impl->m_Variables));
92
94
93 impl->m_Variables.push_back(variable);
95 impl->m_Variables.push_back(variable);
94 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
96 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
95
97
96 endInsertRows();
98 endInsertRows();
97 }
99 }
98
100
99 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
101 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
100 {
102 {
101 auto end = impl->m_Variables.cend();
103 auto end = impl->m_Variables.cend();
102 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
104 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
103 }
105 }
104
106
105 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
107 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
106 const QVariantHash &metadata) noexcept
108 const QVariantHash &metadata) noexcept
107 {
109 {
108 auto variable = std::make_shared<Variable>(name, metadata);
110 auto variable = std::make_shared<Variable>(name, metadata);
109 addVariable(variable);
111 addVariable(variable);
110
112
111 return variable;
113 return variable;
112 }
114 }
113
115
114 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
116 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
115 {
117 {
116 if (!variable) {
118 if (!variable) {
117 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
119 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
118 return;
120 return;
119 }
121 }
120
122
121 // Finds variable in the model
123 // Finds variable in the model
122 auto begin = impl->m_Variables.cbegin();
124 auto begin = impl->m_Variables.cbegin();
123 auto end = impl->m_Variables.cend();
125 auto end = impl->m_Variables.cend();
124 auto it = std::find(begin, end, variable);
126 auto it = std::find(begin, end, variable);
125 if (it != end) {
127 if (it != end) {
126 auto removeIndex = std::distance(begin, it);
128 auto removeIndex = std::distance(begin, it);
127
129
128 // Deletes variable
130 // Deletes variable
129 beginRemoveRows({}, removeIndex, removeIndex);
131 beginRemoveRows({}, removeIndex, removeIndex);
130 impl->m_Variables.erase(it);
132 impl->m_Variables.erase(it);
131 endRemoveRows();
133 endRemoveRows();
132 }
134 }
133 else {
135 else {
134 qCritical(LOG_VariableModel())
136 qCritical(LOG_VariableModel())
135 << tr("Can't delete variable %1 from the model: the variable is not in the model")
137 << tr("Can't delete variable %1 from the model: the variable is not in the model")
136 .arg(variable->name());
138 .arg(variable->name());
137 }
139 }
138
140
139 // Removes variable from progress map
141 // Removes variable from progress map
140 impl->m_VariableToProgress.erase(variable);
142 impl->m_VariableToProgress.erase(variable);
141 }
143 }
142
144
143
145
144 std::shared_ptr<Variable> VariableModel::variable(int index) const
146 std::shared_ptr<Variable> VariableModel::variable(int index) const
145 {
147 {
146 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
148 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
147 }
149 }
148
150
149 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
151 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
150 {
152 {
151 return impl->m_Variables;
153 return impl->m_Variables;
152 }
154 }
153
155
154 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
156 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
155 {
157 {
156 if (progress > 0.0) {
158 if (progress > 0.0) {
157 impl->m_VariableToProgress[variable] = progress;
159 impl->m_VariableToProgress[variable] = progress;
158 }
160 }
159 else {
161 else {
160 impl->m_VariableToProgress.erase(variable);
162 impl->m_VariableToProgress.erase(variable);
161 }
163 }
162 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
164 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
163
165
164 emit dataChanged(modelIndex, modelIndex);
166 emit dataChanged(modelIndex, modelIndex);
165 }
167 }
166
168
167 int VariableModel::columnCount(const QModelIndex &parent) const
169 int VariableModel::columnCount(const QModelIndex &parent) const
168 {
170 {
169 Q_UNUSED(parent);
171 Q_UNUSED(parent);
170
172
171 return NB_COLUMNS;
173 return NB_COLUMNS;
172 }
174 }
173
175
174 int VariableModel::rowCount(const QModelIndex &parent) const
176 int VariableModel::rowCount(const QModelIndex &parent) const
175 {
177 {
176 Q_UNUSED(parent);
178 Q_UNUSED(parent);
177
179
178 return impl->m_Variables.size();
180 return impl->m_Variables.size();
179 }
181 }
180
182
181 QVariant VariableModel::data(const QModelIndex &index, int role) const
183 QVariant VariableModel::data(const QModelIndex &index, int role) const
182 {
184 {
183 if (!index.isValid()) {
185 if (!index.isValid()) {
184 return QVariant{};
186 return QVariant{};
185 }
187 }
186
188
187 if (index.row() < 0 || index.row() >= rowCount()) {
189 if (index.row() < 0 || index.row() >= rowCount()) {
188 return QVariant{};
190 return QVariant{};
189 }
191 }
190
192
191 if (role == Qt::DisplayRole) {
193 if (role == Qt::DisplayRole) {
192 if (auto variable = impl->m_Variables.at(index.row()).get()) {
194 if (auto variable = impl->m_Variables.at(index.row()).get()) {
193 switch (index.column()) {
195 switch (index.column()) {
194 case NAME_COLUMN:
196 case NAME_COLUMN:
195 return variable->name();
197 return variable->name();
196 case TSTART_COLUMN: {
198 case TSTART_COLUMN: {
197 auto range = variable->realRange();
199 auto range = variable->realRange();
198 return range != INVALID_RANGE
200 return range != INVALID_RANGE
199 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
201 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
200 : QVariant{};
202 : QVariant{};
201 }
203 }
202 case TEND_COLUMN: {
204 case TEND_COLUMN: {
203 auto range = variable->realRange();
205 auto range = variable->realRange();
204 return range != INVALID_RANGE
206 return range != INVALID_RANGE
205 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
207 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
206 : QVariant{};
208 : QVariant{};
207 }
209 }
208 case NBPOINTS_COLUMN:
210 case NBPOINTS_COLUMN:
209 return variable->nbPoints();
211 return variable->nbPoints();
210 case UNIT_COLUMN:
212 case UNIT_COLUMN:
211 return variable->metadata().value(QStringLiteral("units"));
213 return variable->metadata().value(QStringLiteral("units"));
212 case MISSION_COLUMN:
214 case MISSION_COLUMN:
213 return variable->metadata().value(QStringLiteral("mission"));
215 return variable->metadata().value(QStringLiteral("mission"));
214 case PLUGIN_COLUMN:
216 case PLUGIN_COLUMN:
215 return variable->metadata().value(QStringLiteral("plugin"));
217 return variable->metadata().value(QStringLiteral("plugin"));
216 default:
218 default:
217 // No action
219 // No action
218 break;
220 break;
219 }
221 }
220
222
221 qWarning(LOG_VariableModel())
223 qWarning(LOG_VariableModel())
222 << tr("Can't get data (unknown column %1)").arg(index.column());
224 << tr("Can't get data (unknown column %1)").arg(index.column());
223 }
225 }
224 else {
226 else {
225 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
227 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
226 }
228 }
227 }
229 }
228 else if (role == VariableRoles::ProgressRole) {
230 else if (role == VariableRoles::ProgressRole) {
229 if (auto variable = impl->m_Variables.at(index.row())) {
231 if (auto variable = impl->m_Variables.at(index.row())) {
230
232
231 auto it = impl->m_VariableToProgress.find(variable);
233 auto it = impl->m_VariableToProgress.find(variable);
232 if (it != impl->m_VariableToProgress.cend()) {
234 if (it != impl->m_VariableToProgress.cend()) {
233 return it->second;
235 return it->second;
234 }
236 }
235 }
237 }
236 }
238 }
237
239
238 return QVariant{};
240 return QVariant{};
239 }
241 }
240
242
241 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
243 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
242 {
244 {
243 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
245 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
244 return QVariant{};
246 return QVariant{};
245 }
247 }
246
248
247 if (orientation == Qt::Horizontal) {
249 if (orientation == Qt::Horizontal) {
248 auto propertiesIt = COLUMN_PROPERTIES.find(section);
250 auto propertiesIt = COLUMN_PROPERTIES.find(section);
249 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
251 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
250 // Role is either DisplayRole or SizeHintRole
252 // Role is either DisplayRole or SizeHintRole
251 return (role == Qt::DisplayRole)
253 return (role == Qt::DisplayRole)
252 ? QVariant{propertiesIt->m_Name}
254 ? QVariant{propertiesIt->m_Name}
253 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
255 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
254 }
256 }
255 else {
257 else {
256 qWarning(LOG_VariableModel())
258 qWarning(LOG_VariableModel())
257 << tr("Can't get header data (unknown column %1)").arg(section);
259 << tr("Can't get header data (unknown column %1)").arg(section);
258 }
260 }
259 }
261 }
260
262
261 return QVariant{};
263 return QVariant{};
262 }
264 }
263
265
264 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
266 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
265 {
267 {
266 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
268 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
267 }
269 }
268
270
269 Qt::DropActions VariableModel::supportedDropActions() const
271 Qt::DropActions VariableModel::supportedDropActions() const
270 {
272 {
271 return Qt::CopyAction | Qt::MoveAction;
273 return Qt::CopyAction | Qt::MoveAction;
272 }
274 }
273
275
274 Qt::DropActions VariableModel::supportedDragActions() const
276 Qt::DropActions VariableModel::supportedDragActions() const
275 {
277 {
276 return Qt::CopyAction | Qt::MoveAction;
278 return Qt::CopyAction | Qt::MoveAction;
277 }
279 }
278
280
279 QStringList VariableModel::mimeTypes() const
281 QStringList VariableModel::mimeTypes() const
280 {
282 {
281 return {MIME_TYPE_VARIABLE_LIST};
283 return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE};
282 }
284 }
283
285
284 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
286 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
285 {
287 {
286 auto mimeData = new QMimeData;
288 auto mimeData = new QMimeData;
287
289
288 QList<std::shared_ptr<Variable> > variableList;
290 QList<std::shared_ptr<Variable> > variableList;
289
291
292
293 SqpRange firstTimeRange;
290 for (const auto &index : indexes) {
294 for (const auto &index : indexes) {
291 if (index.column() == 0) { // only the first column
295 if (index.column() == 0) { // only the first column
292 auto variable = impl->m_Variables.at(index.row());
296 auto variable = impl->m_Variables.at(index.row());
293 if (variable.get() && index.isValid()) {
297 if (variable.get() && index.isValid()) {
298
299 if (variableList.isEmpty()) {
300 // Gets the range of the first variable
301 firstTimeRange = std::move(variable->range());
302 }
303
294 variableList << variable;
304 variableList << variable;
295 }
305 }
296 }
306 }
297 }
307 }
298
308
299 auto encodedData = impl->m_VariableController->mimeDataForVariables(variableList);
309 auto variablesEncodedData = impl->m_VariableController->mimeDataForVariables(variableList);
300 mimeData->setData(MIME_TYPE_VARIABLE_LIST, encodedData);
310 mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData);
311
312 if (variableList.count() == 1) {
313 // No time range MIME data if multiple variables are dragged
314 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
315 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
316 }
301
317
302 return mimeData;
318 return mimeData;
303 }
319 }
304
320
305 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
321 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
306 int column, const QModelIndex &parent) const
322 int column, const QModelIndex &parent) const
307 {
323 {
308 // drop of a product
324 // drop of a product
309 return data->hasFormat(MIME_TYPE_PRODUCT_LIST);
325 return data->hasFormat(MIME_TYPE_PRODUCT_LIST);
310 }
326 }
311
327
312 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
328 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
313 const QModelIndex &parent)
329 const QModelIndex &parent)
314 {
330 {
315 auto dropDone = false;
331 auto dropDone = false;
316
332
317 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
333 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
318 QDataStream stream(data->data(MIME_TYPE_PRODUCT_LIST));
319
334
320 QVariantList productList;
335 auto productList
321 stream >> productList;
336 = DataSourceController::productsDataForMimeData(data->data(MIME_TYPE_PRODUCT_LIST));
322
337
323 for (auto metaData : productList) {
338 for (auto metaData : productList) {
324 emit requestVariable(metaData.toHash());
339 emit requestVariable(metaData.toHash());
325 }
340 }
326
341
327 dropDone = true;
342 dropDone = true;
328 }
343 }
329
344
330 return dropDone;
345 return dropDone;
331 }
346 }
332
347
333 void VariableModel::abortProgress(const QModelIndex &index)
348 void VariableModel::abortProgress(const QModelIndex &index)
334 {
349 {
335 if (auto variable = impl->m_Variables.at(index.row())) {
350 if (auto variable = impl->m_Variables.at(index.row())) {
336 emit abortProgessRequested(variable);
351 emit abortProgessRequested(variable);
337 }
352 }
338 }
353 }
339
354
340 void VariableModel::onVariableUpdated() noexcept
355 void VariableModel::onVariableUpdated() noexcept
341 {
356 {
342 // Finds variable that has been updated in the model
357 // Finds variable that has been updated in the model
343 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
358 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
344 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
359 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
345
360
346 if (updatedVariableIndex > -1) {
361 if (updatedVariableIndex > -1) {
347 emit dataChanged(createIndex(updatedVariableIndex, 0),
362 emit dataChanged(createIndex(updatedVariableIndex, 0),
348 createIndex(updatedVariableIndex, columnCount() - 1));
363 createIndex(updatedVariableIndex, columnCount() - 1));
349 }
364 }
350 }
365 }
351 }
366 }
352
367
353 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
368 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
354 {
369 {
355 auto begin = std::cbegin(m_Variables);
370 auto begin = std::cbegin(m_Variables);
356 auto end = std::cend(m_Variables);
371 auto end = std::cend(m_Variables);
357 auto it
372 auto it
358 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
373 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
359
374
360 if (it != end) {
375 if (it != end) {
361 // Gets the index of the variable in the model: we assume here that views have the same
376 // Gets the index of the variable in the model: we assume here that views have the same
362 // order as the model
377 // order as the model
363 return std::distance(begin, it);
378 return std::distance(begin, it);
364 }
379 }
365 else {
380 else {
366 return -1;
381 return -1;
367 }
382 }
368 }
383 }
@@ -1,32 +1,39
1 #ifndef SCIQLOP_TIMEWIDGET_H
1 #ifndef SCIQLOP_TIMEWIDGET_H
2 #define SCIQLOP_TIMEWIDGET_H
2 #define SCIQLOP_TIMEWIDGET_H
3
3
4 #include <QWidget>
4 #include <QWidget>
5
5
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 namespace Ui {
8 namespace Ui {
9 class TimeWidget;
9 class TimeWidget;
10 } // Ui
10 } // Ui
11
11
12 class TimeWidget : public QWidget {
12 class TimeWidget : public QWidget {
13 Q_OBJECT
13 Q_OBJECT
14
14
15 public:
15 public:
16 explicit TimeWidget(QWidget *parent = 0);
16 explicit TimeWidget(QWidget *parent = 0);
17 virtual ~TimeWidget();
17 virtual ~TimeWidget();
18
18
19 void setTimeRange(SqpRange time);
20
19 signals:
21 signals:
20 /// Signal emitted when the time parameters has beed updated
22 /// Signal emitted when the time parameters has beed updated
21 void timeUpdated(SqpRange time);
23 void timeUpdated(SqpRange time);
22
24
23 public slots:
25 public slots:
24 /// slot called when time parameters update has ben requested
26 /// slot called when time parameters update has ben requested
25 void onTimeUpdateRequested();
27 void onTimeUpdateRequested();
26
28
29 protected:
30 void dragEnterEvent(QDragEnterEvent *event) override;
31 void dragLeaveEvent(QDragLeaveEvent *event) override;
32 void dropEvent(QDropEvent *event) override;
33
27
34
28 private:
35 private:
29 Ui::TimeWidget *ui;
36 Ui::TimeWidget *ui;
30 };
37 };
31
38
32 #endif // SCIQLOP_ SQPSIDEPANE_H
39 #endif // SCIQLOP_ SQPSIDEPANE_H
@@ -1,50 +1,96
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>
6
5 #include <SqpApplication.h>
7 #include <SqpApplication.h>
6 #include <Time/TimeController.h>
8 #include <Time/TimeController.h>
7
9
10 #include <QDragEnterEvent>
11 #include <QDropEvent>
12 #include <QMimeData>
13
8 TimeWidget::TimeWidget(QWidget *parent) : QWidget{parent}, ui{new Ui::TimeWidget}
14 TimeWidget::TimeWidget(QWidget *parent) : QWidget{parent}, ui{new Ui::TimeWidget}
9 {
15 {
10 ui->setupUi(this);
16 ui->setupUi(this);
11
17
12 ui->applyToolButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_DialogApplyButton));
18 ui->applyToolButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_DialogApplyButton));
13
19
14 // Connection
20 // Connection
15 connect(ui->startDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
21 connect(ui->startDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
16 &TimeWidget::onTimeUpdateRequested);
22 &TimeWidget::onTimeUpdateRequested);
17
23
18 connect(ui->endDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
24 connect(ui->endDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
19 &TimeWidget::onTimeUpdateRequested);
25 &TimeWidget::onTimeUpdateRequested);
20
26
21
27
22 connect(ui->applyToolButton, &QToolButton::clicked, &sqpApp->timeController(),
28 connect(ui->applyToolButton, &QToolButton::clicked, &sqpApp->timeController(),
23 &TimeController::onTimeNotify);
29 &TimeController::onTimeNotify);
24
30
25 // Initialisation
31 // Initialisation
26 auto endDateTime = QDateTime::currentDateTimeUtc();
32 auto endDateTime = QDateTime::currentDateTimeUtc();
27 auto startDateTime = endDateTime.addSecs(-3600); // one hour before
33 auto startDateTime = endDateTime.addSecs(-3600); // one hour before
28
34
29 ui->startDateTimeEdit->setDateTime(startDateTime);
35 ui->startDateTimeEdit->setDateTime(startDateTime);
30 ui->endDateTimeEdit->setDateTime(endDateTime);
36 ui->endDateTimeEdit->setDateTime(endDateTime);
31
37
32 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(startDateTime),
38 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(startDateTime),
33 DateUtils::secondsSinceEpoch(endDateTime)};
39 DateUtils::secondsSinceEpoch(endDateTime)};
34
40
35 sqpApp->timeController().onTimeToUpdate(dateTime);
41 sqpApp->timeController().onTimeToUpdate(dateTime);
36 }
42 }
37
43
38
44
39 TimeWidget::~TimeWidget()
45 TimeWidget::~TimeWidget()
40 {
46 {
41 delete ui;
47 delete ui;
42 }
48 }
43
49
50 void TimeWidget::setTimeRange(SqpRange time)
51 {
52 auto startDateTime = DateUtils::dateTime(time.m_TStart);
53 auto endDateTime = DateUtils::dateTime(time.m_TEnd);
54
55 ui->startDateTimeEdit->setDateTime(startDateTime);
56 ui->endDateTimeEdit->setDateTime(endDateTime);
57 }
58
44 void TimeWidget::onTimeUpdateRequested()
59 void TimeWidget::onTimeUpdateRequested()
45 {
60 {
46 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
61 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
47 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
62 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
48
63
49 emit timeUpdated(std::move(dateTime));
64 emit timeUpdated(std::move(dateTime));
50 }
65 }
66
67 void TimeWidget::dragEnterEvent(QDragEnterEvent *event)
68 {
69 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
70 event->acceptProposedAction();
71 setStyleSheet("QDateTimeEdit{background-color: #BBD5EE; border:2px solid #2A7FD4}");
72 }
73 else {
74 event->ignore();
75 }
76 }
77
78 void TimeWidget::dragLeaveEvent(QDragLeaveEvent *event)
79 {
80 setStyleSheet(QString());
81 }
82
83 void TimeWidget::dropEvent(QDropEvent *event)
84 {
85 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
86 auto mimeData = event->mimeData()->data(MIME_TYPE_TIME_RANGE);
87 auto timeRange = TimeController::timeRangeForMimeData(mimeData);
88
89 setTimeRange(timeRange);
90 }
91 else {
92 event->ignore();
93 }
94
95 setStyleSheet(QString());
96 }
@@ -1,397 +1,401
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationDefs.h"
3 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationGraphHelper.h"
4 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
8
8
9 #include <Common/MimeTypesDef.h>
9 #include <Common/MimeTypesDef.h>
10 #include <Data/ArrayData.h>
10 #include <Data/ArrayData.h>
11 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
12 #include <DragDropHelper.h>
12 #include <DragDropHelper.h>
13 #include <Settings/SqpSettingsDefs.h>
13 #include <Settings/SqpSettingsDefs.h>
14 #include <SqpApplication.h>
14 #include <SqpApplication.h>
15 #include <Time/TimeController.h>
15 #include <Variable/Variable.h>
16 #include <Variable/Variable.h>
16 #include <Variable/VariableController.h>
17 #include <Variable/VariableController.h>
17
18
18 #include <unordered_map>
19 #include <unordered_map>
19
20
20 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
21 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
21
22
22 namespace {
23 namespace {
23
24
24 /// Key pressed to enable zoom on horizontal axis
25 /// Key pressed to enable zoom on horizontal axis
25 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
26 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
26
27
27 /// Key pressed to enable zoom on vertical axis
28 /// Key pressed to enable zoom on vertical axis
28 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
29 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
29
30
30 } // namespace
31 } // namespace
31
32
32 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
33 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
33
34
34 explicit VisualizationGraphWidgetPrivate(const QString &name)
35 explicit VisualizationGraphWidgetPrivate(const QString &name)
35 : m_Name{name},
36 : m_Name{name},
36 m_DoAcquisition{true},
37 m_DoAcquisition{true},
37 m_IsCalibration{false},
38 m_IsCalibration{false},
38 m_RenderingDelegate{nullptr}
39 m_RenderingDelegate{nullptr}
39 {
40 {
40 }
41 }
41
42
42 QString m_Name;
43 QString m_Name;
43 // 1 variable -> n qcpplot
44 // 1 variable -> n qcpplot
44 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
45 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
45 bool m_DoAcquisition;
46 bool m_DoAcquisition;
46 bool m_IsCalibration;
47 bool m_IsCalibration;
47 QCPItemTracer *m_TextTracer;
48 QCPItemTracer *m_TextTracer;
48 /// Delegate used to attach rendering features to the plot
49 /// Delegate used to attach rendering features to the plot
49 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
50 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
50 };
51 };
51
52
52 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
53 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
53 : VisualizationDragWidget{parent},
54 : VisualizationDragWidget{parent},
54 ui{new Ui::VisualizationGraphWidget},
55 ui{new Ui::VisualizationGraphWidget},
55 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
56 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
56 {
57 {
57 ui->setupUi(this);
58 ui->setupUi(this);
58
59
59 // 'Close' options : widget is deleted when closed
60 // 'Close' options : widget is deleted when closed
60 setAttribute(Qt::WA_DeleteOnClose);
61 setAttribute(Qt::WA_DeleteOnClose);
61
62
62 // Set qcpplot properties :
63 // Set qcpplot properties :
63 // - Drag (on x-axis) and zoom are enabled
64 // - Drag (on x-axis) and zoom are enabled
64 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
65 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
65 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
66 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
66 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
67 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
67
68
68 // The delegate must be initialized after the ui as it uses the plot
69 // The delegate must be initialized after the ui as it uses the plot
69 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
70 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
70
71
71 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
72 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
72 connect(ui->widget, &QCustomPlot::mouseRelease, this,
73 connect(ui->widget, &QCustomPlot::mouseRelease, this,
73 &VisualizationGraphWidget::onMouseRelease);
74 &VisualizationGraphWidget::onMouseRelease);
74 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
75 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
75 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
76 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
76 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
77 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
77 &QCPAxis::rangeChanged),
78 &QCPAxis::rangeChanged),
78 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
79 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
79
80
80 // Activates menu when right clicking on the graph
81 // Activates menu when right clicking on the graph
81 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
82 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
82 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
83 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
83 &VisualizationGraphWidget::onGraphMenuRequested);
84 &VisualizationGraphWidget::onGraphMenuRequested);
84
85
85 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
86 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
86 &VariableController::onRequestDataLoading);
87 &VariableController::onRequestDataLoading);
87
88
88 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
89 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
89 &VisualizationGraphWidget::onUpdateVarDisplaying);
90 &VisualizationGraphWidget::onUpdateVarDisplaying);
90 }
91 }
91
92
92
93
93 VisualizationGraphWidget::~VisualizationGraphWidget()
94 VisualizationGraphWidget::~VisualizationGraphWidget()
94 {
95 {
95 delete ui;
96 delete ui;
96 }
97 }
97
98
98 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
99 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
99 {
100 {
100 auto parent = parentWidget();
101 auto parent = parentWidget();
101 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
102 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
102 parent = parent->parentWidget();
103 parent = parent->parentWidget();
103 }
104 }
104
105
105 return qobject_cast<VisualizationZoneWidget *>(parent);
106 return qobject_cast<VisualizationZoneWidget *>(parent);
106 }
107 }
107
108
108 void VisualizationGraphWidget::enableAcquisition(bool enable)
109 void VisualizationGraphWidget::enableAcquisition(bool enable)
109 {
110 {
110 impl->m_DoAcquisition = enable;
111 impl->m_DoAcquisition = enable;
111 }
112 }
112
113
113 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
114 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
114 {
115 {
115 // Uses delegate to create the qcpplot components according to the variable
116 // Uses delegate to create the qcpplot components according to the variable
116 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
117 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
117 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
118 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
118
119
119 // Set axes properties according to the units of the data series
120 // Set axes properties according to the units of the data series
120 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
121 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
121 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
122 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
122 auto xAxisUnit = Unit{};
123 auto xAxisUnit = Unit{};
123 auto valuesUnit = Unit{};
124 auto valuesUnit = Unit{};
124
125
125 if (auto dataSeries = variable->dataSeries()) {
126 if (auto dataSeries = variable->dataSeries()) {
126 dataSeries->lockRead();
127 dataSeries->lockRead();
127 xAxisUnit = dataSeries->xAxisUnit();
128 xAxisUnit = dataSeries->xAxisUnit();
128 valuesUnit = dataSeries->valuesUnit();
129 valuesUnit = dataSeries->valuesUnit();
129 dataSeries->unlock();
130 dataSeries->unlock();
130 }
131 }
131 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
132 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
132
133
133 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
134 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
134
135
135 this->enableAcquisition(false);
136 this->enableAcquisition(false);
136 this->setGraphRange(range);
137 this->setGraphRange(range);
137 this->enableAcquisition(true);
138 this->enableAcquisition(true);
138
139
139 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
140 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
140
141
141 emit variableAdded(variable);
142 emit variableAdded(variable);
142 }
143 }
143
144
144 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
145 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
145 {
146 {
146 // Each component associated to the variable :
147 // Each component associated to the variable :
147 // - is removed from qcpplot (which deletes it)
148 // - is removed from qcpplot (which deletes it)
148 // - is no longer referenced in the map
149 // - is no longer referenced in the map
149 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
150 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
150 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
151 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
151 emit variableAboutToBeRemoved(variable);
152 emit variableAboutToBeRemoved(variable);
152
153
153 auto &plottablesMap = variableIt->second;
154 auto &plottablesMap = variableIt->second;
154
155
155 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
156 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
156 plottableIt != plottableEnd;) {
157 plottableIt != plottableEnd;) {
157 ui->widget->removePlottable(plottableIt->second);
158 ui->widget->removePlottable(plottableIt->second);
158 plottableIt = plottablesMap.erase(plottableIt);
159 plottableIt = plottablesMap.erase(plottableIt);
159 }
160 }
160
161
161 impl->m_VariableToPlotMultiMap.erase(variableIt);
162 impl->m_VariableToPlotMultiMap.erase(variableIt);
162 }
163 }
163
164
164 // Updates graph
165 // Updates graph
165 ui->widget->replot();
166 ui->widget->replot();
166 }
167 }
167
168
168 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
169 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
169 {
170 {
170 auto variables = QList<std::shared_ptr<Variable> >{};
171 auto variables = QList<std::shared_ptr<Variable> >{};
171 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
172 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
172 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
173 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
173 variables << it->first;
174 variables << it->first;
174 }
175 }
175
176
176 return variables;
177 return variables;
177 }
178 }
178
179
179 void VisualizationGraphWidget::setYRange(const SqpRange &range)
180 void VisualizationGraphWidget::setYRange(const SqpRange &range)
180 {
181 {
181 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
182 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
182 }
183 }
183
184
184 SqpRange VisualizationGraphWidget::graphRange() const noexcept
185 SqpRange VisualizationGraphWidget::graphRange() const noexcept
185 {
186 {
186 auto graphRange = ui->widget->xAxis->range();
187 auto graphRange = ui->widget->xAxis->range();
187 return SqpRange{graphRange.lower, graphRange.upper};
188 return SqpRange{graphRange.lower, graphRange.upper};
188 }
189 }
189
190
190 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
191 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
191 {
192 {
192 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
193 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
193 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
194 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
194 ui->widget->replot();
195 ui->widget->replot();
195 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
196 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
196 }
197 }
197
198
198 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
199 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
199 {
200 {
200 if (visitor) {
201 if (visitor) {
201 visitor->visit(this);
202 visitor->visit(this);
202 }
203 }
203 else {
204 else {
204 qCCritical(LOG_VisualizationGraphWidget())
205 qCCritical(LOG_VisualizationGraphWidget())
205 << tr("Can't visit widget : the visitor is null");
206 << tr("Can't visit widget : the visitor is null");
206 }
207 }
207 }
208 }
208
209
209 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
210 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
210 {
211 {
211 /// @todo : for the moment, a graph can always accomodate a variable
212 /// @todo : for the moment, a graph can always accomodate a variable
212 Q_UNUSED(variable);
213 Q_UNUSED(variable);
213 return true;
214 return true;
214 }
215 }
215
216
216 bool VisualizationGraphWidget::contains(const Variable &variable) const
217 bool VisualizationGraphWidget::contains(const Variable &variable) const
217 {
218 {
218 // Finds the variable among the keys of the map
219 // Finds the variable among the keys of the map
219 auto variablePtr = &variable;
220 auto variablePtr = &variable;
220 auto findVariable
221 auto findVariable
221 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
222 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
222
223
223 auto end = impl->m_VariableToPlotMultiMap.cend();
224 auto end = impl->m_VariableToPlotMultiMap.cend();
224 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
225 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
225 return it != end;
226 return it != end;
226 }
227 }
227
228
228 QString VisualizationGraphWidget::name() const
229 QString VisualizationGraphWidget::name() const
229 {
230 {
230 return impl->m_Name;
231 return impl->m_Name;
231 }
232 }
232
233
233 QMimeData *VisualizationGraphWidget::mimeData() const
234 QMimeData *VisualizationGraphWidget::mimeData() const
234 {
235 {
235 auto mimeData = new QMimeData;
236 auto mimeData = new QMimeData;
236 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
237 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
237
238
239 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
240 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
241
238 return mimeData;
242 return mimeData;
239 }
243 }
240
244
241 bool VisualizationGraphWidget::isDragAllowed() const
245 bool VisualizationGraphWidget::isDragAllowed() const
242 {
246 {
243 return true;
247 return true;
244 }
248 }
245
249
246 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
250 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
247 {
251 {
248 if (highlighted) {
252 if (highlighted) {
249 plot().setBackground(QBrush(QColor("#BBD5EE")));
253 plot().setBackground(QBrush(QColor("#BBD5EE")));
250 }
254 }
251 else {
255 else {
252 plot().setBackground(QBrush(Qt::white));
256 plot().setBackground(QBrush(Qt::white));
253 }
257 }
254
258
255 plot().update();
259 plot().update();
256 }
260 }
257
261
258 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
262 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
259 {
263 {
260 Q_UNUSED(event);
264 Q_UNUSED(event);
261
265
262 // Prevents that all variables will be removed from graph when it will be closed
266 // Prevents that all variables will be removed from graph when it will be closed
263 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
267 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
264 emit variableAboutToBeRemoved(variableEntry.first);
268 emit variableAboutToBeRemoved(variableEntry.first);
265 }
269 }
266 }
270 }
267
271
268 void VisualizationGraphWidget::enterEvent(QEvent *event)
272 void VisualizationGraphWidget::enterEvent(QEvent *event)
269 {
273 {
270 Q_UNUSED(event);
274 Q_UNUSED(event);
271 impl->m_RenderingDelegate->showGraphOverlay(true);
275 impl->m_RenderingDelegate->showGraphOverlay(true);
272 }
276 }
273
277
274 void VisualizationGraphWidget::leaveEvent(QEvent *event)
278 void VisualizationGraphWidget::leaveEvent(QEvent *event)
275 {
279 {
276 Q_UNUSED(event);
280 Q_UNUSED(event);
277 impl->m_RenderingDelegate->showGraphOverlay(false);
281 impl->m_RenderingDelegate->showGraphOverlay(false);
278 }
282 }
279
283
280 QCustomPlot &VisualizationGraphWidget::plot() noexcept
284 QCustomPlot &VisualizationGraphWidget::plot() noexcept
281 {
285 {
282 return *ui->widget;
286 return *ui->widget;
283 }
287 }
284
288
285 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
289 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
286 {
290 {
287 QMenu graphMenu{};
291 QMenu graphMenu{};
288
292
289 // Iterates on variables (unique keys)
293 // Iterates on variables (unique keys)
290 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
294 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
291 end = impl->m_VariableToPlotMultiMap.cend();
295 end = impl->m_VariableToPlotMultiMap.cend();
292 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
296 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
293 // 'Remove variable' action
297 // 'Remove variable' action
294 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
298 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
295 [ this, var = it->first ]() { removeVariable(var); });
299 [ this, var = it->first ]() { removeVariable(var); });
296 }
300 }
297
301
298 if (!graphMenu.isEmpty()) {
302 if (!graphMenu.isEmpty()) {
299 graphMenu.exec(QCursor::pos());
303 graphMenu.exec(QCursor::pos());
300 }
304 }
301 }
305 }
302
306
303 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
307 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
304 {
308 {
305 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
309 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
306 << QThread::currentThread()->objectName() << "DoAcqui"
310 << QThread::currentThread()->objectName() << "DoAcqui"
307 << impl->m_DoAcquisition;
311 << impl->m_DoAcquisition;
308
312
309 auto graphRange = SqpRange{t1.lower, t1.upper};
313 auto graphRange = SqpRange{t1.lower, t1.upper};
310 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
314 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
311
315
312 if (impl->m_DoAcquisition) {
316 if (impl->m_DoAcquisition) {
313 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
317 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
314
318
315 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
319 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
316 end = impl->m_VariableToPlotMultiMap.end();
320 end = impl->m_VariableToPlotMultiMap.end();
317 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
321 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
318 variableUnderGraphVector.push_back(it->first);
322 variableUnderGraphVector.push_back(it->first);
319 }
323 }
320 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
324 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
321 !impl->m_IsCalibration);
325 !impl->m_IsCalibration);
322
326
323 if (!impl->m_IsCalibration) {
327 if (!impl->m_IsCalibration) {
324 qCDebug(LOG_VisualizationGraphWidget())
328 qCDebug(LOG_VisualizationGraphWidget())
325 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
329 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
326 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
330 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
327 emit synchronize(graphRange, oldGraphRange);
331 emit synchronize(graphRange, oldGraphRange);
328 }
332 }
329 }
333 }
330 }
334 }
331
335
332 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
336 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
333 {
337 {
334 // Handles plot rendering when mouse is moving
338 // Handles plot rendering when mouse is moving
335 impl->m_RenderingDelegate->onMouseMove(event);
339 impl->m_RenderingDelegate->onMouseMove(event);
336
340
337 VisualizationDragWidget::mouseMoveEvent(event);
341 VisualizationDragWidget::mouseMoveEvent(event);
338 }
342 }
339
343
340 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
344 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
341 {
345 {
342 auto zoomOrientations = QFlags<Qt::Orientation>{};
346 auto zoomOrientations = QFlags<Qt::Orientation>{};
343
347
344 // Lambda that enables a zoom orientation if the key modifier related to this orientation
348 // Lambda that enables a zoom orientation if the key modifier related to this orientation
345 // has
349 // has
346 // been pressed
350 // been pressed
347 auto enableOrientation
351 auto enableOrientation
348 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
352 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
349 auto orientationEnabled = event->modifiers().testFlag(modifier);
353 auto orientationEnabled = event->modifiers().testFlag(modifier);
350 zoomOrientations.setFlag(orientation, orientationEnabled);
354 zoomOrientations.setFlag(orientation, orientationEnabled);
351 };
355 };
352 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
356 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
353 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
357 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
354
358
355 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
359 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
356 }
360 }
357
361
358 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
362 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
359 {
363 {
360 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
364 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
361
365
362 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
366 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
363
367
364 VisualizationDragWidget::mousePressEvent(event);
368 VisualizationDragWidget::mousePressEvent(event);
365 }
369 }
366
370
367 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
371 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
368 {
372 {
369 impl->m_IsCalibration = false;
373 impl->m_IsCalibration = false;
370 }
374 }
371
375
372 void VisualizationGraphWidget::onDataCacheVariableUpdated()
376 void VisualizationGraphWidget::onDataCacheVariableUpdated()
373 {
377 {
374 auto graphRange = ui->widget->xAxis->range();
378 auto graphRange = ui->widget->xAxis->range();
375 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
379 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
376
380
377 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
381 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
378 auto variable = variableEntry.first;
382 auto variable = variableEntry.first;
379 qCDebug(LOG_VisualizationGraphWidget())
383 qCDebug(LOG_VisualizationGraphWidget())
380 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
384 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
381 qCDebug(LOG_VisualizationGraphWidget())
385 qCDebug(LOG_VisualizationGraphWidget())
382 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
386 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
383 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
387 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
384 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
388 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
385 variable->range());
389 variable->range());
386 }
390 }
387 }
391 }
388 }
392 }
389
393
390 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
394 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
391 const SqpRange &range)
395 const SqpRange &range)
392 {
396 {
393 auto it = impl->m_VariableToPlotMultiMap.find(variable);
397 auto it = impl->m_VariableToPlotMultiMap.find(variable);
394 if (it != impl->m_VariableToPlotMultiMap.end()) {
398 if (it != impl->m_VariableToPlotMultiMap.end()) {
395 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
399 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
396 }
400 }
397 }
401 }
@@ -1,497 +1,512
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 <Variable/Variable.h>
14 #include <Variable/Variable.h>
14 #include <Variable/VariableController.h>
15 #include <Variable/VariableController.h>
15
16
16 #include <Visualization/operations/FindVariableOperation.h>
17 #include <Visualization/operations/FindVariableOperation.h>
17
18
18 #include <DragDropHelper.h>
19 #include <DragDropHelper.h>
19 #include <QUuid>
20 #include <QUuid>
20 #include <SqpApplication.h>
21 #include <SqpApplication.h>
21 #include <cmath>
22 #include <cmath>
22
23
23 #include <QLayout>
24 #include <QLayout>
24
25
25 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26
27
27 namespace {
28 namespace {
28
29
29
30
30 /// 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
31 /// the zone
32 /// the zone
32 QString defaultGraphName(const QLayout &layout)
33 QString defaultGraphName(const QLayout &layout)
33 {
34 {
34 auto count = 0;
35 auto count = 0;
35 for (auto i = 0; i < layout.count(); ++i) {
36 for (auto i = 0; i < layout.count(); ++i) {
36 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 count++;
38 count++;
38 }
39 }
39 }
40 }
40
41
41 return QObject::tr("Graph %1").arg(count + 1);
42 return QObject::tr("Graph %1").arg(count + 1);
42 }
43 }
43
44
44 /**
45 /**
45 * 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
46 * @param layout the layout that contains graphs
47 * @param layout the layout that contains graphs
47 * @param fun the function to apply to each graph
48 * @param fun the function to apply to each graph
48 */
49 */
49 template <typename Fun>
50 template <typename Fun>
50 void processGraphs(QLayout &layout, Fun fun)
51 void processGraphs(QLayout &layout, Fun fun)
51 {
52 {
52 for (auto i = 0; i < layout.count(); ++i) {
53 for (auto i = 0; i < layout.count(); ++i) {
53 if (auto item = layout.itemAt(i)) {
54 if (auto item = layout.itemAt(i)) {
54 if (auto visualizationGraphWidget
55 if (auto visualizationGraphWidget
55 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
56 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
56 fun(*visualizationGraphWidget);
57 fun(*visualizationGraphWidget);
57 }
58 }
58 }
59 }
59 }
60 }
60 }
61 }
61
62
62 } // namespace
63 } // namespace
63
64
64 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65
66
66 explicit VisualizationZoneWidgetPrivate()
67 explicit VisualizationZoneWidgetPrivate()
67 : m_SynchronisationGroupId{QUuid::createUuid()},
68 : m_SynchronisationGroupId{QUuid::createUuid()},
68 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 {
70 {
70 }
71 }
71 QUuid m_SynchronisationGroupId;
72 QUuid m_SynchronisationGroupId;
72 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73
74
75 // Returns the first graph in the zone or nullptr if there is no graph inside
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
77 {
78 VisualizationGraphWidget *firstGraph = nullptr;
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
80 if (layout->count() > 0) {
81 if (auto visualizationGraphWidget
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
83 firstGraph = visualizationGraphWidget;
84 }
85 }
86
87 return firstGraph;
88 }
89
74 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
75 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
76 VisualizationZoneWidget *zoneWidget);
92 VisualizationZoneWidget *zoneWidget);
77 };
93 };
78
94
79 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
80 : VisualizationDragWidget{parent},
96 : VisualizationDragWidget{parent},
81 ui{new Ui::VisualizationZoneWidget},
97 ui{new Ui::VisualizationZoneWidget},
82 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
83 {
99 {
84 ui->setupUi(this);
100 ui->setupUi(this);
85
101
86 ui->zoneNameLabel->setText(name);
102 ui->zoneNameLabel->setText(name);
87
103
88 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST});
104 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST});
89 ui->dragDropContainer->setMergeAllowedMimeTypes({MIME_TYPE_VARIABLE_LIST});
105 ui->dragDropContainer->setMergeAllowedMimeTypes({MIME_TYPE_VARIABLE_LIST});
90 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
106 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
91 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
107 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
92 ui->dragDropContainer);
108 ui->dragDropContainer);
93 });
109 });
94
110
95 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
111 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
96 &VisualizationZoneWidget::dropMimeData);
112 &VisualizationZoneWidget::dropMimeData);
97 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
113 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
98 &VisualizationZoneWidget::dropMimeDataOnGraph);
114 &VisualizationZoneWidget::dropMimeDataOnGraph);
99
115
100 // 'Close' options : widget is deleted when closed
116 // 'Close' options : widget is deleted when closed
101 setAttribute(Qt::WA_DeleteOnClose);
117 setAttribute(Qt::WA_DeleteOnClose);
102 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
118 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
103 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
119 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
104
120
105 // Synchronisation id
121 // Synchronisation id
106 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
122 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
107 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
123 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
108 }
124 }
109
125
110 VisualizationZoneWidget::~VisualizationZoneWidget()
126 VisualizationZoneWidget::~VisualizationZoneWidget()
111 {
127 {
112 delete ui;
128 delete ui;
113 }
129 }
114
130
115 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
131 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
116 {
132 {
117 // Synchronize new graph with others in the zone
133 // Synchronize new graph with others in the zone
118 impl->m_Synchronizer->addGraph(*graphWidget);
134 impl->m_Synchronizer->addGraph(*graphWidget);
119
135
120 ui->dragDropContainer->addDragWidget(graphWidget);
136 ui->dragDropContainer->addDragWidget(graphWidget);
121 }
137 }
122
138
123 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
139 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
124 {
140 {
125 // Synchronize new graph with others in the zone
141 // Synchronize new graph with others in the zone
126 impl->m_Synchronizer->addGraph(*graphWidget);
142 impl->m_Synchronizer->addGraph(*graphWidget);
127
143
128 ui->dragDropContainer->insertDragWidget(index, graphWidget);
144 ui->dragDropContainer->insertDragWidget(index, graphWidget);
129 }
145 }
130
146
131 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
147 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
132 {
148 {
133 return createGraph(variable, -1);
149 return createGraph(variable, -1);
134 }
150 }
135
151
136 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
152 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
137 int index)
153 int index)
138 {
154 {
139 auto graphWidget
155 auto graphWidget
140 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
156 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
141
157
142
158
143 // Set graph properties
159 // Set graph properties
144 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
160 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
145 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
161 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
146
162
147
163
148 // Lambda to synchronize zone widget
164 // Lambda to synchronize zone widget
149 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
165 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
150 const SqpRange &oldGraphRange) {
166 const SqpRange &oldGraphRange) {
151
167
152 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
168 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
153 auto frameLayout = ui->dragDropContainer->layout();
169 auto frameLayout = ui->dragDropContainer->layout();
154 for (auto i = 0; i < frameLayout->count(); ++i) {
170 for (auto i = 0; i < frameLayout->count(); ++i) {
155 auto graphChild
171 auto graphChild
156 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
172 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
157 if (graphChild && (graphChild != graphWidget)) {
173 if (graphChild && (graphChild != graphWidget)) {
158
174
159 auto graphChildRange = graphChild->graphRange();
175 auto graphChildRange = graphChild->graphRange();
160 switch (zoomType) {
176 switch (zoomType) {
161 case AcquisitionZoomType::ZoomIn: {
177 case AcquisitionZoomType::ZoomIn: {
162 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
178 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
163 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
179 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
164 graphChildRange.m_TStart += deltaLeft;
180 graphChildRange.m_TStart += deltaLeft;
165 graphChildRange.m_TEnd -= deltaRight;
181 graphChildRange.m_TEnd -= deltaRight;
166 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
182 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
167 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
183 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
168 << deltaLeft;
184 << deltaLeft;
169 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
185 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
170 << deltaRight;
186 << deltaRight;
171 qCDebug(LOG_VisualizationZoneWidget())
187 qCDebug(LOG_VisualizationZoneWidget())
172 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
188 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
173
189
174 break;
190 break;
175 }
191 }
176
192
177 case AcquisitionZoomType::ZoomOut: {
193 case AcquisitionZoomType::ZoomOut: {
178 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
194 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
179 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
195 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
180 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
196 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
181 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
197 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
182 << deltaLeft;
198 << deltaLeft;
183 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
184 << deltaRight;
200 << deltaRight;
185 qCDebug(LOG_VisualizationZoneWidget())
201 qCDebug(LOG_VisualizationZoneWidget())
186 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
202 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
187 graphChildRange.m_TStart -= deltaLeft;
203 graphChildRange.m_TStart -= deltaLeft;
188 graphChildRange.m_TEnd += deltaRight;
204 graphChildRange.m_TEnd += deltaRight;
189 break;
205 break;
190 }
206 }
191 case AcquisitionZoomType::PanRight: {
207 case AcquisitionZoomType::PanRight: {
192 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
208 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
193 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
209 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
194 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
210 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
195 graphChildRange.m_TStart += deltaLeft;
211 graphChildRange.m_TStart += deltaLeft;
196 graphChildRange.m_TEnd += deltaRight;
212 graphChildRange.m_TEnd += deltaRight;
197 qCDebug(LOG_VisualizationZoneWidget())
213 qCDebug(LOG_VisualizationZoneWidget())
198 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
214 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
199 break;
215 break;
200 }
216 }
201 case AcquisitionZoomType::PanLeft: {
217 case AcquisitionZoomType::PanLeft: {
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
218 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
203 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
219 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
204 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
220 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
205 graphChildRange.m_TStart -= deltaLeft;
221 graphChildRange.m_TStart -= deltaLeft;
206 graphChildRange.m_TEnd -= deltaRight;
222 graphChildRange.m_TEnd -= deltaRight;
207 break;
223 break;
208 }
224 }
209 case AcquisitionZoomType::Unknown: {
225 case AcquisitionZoomType::Unknown: {
210 qCDebug(LOG_VisualizationZoneWidget())
226 qCDebug(LOG_VisualizationZoneWidget())
211 << tr("Impossible to synchronize: zoom type unknown");
227 << tr("Impossible to synchronize: zoom type unknown");
212 break;
228 break;
213 }
229 }
214 default:
230 default:
215 qCCritical(LOG_VisualizationZoneWidget())
231 qCCritical(LOG_VisualizationZoneWidget())
216 << tr("Impossible to synchronize: zoom type not take into account");
232 << tr("Impossible to synchronize: zoom type not take into account");
217 // No action
233 // No action
218 break;
234 break;
219 }
235 }
220 graphChild->enableAcquisition(false);
236 graphChild->enableAcquisition(false);
221 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
237 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
222 << graphChild->graphRange();
238 << graphChild->graphRange();
223 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
239 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
224 << graphChildRange;
240 << graphChildRange;
225 qCDebug(LOG_VisualizationZoneWidget())
241 qCDebug(LOG_VisualizationZoneWidget())
226 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
242 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
227 graphChild->setGraphRange(graphChildRange);
243 graphChild->setGraphRange(graphChildRange);
228 graphChild->enableAcquisition(true);
244 graphChild->enableAcquisition(true);
229 }
245 }
230 }
246 }
231 };
247 };
232
248
233 // connection for synchronization
249 // connection for synchronization
234 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
250 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
235 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
251 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
236 &VisualizationZoneWidget::onVariableAdded);
252 &VisualizationZoneWidget::onVariableAdded);
237 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
253 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
238 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
254 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
239
255
240 auto range = SqpRange{};
256 auto range = SqpRange{};
241
257 if (auto firstGraph = impl->firstGraph(this)) {
242 // Apply visitor to graph children
243 auto layout = ui->dragDropContainer->layout();
244 if (layout->count() > 0) {
245 // Case of a new graph in a existant zone
258 // Case of a new graph in a existant zone
246 if (auto visualizationGraphWidget
259 range = firstGraph->graphRange();
247 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
248 range = visualizationGraphWidget->graphRange();
249 }
250 }
260 }
251 else {
261 else {
252 // Case of a new graph as the first of the zone
262 // Case of a new graph as the first of the zone
253 range = variable->range();
263 range = variable->range();
254 }
264 }
255
265
256 this->insertGraph(index, graphWidget);
266 this->insertGraph(index, graphWidget);
257
267
258 graphWidget->addVariable(variable, range);
268 graphWidget->addVariable(variable, range);
259
269
260 // get y using variable range
270 // get y using variable range
261 if (auto dataSeries = variable->dataSeries()) {
271 if (auto dataSeries = variable->dataSeries()) {
262 dataSeries->lockRead();
272 dataSeries->lockRead();
263 auto valuesBounds
273 auto valuesBounds
264 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
274 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
265 auto end = dataSeries->cend();
275 auto end = dataSeries->cend();
266 if (valuesBounds.first != end && valuesBounds.second != end) {
276 if (valuesBounds.first != end && valuesBounds.second != end) {
267 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
277 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
268
278
269 auto minValue = rangeValue(valuesBounds.first->minValue());
279 auto minValue = rangeValue(valuesBounds.first->minValue());
270 auto maxValue = rangeValue(valuesBounds.second->maxValue());
280 auto maxValue = rangeValue(valuesBounds.second->maxValue());
271
281
272 graphWidget->setYRange(SqpRange{minValue, maxValue});
282 graphWidget->setYRange(SqpRange{minValue, maxValue});
273 }
283 }
274 dataSeries->unlock();
284 dataSeries->unlock();
275 }
285 }
276
286
277 return graphWidget;
287 return graphWidget;
278 }
288 }
279
289
280 VisualizationGraphWidget *
290 VisualizationGraphWidget *
281 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
291 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
282 {
292 {
283 if (variables.isEmpty()) {
293 if (variables.isEmpty()) {
284 return nullptr;
294 return nullptr;
285 }
295 }
286
296
287 auto graphWidget = createGraph(variables.first(), index);
297 auto graphWidget = createGraph(variables.first(), index);
288 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
298 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
289 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
299 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
290 }
300 }
291
301
292 return graphWidget;
302 return graphWidget;
293 }
303 }
294
304
295 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
305 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
296 {
306 {
297 if (visitor) {
307 if (visitor) {
298 visitor->visitEnter(this);
308 visitor->visitEnter(this);
299
309
300 // Apply visitor to graph children: widgets different from graphs are not visited (no
310 // Apply visitor to graph children: widgets different from graphs are not visited (no
301 // action)
311 // action)
302 processGraphs(
312 processGraphs(
303 *ui->dragDropContainer->layout(),
313 *ui->dragDropContainer->layout(),
304 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
314 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
305
315
306 visitor->visitLeave(this);
316 visitor->visitLeave(this);
307 }
317 }
308 else {
318 else {
309 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
319 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
310 }
320 }
311 }
321 }
312
322
313 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
323 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
314 {
324 {
315 // A tab can always accomodate a variable
325 // A tab can always accomodate a variable
316 Q_UNUSED(variable);
326 Q_UNUSED(variable);
317 return true;
327 return true;
318 }
328 }
319
329
320 bool VisualizationZoneWidget::contains(const Variable &variable) const
330 bool VisualizationZoneWidget::contains(const Variable &variable) const
321 {
331 {
322 Q_UNUSED(variable);
332 Q_UNUSED(variable);
323 return false;
333 return false;
324 }
334 }
325
335
326 QString VisualizationZoneWidget::name() const
336 QString VisualizationZoneWidget::name() const
327 {
337 {
328 return ui->zoneNameLabel->text();
338 return ui->zoneNameLabel->text();
329 }
339 }
330
340
331 QMimeData *VisualizationZoneWidget::mimeData() const
341 QMimeData *VisualizationZoneWidget::mimeData() const
332 {
342 {
333 auto mimeData = new QMimeData;
343 auto mimeData = new QMimeData;
334 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
344 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
335
345
346 if (const auto firstGraph = impl->firstGraph(this)) {
347 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
348 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
349 }
350
336 return mimeData;
351 return mimeData;
337 }
352 }
338
353
339 bool VisualizationZoneWidget::isDragAllowed() const
354 bool VisualizationZoneWidget::isDragAllowed() const
340 {
355 {
341 return true;
356 return true;
342 }
357 }
343
358
344 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
359 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
345 {
360 {
346 // Closes graphs in the zone
361 // Closes graphs in the zone
347 processGraphs(*ui->dragDropContainer->layout(),
362 processGraphs(*ui->dragDropContainer->layout(),
348 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
363 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
349
364
350 // Delete synchronization group from variable controller
365 // Delete synchronization group from variable controller
351 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
366 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
352 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
367 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
353
368
354 QWidget::closeEvent(event);
369 QWidget::closeEvent(event);
355 }
370 }
356
371
357 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
372 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
358 {
373 {
359 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
374 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
360 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
375 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
361 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
376 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
362 }
377 }
363
378
364 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
379 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
365 {
380 {
366 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
381 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
367 Q_ARG(std::shared_ptr<Variable>, variable),
382 Q_ARG(std::shared_ptr<Variable>, variable),
368 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
383 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
369 }
384 }
370
385
371 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
386 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
372 {
387 {
373 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
388 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
374 impl->dropGraph(index, this);
389 impl->dropGraph(index, this);
375 }
390 }
376 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
391 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
377 auto variables = sqpApp->variableController().variablesForMimeData(
392 auto variables = sqpApp->variableController().variablesForMimeData(
378 mimeData->data(MIME_TYPE_VARIABLE_LIST));
393 mimeData->data(MIME_TYPE_VARIABLE_LIST));
379 impl->dropVariables(variables, index, this);
394 impl->dropVariables(variables, index, this);
380 }
395 }
381 else {
396 else {
382 qCWarning(LOG_VisualizationZoneWidget())
397 qCWarning(LOG_VisualizationZoneWidget())
383 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
398 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
384 }
399 }
385 }
400 }
386
401
387 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
402 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
388 const QMimeData *mimeData)
403 const QMimeData *mimeData)
389 {
404 {
390 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
405 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
391 if (!graphWidget) {
406 if (!graphWidget) {
392 qCWarning(LOG_VisualizationZoneWidget())
407 qCWarning(LOG_VisualizationZoneWidget())
393 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
408 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
394 "drop aborted");
409 "drop aborted");
395 Q_ASSERT(false);
410 Q_ASSERT(false);
396 return;
411 return;
397 }
412 }
398
413
399 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
414 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
400 auto variables = sqpApp->variableController().variablesForMimeData(
415 auto variables = sqpApp->variableController().variablesForMimeData(
401 mimeData->data(MIME_TYPE_VARIABLE_LIST));
416 mimeData->data(MIME_TYPE_VARIABLE_LIST));
402 for (const auto &var : variables) {
417 for (const auto &var : variables) {
403 graphWidget->addVariable(var, graphWidget->graphRange());
418 graphWidget->addVariable(var, graphWidget->graphRange());
404 }
419 }
405 }
420 }
406 else {
421 else {
407 qCWarning(LOG_VisualizationZoneWidget())
422 qCWarning(LOG_VisualizationZoneWidget())
408 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
423 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
409 }
424 }
410 }
425 }
411
426
412 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
427 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
413 int index, VisualizationZoneWidget *zoneWidget)
428 int index, VisualizationZoneWidget *zoneWidget)
414 {
429 {
415 auto &helper = sqpApp->dragDropHelper();
430 auto &helper = sqpApp->dragDropHelper();
416
431
417 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
432 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
418 if (!graphWidget) {
433 if (!graphWidget) {
419 qCWarning(LOG_VisualizationZoneWidget())
434 qCWarning(LOG_VisualizationZoneWidget())
420 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
435 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
421 "found or invalid.");
436 "found or invalid.");
422 Q_ASSERT(false);
437 Q_ASSERT(false);
423 return;
438 return;
424 }
439 }
425
440
426 auto parentDragDropContainer
441 auto parentDragDropContainer
427 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
442 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
428 if (!parentDragDropContainer) {
443 if (!parentDragDropContainer) {
429 qCWarning(LOG_VisualizationZoneWidget())
444 qCWarning(LOG_VisualizationZoneWidget())
430 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
445 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
431 "the dropped graph is not found.");
446 "the dropped graph is not found.");
432 Q_ASSERT(false);
447 Q_ASSERT(false);
433 return;
448 return;
434 }
449 }
435
450
436 const auto &variables = graphWidget->variables();
451 const auto &variables = graphWidget->variables();
437
452
438 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
453 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
439 // The drop didn't occur in the same zone
454 // The drop didn't occur in the same zone
440
455
441 // Abort the requests for the variables (if any)
456 // Abort the requests for the variables (if any)
442 // Commented, because it's not sure if it's needed or not
457 // Commented, because it's not sure if it's needed or not
443 // for (const auto& var : variables)
458 // for (const auto& var : variables)
444 //{
459 //{
445 // sqpApp->variableController().onAbortProgressRequested(var);
460 // sqpApp->variableController().onAbortProgressRequested(var);
446 //}
461 //}
447
462
448 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
463 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
449 auto nbGraph = parentDragDropContainer->countDragWidget();
464 auto nbGraph = parentDragDropContainer->countDragWidget();
450 if (nbGraph == 1) {
465 if (nbGraph == 1) {
451 // This is the only graph in the previous zone, close the zone
466 // This is the only graph in the previous zone, close the zone
452 previousParentZoneWidget->close();
467 previousParentZoneWidget->close();
453 }
468 }
454 else {
469 else {
455 // Close the graph
470 // Close the graph
456 graphWidget->close();
471 graphWidget->close();
457 }
472 }
458
473
459 // Creates the new graph in the zone
474 // Creates the new graph in the zone
460 zoneWidget->createGraph(variables, index);
475 zoneWidget->createGraph(variables, index);
461 }
476 }
462 else {
477 else {
463 // The drop occurred in the same zone or the graph is empty
478 // The drop occurred in the same zone or the graph is empty
464 // Simple move of the graph, no variable operation associated
479 // Simple move of the graph, no variable operation associated
465 parentDragDropContainer->layout()->removeWidget(graphWidget);
480 parentDragDropContainer->layout()->removeWidget(graphWidget);
466
481
467 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
482 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
468 // The graph is empty and dropped in a different zone.
483 // The graph is empty and dropped in a different zone.
469 // Take the range of the first graph in the zone (if existing).
484 // Take the range of the first graph in the zone (if existing).
470 auto layout = zoneWidget->ui->dragDropContainer->layout();
485 auto layout = zoneWidget->ui->dragDropContainer->layout();
471 if (layout->count() > 0) {
486 if (layout->count() > 0) {
472 if (auto visualizationGraphWidget
487 if (auto visualizationGraphWidget
473 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
488 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
474 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
489 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
475 }
490 }
476 }
491 }
477 }
492 }
478
493
479 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
494 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
480 }
495 }
481 }
496 }
482
497
483 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
498 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
484 const QList<std::shared_ptr<Variable> > &variables, int index,
499 const QList<std::shared_ptr<Variable> > &variables, int index,
485 VisualizationZoneWidget *zoneWidget)
500 VisualizationZoneWidget *zoneWidget)
486 {
501 {
487 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
502 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
488 // compatible variable here
503 // compatible variable here
489 if (variables.count() > 1) {
504 if (variables.count() > 1) {
490 qCWarning(LOG_VisualizationZoneWidget())
505 qCWarning(LOG_VisualizationZoneWidget())
491 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
506 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
492 "aborted.");
507 "aborted.");
493 return;
508 return;
494 }
509 }
495
510
496 zoneWidget->createGraph(variables, index);
511 zoneWidget->createGraph(variables, index);
497 }
512 }
@@ -1,98 +1,104
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>TimeWidget</class>
3 <class>TimeWidget</class>
4 <widget class="QWidget" name="TimeWidget">
4 <widget class="QWidget" name="TimeWidget">
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>716</width>
9 <width>716</width>
10 <height>48</height>
10 <height>48</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="sizePolicy">
13 <property name="sizePolicy">
14 <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
14 <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
15 <horstretch>0</horstretch>
15 <horstretch>0</horstretch>
16 <verstretch>0</verstretch>
16 <verstretch>0</verstretch>
17 </sizepolicy>
17 </sizepolicy>
18 </property>
18 </property>
19 <property name="acceptDrops">
20 <bool>true</bool>
21 </property>
19 <property name="windowTitle">
22 <property name="windowTitle">
20 <string>Form</string>
23 <string>Form</string>
21 </property>
24 </property>
25 <property name="styleSheet">
26 <string notr="true">b</string>
27 </property>
22 <layout class="QHBoxLayout" name="horizontalLayout_2">
28 <layout class="QHBoxLayout" name="horizontalLayout_2">
23 <item>
29 <item>
24 <widget class="QLabel" name="label">
30 <widget class="QLabel" name="label">
25 <property name="sizePolicy">
31 <property name="sizePolicy">
26 <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
32 <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
27 <horstretch>0</horstretch>
33 <horstretch>0</horstretch>
28 <verstretch>0</verstretch>
34 <verstretch>0</verstretch>
29 </sizepolicy>
35 </sizepolicy>
30 </property>
36 </property>
31 <property name="text">
37 <property name="text">
32 <string>TStart :</string>
38 <string>TStart :</string>
33 </property>
39 </property>
34 </widget>
40 </widget>
35 </item>
41 </item>
36 <item>
42 <item>
37 <widget class="QDateTimeEdit" name="startDateTimeEdit">
43 <widget class="QDateTimeEdit" name="startDateTimeEdit">
38 <property name="sizePolicy">
44 <property name="sizePolicy">
39 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
45 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
40 <horstretch>0</horstretch>
46 <horstretch>0</horstretch>
41 <verstretch>0</verstretch>
47 <verstretch>0</verstretch>
42 </sizepolicy>
48 </sizepolicy>
43 </property>
49 </property>
44 <property name="displayFormat">
50 <property name="displayFormat">
45 <string>dd/MM/yyyy HH:mm:ss:zzz</string>
51 <string>dd/MM/yyyy HH:mm:ss:zzz</string>
46 </property>
52 </property>
47 <property name="calendarPopup">
53 <property name="calendarPopup">
48 <bool>true</bool>
54 <bool>true</bool>
49 </property>
55 </property>
50 <property name="timeSpec">
56 <property name="timeSpec">
51 <enum>Qt::UTC</enum>
57 <enum>Qt::UTC</enum>
52 </property>
58 </property>
53 </widget>
59 </widget>
54 </item>
60 </item>
55 <item>
61 <item>
56 <widget class="QLabel" name="label_2">
62 <widget class="QLabel" name="label_2">
57 <property name="sizePolicy">
63 <property name="sizePolicy">
58 <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
64 <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
59 <horstretch>0</horstretch>
65 <horstretch>0</horstretch>
60 <verstretch>0</verstretch>
66 <verstretch>0</verstretch>
61 </sizepolicy>
67 </sizepolicy>
62 </property>
68 </property>
63 <property name="text">
69 <property name="text">
64 <string>TEnd :</string>
70 <string>TEnd :</string>
65 </property>
71 </property>
66 </widget>
72 </widget>
67 </item>
73 </item>
68 <item>
74 <item>
69 <widget class="QDateTimeEdit" name="endDateTimeEdit">
75 <widget class="QDateTimeEdit" name="endDateTimeEdit">
70 <property name="sizePolicy">
76 <property name="sizePolicy">
71 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
77 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
72 <horstretch>0</horstretch>
78 <horstretch>0</horstretch>
73 <verstretch>0</verstretch>
79 <verstretch>0</verstretch>
74 </sizepolicy>
80 </sizepolicy>
75 </property>
81 </property>
76 <property name="displayFormat">
82 <property name="displayFormat">
77 <string>dd/MM/yyyy HH:mm:ss:zzz</string>
83 <string>dd/MM/yyyy HH:mm:ss:zzz</string>
78 </property>
84 </property>
79 <property name="calendarPopup">
85 <property name="calendarPopup">
80 <bool>true</bool>
86 <bool>true</bool>
81 </property>
87 </property>
82 <property name="timeSpec">
88 <property name="timeSpec">
83 <enum>Qt::UTC</enum>
89 <enum>Qt::UTC</enum>
84 </property>
90 </property>
85 </widget>
91 </widget>
86 </item>
92 </item>
87 <item>
93 <item>
88 <widget class="QToolButton" name="applyToolButton">
94 <widget class="QToolButton" name="applyToolButton">
89 <property name="text">
95 <property name="text">
90 <string>...</string>
96 <string>...</string>
91 </property>
97 </property>
92 </widget>
98 </widget>
93 </item>
99 </item>
94 </layout>
100 </layout>
95 </widget>
101 </widget>
96 <resources/>
102 <resources/>
97 <connections/>
103 <connections/>
98 </ui>
104 </ui>
General Comments 0
You need to be logged in to leave comments. Login now