##// END OF EJS Templates
drop of product on the visu
trabillard -
r875:4aae8a8d06e9 DropProductOnVisu...
parent child
Show More
@@ -1,99 +1,101
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 std::shared_ptr<IDataProvider> providerForProductData(const QVariantHash &productData);
68
67 QByteArray mimeDataForProductsData(const QVariantList &productsData) const;
69 QByteArray mimeDataForProductsData(const QVariantList &productsData) const;
68 QVariantList productsDataForMimeData(const QByteArray &mimeData) const;
70 QVariantList productsDataForMimeData(const QByteArray &mimeData) const;
69
71
70 public slots:
72 public slots:
71 /// Manage init/end of the controller
73 /// Manage init/end of the controller
72 void initialize();
74 void initialize();
73 void finalize();
75 void finalize();
74
76
75 void requestVariable(const QVariantHash &productData);
77 void requestVariable(const QVariantHash &productData);
76
78
77 signals:
79 signals:
78 /// Signal emitted when a structure has been set for a data source
80 /// Signal emitted when a structure has been set for a data source
79 void dataSourceItemSet(DataSourceItem *dataSourceItem);
81 void dataSourceItemSet(DataSourceItem *dataSourceItem);
80
82
81 /**
83 /**
82 * Signal emitted when a variable creation is asked for a product
84 * Signal emitted when a variable creation is asked for a product
83 * @param variableName the name of the variable
85 * @param variableName the name of the variable
84 * @param variableMetadata the metadata of the variable
86 * @param variableMetadata the metadata of the variable
85 * @param variableProvider the provider that will be used to retrieve the data of the variable
87 * @param variableProvider the provider that will be used to retrieve the data of the variable
86 * (can be null)
88 * (can be null)
87 */
89 */
88 void variableCreationRequested(const QString &variableName,
90 void variableCreationRequested(const QString &variableName,
89 const QVariantHash &variableMetadata,
91 const QVariantHash &variableMetadata,
90 std::shared_ptr<IDataProvider> variableProvider);
92 std::shared_ptr<IDataProvider> variableProvider);
91
93
92 private:
94 private:
93 void waitForFinish();
95 void waitForFinish();
94
96
95 class DataSourceControllerPrivate;
97 class DataSourceControllerPrivate;
96 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
98 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
97 };
99 };
98
100
99 #endif // SCIQLOP_DATASOURCECONTROLLER_H
101 #endif // SCIQLOP_DATASOURCECONTROLLER_H
@@ -1,192 +1,212
1 #include "DataSource/DataSourceController.h"
1 #include "DataSource/DataSourceController.h"
2 #include "DataSource/DataSourceItem.h"
2 #include "DataSource/DataSourceItem.h"
3
3
4 #include <Data/IDataProvider.h>
4 #include <Data/IDataProvider.h>
5
5
6 #include <QMutex>
6 #include <QMutex>
7 #include <QThread>
7 #include <QThread>
8
8
9 #include <QDataStream>
9 #include <QDataStream>
10 #include <QDir>
10 #include <QDir>
11 #include <QStandardPaths>
11 #include <QStandardPaths>
12
12
13 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
13 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
14
14
15 namespace {
15 namespace {
16
16
17 /**
17 /**
18 * Builds the metadata of the variable that will be generated from the loading of an item
18 * Builds the metadata of the variable that will be generated from the loading of an item
19 * @param dataSourceItem the data source item from which to generate the metadata
19 * @param dataSourceItem the data source item from which to generate the metadata
20 * @return the metadata of the variable
20 * @return the metadata of the variable
21 */
21 */
22 QVariantHash variableMetadata(const DataSourceItem &dataSourceItem)
22 QVariantHash variableMetadata(const DataSourceItem &dataSourceItem)
23 {
23 {
24 // Variable metadata contains...
24 // Variable metadata contains...
25
25
26 // ... all metadata of the item
26 // ... all metadata of the item
27 auto result = dataSourceItem.data();
27 auto result = dataSourceItem.data();
28
28
29 // ... and the name of the plugin, recovered from root item
29 // ... and the name of the plugin, recovered from root item
30 result.insert(QStringLiteral("plugin"), dataSourceItem.rootItem().name());
30 result.insert(QStringLiteral("plugin"), dataSourceItem.rootItem().name());
31
31
32 return result;
32 return result;
33 }
33 }
34
34
35 } // namespace
35 } // namespace
36
36
37 class DataSourceController::DataSourceControllerPrivate {
37 class DataSourceController::DataSourceControllerPrivate {
38 public:
38 public:
39 QMutex m_WorkingMutex;
39 QMutex m_WorkingMutex;
40 /// Data sources registered
40 /// Data sources registered
41 QHash<QUuid, QString> m_DataSources;
41 QHash<QUuid, QString> m_DataSources;
42 /// Data sources structures
42 /// Data sources structures
43 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
43 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
44 /// Data providers registered
44 /// Data providers registered
45 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
45 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
46 /// continue to live without necessarily the data source controller
46 /// continue to live without necessarily the data source controller
47 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
47 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
48
48
49 // Search for the first datasource item matching the specified data
49 // Search for the first datasource item matching the specified data
50 DataSourceItem *findDataSourceItem(const QVariantHash &data)
50 DataSourceItem *findDataSourceItem(const QVariantHash &data)
51 {
51 {
52 DataSourceItem *sourceItem = nullptr;
52 DataSourceItem *sourceItem = nullptr;
53 for (const auto &item : m_DataSourceItems) {
53 for (const auto &item : m_DataSourceItems) {
54 sourceItem = item.second->findItem(data, true);
54 sourceItem = item.second->findItem(data, true);
55 if (sourceItem) {
55 if (sourceItem) {
56 break;
56 break;
57 }
57 }
58 }
58 }
59
59
60 return sourceItem;
60 return sourceItem;
61 }
61 }
62 };
62 };
63
63
64 DataSourceController::DataSourceController(QObject *parent)
64 DataSourceController::DataSourceController(QObject *parent)
65 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
65 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
66 {
66 {
67 qCDebug(LOG_DataSourceController())
67 qCDebug(LOG_DataSourceController())
68 << tr("DataSourceController construction") << QThread::currentThread();
68 << tr("DataSourceController construction") << QThread::currentThread();
69 }
69 }
70
70
71 DataSourceController::~DataSourceController()
71 DataSourceController::~DataSourceController()
72 {
72 {
73 qCDebug(LOG_DataSourceController())
73 qCDebug(LOG_DataSourceController())
74 << tr("DataSourceController destruction") << QThread::currentThread();
74 << tr("DataSourceController destruction") << QThread::currentThread();
75 this->waitForFinish();
75 this->waitForFinish();
76 }
76 }
77
77
78 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
78 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
79 {
79 {
80 auto dataSourceUid = QUuid::createUuid();
80 auto dataSourceUid = QUuid::createUuid();
81 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
81 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
82
82
83 return dataSourceUid;
83 return dataSourceUid;
84 }
84 }
85
85
86 void DataSourceController::setDataSourceItem(
86 void DataSourceController::setDataSourceItem(
87 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
87 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
88 {
88 {
89 if (!dataSourceItem) {
89 if (!dataSourceItem) {
90 qCWarning(LOG_DataSourceController())
90 qCWarning(LOG_DataSourceController())
91 << tr("Data source item can't be registered (null item)");
91 << tr("Data source item can't be registered (null item)");
92 return;
92 return;
93 }
93 }
94
94
95 if (impl->m_DataSources.contains(dataSourceUid)) {
95 if (impl->m_DataSources.contains(dataSourceUid)) {
96 // The data provider is implicitly converted to a shared_ptr
96 // The data provider is implicitly converted to a shared_ptr
97 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
97 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
98
98
99 // Retrieves the data source item to emit the signal with it
99 // Retrieves the data source item to emit the signal with it
100 auto it = impl->m_DataSourceItems.find(dataSourceUid);
100 auto it = impl->m_DataSourceItems.find(dataSourceUid);
101 if (it != impl->m_DataSourceItems.end()) {
101 if (it != impl->m_DataSourceItems.end()) {
102 emit dataSourceItemSet(it->second.get());
102 emit dataSourceItemSet(it->second.get());
103 }
103 }
104 }
104 }
105 else {
105 else {
106 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
106 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
107 "data source has been registered with the uid")
107 "data source has been registered with the uid")
108 .arg(dataSourceUid.toString());
108 .arg(dataSourceUid.toString());
109 }
109 }
110 }
110 }
111
111
112 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
112 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
113 std::unique_ptr<IDataProvider> dataProvider) noexcept
113 std::unique_ptr<IDataProvider> dataProvider) noexcept
114 {
114 {
115 if (impl->m_DataSources.contains(dataSourceUid)) {
115 if (impl->m_DataSources.contains(dataSourceUid)) {
116 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
116 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
117 }
117 }
118 else {
118 else {
119 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
119 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
120 "source has been registered with the uid")
120 "source has been registered with the uid")
121 .arg(dataSourceUid.toString());
121 .arg(dataSourceUid.toString());
122 }
122 }
123 }
123 }
124
124
125 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
125 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
126 const DataSourceItem &productItem) noexcept
126 const DataSourceItem &productItem) noexcept
127 {
127 {
128 if (productItem.type() == DataSourceItemType::PRODUCT
128 if (productItem.type() == DataSourceItemType::PRODUCT
129 || productItem.type() == DataSourceItemType::COMPONENT) {
129 || productItem.type() == DataSourceItemType::COMPONENT) {
130 /// Retrieves the data provider of the data source (if any)
130 /// Retrieves the data provider of the data source (if any)
131 auto it = impl->m_DataProviders.find(dataSourceUid);
131 auto it = impl->m_DataProviders.find(dataSourceUid);
132 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
132 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
133
133
134 emit variableCreationRequested(productItem.name(), variableMetadata(productItem),
134 emit variableCreationRequested(productItem.name(), variableMetadata(productItem),
135 dataProvider);
135 dataProvider);
136 }
136 }
137 else {
137 else {
138 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
138 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
139 }
139 }
140 }
140 }
141
141
142 std::shared_ptr<IDataProvider>
143 DataSourceController::providerForProductData(const QVariantHash &productData)
144 {
145 DataSourceItem *sourceItem = impl->findDataSourceItem(productData);
146
147 if (sourceItem && sourceItem->type() == DataSourceItemType::PRODUCT
148 || sourceItem->type() == DataSourceItemType::COMPONENT) {
149 auto sourceName = sourceItem->rootItem().name();
150 auto sourceId = impl->m_DataSources.key(sourceName);
151 auto it = impl->m_DataProviders.find(sourceId);
152 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
153 return dataProvider;
154 }
155 else {
156 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
157 }
158
159 return nullptr;
160 }
161
142 QByteArray DataSourceController::mimeDataForProductsData(const QVariantList &productsData) const
162 QByteArray DataSourceController::mimeDataForProductsData(const QVariantList &productsData) const
143 {
163 {
144 QByteArray encodedData;
164 QByteArray encodedData;
145 QDataStream stream(&encodedData, QIODevice::WriteOnly);
165 QDataStream stream(&encodedData, QIODevice::WriteOnly);
146
166
147 stream << productsData;
167 stream << productsData;
148
168
149 return encodedData;
169 return encodedData;
150 }
170 }
151
171
152 QVariantList DataSourceController::productsDataForMimeData(const QByteArray &mimeData) const
172 QVariantList DataSourceController::productsDataForMimeData(const QByteArray &mimeData) const
153 {
173 {
154 QDataStream stream(mimeData);
174 QDataStream stream(mimeData);
155
175
156 QVariantList productList;
176 QVariantList productList;
157 stream >> productList;
177 stream >> productList;
158
178
159 return productList;
179 return productList;
160 }
180 }
161
181
162 void DataSourceController::initialize()
182 void DataSourceController::initialize()
163 {
183 {
164 qCDebug(LOG_DataSourceController())
184 qCDebug(LOG_DataSourceController())
165 << tr("DataSourceController init") << QThread::currentThread();
185 << tr("DataSourceController init") << QThread::currentThread();
166 impl->m_WorkingMutex.lock();
186 impl->m_WorkingMutex.lock();
167 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
187 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
168 }
188 }
169
189
170 void DataSourceController::finalize()
190 void DataSourceController::finalize()
171 {
191 {
172 impl->m_WorkingMutex.unlock();
192 impl->m_WorkingMutex.unlock();
173 }
193 }
174
194
175 void DataSourceController::requestVariable(const QVariantHash &productData)
195 void DataSourceController::requestVariable(const QVariantHash &productData)
176 {
196 {
177 DataSourceItem *sourceItem = impl->findDataSourceItem(productData);
197 DataSourceItem *sourceItem = impl->findDataSourceItem(productData);
178
198
179 if (sourceItem) {
199 if (sourceItem) {
180 auto sourceName = sourceItem->rootItem().name();
200 auto sourceName = sourceItem->rootItem().name();
181 auto sourceId = impl->m_DataSources.key(sourceName);
201 auto sourceId = impl->m_DataSources.key(sourceName);
182 loadProductItem(sourceId, *sourceItem);
202 loadProductItem(sourceId, *sourceItem);
183 }
203 }
184 else {
204 else {
185 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
205 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
186 }
206 }
187 }
207 }
188
208
189 void DataSourceController::waitForFinish()
209 void DataSourceController::waitForFinish()
190 {
210 {
191 QMutexLocker locker{&impl->m_WorkingMutex};
211 QMutexLocker locker{&impl->m_WorkingMutex};
192 }
212 }
@@ -1,287 +1,295
1 #include "DragDropHelper.h"
1 #include "DragDropHelper.h"
2 #include "SqpApplication.h"
2 #include "SqpApplication.h"
3 #include "Visualization/VisualizationDragDropContainer.h"
3 #include "Visualization/VisualizationDragDropContainer.h"
4 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5 #include "Visualization/VisualizationWidget.h"
5 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/operations/FindVariableOperation.h"
6 #include "Visualization/operations/FindVariableOperation.h"
7
7
8 #include "Variable/VariableController.h"
8 #include "Variable/VariableController.h"
9
9
10 #include "Common/MimeTypesDef.h"
10 #include "Common/MimeTypesDef.h"
11 #include "Common/VisualizationDef.h"
11 #include "Common/VisualizationDef.h"
12
12
13 #include <QDir>
13 #include <QDir>
14 #include <QDragEnterEvent>
14 #include <QDragEnterEvent>
15 #include <QDragMoveEvent>
15 #include <QDragMoveEvent>
16 #include <QScrollArea>
16 #include <QScrollArea>
17 #include <QScrollBar>
17 #include <QScrollBar>
18 #include <QTimer>
18 #include <QTimer>
19 #include <QVBoxLayout>
19 #include <QVBoxLayout>
20
20
21 const int SCROLL_SPEED = 5;
21 const int SCROLL_SPEED = 5;
22 const int SCROLL_ZONE_SIZE = 50;
22 const int SCROLL_ZONE_SIZE = 50;
23
23
24 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDrophelper")
24 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDrophelper")
25
25
26 struct DragDropScroller::DragDropScrollerPrivate {
26 struct DragDropScroller::DragDropScrollerPrivate {
27
27
28 QList<QScrollArea *> m_ScrollAreas;
28 QList<QScrollArea *> m_ScrollAreas;
29 QScrollArea *m_CurrentScrollArea = nullptr;
29 QScrollArea *m_CurrentScrollArea = nullptr;
30 std::unique_ptr<QTimer> m_Timer = nullptr;
30 std::unique_ptr<QTimer> m_Timer = nullptr;
31
31
32
32
33 enum class ScrollDirection { up, down, unknown };
33 enum class ScrollDirection { up, down, unknown };
34 ScrollDirection m_Direction = ScrollDirection::unknown;
34 ScrollDirection m_Direction = ScrollDirection::unknown;
35
35
36 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
36 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
37 {
37 {
38 m_Timer->setInterval(0);
38 m_Timer->setInterval(0);
39 }
39 }
40 };
40 };
41
41
42 DragDropScroller::DragDropScroller(QObject *parent)
42 DragDropScroller::DragDropScroller(QObject *parent)
43 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
43 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
44 {
44 {
45 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
45 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
46 }
46 }
47
47
48 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
48 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
49 {
49 {
50 impl->m_ScrollAreas << scrollArea;
50 impl->m_ScrollAreas << scrollArea;
51 scrollArea->viewport()->setAcceptDrops(true);
51 scrollArea->viewport()->setAcceptDrops(true);
52 }
52 }
53
53
54 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
54 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
55 {
55 {
56 impl->m_ScrollAreas.removeAll(scrollArea);
56 impl->m_ScrollAreas.removeAll(scrollArea);
57 scrollArea->viewport()->setAcceptDrops(false);
57 scrollArea->viewport()->setAcceptDrops(false);
58 }
58 }
59
59
60 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
60 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
61 {
61 {
62 if (event->type() == QEvent::DragMove) {
62 if (event->type() == QEvent::DragMove) {
63 auto w = static_cast<QWidget *>(obj);
63 auto w = static_cast<QWidget *>(obj);
64
64
65 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
65 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
66 auto moveEvent = static_cast<QDragMoveEvent *>(event);
66 auto moveEvent = static_cast<QDragMoveEvent *>(event);
67
67
68 auto pos = moveEvent->pos();
68 auto pos = moveEvent->pos();
69 if (impl->m_CurrentScrollArea->viewport() != w) {
69 if (impl->m_CurrentScrollArea->viewport() != w) {
70 auto globalPos = w->mapToGlobal(moveEvent->pos());
70 auto globalPos = w->mapToGlobal(moveEvent->pos());
71 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
71 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
72 }
72 }
73
73
74 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
74 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
75 - SCROLL_ZONE_SIZE;
75 - SCROLL_ZONE_SIZE;
76 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
76 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
77
77
78 if (!isInTopZone && !isInBottomZone) {
78 if (!isInTopZone && !isInBottomZone) {
79 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
79 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
80 impl->m_Timer->stop();
80 impl->m_Timer->stop();
81 }
81 }
82 else if (!impl->m_Timer->isActive()) {
82 else if (!impl->m_Timer->isActive()) {
83 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
83 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
84 : DragDropScrollerPrivate::ScrollDirection::down;
84 : DragDropScrollerPrivate::ScrollDirection::down;
85 impl->m_Timer->start();
85 impl->m_Timer->start();
86 }
86 }
87 }
87 }
88 }
88 }
89 else if (event->type() == QEvent::DragEnter) {
89 else if (event->type() == QEvent::DragEnter) {
90 auto w = static_cast<QWidget *>(obj);
90 auto w = static_cast<QWidget *>(obj);
91
91
92 for (auto scrollArea : impl->m_ScrollAreas) {
92 for (auto scrollArea : impl->m_ScrollAreas) {
93 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
93 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
94 auto enterEvent = static_cast<QDragEnterEvent *>(event);
94 auto enterEvent = static_cast<QDragEnterEvent *>(event);
95 enterEvent->acceptProposedAction();
95 enterEvent->acceptProposedAction();
96 enterEvent->setDropAction(Qt::IgnoreAction);
96 enterEvent->setDropAction(Qt::IgnoreAction);
97 impl->m_CurrentScrollArea = scrollArea;
97 impl->m_CurrentScrollArea = scrollArea;
98 break;
98 break;
99 }
99 }
100 }
100 }
101 }
101 }
102 else if (event->type() == QEvent::DragLeave) {
102 else if (event->type() == QEvent::DragLeave) {
103 if (impl->m_CurrentScrollArea) {
103 if (impl->m_CurrentScrollArea) {
104 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
104 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
105 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
105 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
106 impl->m_CurrentScrollArea = nullptr;
106 impl->m_CurrentScrollArea = nullptr;
107 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
107 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
108 impl->m_Timer->stop();
108 impl->m_Timer->stop();
109 }
109 }
110 }
110 }
111 }
111 }
112 else if (event->type() == QEvent::Drop) {
112 else if (event->type() == QEvent::Drop) {
113 if (impl->m_CurrentScrollArea) {
113 if (impl->m_CurrentScrollArea) {
114 impl->m_CurrentScrollArea = nullptr;
114 impl->m_CurrentScrollArea = nullptr;
115 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
115 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
116 impl->m_Timer->stop();
116 impl->m_Timer->stop();
117 }
117 }
118 }
118 }
119
119
120 return false;
120 return false;
121 }
121 }
122
122
123 void DragDropScroller::onTimer()
123 void DragDropScroller::onTimer()
124 {
124 {
125 if (impl->m_CurrentScrollArea) {
125 if (impl->m_CurrentScrollArea) {
126 auto mvt = 0;
126 auto mvt = 0;
127 switch (impl->m_Direction) {
127 switch (impl->m_Direction) {
128 case DragDropScrollerPrivate::ScrollDirection::up:
128 case DragDropScrollerPrivate::ScrollDirection::up:
129 mvt = SCROLL_SPEED;
129 mvt = SCROLL_SPEED;
130 break;
130 break;
131 case DragDropScrollerPrivate::ScrollDirection::down:
131 case DragDropScrollerPrivate::ScrollDirection::down:
132 mvt = -SCROLL_SPEED;
132 mvt = -SCROLL_SPEED;
133 break;
133 break;
134 default:
134 default:
135 break;
135 break;
136 }
136 }
137
137
138 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
138 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
139 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
139 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
140 }
140 }
141 }
141 }
142
142
143 struct DragDropHelper::DragDropHelperPrivate {
143 struct DragDropHelper::DragDropHelperPrivate {
144
144
145 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
145 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
146 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
146 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
147 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
147 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
148 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
148 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
149 // QTemporaryFile to have a name which is not generated.
149 // QTemporaryFile to have a name which is not generated.
150
150
151 explicit DragDropHelperPrivate()
151 explicit DragDropHelperPrivate()
152 : m_PlaceHolder{std::make_unique<QWidget>()},
152 : m_PlaceHolder{std::make_unique<QWidget>()},
153 m_DragDropScroller{std::make_unique<DragDropScroller>()}
153 m_DragDropScroller{std::make_unique<DragDropScroller>()}
154 {
154 {
155 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
155 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
156 sqpApp->installEventFilter(m_DragDropScroller.get());
156 sqpApp->installEventFilter(m_DragDropScroller.get());
157
157
158
158
159 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
159 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
160 }
160 }
161
161
162 void preparePlaceHolder() const
162 void preparePlaceHolder() const
163 {
163 {
164 if (m_CurrentDragWidget) {
164 if (m_CurrentDragWidget) {
165 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
165 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
166 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
166 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
167 }
167 }
168 else {
168 else {
169 // Configuration of the placeHolder when there is no dragWidget
169 // Configuration of the placeHolder when there is no dragWidget
170 // (for instance with a drag from a variable)
170 // (for instance with a drag from a variable)
171
171
172 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
172 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
173 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
173 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
174 }
174 }
175 }
175 }
176 };
176 };
177
177
178
178
179 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()} {}
179 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()} {}
180
180
181 DragDropHelper::~DragDropHelper()
181 DragDropHelper::~DragDropHelper()
182 {
182 {
183 QFile::remove(impl->m_ImageTempUrl);
183 QFile::remove(impl->m_ImageTempUrl);
184 }
184 }
185
185
186 void DragDropHelper::resetDragAndDrop()
186 void DragDropHelper::resetDragAndDrop()
187 {
187 {
188 setCurrentDragWidget(nullptr);
188 setCurrentDragWidget(nullptr);
189 }
189 }
190
190
191 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
191 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
192 {
192 {
193 impl->m_CurrentDragWidget = dragWidget;
193 impl->m_CurrentDragWidget = dragWidget;
194 }
194 }
195
195
196 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
196 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
197 {
197 {
198 return impl->m_CurrentDragWidget;
198 return impl->m_CurrentDragWidget;
199 }
199 }
200
200
201
201
202 QWidget &DragDropHelper::placeHolder() const
202 QWidget &DragDropHelper::placeHolder() const
203 {
203 {
204 return *impl->m_PlaceHolder;
204 return *impl->m_PlaceHolder;
205 }
205 }
206
206
207 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
207 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
208 {
208 {
209 removePlaceHolder();
209 removePlaceHolder();
210 impl->preparePlaceHolder();
210 impl->preparePlaceHolder();
211 layout->insertWidget(index, impl->m_PlaceHolder.get());
211 layout->insertWidget(index, impl->m_PlaceHolder.get());
212 impl->m_PlaceHolder->show();
212 impl->m_PlaceHolder->show();
213 }
213 }
214
214
215 void DragDropHelper::removePlaceHolder()
215 void DragDropHelper::removePlaceHolder()
216 {
216 {
217 auto parentWidget = impl->m_PlaceHolder->parentWidget();
217 auto parentWidget = impl->m_PlaceHolder->parentWidget();
218 if (parentWidget) {
218 if (parentWidget) {
219 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
219 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
220 impl->m_PlaceHolder->setParent(nullptr);
220 impl->m_PlaceHolder->setParent(nullptr);
221 impl->m_PlaceHolder->hide();
221 impl->m_PlaceHolder->hide();
222 }
222 }
223 }
223 }
224
224
225 bool DragDropHelper::isPlaceHolderSet() const
225 bool DragDropHelper::isPlaceHolderSet() const
226 {
226 {
227 return impl->m_PlaceHolder->parentWidget();
227 return impl->m_PlaceHolder->parentWidget();
228 }
228 }
229
229
230 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
230 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
231 {
231 {
232 impl->m_DragDropScroller->addScrollArea(scrollArea);
232 impl->m_DragDropScroller->addScrollArea(scrollArea);
233 }
233 }
234
234
235 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
235 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
236 {
236 {
237 impl->m_DragDropScroller->removeScrollArea(scrollArea);
237 impl->m_DragDropScroller->removeScrollArea(scrollArea);
238 }
238 }
239
239
240 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
240 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
241 {
241 {
242 image.save(impl->m_ImageTempUrl);
242 image.save(impl->m_ImageTempUrl);
243 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
243 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
244 }
244 }
245
245
246 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
246 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
247 VisualizationDragDropContainer *dropContainer)
247 VisualizationDragDropContainer *dropContainer)
248 {
248 {
249 auto result = true;
249 auto result = true;
250
250
251 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
251 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
252 auto variables = sqpApp->variableController().variablesForMimeData(
252 auto variables = sqpApp->variableController().variablesForMimeData(
253 mimeData->data(MIME_TYPE_VARIABLE_LIST));
253 mimeData->data(MIME_TYPE_VARIABLE_LIST));
254
254
255 if (variables.count() == 1) {
255 if (variables.count() == 1) {
256 // Check that the viariable is not already in a graph
256 // Check that the viariable is not already in a graph
257
257
258 // Search for the top level VisualizationWidget
258 // Search for the top level VisualizationWidget
259 auto parent = dropContainer->parentWidget();
259 auto parent = dropContainer->parentWidget();
260 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
260 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
261 parent = parent->parentWidget();
261 parent = parent->parentWidget();
262 }
262 }
263
263
264 if (parent) {
264 if (parent) {
265 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
265 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
266
266
267 FindVariableOperation findVariableOperation{variables.first()};
267 FindVariableOperation findVariableOperation{variables.first()};
268 visualizationWidget->accept(&findVariableOperation);
268 visualizationWidget->accept(&findVariableOperation);
269 auto variableContainers = findVariableOperation.result();
269 auto variableContainers = findVariableOperation.result();
270 if (!variableContainers.empty()) {
270 if (!variableContainers.empty()) {
271 result = false;
271 result = false;
272 }
272 }
273 }
273 }
274 else {
274 else {
275 qCWarning(LOG_DragDropHelper()) << QObject::tr(
275 qCWarning(LOG_DragDropHelper()) << QObject::tr(
276 "DragDropHelper::checkMimeDataForVisualization, the parent "
276 "DragDropHelper::checkMimeDataForVisualization, the parent "
277 "VisualizationWidget cannot be found.");
277 "VisualizationWidget cannot be found.");
278 result = false;
278 result = false;
279 }
279 }
280 }
280 }
281 else {
281 else {
282 result = false;
282 result = false;
283 }
283 }
284 }
284 }
285 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
286 QDataStream stream(mimeData->data(MIME_TYPE_PRODUCT_LIST));
287
288 QVariantList productList;
289 stream >> productList;
290
291 result = productList.count() == 1;
292 }
285
293
286 return result;
294 return result;
287 }
295 }
@@ -1,294 +1,330
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 "DataSource/DataSourceController.h"
9 #include "DataSource/DataSourceItem.h"
8 #include "Variable/VariableController.h"
10 #include "Variable/VariableController.h"
9
11
10 #include "Common/MimeTypesDef.h"
12 #include "Common/MimeTypesDef.h"
11
13
12 #include "DragDropHelper.h"
14 #include "DragDropHelper.h"
13 #include "SqpApplication.h"
15 #include "SqpApplication.h"
14
16
17 #include <QTimer>
18
15 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
19 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
16
20
17 namespace {
21 namespace {
18
22
19 /// Generates a default name for a new zone, according to the number of zones already displayed in
23 /// Generates a default name for a new zone, according to the number of zones already displayed in
20 /// the tab
24 /// the tab
21 QString defaultZoneName(const QLayout &layout)
25 QString defaultZoneName(const QLayout &layout)
22 {
26 {
23 auto count = 0;
27 auto count = 0;
24 for (auto i = 0; i < layout.count(); ++i) {
28 for (auto i = 0; i < layout.count(); ++i) {
25 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
29 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
26 count++;
30 count++;
27 }
31 }
28 }
32 }
29
33
30 return QObject::tr("Zone %1").arg(count + 1);
34 return QObject::tr("Zone %1").arg(count + 1);
31 }
35 }
32
36
33 /**
37 /**
34 * Applies a function to all zones of the tab represented by its layout
38 * Applies a function to all zones of the tab represented by its layout
35 * @param layout the layout that contains zones
39 * @param layout the layout that contains zones
36 * @param fun the function to apply to each zone
40 * @param fun the function to apply to each zone
37 */
41 */
38 template <typename Fun>
42 template <typename Fun>
39 void processZones(QLayout &layout, Fun fun)
43 void processZones(QLayout &layout, Fun fun)
40 {
44 {
41 for (auto i = 0; i < layout.count(); ++i) {
45 for (auto i = 0; i < layout.count(); ++i) {
42 if (auto item = layout.itemAt(i)) {
46 if (auto item = layout.itemAt(i)) {
43 if (auto visualizationZoneWidget
47 if (auto visualizationZoneWidget
44 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
48 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
45 fun(*visualizationZoneWidget);
49 fun(*visualizationZoneWidget);
46 }
50 }
47 }
51 }
48 }
52 }
49 }
53 }
50
54
51 } // namespace
55 } // namespace
52
56
53 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
57 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
54 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
58 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
55
59
56 QString m_Name;
60 QString m_Name;
57
61
58 void dropGraph(int index, VisualizationTabWidget *tabWidget);
62 void dropGraph(int index, VisualizationTabWidget *tabWidget);
59 void dropZone(int index, VisualizationTabWidget *tabWidget);
63 void dropZone(int index, VisualizationTabWidget *tabWidget);
60 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
64 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
61 VisualizationTabWidget *tabWidget);
65 VisualizationTabWidget *tabWidget);
66 void dropProduct(const QVariantList &productDataList, int index,
67 VisualizationTabWidget *tabWidget);
62 };
68 };
63
69
64 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
70 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
65 : QWidget{parent},
71 : QWidget{parent},
66 ui{new Ui::VisualizationTabWidget},
72 ui{new Ui::VisualizationTabWidget},
67 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
73 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
68 {
74 {
69 ui->setupUi(this);
75 ui->setupUi(this);
70
76
71 ui->dragDropContainer->setAcceptedMimeTypes(
77 ui->dragDropContainer->setAcceptedMimeTypes(
72 {MIME_TYPE_GRAPH, MIME_TYPE_ZONE, MIME_TYPE_VARIABLE_LIST});
78 {MIME_TYPE_GRAPH, MIME_TYPE_ZONE, MIME_TYPE_VARIABLE_LIST, MIME_TYPE_PRODUCT_LIST});
73 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
79 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
74 &VisualizationTabWidget::dropMimeData);
80 &VisualizationTabWidget::dropMimeData);
75 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
81 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
76 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
82 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
77 ui->dragDropContainer);
83 ui->dragDropContainer);
78 });
84 });
79 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
85 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
80
86
81 // Widget is deleted when closed
87 // Widget is deleted when closed
82 setAttribute(Qt::WA_DeleteOnClose);
88 setAttribute(Qt::WA_DeleteOnClose);
83 }
89 }
84
90
85 VisualizationTabWidget::~VisualizationTabWidget()
91 VisualizationTabWidget::~VisualizationTabWidget()
86 {
92 {
87 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
93 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
88 delete ui;
94 delete ui;
89 }
95 }
90
96
91 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
97 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
92 {
98 {
93 ui->dragDropContainer->addDragWidget(zoneWidget);
99 ui->dragDropContainer->addDragWidget(zoneWidget);
94 }
100 }
95
101
96 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
102 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
97 {
103 {
98 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
104 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
99 }
105 }
100
106
101 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
107 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
102 {
108 {
103 return createZone({variable}, -1);
109 return createZone({variable}, -1);
104 }
110 }
105
111
106 VisualizationZoneWidget *
112 VisualizationZoneWidget *
107 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
113 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
108 {
114 {
109 auto zoneWidget = createEmptyZone(index);
115 auto zoneWidget = createEmptyZone(index);
110
116
111 // Creates a new graph into the zone
117 // Creates a new graph into the zone
112 zoneWidget->createGraph(variables, index);
118 zoneWidget->createGraph(variables, index);
113
119
114 return zoneWidget;
120 return zoneWidget;
115 }
121 }
116
122
117 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
123 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
118 {
124 {
119 auto zoneWidget
125 auto zoneWidget
120 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
126 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
121 this->insertZone(index, zoneWidget);
127 this->insertZone(index, zoneWidget);
122
128
123 return zoneWidget;
129 return zoneWidget;
124 }
130 }
125
131
126 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
132 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
127 {
133 {
128 if (visitor) {
134 if (visitor) {
129 visitor->visitEnter(this);
135 visitor->visitEnter(this);
130
136
131 // Apply visitor to zone children: widgets different from zones are not visited (no action)
137 // Apply visitor to zone children: widgets different from zones are not visited (no action)
132 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
138 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
133 zoneWidget.accept(visitor);
139 zoneWidget.accept(visitor);
134 });
140 });
135
141
136 visitor->visitLeave(this);
142 visitor->visitLeave(this);
137 }
143 }
138 else {
144 else {
139 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
145 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
140 }
146 }
141 }
147 }
142
148
143 bool VisualizationTabWidget::canDrop(const Variable &variable) const
149 bool VisualizationTabWidget::canDrop(const Variable &variable) const
144 {
150 {
145 // A tab can always accomodate a variable
151 // A tab can always accomodate a variable
146 Q_UNUSED(variable);
152 Q_UNUSED(variable);
147 return true;
153 return true;
148 }
154 }
149
155
150 bool VisualizationTabWidget::contains(const Variable &variable) const
156 bool VisualizationTabWidget::contains(const Variable &variable) const
151 {
157 {
152 Q_UNUSED(variable);
158 Q_UNUSED(variable);
153 return false;
159 return false;
154 }
160 }
155
161
156 QString VisualizationTabWidget::name() const
162 QString VisualizationTabWidget::name() const
157 {
163 {
158 return impl->m_Name;
164 return impl->m_Name;
159 }
165 }
160
166
161 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
167 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
162 {
168 {
163 // Closes zones in the tab
169 // Closes zones in the tab
164 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
170 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
165
171
166 QWidget::closeEvent(event);
172 QWidget::closeEvent(event);
167 }
173 }
168
174
169 QLayout &VisualizationTabWidget::tabLayout() const noexcept
175 QLayout &VisualizationTabWidget::tabLayout() const noexcept
170 {
176 {
171 return *ui->dragDropContainer->layout();
177 return *ui->dragDropContainer->layout();
172 }
178 }
173
179
174 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
180 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
175 {
181 {
176 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
182 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
177 impl->dropGraph(index, this);
183 impl->dropGraph(index, this);
178 }
184 }
179 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
185 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
180 impl->dropZone(index, this);
186 impl->dropZone(index, this);
181 }
187 }
182 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
188 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
183 auto variables = sqpApp->variableController().variablesForMimeData(
189 auto variables = sqpApp->variableController().variablesForMimeData(
184 mimeData->data(MIME_TYPE_VARIABLE_LIST));
190 mimeData->data(MIME_TYPE_VARIABLE_LIST));
185 impl->dropVariables(variables, index, this);
191 impl->dropVariables(variables, index, this);
186 }
192 }
193 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
194 auto productList = sqpApp->dataSourceController().productsDataForMimeData(
195 mimeData->data(MIME_TYPE_PRODUCT_LIST));
196 impl->dropProduct(productList, index, this);
197 }
187 else {
198 else {
188 qCWarning(LOG_VisualizationZoneWidget())
199 qCWarning(LOG_VisualizationZoneWidget())
189 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
200 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
190 }
201 }
191 }
202 }
192
203
193 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
204 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
194 int index, VisualizationTabWidget *tabWidget)
205 int index, VisualizationTabWidget *tabWidget)
195 {
206 {
196 auto &helper = sqpApp->dragDropHelper();
207 auto &helper = sqpApp->dragDropHelper();
197
208
198 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
209 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
199 if (!graphWidget) {
210 if (!graphWidget) {
200 qCWarning(LOG_VisualizationZoneWidget())
211 qCWarning(LOG_VisualizationZoneWidget())
201 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
212 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
202 "found or invalid.");
213 "found or invalid.");
203 Q_ASSERT(false);
214 Q_ASSERT(false);
204 return;
215 return;
205 }
216 }
206
217
207 auto parentDragDropContainer
218 auto parentDragDropContainer
208 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
219 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
209 if (!parentDragDropContainer) {
220 if (!parentDragDropContainer) {
210 qCWarning(LOG_VisualizationZoneWidget())
221 qCWarning(LOG_VisualizationZoneWidget())
211 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
222 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
212 "the dropped graph is not found.");
223 "the dropped graph is not found.");
213 Q_ASSERT(false);
224 Q_ASSERT(false);
214 return;
225 return;
215 }
226 }
216
227
217 auto nbGraph = parentDragDropContainer->countDragWidget();
228 auto nbGraph = parentDragDropContainer->countDragWidget();
218
229
219 const auto &variables = graphWidget->variables();
230 const auto &variables = graphWidget->variables();
220
231
221 if (!variables.isEmpty()) {
232 if (!variables.isEmpty()) {
222 // Abort the requests for the variables (if any)
233 // Abort the requests for the variables (if any)
223 // Commented, because it's not sure if it's needed or not
234 // Commented, because it's not sure if it's needed or not
224 // for (const auto& var : variables)
235 // for (const auto& var : variables)
225 //{
236 //{
226 // sqpApp->variableController().onAbortProgressRequested(var);
237 // sqpApp->variableController().onAbortProgressRequested(var);
227 //}
238 //}
228
239
229 if (nbGraph == 1) {
240 if (nbGraph == 1) {
230 // This is the only graph in the previous zone, close the zone
241 // This is the only graph in the previous zone, close the zone
231 graphWidget->parentZoneWidget()->close();
242 graphWidget->parentZoneWidget()->close();
232 }
243 }
233 else {
244 else {
234 // Close the graph
245 // Close the graph
235 graphWidget->close();
246 graphWidget->close();
236 }
247 }
237
248
238 tabWidget->createZone(variables, index);
249 tabWidget->createZone(variables, index);
239 }
250 }
240 else {
251 else {
241 // The graph is empty, create an empty zone and move the graph inside
252 // The graph is empty, create an empty zone and move the graph inside
242
253
243 auto parentZoneWidget = graphWidget->parentZoneWidget();
254 auto parentZoneWidget = graphWidget->parentZoneWidget();
244
255
245 parentDragDropContainer->layout()->removeWidget(graphWidget);
256 parentDragDropContainer->layout()->removeWidget(graphWidget);
246
257
247 auto zoneWidget = tabWidget->createEmptyZone(index);
258 auto zoneWidget = tabWidget->createEmptyZone(index);
248 zoneWidget->addGraph(graphWidget);
259 zoneWidget->addGraph(graphWidget);
249
260
250 // Close the old zone if it was the only graph inside
261 // Close the old zone if it was the only graph inside
251 if (nbGraph == 1) {
262 if (nbGraph == 1) {
252 parentZoneWidget->close();
263 parentZoneWidget->close();
253 }
264 }
254 }
265 }
255 }
266 }
256
267
257 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
268 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
258 int index, VisualizationTabWidget *tabWidget)
269 int index, VisualizationTabWidget *tabWidget)
259 {
270 {
260 auto &helper = sqpApp->dragDropHelper();
271 auto &helper = sqpApp->dragDropHelper();
261
272
262 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
273 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
263 if (!zoneWidget) {
274 if (!zoneWidget) {
264 qCWarning(LOG_VisualizationZoneWidget())
275 qCWarning(LOG_VisualizationZoneWidget())
265 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
276 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
266 "found or invalid.");
277 "found or invalid.");
267 Q_ASSERT(false);
278 Q_ASSERT(false);
268 return;
279 return;
269 }
280 }
270
281
271 auto parentDragDropContainer
282 auto parentDragDropContainer
272 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
283 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
273 if (!parentDragDropContainer) {
284 if (!parentDragDropContainer) {
274 qCWarning(LOG_VisualizationZoneWidget())
285 qCWarning(LOG_VisualizationZoneWidget())
275 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
286 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
276 "the dropped zone is not found.");
287 "the dropped zone is not found.");
277 Q_ASSERT(false);
288 Q_ASSERT(false);
278 return;
289 return;
279 }
290 }
280
291
281 // Simple move of the zone, no variable operation associated
292 // Simple move of the zone, no variable operation associated
282 parentDragDropContainer->layout()->removeWidget(zoneWidget);
293 parentDragDropContainer->layout()->removeWidget(zoneWidget);
283 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
294 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
284 }
295 }
285
296
286 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
297 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
287 const QList<std::shared_ptr<Variable> > &variables, int index,
298 const QList<std::shared_ptr<Variable> > &variables, int index,
288 VisualizationTabWidget *tabWidget)
299 VisualizationTabWidget *tabWidget)
289 {
300 {
290 // Note: we are sure that there is a single and compatible variable here
301 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
291 // because the AcceptMimeDataFunction, set on the drop container, makes the check before the
302 // compatible variable here
292 // drop can occur.
303 if (variables.count() > 1) {
304 qCWarning(LOG_VisualizationZoneWidget())
305 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
306 "aborted.");
307 return;
308 }
309
293 tabWidget->createZone(variables, index);
310 tabWidget->createZone(variables, index);
294 }
311 }
312
313 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropProduct(
314 const QVariantList &productDataList, int index, VisualizationTabWidget *tabWidget)
315 {
316 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
317 // compatible product here
318 if (productDataList.count() > 1) {
319 qCWarning(LOG_VisualizationZoneWidget()) << tr(
320 "VisualizationTabWidget::dropProduct, dropping multiple products, operation aborted.");
321 return;
322 }
323
324 auto productData = productDataList.first().toHash();
325 auto provider = sqpApp->dataSourceController().providerForProductData(productData);
326 auto name = productData.value(DataSourceItem::NAME_DATA_KEY).toString();
327 auto variable = sqpApp->variableController().createVariable(name, productData, provider);
328 QTimer::singleShot(
329 3000, [tabWidget, variable, index]() { tabWidget->createZone({variable}, index); });
330 }
@@ -1,484 +1,497
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>
14 #include <DataSource/DataSourceItem.h>
13 #include <Variable/Variable.h>
15 #include <Variable/Variable.h>
14 #include <Variable/VariableController.h>
16 #include <Variable/VariableController.h>
15
17
16 #include <Visualization/operations/FindVariableOperation.h>
18 #include <Visualization/operations/FindVariableOperation.h>
17
19
18 #include <DragDropHelper.h>
20 #include <DragDropHelper.h>
19 #include <QUuid>
21 #include <QUuid>
20 #include <SqpApplication.h>
22 #include <SqpApplication.h>
21 #include <cmath>
23 #include <cmath>
22
24
23 #include <QLayout>
25 #include <QLayout>
24
26
25 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26
28
27 namespace {
29 namespace {
28
30
29
31
30 /// Generates a default name for a new graph, according to the number of graphs already displayed in
32 /// Generates a default name for a new graph, according to the number of graphs already displayed in
31 /// the zone
33 /// the zone
32 QString defaultGraphName(const QLayout &layout)
34 QString defaultGraphName(const QLayout &layout)
33 {
35 {
34 auto count = 0;
36 auto count = 0;
35 for (auto i = 0; i < layout.count(); ++i) {
37 for (auto i = 0; i < layout.count(); ++i) {
36 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
38 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 count++;
39 count++;
38 }
40 }
39 }
41 }
40
42
41 return QObject::tr("Graph %1").arg(count + 1);
43 return QObject::tr("Graph %1").arg(count + 1);
42 }
44 }
43
45
44 /**
46 /**
45 * Applies a function to all graphs of the zone represented by its layout
47 * Applies a function to all graphs of the zone represented by its layout
46 * @param layout the layout that contains graphs
48 * @param layout the layout that contains graphs
47 * @param fun the function to apply to each graph
49 * @param fun the function to apply to each graph
48 */
50 */
49 template <typename Fun>
51 template <typename Fun>
50 void processGraphs(QLayout &layout, Fun fun)
52 void processGraphs(QLayout &layout, Fun fun)
51 {
53 {
52 for (auto i = 0; i < layout.count(); ++i) {
54 for (auto i = 0; i < layout.count(); ++i) {
53 if (auto item = layout.itemAt(i)) {
55 if (auto item = layout.itemAt(i)) {
54 if (auto visualizationGraphWidget
56 if (auto visualizationGraphWidget
55 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
57 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
56 fun(*visualizationGraphWidget);
58 fun(*visualizationGraphWidget);
57 }
59 }
58 }
60 }
59 }
61 }
60 }
62 }
61
63
62 } // namespace
64 } // namespace
63
65
64 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
66 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65
67
66 explicit VisualizationZoneWidgetPrivate()
68 explicit VisualizationZoneWidgetPrivate()
67 : m_SynchronisationGroupId{QUuid::createUuid()},
69 : m_SynchronisationGroupId{QUuid::createUuid()},
68 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
70 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 {
71 {
70 }
72 }
71 QUuid m_SynchronisationGroupId;
73 QUuid m_SynchronisationGroupId;
72 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
74 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73
75
74 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
76 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
75 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
77 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
76 VisualizationZoneWidget *zoneWidget);
78 VisualizationZoneWidget *zoneWidget);
79 void dropProduct(const QVariantList &productDataList, int index,
80 VisualizationZoneWidget *zoneWidget);
77 };
81 };
78
82
79 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
83 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
80 : VisualizationDragWidget{parent},
84 : VisualizationDragWidget{parent},
81 ui{new Ui::VisualizationZoneWidget},
85 ui{new Ui::VisualizationZoneWidget},
82 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
86 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
83 {
87 {
84 ui->setupUi(this);
88 ui->setupUi(this);
85
89
86 ui->zoneNameLabel->setText(name);
90 ui->zoneNameLabel->setText(name);
87
91
88 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST});
92 ui->dragDropContainer->setAcceptedMimeTypes(
93 {MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST, MIME_TYPE_PRODUCT_LIST});
89 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
94 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
90 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
95 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
91 ui->dragDropContainer);
96 ui->dragDropContainer);
92 });
97 });
93 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
98 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
94 &VisualizationZoneWidget::dropMimeData);
99 &VisualizationZoneWidget::dropMimeData);
95
100
96 // 'Close' options : widget is deleted when closed
101 // 'Close' options : widget is deleted when closed
97 setAttribute(Qt::WA_DeleteOnClose);
102 setAttribute(Qt::WA_DeleteOnClose);
98 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
103 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
99 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
104 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
100
105
101 // Synchronisation id
106 // Synchronisation id
102 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
107 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
103 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
108 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
104 }
109 }
105
110
106 VisualizationZoneWidget::~VisualizationZoneWidget()
111 VisualizationZoneWidget::~VisualizationZoneWidget()
107 {
112 {
108 delete ui;
113 delete ui;
109 }
114 }
110
115
111 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
116 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
112 {
117 {
113 // Synchronize new graph with others in the zone
118 // Synchronize new graph with others in the zone
114 impl->m_Synchronizer->addGraph(*graphWidget);
119 impl->m_Synchronizer->addGraph(*graphWidget);
115
120
116 ui->dragDropContainer->addDragWidget(graphWidget);
121 ui->dragDropContainer->addDragWidget(graphWidget);
117 }
122 }
118
123
119 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
124 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
120 {
125 {
121 // Synchronize new graph with others in the zone
126 // Synchronize new graph with others in the zone
122 impl->m_Synchronizer->addGraph(*graphWidget);
127 impl->m_Synchronizer->addGraph(*graphWidget);
123
128
124 ui->dragDropContainer->insertDragWidget(index, graphWidget);
129 ui->dragDropContainer->insertDragWidget(index, graphWidget);
125 }
130 }
126
131
127 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
132 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
128 {
133 {
129 return createGraph(variable, -1);
134 return createGraph(variable, -1);
130 }
135 }
131
136
132 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
137 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
133 int index)
138 int index)
134 {
139 {
135 auto graphWidget
140 auto graphWidget
136 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
141 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
137
142
138
143
139 // Set graph properties
144 // Set graph properties
140 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
145 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
141 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
146 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
142
147
143
148
144 // Lambda to synchronize zone widget
149 // Lambda to synchronize zone widget
145 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
150 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
146 const SqpRange &oldGraphRange) {
151 const SqpRange &oldGraphRange) {
147
152
148 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
153 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
149 auto frameLayout = ui->dragDropContainer->layout();
154 auto frameLayout = ui->dragDropContainer->layout();
150 for (auto i = 0; i < frameLayout->count(); ++i) {
155 for (auto i = 0; i < frameLayout->count(); ++i) {
151 auto graphChild
156 auto graphChild
152 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
157 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
153 if (graphChild && (graphChild != graphWidget)) {
158 if (graphChild && (graphChild != graphWidget)) {
154
159
155 auto graphChildRange = graphChild->graphRange();
160 auto graphChildRange = graphChild->graphRange();
156 switch (zoomType) {
161 switch (zoomType) {
157 case AcquisitionZoomType::ZoomIn: {
162 case AcquisitionZoomType::ZoomIn: {
158 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
163 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
159 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
164 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
160 graphChildRange.m_TStart += deltaLeft;
165 graphChildRange.m_TStart += deltaLeft;
161 graphChildRange.m_TEnd -= deltaRight;
166 graphChildRange.m_TEnd -= deltaRight;
162 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
167 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
163 qCDebug(LOG_VisualizationZoneWidget())
168 qCDebug(LOG_VisualizationZoneWidget())
164 << tr("TORM: deltaLeft") << deltaLeft;
169 << tr("TORM: deltaLeft") << deltaLeft;
165 qCDebug(LOG_VisualizationZoneWidget())
170 qCDebug(LOG_VisualizationZoneWidget())
166 << tr("TORM: deltaRight") << deltaRight;
171 << tr("TORM: deltaRight") << deltaRight;
167 qCDebug(LOG_VisualizationZoneWidget())
172 qCDebug(LOG_VisualizationZoneWidget())
168 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
173 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
169
174
170 break;
175 break;
171 }
176 }
172
177
173 case AcquisitionZoomType::ZoomOut: {
178 case AcquisitionZoomType::ZoomOut: {
174 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
179 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
175 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
180 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
176 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
181 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
177 qCDebug(LOG_VisualizationZoneWidget())
182 qCDebug(LOG_VisualizationZoneWidget())
178 << tr("TORM: deltaLeft") << deltaLeft;
183 << tr("TORM: deltaLeft") << deltaLeft;
179 qCDebug(LOG_VisualizationZoneWidget())
184 qCDebug(LOG_VisualizationZoneWidget())
180 << tr("TORM: deltaRight") << deltaRight;
185 << tr("TORM: deltaRight") << deltaRight;
181 qCDebug(LOG_VisualizationZoneWidget())
186 qCDebug(LOG_VisualizationZoneWidget())
182 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
187 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
183 graphChildRange.m_TStart -= deltaLeft;
188 graphChildRange.m_TStart -= deltaLeft;
184 graphChildRange.m_TEnd += deltaRight;
189 graphChildRange.m_TEnd += deltaRight;
185 break;
190 break;
186 }
191 }
187 case AcquisitionZoomType::PanRight: {
192 case AcquisitionZoomType::PanRight: {
188 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
193 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
189 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
194 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
190 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
195 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
191 graphChildRange.m_TStart += deltaLeft;
196 graphChildRange.m_TStart += deltaLeft;
192 graphChildRange.m_TEnd += deltaRight;
197 graphChildRange.m_TEnd += deltaRight;
193 qCDebug(LOG_VisualizationZoneWidget())
198 qCDebug(LOG_VisualizationZoneWidget())
194 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
199 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
195 break;
200 break;
196 }
201 }
197 case AcquisitionZoomType::PanLeft: {
202 case AcquisitionZoomType::PanLeft: {
198 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
203 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
199 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
204 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
200 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
205 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
201 graphChildRange.m_TStart -= deltaLeft;
206 graphChildRange.m_TStart -= deltaLeft;
202 graphChildRange.m_TEnd -= deltaRight;
207 graphChildRange.m_TEnd -= deltaRight;
203 break;
208 break;
204 }
209 }
205 case AcquisitionZoomType::Unknown: {
210 case AcquisitionZoomType::Unknown: {
206 qCDebug(LOG_VisualizationZoneWidget())
211 qCDebug(LOG_VisualizationZoneWidget())
207 << tr("Impossible to synchronize: zoom type unknown");
212 << tr("Impossible to synchronize: zoom type unknown");
208 break;
213 break;
209 }
214 }
210 default:
215 default:
211 qCCritical(LOG_VisualizationZoneWidget())
216 qCCritical(LOG_VisualizationZoneWidget())
212 << tr("Impossible to synchronize: zoom type not take into account");
217 << tr("Impossible to synchronize: zoom type not take into account");
213 // No action
218 // No action
214 break;
219 break;
215 }
220 }
216 graphChild->enableAcquisition(false);
221 graphChild->enableAcquisition(false);
217 qCDebug(LOG_VisualizationZoneWidget())
222 qCDebug(LOG_VisualizationZoneWidget())
218 << tr("TORM: Range before: ") << graphChild->graphRange();
223 << tr("TORM: Range before: ") << graphChild->graphRange();
219 qCDebug(LOG_VisualizationZoneWidget())
224 qCDebug(LOG_VisualizationZoneWidget())
220 << tr("TORM: Range after : ") << graphChildRange;
225 << tr("TORM: Range after : ") << graphChildRange;
221 qCDebug(LOG_VisualizationZoneWidget())
226 qCDebug(LOG_VisualizationZoneWidget())
222 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
227 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
223 graphChild->setGraphRange(graphChildRange);
228 graphChild->setGraphRange(graphChildRange);
224 graphChild->enableAcquisition(true);
229 graphChild->enableAcquisition(true);
225 }
230 }
226 }
231 }
227 };
232 };
228
233
229 // connection for synchronization
234 // connection for synchronization
230 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
235 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
231 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
236 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
232 &VisualizationZoneWidget::onVariableAdded);
237 &VisualizationZoneWidget::onVariableAdded);
233 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
238 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
234 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
239 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
235
240
236 auto range = SqpRange{};
241 auto range = SqpRange{};
237
242
238 // Apply visitor to graph children
243 // Apply visitor to graph children
239 auto layout = ui->dragDropContainer->layout();
244 auto layout = ui->dragDropContainer->layout();
240 if (layout->count() > 0) {
245 if (layout->count() > 0) {
241 // Case of a new graph in a existant zone
246 // Case of a new graph in a existant zone
242 if (auto visualizationGraphWidget
247 if (auto visualizationGraphWidget
243 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
248 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
244 range = visualizationGraphWidget->graphRange();
249 range = visualizationGraphWidget->graphRange();
245 }
250 }
246 }
251 }
247 else {
252 else {
248 // Case of a new graph as the first of the zone
253 // Case of a new graph as the first of the zone
249 range = variable->range();
254 range = variable->range();
250 }
255 }
251
256
252 this->insertGraph(index, graphWidget);
257 this->insertGraph(index, graphWidget);
253
258
254 graphWidget->addVariable(variable, range);
259 graphWidget->addVariable(variable, range);
255
260
256 // get y using variable range
261 // get y using variable range
257 if (auto dataSeries = variable->dataSeries()) {
262 if (auto dataSeries = variable->dataSeries()) {
258 dataSeries->lockRead();
263 dataSeries->lockRead();
259 auto valuesBounds
264 auto valuesBounds
260 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
265 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
261 auto end = dataSeries->cend();
266 auto end = dataSeries->cend();
262 if (valuesBounds.first != end && valuesBounds.second != end) {
267 if (valuesBounds.first != end && valuesBounds.second != end) {
263 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
268 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
264
269
265 auto minValue = rangeValue(valuesBounds.first->minValue());
270 auto minValue = rangeValue(valuesBounds.first->minValue());
266 auto maxValue = rangeValue(valuesBounds.second->maxValue());
271 auto maxValue = rangeValue(valuesBounds.second->maxValue());
267
272
268 graphWidget->setYRange(SqpRange{minValue, maxValue});
273 graphWidget->setYRange(SqpRange{minValue, maxValue});
269 }
274 }
270 dataSeries->unlock();
275 dataSeries->unlock();
271 }
276 }
272
277
273 return graphWidget;
278 return graphWidget;
274 }
279 }
275
280
276 VisualizationGraphWidget *
281 VisualizationGraphWidget *
277 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
282 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
278 {
283 {
279 if (variables.isEmpty()) {
284 if (variables.isEmpty()) {
280 return nullptr;
285 return nullptr;
281 }
286 }
282
287
283 auto graphWidget = createGraph(variables.first(), index);
288 auto graphWidget = createGraph(variables.first(), index);
284 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
289 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
285 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
290 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
286 }
291 }
287
292
288 return graphWidget;
293 return graphWidget;
289 }
294 }
290
295
291 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
296 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
292 {
297 {
293 if (visitor) {
298 if (visitor) {
294 visitor->visitEnter(this);
299 visitor->visitEnter(this);
295
300
296 // Apply visitor to graph children: widgets different from graphs are not visited (no
301 // Apply visitor to graph children: widgets different from graphs are not visited (no
297 // action)
302 // action)
298 processGraphs(
303 processGraphs(
299 *ui->dragDropContainer->layout(),
304 *ui->dragDropContainer->layout(),
300 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
305 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
301
306
302 visitor->visitLeave(this);
307 visitor->visitLeave(this);
303 }
308 }
304 else {
309 else {
305 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
310 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
306 }
311 }
307 }
312 }
308
313
309 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
314 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
310 {
315 {
311 // A tab can always accomodate a variable
316 // A tab can always accomodate a variable
312 Q_UNUSED(variable);
317 Q_UNUSED(variable);
313 return true;
318 return true;
314 }
319 }
315
320
316 bool VisualizationZoneWidget::contains(const Variable &variable) const
321 bool VisualizationZoneWidget::contains(const Variable &variable) const
317 {
322 {
318 Q_UNUSED(variable);
323 Q_UNUSED(variable);
319 return false;
324 return false;
320 }
325 }
321
326
322 QString VisualizationZoneWidget::name() const
327 QString VisualizationZoneWidget::name() const
323 {
328 {
324 return ui->zoneNameLabel->text();
329 return ui->zoneNameLabel->text();
325 }
330 }
326
331
327 QMimeData *VisualizationZoneWidget::mimeData() const
332 QMimeData *VisualizationZoneWidget::mimeData() const
328 {
333 {
329 auto mimeData = new QMimeData;
334 auto mimeData = new QMimeData;
330 mimeData->setData(MIME_TYPE_ZONE, QByteArray());
335 mimeData->setData(MIME_TYPE_ZONE, QByteArray());
331
336
332 return mimeData;
337 return mimeData;
333 }
338 }
334
339
335 bool VisualizationZoneWidget::isDragAllowed() const
340 bool VisualizationZoneWidget::isDragAllowed() const
336 {
341 {
337 return true;
342 return true;
338 }
343 }
339
344
340 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
345 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
341 {
346 {
342 // Closes graphs in the zone
347 // Closes graphs in the zone
343 processGraphs(*ui->dragDropContainer->layout(),
348 processGraphs(*ui->dragDropContainer->layout(),
344 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
349 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
345
350
346 // Delete synchronization group from variable controller
351 // Delete synchronization group from variable controller
347 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
352 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
348 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
353 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
349
354
350 QWidget::closeEvent(event);
355 QWidget::closeEvent(event);
351 }
356 }
352
357
353 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
358 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
354 {
359 {
355 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
360 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
356 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
361 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
357 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
362 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
358 }
363 }
359
364
360 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
365 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
361 {
366 {
362 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
367 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
363 Q_ARG(std::shared_ptr<Variable>, variable),
368 Q_ARG(std::shared_ptr<Variable>, variable),
364 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
369 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
365 }
370 }
366
371
367 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
372 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
368 {
373 {
369 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
374 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
370 impl->dropGraph(index, this);
375 impl->dropGraph(index, this);
371 }
376 }
372 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
377 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
373 auto variables = sqpApp->variableController().variablesForMimeData(
378 auto variables = sqpApp->variableController().variablesForMimeData(
374 mimeData->data(MIME_TYPE_VARIABLE_LIST));
379 mimeData->data(MIME_TYPE_VARIABLE_LIST));
375 impl->dropVariables(variables, index, this);
380 impl->dropVariables(variables, index, this);
376 }
381 }
382 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
383 auto productList = sqpApp->dataSourceController().productsDataForMimeData(
384 mimeData->data(MIME_TYPE_PRODUCT_LIST));
385 impl->dropProduct(productList, index, this);
386 }
377 else {
387 else {
378 qCWarning(LOG_VisualizationZoneWidget())
388 qCWarning(LOG_VisualizationZoneWidget())
379 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
389 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
380 }
390 }
381 }
391 }
382
392
383 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
393 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
384 int index, VisualizationZoneWidget *zoneWidget)
394 int index, VisualizationZoneWidget *zoneWidget)
385 {
395 {
386 auto &helper = sqpApp->dragDropHelper();
396 auto &helper = sqpApp->dragDropHelper();
387
397
388 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
398 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
389 if (!graphWidget) {
399 if (!graphWidget) {
390 qCWarning(LOG_VisualizationZoneWidget())
400 qCWarning(LOG_VisualizationZoneWidget())
391 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
401 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
392 "found or invalid.");
402 "found or invalid.");
393 Q_ASSERT(false);
403 Q_ASSERT(false);
394 return;
404 return;
395 }
405 }
396
406
397 auto parentDragDropContainer
407 auto parentDragDropContainer
398 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
408 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
399 if (!parentDragDropContainer) {
409 if (!parentDragDropContainer) {
400 qCWarning(LOG_VisualizationZoneWidget())
410 qCWarning(LOG_VisualizationZoneWidget())
401 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
411 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
402 "the dropped graph is not found.");
412 "the dropped graph is not found.");
403 Q_ASSERT(false);
413 Q_ASSERT(false);
404 return;
414 return;
405 }
415 }
406
416
407 const auto &variables = graphWidget->variables();
417 const auto &variables = graphWidget->variables();
408
418
409 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
419 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
410 // The drop didn't occur in the same zone
420 // The drop didn't occur in the same zone
411
421
412 // Abort the requests for the variables (if any)
422 // Abort the requests for the variables (if any)
413 // Commented, because it's not sure if it's needed or not
423 // Commented, because it's not sure if it's needed or not
414 // for (const auto& var : variables)
424 // for (const auto& var : variables)
415 //{
425 //{
416 // sqpApp->variableController().onAbortProgressRequested(var);
426 // sqpApp->variableController().onAbortProgressRequested(var);
417 //}
427 //}
418
428
419 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
429 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
420 auto nbGraph = parentDragDropContainer->countDragWidget();
430 auto nbGraph = parentDragDropContainer->countDragWidget();
421 if (nbGraph == 1) {
431 if (nbGraph == 1) {
422 // This is the only graph in the previous zone, close the zone
432 // This is the only graph in the previous zone, close the zone
423 previousParentZoneWidget->close();
433 previousParentZoneWidget->close();
424 }
434 }
425 else {
435 else {
426 // Close the graph
436 // Close the graph
427 graphWidget->close();
437 graphWidget->close();
428 }
438 }
429
439
430 // Creates the new graph in the zone
440 // Creates the new graph in the zone
431 zoneWidget->createGraph(variables, index);
441 zoneWidget->createGraph(variables, index);
432 }
442 }
433 else {
443 else {
434 // The drop occurred in the same zone or the graph is empty
444 // The drop occurred in the same zone or the graph is empty
435 // Simple move of the graph, no variable operation associated
445 // Simple move of the graph, no variable operation associated
436 parentDragDropContainer->layout()->removeWidget(graphWidget);
446 parentDragDropContainer->layout()->removeWidget(graphWidget);
437
447
438 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
448 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
439 // The graph is empty and dropped in a different zone.
449 // The graph is empty and dropped in a different zone.
440 // Take the range of the first graph in the zone (if existing).
450 // Take the range of the first graph in the zone (if existing).
441 auto layout = zoneWidget->ui->dragDropContainer->layout();
451 auto layout = zoneWidget->ui->dragDropContainer->layout();
442 if (layout->count() > 0) {
452 if (layout->count() > 0) {
443 if (auto visualizationGraphWidget
453 if (auto visualizationGraphWidget
444 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
454 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
445 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
455 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
446 }
456 }
447 }
457 }
448 }
458 }
449
459
450 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
460 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
451 }
461 }
452 }
462 }
453
463
454 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
464 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
455 const QList<std::shared_ptr<Variable> > &variables, int index,
465 const QList<std::shared_ptr<Variable> > &variables, int index,
456 VisualizationZoneWidget *zoneWidget)
466 VisualizationZoneWidget *zoneWidget)
457 {
467 {
458 // Search for the top level VisualizationWidget
468 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
459 auto parent = zoneWidget->parentWidget();
469 // compatible variable here
460 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
470 if (variables.count() > 1) {
461 parent = parent->parentWidget();
462 }
463
464 if (!parent) {
465 qCWarning(LOG_VisualizationZoneWidget())
471 qCWarning(LOG_VisualizationZoneWidget())
466 << tr("VisualizationZoneWidget::dropVariables, drop aborted, the parent "
472 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
467 "VisualizationWidget cannot be found.");
473 "aborted.");
468 Q_ASSERT(false);
469 return;
474 return;
470 }
475 }
471
476
472 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
477 Q_ASSERT(variables.count() == 1);
478 zoneWidget->createGraph(variables, index);
479 }
473
480
474 // Search for the first variable which can be dropped
481 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProduct(
475 for (auto variable : variables) {
482 const QVariantList &productDataList, int index, VisualizationZoneWidget *zoneWidget)
476 FindVariableOperation findVariableOperation{variable};
483 {
477 visualizationWidget->accept(&findVariableOperation);
484 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
478 auto variableContainers = findVariableOperation.result();
485 // compatible product here
479 if (variableContainers.empty()) {
486 if (productDataList.count() > 1) {
480 zoneWidget->createGraph(variable, index);
487 qCWarning(LOG_VisualizationZoneWidget()) << tr(
481 break;
488 "VisualizationZoneWidget::dropProduct, dropping multiple products, operation aborted.");
482 }
489 return;
483 }
490 }
491
492 auto productData = productDataList.first().toHash();
493 auto provider = sqpApp->dataSourceController().providerForProductData(productData);
494 auto name = productData.value(DataSourceItem::NAME_DATA_KEY).toString();
495 auto variable = sqpApp->variableController().createVariable(name, productData, provider);
496 zoneWidget->createGraph(variable, index);
484 }
497 }
General Comments 0
You need to be logged in to leave comments. Login now