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