##// END OF EJS Templates
drop of products in visu
trabillard -
r1341:36d2186e2f24
parent child
Show More
@@ -1,106 +1,106
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 /// Returns the MIME data associated to a list of product meta data
67 /// Returns the MIME data associated to a list of product meta data
68 static QByteArray mimeDataForProductsData(const QVariantList &productsData);
68 static QByteArray mimeDataForProductsData(const QVariantList &productsData);
69
69
70 /// Returns the list of meta data contained in a MIME data
70 /// Returns the list of meta data contained in a MIME data
71 static QVariantList productsDataForMimeData(const QByteArray &mimeData);
71 static QVariantList productsDataForMimeData(const QByteArray &mimeData);
72
72
73 public slots:
73 public slots:
74 /// Manage init/end of the controller
74 /// Manage init/end of the controller
75 void initialize();
75 void initialize();
76 void finalize();
76 void finalize();
77
77
78 /// Request the creation of a variable from the ID_DATA_KEY of a product
78 /// Request the creation of a variable from the ID_DATA_KEY of a product
79 void requestVariable(const QString &datasourceIdKey);
79 void requestVariableFromProductIdKey(const QString &datasourceIdKey);
80
80
81 /// Request the creation of a variable from metadata of a product
81 /// Request the creation of a variable from metadata of a product
82 void requestVariable(const QVariantHash &productData);
82 void requestVariable(const QVariantHash &productData);
83
83
84 signals:
84 signals:
85 /// Signal emitted when a structure has been set for a data source
85 /// Signal emitted when a structure has been set for a data source
86 void dataSourceItemSet(DataSourceItem *dataSourceItem);
86 void dataSourceItemSet(DataSourceItem *dataSourceItem);
87
87
88 /**
88 /**
89 * Signal emitted when a variable creation is asked for a product
89 * Signal emitted when a variable creation is asked for a product
90 * @param variableName the name of the variable
90 * @param variableName the name of the variable
91 * @param variableMetadata the metadata of the variable
91 * @param variableMetadata the metadata of the variable
92 * @param variableProvider the provider that will be used to retrieve the data of the variable
92 * @param variableProvider the provider that will be used to retrieve the data of the variable
93 * (can be null)
93 * (can be null)
94 */
94 */
95 void variableCreationRequested(const QString &variableName,
95 void variableCreationRequested(const QString &variableName,
96 const QVariantHash &variableMetadata,
96 const QVariantHash &variableMetadata,
97 std::shared_ptr<IDataProvider> variableProvider);
97 std::shared_ptr<IDataProvider> variableProvider);
98
98
99 private:
99 private:
100 void waitForFinish();
100 void waitForFinish();
101
101
102 class DataSourceControllerPrivate;
102 class DataSourceControllerPrivate;
103 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
103 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
104 };
104 };
105
105
106 #endif // SCIQLOP_DATASOURCECONTROLLER_H
106 #endif // SCIQLOP_DATASOURCECONTROLLER_H
@@ -1,197 +1,197
1 #include "DataSource/DataSourceController.h"
1 #include "DataSource/DataSourceController.h"
2 #include "DataSource/DataSourceItem.h"
2 #include "DataSource/DataSourceItem.h"
3
3
4 #include <Data/IDataProvider.h>
4 #include <Data/IDataProvider.h>
5
5
6 #include <QMutex>
6 #include <QMutex>
7 #include <QThread>
7 #include <QThread>
8
8
9 #include <QDataStream>
9 #include <QDataStream>
10 #include <QDir>
10 #include <QDir>
11 #include <QStandardPaths>
11 #include <QStandardPaths>
12
12
13 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
13 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
14
14
15 class DataSourceController::DataSourceControllerPrivate {
15 class DataSourceController::DataSourceControllerPrivate {
16 public:
16 public:
17 QMutex m_WorkingMutex;
17 QMutex m_WorkingMutex;
18 /// Data sources registered
18 /// Data sources registered
19 QHash<QUuid, QString> m_DataSources;
19 QHash<QUuid, QString> m_DataSources;
20 /// Data sources structures
20 /// Data sources structures
21 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
21 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
22 /// Data providers registered
22 /// Data providers registered
23 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
23 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
24 /// continue to live without necessarily the data source controller
24 /// continue to live without necessarily the data source controller
25 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
25 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
26
26
27 // Search for the first datasource item matching the specified data
27 // Search for the first datasource item matching the specified data
28 DataSourceItem *findDataSourceItem(const QVariantHash &data)
28 DataSourceItem *findDataSourceItem(const QVariantHash &data)
29 {
29 {
30 DataSourceItem *sourceItem = nullptr;
30 DataSourceItem *sourceItem = nullptr;
31 for (const auto &item : m_DataSourceItems) {
31 for (const auto &item : m_DataSourceItems) {
32 sourceItem = item.second->findItem(data, true);
32 sourceItem = item.second->findItem(data, true);
33 if (sourceItem) {
33 if (sourceItem) {
34 break;
34 break;
35 }
35 }
36 }
36 }
37
37
38 return sourceItem;
38 return sourceItem;
39 }
39 }
40
40
41 // Search for the first datasource item matching the specified ID_DATA_KEY
41 // Search for the first datasource item matching the specified ID_DATA_KEY
42 DataSourceItem *findDataSourceItem(const QString &datasourceIdKey)
42 DataSourceItem *findDataSourceItem(const QString &datasourceIdKey)
43 {
43 {
44 DataSourceItem *sourceItem = nullptr;
44 DataSourceItem *sourceItem = nullptr;
45 for (const auto &item : m_DataSourceItems) {
45 for (const auto &item : m_DataSourceItems) {
46 sourceItem = item.second->findItem(datasourceIdKey, true);
46 sourceItem = item.second->findItem(datasourceIdKey, true);
47 if (sourceItem) {
47 if (sourceItem) {
48 break;
48 break;
49 }
49 }
50 }
50 }
51
51
52 return sourceItem;
52 return sourceItem;
53 }
53 }
54 };
54 };
55
55
56 DataSourceController::DataSourceController(QObject *parent)
56 DataSourceController::DataSourceController(QObject *parent)
57 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
57 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
58 {
58 {
59 qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction")
59 qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction")
60 << QThread::currentThread();
60 << QThread::currentThread();
61 }
61 }
62
62
63 DataSourceController::~DataSourceController()
63 DataSourceController::~DataSourceController()
64 {
64 {
65 qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction")
65 qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction")
66 << QThread::currentThread();
66 << QThread::currentThread();
67 this->waitForFinish();
67 this->waitForFinish();
68 }
68 }
69
69
70 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
70 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
71 {
71 {
72 auto dataSourceUid = QUuid::createUuid();
72 auto dataSourceUid = QUuid::createUuid();
73 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
73 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
74
74
75 return dataSourceUid;
75 return dataSourceUid;
76 }
76 }
77
77
78 void DataSourceController::setDataSourceItem(
78 void DataSourceController::setDataSourceItem(
79 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
79 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
80 {
80 {
81 if (!dataSourceItem) {
81 if (!dataSourceItem) {
82 qCWarning(LOG_DataSourceController())
82 qCWarning(LOG_DataSourceController())
83 << tr("Data source item can't be registered (null item)");
83 << tr("Data source item can't be registered (null item)");
84 return;
84 return;
85 }
85 }
86
86
87 if (impl->m_DataSources.contains(dataSourceUid)) {
87 if (impl->m_DataSources.contains(dataSourceUid)) {
88 // The data provider is implicitly converted to a shared_ptr
88 // The data provider is implicitly converted to a shared_ptr
89 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
89 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
90
90
91 // Retrieves the data source item to emit the signal with it
91 // Retrieves the data source item to emit the signal with it
92 auto it = impl->m_DataSourceItems.find(dataSourceUid);
92 auto it = impl->m_DataSourceItems.find(dataSourceUid);
93 if (it != impl->m_DataSourceItems.end()) {
93 if (it != impl->m_DataSourceItems.end()) {
94 emit dataSourceItemSet(it->second.get());
94 emit dataSourceItemSet(it->second.get());
95 }
95 }
96 }
96 }
97 else {
97 else {
98 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
98 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
99 "data source has been registered with the uid")
99 "data source has been registered with the uid")
100 .arg(dataSourceUid.toString());
100 .arg(dataSourceUid.toString());
101 }
101 }
102 }
102 }
103
103
104 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
104 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
105 std::unique_ptr<IDataProvider> dataProvider) noexcept
105 std::unique_ptr<IDataProvider> dataProvider) noexcept
106 {
106 {
107 if (impl->m_DataSources.contains(dataSourceUid)) {
107 if (impl->m_DataSources.contains(dataSourceUid)) {
108 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
108 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
109 }
109 }
110 else {
110 else {
111 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
111 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
112 "source has been registered with the uid")
112 "source has been registered with the uid")
113 .arg(dataSourceUid.toString());
113 .arg(dataSourceUid.toString());
114 }
114 }
115 }
115 }
116
116
117 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
117 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
118 const DataSourceItem &productItem) noexcept
118 const DataSourceItem &productItem) noexcept
119 {
119 {
120 if (productItem.type() == DataSourceItemType::PRODUCT
120 if (productItem.type() == DataSourceItemType::PRODUCT
121 || productItem.type() == DataSourceItemType::COMPONENT) {
121 || productItem.type() == DataSourceItemType::COMPONENT) {
122 /// Retrieves the data provider of the data source (if any)
122 /// Retrieves the data provider of the data source (if any)
123 auto it = impl->m_DataProviders.find(dataSourceUid);
123 auto it = impl->m_DataProviders.find(dataSourceUid);
124 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
124 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
125
125
126 emit variableCreationRequested(productItem.name(), productItem.data(), dataProvider);
126 emit variableCreationRequested(productItem.name(), productItem.data(), dataProvider);
127 }
127 }
128 else {
128 else {
129 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
129 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
130 }
130 }
131 }
131 }
132
132
133 QByteArray DataSourceController::mimeDataForProductsData(const QVariantList &productsData)
133 QByteArray DataSourceController::mimeDataForProductsData(const QVariantList &productsData)
134 {
134 {
135 QByteArray encodedData;
135 QByteArray encodedData;
136 QDataStream stream{&encodedData, QIODevice::WriteOnly};
136 QDataStream stream{&encodedData, QIODevice::WriteOnly};
137
137
138 stream << productsData;
138 stream << productsData;
139
139
140 return encodedData;
140 return encodedData;
141 }
141 }
142
142
143 QVariantList DataSourceController::productsDataForMimeData(const QByteArray &mimeData)
143 QVariantList DataSourceController::productsDataForMimeData(const QByteArray &mimeData)
144 {
144 {
145 QDataStream stream{mimeData};
145 QDataStream stream{mimeData};
146
146
147 QVariantList productList;
147 QVariantList productList;
148 stream >> productList;
148 stream >> productList;
149
149
150 return productList;
150 return productList;
151 }
151 }
152
152
153 void DataSourceController::initialize()
153 void DataSourceController::initialize()
154 {
154 {
155 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init")
155 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init")
156 << QThread::currentThread();
156 << QThread::currentThread();
157 impl->m_WorkingMutex.lock();
157 impl->m_WorkingMutex.lock();
158 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
158 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
159 }
159 }
160
160
161 void DataSourceController::finalize()
161 void DataSourceController::finalize()
162 {
162 {
163 impl->m_WorkingMutex.unlock();
163 impl->m_WorkingMutex.unlock();
164 }
164 }
165
165
166 void DataSourceController::requestVariable(const QString &datasourceIdKey)
166 void DataSourceController::requestVariableFromProductIdKey(const QString &datasourceIdKey)
167 {
167 {
168 auto sourceItem = impl->findDataSourceItem(datasourceIdKey);
168 auto sourceItem = impl->findDataSourceItem(datasourceIdKey);
169
169
170 if (sourceItem) {
170 if (sourceItem) {
171 auto sourceName = sourceItem->rootItem().name();
171 auto sourceName = sourceItem->rootItem().name();
172 auto sourceId = impl->m_DataSources.key(sourceName);
172 auto sourceId = impl->m_DataSources.key(sourceName);
173 loadProductItem(sourceId, *sourceItem);
173 loadProductItem(sourceId, *sourceItem);
174 }
174 }
175 else {
175 else {
176 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
176 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
177 }
177 }
178 }
178 }
179
179
180 void DataSourceController::requestVariable(const QVariantHash &productData)
180 void DataSourceController::requestVariable(const QVariantHash &productData)
181 {
181 {
182 auto sourceItem = impl->findDataSourceItem(productData);
182 auto sourceItem = impl->findDataSourceItem(productData);
183
183
184 if (sourceItem) {
184 if (sourceItem) {
185 auto sourceName = sourceItem->rootItem().name();
185 auto sourceName = sourceItem->rootItem().name();
186 auto sourceId = impl->m_DataSources.key(sourceName);
186 auto sourceId = impl->m_DataSources.key(sourceName);
187 loadProductItem(sourceId, *sourceItem);
187 loadProductItem(sourceId, *sourceItem);
188 }
188 }
189 else {
189 else {
190 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
190 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
191 }
191 }
192 }
192 }
193
193
194 void DataSourceController::waitForFinish()
194 void DataSourceController::waitForFinish()
195 {
195 {
196 QMutexLocker locker{&impl->m_WorkingMutex};
196 QMutexLocker locker{&impl->m_WorkingMutex};
197 }
197 }
@@ -1,296 +1,308
1 #include "DragAndDrop/DragDropGuiController.h"
1 #include "DragAndDrop/DragDropGuiController.h"
2 #include "DragAndDrop/DragDropScroller.h"
2 #include "DragAndDrop/DragDropScroller.h"
3 #include "DragAndDrop/DragDropTabSwitcher.h"
3 #include "DragAndDrop/DragDropTabSwitcher.h"
4 #include "SqpApplication.h"
4 #include "SqpApplication.h"
5 #include "Visualization/VisualizationDragDropContainer.h"
5 #include "Visualization/VisualizationDragDropContainer.h"
6 #include "Visualization/VisualizationDragWidget.h"
6 #include "Visualization/VisualizationDragWidget.h"
7 #include "Visualization/VisualizationWidget.h"
7 #include "Visualization/VisualizationWidget.h"
8 #include "Visualization/operations/FindVariableOperation.h"
8 #include "Visualization/operations/FindVariableOperation.h"
9
9
10 #include "DataSource/DataSourceController.h"
10 #include "Variable/Variable.h"
11 #include "Variable/Variable.h"
11 #include "Variable/VariableController.h"
12 #include "Variable/VariableController.h"
12
13
13 #include "Common/MimeTypesDef.h"
14 #include "Common/MimeTypesDef.h"
14 #include "Common/VisualizationDef.h"
15 #include "Common/VisualizationDef.h"
15
16
16 #include <QDir>
17 #include <QDir>
17 #include <QLabel>
18 #include <QLabel>
18 #include <QUrl>
19 #include <QUrl>
19 #include <QVBoxLayout>
20 #include <QVBoxLayout>
20
21
21
22
22 Q_LOGGING_CATEGORY(LOG_DragDropGuiController, "DragDropGuiController")
23 Q_LOGGING_CATEGORY(LOG_DragDropGuiController, "DragDropGuiController")
23
24
24
25
25 struct DragDropGuiController::DragDropGuiControllerPrivate {
26 struct DragDropGuiController::DragDropGuiControllerPrivate {
26
27
27 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
28 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
28 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
29 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
29 QLabel *m_PlaceHolderLabel;
30 QLabel *m_PlaceHolderLabel;
30 QWidget *m_PlaceBackground;
31 QWidget *m_PlaceBackground;
31 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
32 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
32 std::unique_ptr<DragDropTabSwitcher> m_DragDropTabSwitcher = nullptr;
33 std::unique_ptr<DragDropTabSwitcher> m_DragDropTabSwitcher = nullptr;
33 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
34 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
34 // QTemporaryFile to have a name which is not generated.
35 // QTemporaryFile to have a name which is not generated.
35
36
36 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
37 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
37
38
38 QMetaObject::Connection m_DragWidgetDestroyedConnection;
39 QMetaObject::Connection m_DragWidgetDestroyedConnection;
39 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
40 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
40
41
41 QList<QWidget *> m_WidgetToClose;
42 QList<QWidget *> m_WidgetToClose;
42
43
43 explicit DragDropGuiControllerPrivate()
44 explicit DragDropGuiControllerPrivate()
44 : m_PlaceHolder{std::make_unique<QWidget>()},
45 : m_PlaceHolder{std::make_unique<QWidget>()},
45 m_DragDropScroller{std::make_unique<DragDropScroller>()},
46 m_DragDropScroller{std::make_unique<DragDropScroller>()},
46 m_DragDropTabSwitcher{std::make_unique<DragDropTabSwitcher>()}
47 m_DragDropTabSwitcher{std::make_unique<DragDropTabSwitcher>()}
47 {
48 {
48
49
49 auto layout = new QVBoxLayout{m_PlaceHolder.get()};
50 auto layout = new QVBoxLayout{m_PlaceHolder.get()};
50 layout->setSpacing(0);
51 layout->setSpacing(0);
51 layout->setContentsMargins(0, 0, 0, 0);
52 layout->setContentsMargins(0, 0, 0, 0);
52
53
53 m_PlaceHolderLabel = new QLabel{"", m_PlaceHolder.get()};
54 m_PlaceHolderLabel = new QLabel{"", m_PlaceHolder.get()};
54 m_PlaceHolderLabel->setMinimumHeight(25);
55 m_PlaceHolderLabel->setMinimumHeight(25);
55 layout->addWidget(m_PlaceHolderLabel);
56 layout->addWidget(m_PlaceHolderLabel);
56
57
57 m_PlaceBackground = new QWidget{m_PlaceHolder.get()};
58 m_PlaceBackground = new QWidget{m_PlaceHolder.get()};
58 m_PlaceBackground->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
59 m_PlaceBackground->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
59 layout->addWidget(m_PlaceBackground);
60 layout->addWidget(m_PlaceBackground);
60
61
61 sqpApp->installEventFilter(m_DragDropScroller.get());
62 sqpApp->installEventFilter(m_DragDropScroller.get());
62 sqpApp->installEventFilter(m_DragDropTabSwitcher.get());
63 sqpApp->installEventFilter(m_DragDropTabSwitcher.get());
63
64
64 m_ImageTempUrl = QDir::temp().absoluteFilePath("Sciqlop_graph.png");
65 m_ImageTempUrl = QDir::temp().absoluteFilePath("Sciqlop_graph.png");
65 }
66 }
66
67
67 void preparePlaceHolder(DragDropGuiController::PlaceHolderType type,
68 void preparePlaceHolder(DragDropGuiController::PlaceHolderType type,
68 const QString &topLabelText) const
69 const QString &topLabelText) const
69 {
70 {
70 if (m_CurrentDragWidget) {
71 if (m_CurrentDragWidget) {
71 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
72 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
72 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
73 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
73 }
74 }
74 else {
75 else {
75 // Configuration of the placeHolder when there is no dragWidget
76 // Configuration of the placeHolder when there is no dragWidget
76 // (for instance with a drag from a variable)
77 // (for instance with a drag from a variable)
77
78
78 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
79 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
79 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
80 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
80 }
81 }
81
82
82 switch (type) {
83 switch (type) {
83 case DragDropGuiController::PlaceHolderType::Graph:
84 case DragDropGuiController::PlaceHolderType::Graph:
84 m_PlaceBackground->setStyleSheet(
85 m_PlaceBackground->setStyleSheet(
85 "background-color: #BBD5EE; border: 1px solid #2A7FD4");
86 "background-color: #BBD5EE; border: 1px solid #2A7FD4");
86 break;
87 break;
87 case DragDropGuiController::PlaceHolderType::Zone:
88 case DragDropGuiController::PlaceHolderType::Zone:
88 case DragDropGuiController::PlaceHolderType::Default:
89 case DragDropGuiController::PlaceHolderType::Default:
89 m_PlaceBackground->setStyleSheet(
90 m_PlaceBackground->setStyleSheet(
90 "background-color: #BBD5EE; border: 2px solid #2A7FD4");
91 "background-color: #BBD5EE; border: 2px solid #2A7FD4");
91 m_PlaceHolderLabel->setStyleSheet("color: #2A7FD4");
92 m_PlaceHolderLabel->setStyleSheet("color: #2A7FD4");
92 break;
93 break;
93 }
94 }
94
95
95 m_PlaceHolderLabel->setText(topLabelText);
96 m_PlaceHolderLabel->setText(topLabelText);
96 m_PlaceHolderLabel->setVisible(!topLabelText.isEmpty());
97 m_PlaceHolderLabel->setVisible(!topLabelText.isEmpty());
97 }
98 }
98 };
99 };
99
100
100
101
101 DragDropGuiController::DragDropGuiController()
102 DragDropGuiController::DragDropGuiController()
102 : impl{spimpl::make_unique_impl<DragDropGuiControllerPrivate>()}
103 : impl{spimpl::make_unique_impl<DragDropGuiControllerPrivate>()}
103 {
104 {
104 }
105 }
105
106
106 DragDropGuiController::~DragDropGuiController()
107 DragDropGuiController::~DragDropGuiController()
107 {
108 {
108 QFile::remove(impl->m_ImageTempUrl);
109 QFile::remove(impl->m_ImageTempUrl);
109 }
110 }
110
111
111 void DragDropGuiController::resetDragAndDrop()
112 void DragDropGuiController::resetDragAndDrop()
112 {
113 {
113 setCurrentDragWidget(nullptr);
114 setCurrentDragWidget(nullptr);
114 impl->m_HighlightedDragWidget = nullptr;
115 impl->m_HighlightedDragWidget = nullptr;
115 }
116 }
116
117
117 void DragDropGuiController::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
118 void DragDropGuiController::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
118 {
119 {
119 if (impl->m_CurrentDragWidget) {
120 if (impl->m_CurrentDragWidget) {
120
121
121 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
122 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
122 }
123 }
123
124
124 if (dragWidget) {
125 if (dragWidget) {
125 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
126 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
126 impl->m_DragWidgetDestroyedConnection
127 impl->m_DragWidgetDestroyedConnection
127 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
128 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
128 [this]() { impl->m_CurrentDragWidget = nullptr; });
129 [this]() { impl->m_CurrentDragWidget = nullptr; });
129 }
130 }
130
131
131 impl->m_CurrentDragWidget = dragWidget;
132 impl->m_CurrentDragWidget = dragWidget;
132 }
133 }
133
134
134 VisualizationDragWidget *DragDropGuiController::getCurrentDragWidget() const
135 VisualizationDragWidget *DragDropGuiController::getCurrentDragWidget() const
135 {
136 {
136 return impl->m_CurrentDragWidget;
137 return impl->m_CurrentDragWidget;
137 }
138 }
138
139
139 QWidget &DragDropGuiController::placeHolder() const
140 QWidget &DragDropGuiController::placeHolder() const
140 {
141 {
141 return *impl->m_PlaceHolder;
142 return *impl->m_PlaceHolder;
142 }
143 }
143
144
144 void DragDropGuiController::insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
145 void DragDropGuiController::insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
145 const QString &topLabelText)
146 const QString &topLabelText)
146 {
147 {
147 removePlaceHolder();
148 removePlaceHolder();
148 impl->preparePlaceHolder(type, topLabelText);
149 impl->preparePlaceHolder(type, topLabelText);
149 layout->insertWidget(index, impl->m_PlaceHolder.get());
150 layout->insertWidget(index, impl->m_PlaceHolder.get());
150 impl->m_PlaceHolder->show();
151 impl->m_PlaceHolder->show();
151 }
152 }
152
153
153 void DragDropGuiController::removePlaceHolder()
154 void DragDropGuiController::removePlaceHolder()
154 {
155 {
155 auto parentWidget = impl->m_PlaceHolder->parentWidget();
156 auto parentWidget = impl->m_PlaceHolder->parentWidget();
156 if (parentWidget) {
157 if (parentWidget) {
157 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
158 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
158 impl->m_PlaceHolder->setParent(nullptr);
159 impl->m_PlaceHolder->setParent(nullptr);
159 impl->m_PlaceHolder->hide();
160 impl->m_PlaceHolder->hide();
160 }
161 }
161 }
162 }
162
163
163 bool DragDropGuiController::isPlaceHolderSet() const
164 bool DragDropGuiController::isPlaceHolderSet() const
164 {
165 {
165 return impl->m_PlaceHolder->parentWidget();
166 return impl->m_PlaceHolder->parentWidget();
166 }
167 }
167
168
168 void DragDropGuiController::addDragDropScrollArea(QScrollArea *scrollArea)
169 void DragDropGuiController::addDragDropScrollArea(QScrollArea *scrollArea)
169 {
170 {
170 impl->m_DragDropScroller->addScrollArea(scrollArea);
171 impl->m_DragDropScroller->addScrollArea(scrollArea);
171 }
172 }
172
173
173 void DragDropGuiController::removeDragDropScrollArea(QScrollArea *scrollArea)
174 void DragDropGuiController::removeDragDropScrollArea(QScrollArea *scrollArea)
174 {
175 {
175 impl->m_DragDropScroller->removeScrollArea(scrollArea);
176 impl->m_DragDropScroller->removeScrollArea(scrollArea);
176 }
177 }
177
178
178 void DragDropGuiController::addDragDropTabBar(QTabBar *tabBar)
179 void DragDropGuiController::addDragDropTabBar(QTabBar *tabBar)
179 {
180 {
180 impl->m_DragDropTabSwitcher->addTabBar(tabBar);
181 impl->m_DragDropTabSwitcher->addTabBar(tabBar);
181 }
182 }
182
183
183 void DragDropGuiController::removeDragDropTabBar(QTabBar *tabBar)
184 void DragDropGuiController::removeDragDropTabBar(QTabBar *tabBar)
184 {
185 {
185 impl->m_DragDropTabSwitcher->removeTabBar(tabBar);
186 impl->m_DragDropTabSwitcher->removeTabBar(tabBar);
186 }
187 }
187
188
188 QUrl DragDropGuiController::imageTemporaryUrl(const QImage &image) const
189 QUrl DragDropGuiController::imageTemporaryUrl(const QImage &image) const
189 {
190 {
190 image.save(impl->m_ImageTempUrl);
191 image.save(impl->m_ImageTempUrl);
191 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
192 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
192 }
193 }
193
194
194 void DragDropGuiController::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
195 void DragDropGuiController::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
195 {
196 {
196 if (impl->m_HighlightedDragWidget) {
197 if (impl->m_HighlightedDragWidget) {
197 impl->m_HighlightedDragWidget->highlightForMerge(false);
198 impl->m_HighlightedDragWidget->highlightForMerge(false);
198 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
199 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
199 }
200 }
200
201
201 if (dragWidget) {
202 if (dragWidget) {
202 dragWidget->highlightForMerge(true);
203 dragWidget->highlightForMerge(true);
203
204
204 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
205 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
205 impl->m_DragWidgetDestroyedConnection
206 impl->m_DragWidgetDestroyedConnection
206 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
207 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
207 [this]() { impl->m_HighlightedDragWidget = nullptr; });
208 [this]() { impl->m_HighlightedDragWidget = nullptr; });
208 }
209 }
209
210
210 impl->m_HighlightedDragWidget = dragWidget;
211 impl->m_HighlightedDragWidget = dragWidget;
211 }
212 }
212
213
213 VisualizationDragWidget *DragDropGuiController::getHightlightedDragWidget() const
214 VisualizationDragWidget *DragDropGuiController::getHightlightedDragWidget() const
214 {
215 {
215 return impl->m_HighlightedDragWidget;
216 return impl->m_HighlightedDragWidget;
216 }
217 }
217
218
218 void DragDropGuiController::delayedCloseWidget(QWidget *widget)
219 void DragDropGuiController::delayedCloseWidget(QWidget *widget)
219 {
220 {
220 widget->hide();
221 widget->hide();
221 impl->m_WidgetToClose << widget;
222 impl->m_WidgetToClose << widget;
222 }
223 }
223
224
224 void DragDropGuiController::doCloseWidgets()
225 void DragDropGuiController::doCloseWidgets()
225 {
226 {
226 for (auto widget : impl->m_WidgetToClose) {
227 for (auto widget : impl->m_WidgetToClose) {
227 widget->close();
228 widget->close();
228 }
229 }
229
230
230 impl->m_WidgetToClose.clear();
231 impl->m_WidgetToClose.clear();
231 }
232 }
232
233
233 bool DragDropGuiController::checkMimeDataForVisualization(
234 bool DragDropGuiController::checkMimeDataForVisualization(
234 const QMimeData *mimeData, VisualizationDragDropContainer *dropContainer)
235 const QMimeData *mimeData, VisualizationDragDropContainer *dropContainer)
235 {
236 {
236 if (!mimeData || !dropContainer) {
237 if (!mimeData || !dropContainer) {
237 qCWarning(LOG_DragDropGuiController()) << QObject::tr(
238 qCWarning(LOG_DragDropGuiController()) << QObject::tr(
238 "DragDropGuiController::checkMimeDataForVisualization, invalid input parameters.");
239 "DragDropGuiController::checkMimeDataForVisualization, invalid input parameters.");
239 Q_ASSERT(false);
240 Q_ASSERT(false);
240 return false;
241 return false;
241 }
242 }
242
243
243 auto result = false;
244 auto result = false;
244
245
245 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
246 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
246 auto variables = sqpApp->variableController().variablesForMimeData(
247 auto variables = sqpApp->variableController().variablesForMimeData(
247 mimeData->data(MIME_TYPE_VARIABLE_LIST));
248 mimeData->data(MIME_TYPE_VARIABLE_LIST));
248
249
249 if (variables.count() == 1) {
250 if (variables.count() == 1) {
250
251
251 auto variable = variables.first();
252 auto variable = variables.first();
252 if (variable->dataSeries() != nullptr) {
253 if (variable->dataSeries() != nullptr) {
253
254
254 // Check that the variable is not already in a graph
255 // Check that the variable is not already in a graph
255
256
256 auto parent = dropContainer->parentWidget();
257 auto parent = dropContainer->parentWidget();
257 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
258 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
258 parent = parent->parentWidget(); // Search for the top level VisualizationWidget
259 parent = parent->parentWidget(); // Search for the top level VisualizationWidget
259 }
260 }
260
261
261 if (parent) {
262 if (parent) {
262 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
263 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
263
264
264 FindVariableOperation findVariableOperation{variable};
265 FindVariableOperation findVariableOperation{variable};
265 visualizationWidget->accept(&findVariableOperation);
266 visualizationWidget->accept(&findVariableOperation);
266 auto variableContainers = findVariableOperation.result();
267 auto variableContainers = findVariableOperation.result();
267 if (variableContainers.empty()) {
268 if (variableContainers.empty()) {
268 result = true;
269 result = true;
269 }
270 }
270 else {
271 else {
271 // result = false: the variable already exist in the visualisation
272 // result = false: the variable already exist in the visualisation
272 }
273 }
273 }
274 }
274 else {
275 else {
275 qCWarning(LOG_DragDropGuiController()) << QObject::tr(
276 qCWarning(LOG_DragDropGuiController()) << QObject::tr(
276 "DragDropGuiController::checkMimeDataForVisualization, the parent "
277 "DragDropGuiController::checkMimeDataForVisualization, the parent "
277 "VisualizationWidget cannot be found. Cannot check if the variable is "
278 "VisualizationWidget cannot be found. Cannot check if the variable is "
278 "already used or not.");
279 "already used or not.");
279 }
280 }
280 }
281 }
281 else {
282 else {
282 // result = false: the variable is not fully loaded
283 // result = false: the variable is not fully loaded
283 }
284 }
284 }
285 }
285 else {
286 else {
286 // result = false: cannot drop multiple variables in the visualisation
287 // result = false: cannot drop multiple variables in the visualisation
287 }
288 }
288 }
289 }
290 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
291 auto productDataList = sqpApp->dataSourceController().productsDataForMimeData(
292 mimeData->data(MIME_TYPE_PRODUCT_LIST));
293 if (productDataList.count() == 1) {
294 result = true;
295 }
296 else {
297 // result = false: cannot drop multiple products in the visualisation
298 }
299 }
289 else {
300 else {
290 // Other MIME data
301 // Other MIME data
291 // no special rules, accepted by default
302 // no special rules, accepted by default
292 result = true;
303 result = true;
293 }
304 }
294
305
306
295 return result;
307 return result;
296 }
308 }
@@ -1,354 +1,384
1 #include "Visualization/VisualizationTabWidget.h"
1 #include "Visualization/VisualizationTabWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "ui_VisualizationTabWidget.h"
3 #include "ui_VisualizationTabWidget.h"
4
4
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7
7
8 #include "Visualization/MacScrollBarStyle.h"
8 #include "Visualization/MacScrollBarStyle.h"
9
9
10 #include "DataSource/DataSourceController.h"
10 #include "Variable/VariableController.h"
11 #include "Variable/VariableController.h"
11
12
12 #include "Common/MimeTypesDef.h"
13 #include "Common/MimeTypesDef.h"
13
14
14 #include "DragAndDrop/DragDropGuiController.h"
15 #include "DragAndDrop/DragDropGuiController.h"
15 #include "SqpApplication.h"
16 #include "SqpApplication.h"
16
17
17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
18 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
18
19
19 namespace {
20 namespace {
20
21
21 /**
22 /**
22 * Applies a function to all zones of the tab represented by its layout
23 * Applies a function to all zones of the tab represented by its layout
23 * @param layout the layout that contains zones
24 * @param layout the layout that contains zones
24 * @param fun the function to apply to each zone
25 * @param fun the function to apply to each zone
25 */
26 */
26 template <typename Fun>
27 template <typename Fun>
27 void processZones(QLayout &layout, Fun fun)
28 void processZones(QLayout &layout, Fun fun)
28 {
29 {
29 for (auto i = 0; i < layout.count(); ++i) {
30 for (auto i = 0; i < layout.count(); ++i) {
30 if (auto item = layout.itemAt(i)) {
31 if (auto item = layout.itemAt(i)) {
31 if (auto visualizationZoneWidget
32 if (auto visualizationZoneWidget
32 = qobject_cast<VisualizationZoneWidget *>(item->widget())) {
33 = qobject_cast<VisualizationZoneWidget *>(item->widget())) {
33 fun(*visualizationZoneWidget);
34 fun(*visualizationZoneWidget);
34 }
35 }
35 }
36 }
36 }
37 }
37 }
38 }
38
39
39 /// Generates a default name for a new zone, according to the number of zones already displayed in
40 /// Generates a default name for a new zone, according to the number of zones already displayed in
40 /// the tab
41 /// the tab
41 QString defaultZoneName(QLayout &layout)
42 QString defaultZoneName(QLayout &layout)
42 {
43 {
43 QSet<QString> existingNames;
44 QSet<QString> existingNames;
44 processZones(layout,
45 processZones(layout,
45 [&existingNames](auto &zoneWidget) { existingNames.insert(zoneWidget.name()); });
46 [&existingNames](auto &zoneWidget) { existingNames.insert(zoneWidget.name()); });
46
47
47 int zoneNum = 1;
48 int zoneNum = 1;
48 QString name;
49 QString name;
49 do {
50 do {
50 name = QObject::tr("Zone ").append(QString::number(zoneNum));
51 name = QObject::tr("Zone ").append(QString::number(zoneNum));
51 ++zoneNum;
52 ++zoneNum;
52 } while (existingNames.contains(name));
53 } while (existingNames.contains(name));
53
54
54 return name;
55 return name;
55 }
56 }
56
57
57 } // namespace
58 } // namespace
58
59
59 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
60 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
60 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
61 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
61
62
62 QString m_Name;
63 QString m_Name;
63
64
64 #ifdef Q_OS_MAC
65 #ifdef Q_OS_MAC
65 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
66 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
66 #endif
67 #endif
67
68
68 void dropGraph(int index, VisualizationTabWidget *tabWidget);
69 void dropGraph(int index, VisualizationTabWidget *tabWidget);
69 void dropZone(int index, VisualizationTabWidget *tabWidget);
70 void dropZone(int index, VisualizationTabWidget *tabWidget);
70 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
71 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
71 VisualizationTabWidget *tabWidget);
72 VisualizationTabWidget *tabWidget);
73 void dropProducts(const QVariantList &productsMetaData, int index,
74 VisualizationTabWidget *tabWidget);
72 };
75 };
73
76
74 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
77 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
75 : QWidget{parent},
78 : QWidget{parent},
76 ui{new Ui::VisualizationTabWidget},
79 ui{new Ui::VisualizationTabWidget},
77 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
80 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
78 {
81 {
79 ui->setupUi(this);
82 ui->setupUi(this);
80
83
81 #ifdef Q_OS_MAC
84 #ifdef Q_OS_MAC
82 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
85 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
83 #endif
86 #endif
84
87
85 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Zone, "Zone");
88 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Zone, "Zone");
86 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
89 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
87 ui->dragDropContainer->layout()->setSpacing(0);
90 ui->dragDropContainer->layout()->setSpacing(0);
88 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
91 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
89 VisualizationDragDropContainer::DropBehavior::Inserted);
92 VisualizationDragDropContainer::DropBehavior::Inserted);
90 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
93 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
91 VisualizationDragDropContainer::DropBehavior::Inserted);
94 VisualizationDragDropContainer::DropBehavior::Inserted);
92 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
95 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
93 VisualizationDragDropContainer::DropBehavior::Inserted);
96 VisualizationDragDropContainer::DropBehavior::Inserted);
97 ui->dragDropContainer->setMimeType(MIME_TYPE_PRODUCT_LIST,
98 VisualizationDragDropContainer::DropBehavior::Inserted);
94
99
95 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
100 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
96 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
101 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
97 ui->dragDropContainer);
102 ui->dragDropContainer);
98 });
103 });
99
104
100 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
105 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
101 &VisualizationTabWidget::dropMimeData);
106 &VisualizationTabWidget::dropMimeData);
102
107
103 sqpApp->dragDropGuiController().addDragDropScrollArea(ui->scrollArea);
108 sqpApp->dragDropGuiController().addDragDropScrollArea(ui->scrollArea);
104
109
105 // Widget is deleted when closed
110 // Widget is deleted when closed
106 setAttribute(Qt::WA_DeleteOnClose);
111 setAttribute(Qt::WA_DeleteOnClose);
107 }
112 }
108
113
109 VisualizationTabWidget::~VisualizationTabWidget()
114 VisualizationTabWidget::~VisualizationTabWidget()
110 {
115 {
111 sqpApp->dragDropGuiController().removeDragDropScrollArea(ui->scrollArea);
116 sqpApp->dragDropGuiController().removeDragDropScrollArea(ui->scrollArea);
112 delete ui;
117 delete ui;
113 }
118 }
114
119
115 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
120 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
116 {
121 {
117 ui->dragDropContainer->addDragWidget(zoneWidget);
122 ui->dragDropContainer->addDragWidget(zoneWidget);
118 }
123 }
119
124
120 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
125 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
121 {
126 {
122 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
127 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
123 }
128 }
124
129
125 QStringList VisualizationTabWidget::availableZoneWidgets() const
130 QStringList VisualizationTabWidget::availableZoneWidgets() const
126 {
131 {
127 QStringList zones;
132 QStringList zones;
128 processZones(tabLayout(),
133 processZones(tabLayout(),
129 [&zones](VisualizationZoneWidget &zoneWidget) { zones << zoneWidget.name(); });
134 [&zones](VisualizationZoneWidget &zoneWidget) { zones << zoneWidget.name(); });
130
135
131 return zones;
136 return zones;
132 }
137 }
133
138
134 VisualizationZoneWidget *VisualizationTabWidget::getZoneWithName(const QString &zoneName)
139 VisualizationZoneWidget *VisualizationTabWidget::getZoneWithName(const QString &zoneName)
135 {
140 {
136 VisualizationZoneWidget *result = nullptr;
141 VisualizationZoneWidget *result = nullptr;
137 processZones(tabLayout(), [&zoneName, &result](VisualizationZoneWidget &zoneWidget) {
142 processZones(tabLayout(), [&zoneName, &result](VisualizationZoneWidget &zoneWidget) {
138 if (!result && zoneWidget.name() == zoneName) {
143 if (!result && zoneWidget.name() == zoneName) {
139 result = &zoneWidget;
144 result = &zoneWidget;
140 }
145 }
141 });
146 });
142
147
143 return result;
148 return result;
144 }
149 }
145
150
146 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
151 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
147 {
152 {
148 return createZone({variable}, -1);
153 return createZone({variable}, -1);
149 }
154 }
150
155
151 VisualizationZoneWidget *
156 VisualizationZoneWidget *
152 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
157 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
153 {
158 {
154 auto zoneWidget = createEmptyZone(index);
159 auto zoneWidget = createEmptyZone(index);
155
160
156 // Creates a new graph into the zone
161 // Creates a new graph into the zone
157 zoneWidget->createGraph(variables, index);
162 zoneWidget->createGraph(variables, index);
158
163
159 return zoneWidget;
164 return zoneWidget;
160 }
165 }
161
166
162 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
167 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
163 {
168 {
164 auto zoneWidget
169 auto zoneWidget
165 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
170 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
166 this->insertZone(index, zoneWidget);
171 this->insertZone(index, zoneWidget);
167
172
168 return zoneWidget;
173 return zoneWidget;
169 }
174 }
170
175
171 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
176 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
172 {
177 {
173 if (visitor) {
178 if (visitor) {
174 visitor->visitEnter(this);
179 visitor->visitEnter(this);
175
180
176 // Apply visitor to zone children: widgets different from zones are not visited (no action)
181 // Apply visitor to zone children: widgets different from zones are not visited (no action)
177 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
182 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
178 zoneWidget.accept(visitor);
183 zoneWidget.accept(visitor);
179 });
184 });
180
185
181 visitor->visitLeave(this);
186 visitor->visitLeave(this);
182 }
187 }
183 else {
188 else {
184 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
189 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
185 }
190 }
186 }
191 }
187
192
188 bool VisualizationTabWidget::canDrop(const Variable &variable) const
193 bool VisualizationTabWidget::canDrop(const Variable &variable) const
189 {
194 {
190 // A tab can always accomodate a variable
195 // A tab can always accomodate a variable
191 Q_UNUSED(variable);
196 Q_UNUSED(variable);
192 return true;
197 return true;
193 }
198 }
194
199
195 bool VisualizationTabWidget::contains(const Variable &variable) const
200 bool VisualizationTabWidget::contains(const Variable &variable) const
196 {
201 {
197 Q_UNUSED(variable);
202 Q_UNUSED(variable);
198 return false;
203 return false;
199 }
204 }
200
205
201 QString VisualizationTabWidget::name() const
206 QString VisualizationTabWidget::name() const
202 {
207 {
203 return impl->m_Name;
208 return impl->m_Name;
204 }
209 }
205
210
206 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
211 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
207 {
212 {
208 // Closes zones in the tab
213 // Closes zones in the tab
209 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
214 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
210
215
211 QWidget::closeEvent(event);
216 QWidget::closeEvent(event);
212 }
217 }
213
218
214 QLayout &VisualizationTabWidget::tabLayout() const noexcept
219 QLayout &VisualizationTabWidget::tabLayout() const noexcept
215 {
220 {
216 return *ui->dragDropContainer->layout();
221 return *ui->dragDropContainer->layout();
217 }
222 }
218
223
219 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
224 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
220 {
225 {
221 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
226 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
222 impl->dropGraph(index, this);
227 impl->dropGraph(index, this);
223 }
228 }
224 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
229 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
225 impl->dropZone(index, this);
230 impl->dropZone(index, this);
226 }
231 }
227 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
232 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
228 auto variables = sqpApp->variableController().variablesForMimeData(
233 auto variables = sqpApp->variableController().variablesForMimeData(
229 mimeData->data(MIME_TYPE_VARIABLE_LIST));
234 mimeData->data(MIME_TYPE_VARIABLE_LIST));
230 impl->dropVariables(variables, index, this);
235 impl->dropVariables(variables, index, this);
231 }
236 }
237 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
238 auto productsData = sqpApp->dataSourceController().productsDataForMimeData(
239 mimeData->data(MIME_TYPE_PRODUCT_LIST));
240 impl->dropProducts(productsData, index, this);
241 }
232 else {
242 else {
233 qCWarning(LOG_VisualizationZoneWidget())
243 qCWarning(LOG_VisualizationZoneWidget())
234 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
244 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
235 }
245 }
236 }
246 }
237
247
238 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
248 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
239 int index, VisualizationTabWidget *tabWidget)
249 int index, VisualizationTabWidget *tabWidget)
240 {
250 {
241 auto &helper = sqpApp->dragDropGuiController();
251 auto &helper = sqpApp->dragDropGuiController();
242
252
243 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
253 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
244 if (!graphWidget) {
254 if (!graphWidget) {
245 qCWarning(LOG_VisualizationZoneWidget())
255 qCWarning(LOG_VisualizationZoneWidget())
246 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
256 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
247 "found or invalid.");
257 "found or invalid.");
248 Q_ASSERT(false);
258 Q_ASSERT(false);
249 return;
259 return;
250 }
260 }
251
261
252 auto parentDragDropContainer
262 auto parentDragDropContainer
253 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
263 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
254 if (!parentDragDropContainer) {
264 if (!parentDragDropContainer) {
255 qCWarning(LOG_VisualizationZoneWidget())
265 qCWarning(LOG_VisualizationZoneWidget())
256 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
266 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
257 "the dropped graph is not found.");
267 "the dropped graph is not found.");
258 Q_ASSERT(false);
268 Q_ASSERT(false);
259 return;
269 return;
260 }
270 }
261
271
262 auto nbGraph = parentDragDropContainer->countDragWidget();
272 auto nbGraph = parentDragDropContainer->countDragWidget();
263
273
264 const auto &variables = graphWidget->variables();
274 const auto &variables = graphWidget->variables();
265
275
266 if (!variables.isEmpty()) {
276 if (!variables.isEmpty()) {
267 // Abort the requests for the variables (if any)
277 // Abort the requests for the variables (if any)
268 // Commented, because it's not sure if it's needed or not
278 // Commented, because it's not sure if it's needed or not
269 // for (const auto& var : variables)
279 // for (const auto& var : variables)
270 //{
280 //{
271 // sqpApp->variableController().onAbortProgressRequested(var);
281 // sqpApp->variableController().onAbortProgressRequested(var);
272 //}
282 //}
273
283
274 if (nbGraph == 1) {
284 if (nbGraph == 1) {
275 // This is the only graph in the previous zone, close the zone
285 // This is the only graph in the previous zone, close the zone
276 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
286 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
277 }
287 }
278 else {
288 else {
279 // Close the graph
289 // Close the graph
280 helper.delayedCloseWidget(graphWidget);
290 helper.delayedCloseWidget(graphWidget);
281 }
291 }
282
292
283 auto zoneWidget = tabWidget->createZone(variables, index);
293 auto zoneWidget = tabWidget->createZone(variables, index);
284 auto firstGraph = zoneWidget->firstGraph();
294 auto firstGraph = zoneWidget->firstGraph();
285 if (firstGraph) {
295 if (firstGraph) {
286 firstGraph->addSelectionZones(graphWidget->selectionZoneRanges());
296 firstGraph->addSelectionZones(graphWidget->selectionZoneRanges());
287 }
297 }
288 else {
298 else {
289 qCWarning(LOG_VisualizationZoneWidget())
299 qCWarning(LOG_VisualizationZoneWidget())
290 << tr("VisualizationTabWidget::dropGraph, no graph added in the widget.");
300 << tr("VisualizationTabWidget::dropGraph, no graph added in the widget.");
291 Q_ASSERT(false);
301 Q_ASSERT(false);
292 }
302 }
293 }
303 }
294 else {
304 else {
295 // The graph is empty, create an empty zone and move the graph inside
305 // The graph is empty, create an empty zone and move the graph inside
296
306
297 auto parentZoneWidget = graphWidget->parentZoneWidget();
307 auto parentZoneWidget = graphWidget->parentZoneWidget();
298
308
299 parentDragDropContainer->layout()->removeWidget(graphWidget);
309 parentDragDropContainer->layout()->removeWidget(graphWidget);
300
310
301 auto zoneWidget = tabWidget->createEmptyZone(index);
311 auto zoneWidget = tabWidget->createEmptyZone(index);
302 zoneWidget->addGraph(graphWidget);
312 zoneWidget->addGraph(graphWidget);
303
313
304 // Close the old zone if it was the only graph inside
314 // Close the old zone if it was the only graph inside
305 if (nbGraph == 1) {
315 if (nbGraph == 1) {
306 helper.delayedCloseWidget(parentZoneWidget);
316 helper.delayedCloseWidget(parentZoneWidget);
307 }
317 }
308 }
318 }
309 }
319 }
310
320
311 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
321 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
312 int index, VisualizationTabWidget *tabWidget)
322 int index, VisualizationTabWidget *tabWidget)
313 {
323 {
314 auto &helper = sqpApp->dragDropGuiController();
324 auto &helper = sqpApp->dragDropGuiController();
315
325
316 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
326 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
317 if (!zoneWidget) {
327 if (!zoneWidget) {
318 qCWarning(LOG_VisualizationZoneWidget())
328 qCWarning(LOG_VisualizationZoneWidget())
319 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
329 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
320 "found or invalid.");
330 "found or invalid.");
321 Q_ASSERT(false);
331 Q_ASSERT(false);
322 return;
332 return;
323 }
333 }
324
334
325 auto parentDragDropContainer
335 auto parentDragDropContainer
326 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
336 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
327 if (!parentDragDropContainer) {
337 if (!parentDragDropContainer) {
328 qCWarning(LOG_VisualizationZoneWidget())
338 qCWarning(LOG_VisualizationZoneWidget())
329 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
339 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
330 "the dropped zone is not found.");
340 "the dropped zone is not found.");
331 Q_ASSERT(false);
341 Q_ASSERT(false);
332 return;
342 return;
333 }
343 }
334
344
335 // Simple move of the zone, no variable operation associated
345 // Simple move of the zone, no variable operation associated
336 parentDragDropContainer->layout()->removeWidget(zoneWidget);
346 parentDragDropContainer->layout()->removeWidget(zoneWidget);
337 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
347 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
338 }
348 }
339
349
340 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
350 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
341 const QList<std::shared_ptr<Variable> > &variables, int index,
351 const QList<std::shared_ptr<Variable> > &variables, int index,
342 VisualizationTabWidget *tabWidget)
352 VisualizationTabWidget *tabWidget)
343 {
353 {
344 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
354 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
345 // compatible variable here
355 // compatible variable here
346 if (variables.count() > 1) {
356 if (variables.count() > 1) {
347 qCWarning(LOG_VisualizationZoneWidget())
357 qCWarning(LOG_VisualizationZoneWidget())
348 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
358 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
349 "aborted.");
359 "aborted.");
350 return;
360 return;
351 }
361 }
352
362
353 tabWidget->createZone(variables, index);
363 tabWidget->createZone(variables, index);
354 }
364 }
365
366 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropProducts(
367 const QVariantList &productsMetaData, int index, VisualizationTabWidget *tabWidget)
368 {
369 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
370 // compatible variable here
371 if (productsMetaData.count() != 1) {
372 qCWarning(LOG_VisualizationZoneWidget())
373 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
374 "aborted.");
375 return;
376 }
377
378 auto productData = productsMetaData.first().toHash();
379 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
380 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
381
382
383 // TODO: add graph
384 }
@@ -1,601 +1,639
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 <DataSource/DataSourceController.h>
13 #include <Time/TimeController.h>
14 #include <Time/TimeController.h>
14 #include <Variable/Variable.h>
15 #include <Variable/Variable.h>
15 #include <Variable/VariableController.h>
16 #include <Variable/VariableController.h>
16
17
17 #include <Visualization/operations/FindVariableOperation.h>
18 #include <Visualization/operations/FindVariableOperation.h>
18
19
19 #include <DragAndDrop/DragDropGuiController.h>
20 #include <DragAndDrop/DragDropGuiController.h>
20 #include <QUuid>
21 #include <QUuid>
21 #include <SqpApplication.h>
22 #include <SqpApplication.h>
22 #include <cmath>
23 #include <cmath>
23
24
24 #include <QLayout>
25 #include <QLayout>
25
26
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27
28
28 namespace {
29 namespace {
29
30
30 /**
31 /**
31 * Applies a function to all graphs of the zone represented by its layout
32 * Applies a function to all graphs of the zone represented by its layout
32 * @param layout the layout that contains graphs
33 * @param layout the layout that contains graphs
33 * @param fun the function to apply to each graph
34 * @param fun the function to apply to each graph
34 */
35 */
35 template <typename Fun>
36 template <typename Fun>
36 void processGraphs(QLayout &layout, Fun fun)
37 void processGraphs(QLayout &layout, Fun fun)
37 {
38 {
38 for (auto i = 0; i < layout.count(); ++i) {
39 for (auto i = 0; i < layout.count(); ++i) {
39 if (auto item = layout.itemAt(i)) {
40 if (auto item = layout.itemAt(i)) {
40 if (auto visualizationGraphWidget
41 if (auto visualizationGraphWidget
41 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
42 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
42 fun(*visualizationGraphWidget);
43 fun(*visualizationGraphWidget);
43 }
44 }
44 }
45 }
45 }
46 }
46 }
47 }
47
48
48 /// Generates a default name for a new graph, according to the number of graphs already displayed in
49 /// Generates a default name for a new graph, according to the number of graphs already displayed in
49 /// the zone
50 /// the zone
50 QString defaultGraphName(QLayout &layout)
51 QString defaultGraphName(QLayout &layout)
51 {
52 {
52 QSet<QString> existingNames;
53 QSet<QString> existingNames;
53 processGraphs(
54 processGraphs(
54 layout, [&existingNames](auto &graphWidget) { existingNames.insert(graphWidget.name()); });
55 layout, [&existingNames](auto &graphWidget) { existingNames.insert(graphWidget.name()); });
55
56
56 int zoneNum = 1;
57 int zoneNum = 1;
57 QString name;
58 QString name;
58 do {
59 do {
59 name = QObject::tr("Graph ").append(QString::number(zoneNum));
60 name = QObject::tr("Graph ").append(QString::number(zoneNum));
60 ++zoneNum;
61 ++zoneNum;
61 } while (existingNames.contains(name));
62 } while (existingNames.contains(name));
62
63
63 return name;
64 return name;
64 }
65 }
65
66
66 } // namespace
67 } // namespace
67
68
68 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
69 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
69
70
70 explicit VisualizationZoneWidgetPrivate()
71 explicit VisualizationZoneWidgetPrivate()
71 : m_SynchronisationGroupId{QUuid::createUuid()},
72 : m_SynchronisationGroupId{QUuid::createUuid()},
72 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
73 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
73 {
74 {
74 }
75 }
75 QUuid m_SynchronisationGroupId;
76 QUuid m_SynchronisationGroupId;
76 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
77 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
77
78
78 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
79 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
79 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
80 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
80 VisualizationZoneWidget *zoneWidget);
81 VisualizationZoneWidget *zoneWidget);
82 void dropProducts(const QVariantList &productsData, int index,
83 VisualizationZoneWidget *zoneWidget);
81 };
84 };
82
85
83 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
86 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
84 : VisualizationDragWidget{parent},
87 : VisualizationDragWidget{parent},
85 ui{new Ui::VisualizationZoneWidget},
88 ui{new Ui::VisualizationZoneWidget},
86 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
89 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
87 {
90 {
88 ui->setupUi(this);
91 ui->setupUi(this);
89
92
90 ui->zoneNameLabel->setText(name);
93 ui->zoneNameLabel->setText(name);
91
94
92 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
95 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
93 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
96 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
94 VisualizationDragDropContainer::DropBehavior::Inserted);
97 VisualizationDragDropContainer::DropBehavior::Inserted);
95 ui->dragDropContainer->setMimeType(
98 ui->dragDropContainer->setMimeType(
96 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
99 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
100 ui->dragDropContainer->setMimeType(
101 MIME_TYPE_PRODUCT_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
97 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
102 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
98 VisualizationDragDropContainer::DropBehavior::Merged);
103 VisualizationDragDropContainer::DropBehavior::Merged);
99 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
104 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
100 VisualizationDragDropContainer::DropBehavior::Forbidden);
105 VisualizationDragDropContainer::DropBehavior::Forbidden);
101 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
106 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
102 VisualizationDragDropContainer::DropBehavior::Forbidden);
107 VisualizationDragDropContainer::DropBehavior::Forbidden);
103 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
108 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
104 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
109 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
105 ui->dragDropContainer);
110 ui->dragDropContainer);
106 });
111 });
107
112
108 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
113 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
109 if (!mimeData) {
114 if (!mimeData) {
110 return false;
115 return false;
111 }
116 }
112
117
113 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
118 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
114 auto variables = sqpApp->variableController().variablesForMimeData(
119 auto variables = sqpApp->variableController().variablesForMimeData(
115 mimeData->data(MIME_TYPE_VARIABLE_LIST));
120 mimeData->data(MIME_TYPE_VARIABLE_LIST));
116
121
117 if (variables.count() != 1) {
122 if (variables.count() != 1) {
118 return false;
123 return false;
119 }
124 }
120 auto variable = variables.first();
125 auto variable = variables.first();
121
126
122 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
127 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
123 return graphWidget->canDrop(*variable);
128 return graphWidget->canDrop(*variable);
124 }
129 }
125 }
130 }
126
131
127 return true;
132 return true;
128 };
133 };
129 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
134 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
130
135
131 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
136 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
132 &VisualizationZoneWidget::dropMimeData);
137 &VisualizationZoneWidget::dropMimeData);
133 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
138 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
134 &VisualizationZoneWidget::dropMimeDataOnGraph);
139 &VisualizationZoneWidget::dropMimeDataOnGraph);
135
140
136 // 'Close' options : widget is deleted when closed
141 // 'Close' options : widget is deleted when closed
137 setAttribute(Qt::WA_DeleteOnClose);
142 setAttribute(Qt::WA_DeleteOnClose);
138 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
143 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
139 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
144 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
140
145
141 // Synchronisation id
146 // Synchronisation id
142 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
147 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
143 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
148 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
144 }
149 }
145
150
146 VisualizationZoneWidget::~VisualizationZoneWidget()
151 VisualizationZoneWidget::~VisualizationZoneWidget()
147 {
152 {
148 delete ui;
153 delete ui;
149 }
154 }
150
155
151 void VisualizationZoneWidget::setZoneRange(const SqpRange &range)
156 void VisualizationZoneWidget::setZoneRange(const SqpRange &range)
152 {
157 {
153 if (auto graph = firstGraph()) {
158 if (auto graph = firstGraph()) {
154 graph->setGraphRange(range);
159 graph->setGraphRange(range);
155 }
160 }
156 else {
161 else {
157 qCWarning(LOG_VisualizationZoneWidget())
162 qCWarning(LOG_VisualizationZoneWidget())
158 << tr("setZoneRange:Cannot set the range of an empty zone.");
163 << tr("setZoneRange:Cannot set the range of an empty zone.");
159 }
164 }
160 }
165 }
161
166
162 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
167 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
163 {
168 {
164 // Synchronize new graph with others in the zone
169 // Synchronize new graph with others in the zone
165 impl->m_Synchronizer->addGraph(*graphWidget);
170 impl->m_Synchronizer->addGraph(*graphWidget);
166
171
167 ui->dragDropContainer->addDragWidget(graphWidget);
172 ui->dragDropContainer->addDragWidget(graphWidget);
168 }
173 }
169
174
170 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
175 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
171 {
176 {
172 // Synchronize new graph with others in the zone
177 // Synchronize new graph with others in the zone
173 impl->m_Synchronizer->addGraph(*graphWidget);
178 impl->m_Synchronizer->addGraph(*graphWidget);
174
179
175 ui->dragDropContainer->insertDragWidget(index, graphWidget);
180 ui->dragDropContainer->insertDragWidget(index, graphWidget);
176 }
181 }
177
182
178 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
183 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
179 {
184 {
180 return createGraph(variable, -1);
185 return createGraph(variable, -1);
181 }
186 }
182
187
183 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
188 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
184 int index)
189 int index)
185 {
190 {
186 auto graphWidget
191 auto graphWidget
187 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
192 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
188
193
189
194
190 // Set graph properties
195 // Set graph properties
191 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
196 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
192 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
197 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
193
198
194
199
195 // Lambda to synchronize zone widget
200 // Lambda to synchronize zone widget
196 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
201 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
197 const SqpRange &oldGraphRange) {
202 const SqpRange &oldGraphRange) {
198
203
199 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
204 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
200 auto frameLayout = ui->dragDropContainer->layout();
205 auto frameLayout = ui->dragDropContainer->layout();
201 for (auto i = 0; i < frameLayout->count(); ++i) {
206 for (auto i = 0; i < frameLayout->count(); ++i) {
202 auto graphChild
207 auto graphChild
203 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
208 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
204 if (graphChild && (graphChild != graphWidget)) {
209 if (graphChild && (graphChild != graphWidget)) {
205
210
206 auto graphChildRange = graphChild->graphRange();
211 auto graphChildRange = graphChild->graphRange();
207 switch (zoomType) {
212 switch (zoomType) {
208 case AcquisitionZoomType::ZoomIn: {
213 case AcquisitionZoomType::ZoomIn: {
209 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
214 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
210 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
215 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
211 graphChildRange.m_TStart += deltaLeft;
216 graphChildRange.m_TStart += deltaLeft;
212 graphChildRange.m_TEnd -= deltaRight;
217 graphChildRange.m_TEnd -= deltaRight;
213 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
218 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
214 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
219 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
215 << deltaLeft;
220 << deltaLeft;
216 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
221 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
217 << deltaRight;
222 << deltaRight;
218 qCDebug(LOG_VisualizationZoneWidget())
223 qCDebug(LOG_VisualizationZoneWidget())
219 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
224 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
220
225
221 break;
226 break;
222 }
227 }
223
228
224 case AcquisitionZoomType::ZoomOut: {
229 case AcquisitionZoomType::ZoomOut: {
225 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
230 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
226 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
231 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
227 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
232 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
228 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
233 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
229 << deltaLeft;
234 << deltaLeft;
230 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
235 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
231 << deltaRight;
236 << deltaRight;
232 qCDebug(LOG_VisualizationZoneWidget())
237 qCDebug(LOG_VisualizationZoneWidget())
233 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
238 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
234 graphChildRange.m_TStart -= deltaLeft;
239 graphChildRange.m_TStart -= deltaLeft;
235 graphChildRange.m_TEnd += deltaRight;
240 graphChildRange.m_TEnd += deltaRight;
236 break;
241 break;
237 }
242 }
238 case AcquisitionZoomType::PanRight: {
243 case AcquisitionZoomType::PanRight: {
239 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
240 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
245 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
241 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
246 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
242 graphChildRange.m_TStart += deltaLeft;
247 graphChildRange.m_TStart += deltaLeft;
243 graphChildRange.m_TEnd += deltaRight;
248 graphChildRange.m_TEnd += deltaRight;
244 qCDebug(LOG_VisualizationZoneWidget())
249 qCDebug(LOG_VisualizationZoneWidget())
245 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
250 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
246 break;
251 break;
247 }
252 }
248 case AcquisitionZoomType::PanLeft: {
253 case AcquisitionZoomType::PanLeft: {
249 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
254 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
250 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
255 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
251 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
256 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
252 graphChildRange.m_TStart -= deltaLeft;
257 graphChildRange.m_TStart -= deltaLeft;
253 graphChildRange.m_TEnd -= deltaRight;
258 graphChildRange.m_TEnd -= deltaRight;
254 break;
259 break;
255 }
260 }
256 case AcquisitionZoomType::Unknown: {
261 case AcquisitionZoomType::Unknown: {
257 qCDebug(LOG_VisualizationZoneWidget())
262 qCDebug(LOG_VisualizationZoneWidget())
258 << tr("Impossible to synchronize: zoom type unknown");
263 << tr("Impossible to synchronize: zoom type unknown");
259 break;
264 break;
260 }
265 }
261 default:
266 default:
262 qCCritical(LOG_VisualizationZoneWidget())
267 qCCritical(LOG_VisualizationZoneWidget())
263 << tr("Impossible to synchronize: zoom type not take into account");
268 << tr("Impossible to synchronize: zoom type not take into account");
264 // No action
269 // No action
265 break;
270 break;
266 }
271 }
267 graphChild->setFlags(GraphFlag::DisableAll);
272 graphChild->setFlags(GraphFlag::DisableAll);
268 qCDebug(LOG_VisualizationZoneWidget())
273 qCDebug(LOG_VisualizationZoneWidget())
269 << tr("TORM: Range before: ") << graphChild->graphRange();
274 << tr("TORM: Range before: ") << graphChild->graphRange();
270 qCDebug(LOG_VisualizationZoneWidget())
275 qCDebug(LOG_VisualizationZoneWidget())
271 << tr("TORM: Range after : ") << graphChildRange;
276 << tr("TORM: Range after : ") << graphChildRange;
272 qCDebug(LOG_VisualizationZoneWidget())
277 qCDebug(LOG_VisualizationZoneWidget())
273 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
278 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
274 graphChild->setGraphRange(graphChildRange);
279 graphChild->setGraphRange(graphChildRange);
275 graphChild->setFlags(GraphFlag::EnableAll);
280 graphChild->setFlags(GraphFlag::EnableAll);
276 }
281 }
277 }
282 }
278 };
283 };
279
284
280 // connection for synchronization
285 // connection for synchronization
281 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
286 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
282 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
287 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
283 &VisualizationZoneWidget::onVariableAdded);
288 &VisualizationZoneWidget::onVariableAdded);
284 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
289 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
285 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
290 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
286
291
287 auto range = SqpRange{};
292 auto range = SqpRange{};
288 if (auto firstGraph = this->firstGraph()) {
293 if (auto firstGraph = this->firstGraph()) {
289 // Case of a new graph in a existant zone
294 // Case of a new graph in a existant zone
290 range = firstGraph->graphRange();
295 range = firstGraph->graphRange();
291 }
296 }
292 else {
297 else {
293 // Case of a new graph as the first of the zone
298 // Case of a new graph as the first of the zone
294 range = variable->range();
299 range = variable->range();
295 }
300 }
296
301
297 this->insertGraph(index, graphWidget);
302 this->insertGraph(index, graphWidget);
298
303
299 graphWidget->addVariable(variable, range);
304 graphWidget->addVariable(variable, range);
300 graphWidget->setYRange(variable);
305 graphWidget->setYRange(variable);
301
306
302 return graphWidget;
307 return graphWidget;
303 }
308 }
304
309
305 VisualizationGraphWidget *
310 VisualizationGraphWidget *
306 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
311 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
307 {
312 {
308 if (variables.isEmpty()) {
313 if (variables.isEmpty()) {
309 return nullptr;
314 return nullptr;
310 }
315 }
311
316
312 auto graphWidget = createGraph(variables.first(), index);
317 auto graphWidget = createGraph(variables.first(), index);
313 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
318 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
314 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
319 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
315 }
320 }
316
321
317 return graphWidget;
322 return graphWidget;
318 }
323 }
319
324
320 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
325 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
321 {
326 {
322 VisualizationGraphWidget *firstGraph = nullptr;
327 VisualizationGraphWidget *firstGraph = nullptr;
323 auto layout = ui->dragDropContainer->layout();
328 auto layout = ui->dragDropContainer->layout();
324 if (layout->count() > 0) {
329 if (layout->count() > 0) {
325 if (auto visualizationGraphWidget
330 if (auto visualizationGraphWidget
326 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
331 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
327 firstGraph = visualizationGraphWidget;
332 firstGraph = visualizationGraphWidget;
328 }
333 }
329 }
334 }
330
335
331 return firstGraph;
336 return firstGraph;
332 }
337 }
333
338
334 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
339 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
335 {
340 {
336 if (visitor) {
341 if (visitor) {
337 visitor->visitEnter(this);
342 visitor->visitEnter(this);
338
343
339 // Apply visitor to graph children: widgets different from graphs are not visited (no
344 // Apply visitor to graph children: widgets different from graphs are not visited (no
340 // action)
345 // action)
341 processGraphs(
346 processGraphs(
342 *ui->dragDropContainer->layout(),
347 *ui->dragDropContainer->layout(),
343 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
348 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
344
349
345 visitor->visitLeave(this);
350 visitor->visitLeave(this);
346 }
351 }
347 else {
352 else {
348 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
353 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
349 }
354 }
350 }
355 }
351
356
352 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
357 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
353 {
358 {
354 // A tab can always accomodate a variable
359 // A tab can always accomodate a variable
355 Q_UNUSED(variable);
360 Q_UNUSED(variable);
356 return true;
361 return true;
357 }
362 }
358
363
359 bool VisualizationZoneWidget::contains(const Variable &variable) const
364 bool VisualizationZoneWidget::contains(const Variable &variable) const
360 {
365 {
361 Q_UNUSED(variable);
366 Q_UNUSED(variable);
362 return false;
367 return false;
363 }
368 }
364
369
365 QString VisualizationZoneWidget::name() const
370 QString VisualizationZoneWidget::name() const
366 {
371 {
367 return ui->zoneNameLabel->text();
372 return ui->zoneNameLabel->text();
368 }
373 }
369
374
370 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
375 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
371 {
376 {
372 Q_UNUSED(position);
377 Q_UNUSED(position);
373
378
374 auto mimeData = new QMimeData;
379 auto mimeData = new QMimeData;
375 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
380 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
376
381
377 if (auto firstGraph = this->firstGraph()) {
382 if (auto firstGraph = this->firstGraph()) {
378 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
383 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
379 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
384 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
380 }
385 }
381
386
382 return mimeData;
387 return mimeData;
383 }
388 }
384
389
385 bool VisualizationZoneWidget::isDragAllowed() const
390 bool VisualizationZoneWidget::isDragAllowed() const
386 {
391 {
387 return true;
392 return true;
388 }
393 }
389
394
390 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
395 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
391 const QPointF &plotPosition,
396 const QPointF &plotPosition,
392 VisualizationGraphWidget *graphWidget)
397 VisualizationGraphWidget *graphWidget)
393 {
398 {
394 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
399 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
395 VisualizationGraphWidget &processedGraph) {
400 VisualizationGraphWidget &processedGraph) {
396
401
397 switch (sqpApp->plotsCursorMode()) {
402 switch (sqpApp->plotsCursorMode()) {
398 case SqpApplication::PlotsCursorMode::Vertical:
403 case SqpApplication::PlotsCursorMode::Vertical:
399 processedGraph.removeHorizontalCursor();
404 processedGraph.removeHorizontalCursor();
400 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
405 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
401 break;
406 break;
402 case SqpApplication::PlotsCursorMode::Temporal:
407 case SqpApplication::PlotsCursorMode::Temporal:
403 processedGraph.addVerticalCursor(plotPosition.x());
408 processedGraph.addVerticalCursor(plotPosition.x());
404 processedGraph.removeHorizontalCursor();
409 processedGraph.removeHorizontalCursor();
405 break;
410 break;
406 case SqpApplication::PlotsCursorMode::Horizontal:
411 case SqpApplication::PlotsCursorMode::Horizontal:
407 processedGraph.removeVerticalCursor();
412 processedGraph.removeVerticalCursor();
408 if (&processedGraph == graphWidget) {
413 if (&processedGraph == graphWidget) {
409 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
414 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
410 }
415 }
411 else {
416 else {
412 processedGraph.removeHorizontalCursor();
417 processedGraph.removeHorizontalCursor();
413 }
418 }
414 break;
419 break;
415 case SqpApplication::PlotsCursorMode::Cross:
420 case SqpApplication::PlotsCursorMode::Cross:
416 if (&processedGraph == graphWidget) {
421 if (&processedGraph == graphWidget) {
417 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
422 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
418 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
423 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
419 }
424 }
420 else {
425 else {
421 processedGraph.removeHorizontalCursor();
426 processedGraph.removeHorizontalCursor();
422 processedGraph.removeVerticalCursor();
427 processedGraph.removeVerticalCursor();
423 }
428 }
424 break;
429 break;
425 case SqpApplication::PlotsCursorMode::NoCursor:
430 case SqpApplication::PlotsCursorMode::NoCursor:
426 processedGraph.removeHorizontalCursor();
431 processedGraph.removeHorizontalCursor();
427 processedGraph.removeVerticalCursor();
432 processedGraph.removeVerticalCursor();
428 break;
433 break;
429 }
434 }
430
435
431
436
432 });
437 });
433 }
438 }
434
439
435 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
440 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
436 {
441 {
437 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
442 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
438 processedGraph.removeHorizontalCursor();
443 processedGraph.removeHorizontalCursor();
439 processedGraph.removeVerticalCursor();
444 processedGraph.removeVerticalCursor();
440 });
445 });
441 }
446 }
442
447
443 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
448 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
444 {
449 {
445 // Closes graphs in the zone
450 // Closes graphs in the zone
446 processGraphs(*ui->dragDropContainer->layout(),
451 processGraphs(*ui->dragDropContainer->layout(),
447 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
452 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
448
453
449 // Delete synchronization group from variable controller
454 // Delete synchronization group from variable controller
450 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
455 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
451 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
456 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
452
457
453 QWidget::closeEvent(event);
458 QWidget::closeEvent(event);
454 }
459 }
455
460
456 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
461 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
457 {
462 {
458 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
463 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
459 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
464 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
460 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
465 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
461 }
466 }
462
467
463 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
468 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
464 {
469 {
465 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
470 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
466 Q_ARG(std::shared_ptr<Variable>, variable),
471 Q_ARG(std::shared_ptr<Variable>, variable),
467 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
472 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
468 }
473 }
469
474
470 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
475 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
471 {
476 {
472 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
477 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
473 impl->dropGraph(index, this);
478 impl->dropGraph(index, this);
474 }
479 }
475 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
480 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
476 auto variables = sqpApp->variableController().variablesForMimeData(
481 auto variables = sqpApp->variableController().variablesForMimeData(
477 mimeData->data(MIME_TYPE_VARIABLE_LIST));
482 mimeData->data(MIME_TYPE_VARIABLE_LIST));
478 impl->dropVariables(variables, index, this);
483 impl->dropVariables(variables, index, this);
479 }
484 }
485 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
486 auto products = sqpApp->dataSourceController().productsDataForMimeData(
487 mimeData->data(MIME_TYPE_PRODUCT_LIST));
488 impl->dropProducts(products, index, this);
489 }
480 else {
490 else {
481 qCWarning(LOG_VisualizationZoneWidget())
491 qCWarning(LOG_VisualizationZoneWidget())
482 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
492 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
483 }
493 }
484 }
494 }
485
495
486 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
496 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
487 const QMimeData *mimeData)
497 const QMimeData *mimeData)
488 {
498 {
489 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
499 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
490 if (!graphWidget) {
500 if (!graphWidget) {
491 qCWarning(LOG_VisualizationZoneWidget())
501 qCWarning(LOG_VisualizationZoneWidget())
492 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
502 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
493 "drop aborted");
503 "drop aborted");
494 Q_ASSERT(false);
504 Q_ASSERT(false);
495 return;
505 return;
496 }
506 }
497
507
498 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
508 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
499 auto variables = sqpApp->variableController().variablesForMimeData(
509 auto variables = sqpApp->variableController().variablesForMimeData(
500 mimeData->data(MIME_TYPE_VARIABLE_LIST));
510 mimeData->data(MIME_TYPE_VARIABLE_LIST));
501 for (const auto &var : variables) {
511 for (const auto &var : variables) {
502 graphWidget->addVariable(var, graphWidget->graphRange());
512 graphWidget->addVariable(var, graphWidget->graphRange());
503 }
513 }
504 }
514 }
515 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
516 auto products = sqpApp->dataSourceController().productsDataForMimeData(
517 mimeData->data(MIME_TYPE_PRODUCT_LIST));
518
519 auto productData = products.first().toHash();
520 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
521 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
522 }
505 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
523 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
506 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
524 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
507 graphWidget->setGraphRange(range);
525 graphWidget->setGraphRange(range);
508 }
526 }
509 else {
527 else {
510 qCWarning(LOG_VisualizationZoneWidget())
528 qCWarning(LOG_VisualizationZoneWidget())
511 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
529 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
512 }
530 }
513 }
531 }
514
532
515 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
533 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
516 int index, VisualizationZoneWidget *zoneWidget)
534 int index, VisualizationZoneWidget *zoneWidget)
517 {
535 {
518 auto &helper = sqpApp->dragDropGuiController();
536 auto &helper = sqpApp->dragDropGuiController();
519
537
520 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
538 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
521 if (!graphWidget) {
539 if (!graphWidget) {
522 qCWarning(LOG_VisualizationZoneWidget())
540 qCWarning(LOG_VisualizationZoneWidget())
523 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
541 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
524 "found or invalid.");
542 "found or invalid.");
525 Q_ASSERT(false);
543 Q_ASSERT(false);
526 return;
544 return;
527 }
545 }
528
546
529 auto parentDragDropContainer
547 auto parentDragDropContainer
530 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
548 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
531 if (!parentDragDropContainer) {
549 if (!parentDragDropContainer) {
532 qCWarning(LOG_VisualizationZoneWidget())
550 qCWarning(LOG_VisualizationZoneWidget())
533 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
551 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
534 "the dropped graph is not found.");
552 "the dropped graph is not found.");
535 Q_ASSERT(false);
553 Q_ASSERT(false);
536 return;
554 return;
537 }
555 }
538
556
539 const auto &variables = graphWidget->variables();
557 const auto &variables = graphWidget->variables();
540
558
541 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
559 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
542 // The drop didn't occur in the same zone
560 // The drop didn't occur in the same zone
543
561
544 // Abort the requests for the variables (if any)
562 // Abort the requests for the variables (if any)
545 // Commented, because it's not sure if it's needed or not
563 // Commented, because it's not sure if it's needed or not
546 // for (const auto& var : variables)
564 // for (const auto& var : variables)
547 //{
565 //{
548 // sqpApp->variableController().onAbortProgressRequested(var);
566 // sqpApp->variableController().onAbortProgressRequested(var);
549 //}
567 //}
550
568
551 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
569 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
552 auto nbGraph = parentDragDropContainer->countDragWidget();
570 auto nbGraph = parentDragDropContainer->countDragWidget();
553 if (nbGraph == 1) {
571 if (nbGraph == 1) {
554 // This is the only graph in the previous zone, close the zone
572 // This is the only graph in the previous zone, close the zone
555 helper.delayedCloseWidget(previousParentZoneWidget);
573 helper.delayedCloseWidget(previousParentZoneWidget);
556 }
574 }
557 else {
575 else {
558 // Close the graph
576 // Close the graph
559 helper.delayedCloseWidget(graphWidget);
577 helper.delayedCloseWidget(graphWidget);
560 }
578 }
561
579
562 // Creates the new graph in the zone
580 // Creates the new graph in the zone
563 auto newGraphWidget = zoneWidget->createGraph(variables, index);
581 auto newGraphWidget = zoneWidget->createGraph(variables, index);
564 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
582 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
565 }
583 }
566 else {
584 else {
567 // The drop occurred in the same zone or the graph is empty
585 // The drop occurred in the same zone or the graph is empty
568 // Simple move of the graph, no variable operation associated
586 // Simple move of the graph, no variable operation associated
569 parentDragDropContainer->layout()->removeWidget(graphWidget);
587 parentDragDropContainer->layout()->removeWidget(graphWidget);
570
588
571 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
589 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
572 // The graph is empty and dropped in a different zone.
590 // The graph is empty and dropped in a different zone.
573 // Take the range of the first graph in the zone (if existing).
591 // Take the range of the first graph in the zone (if existing).
574 auto layout = zoneWidget->ui->dragDropContainer->layout();
592 auto layout = zoneWidget->ui->dragDropContainer->layout();
575 if (layout->count() > 0) {
593 if (layout->count() > 0) {
576 if (auto visualizationGraphWidget
594 if (auto visualizationGraphWidget
577 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
595 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
578 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
596 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
579 }
597 }
580 }
598 }
581 }
599 }
582
600
583 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
601 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
584 }
602 }
585 }
603 }
586
604
587 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
605 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
588 const QList<std::shared_ptr<Variable> > &variables, int index,
606 const QList<std::shared_ptr<Variable> > &variables, int index,
589 VisualizationZoneWidget *zoneWidget)
607 VisualizationZoneWidget *zoneWidget)
590 {
608 {
591 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
609 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
592 // compatible variable here
610 // compatible variable here
593 if (variables.count() > 1) {
611 if (variables.count() > 1) {
594 qCWarning(LOG_VisualizationZoneWidget())
612 qCWarning(LOG_VisualizationZoneWidget())
595 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
613 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
596 "aborted.");
614 "aborted.");
597 return;
615 return;
598 }
616 }
599
617
600 zoneWidget->createGraph(variables, index);
618 zoneWidget->createGraph(variables, index);
601 }
619 }
620
621 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProducts(
622 const QVariantList &productsData, int index, VisualizationZoneWidget *zoneWidget)
623 {
624 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
625 // compatible variable here
626 if (productsData.count() != 1) {
627 qCWarning(LOG_VisualizationZoneWidget())
628 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
629 "aborted.");
630 return;
631 }
632
633 auto productData = productsData.first().toHash();
634 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
635 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
636
637
638 // TODO: add graph
639 }
General Comments 0
You need to be logged in to leave comments. Login now