##// END OF EJS Templates
Fix for D&D bug on mac
Thibaud Rabillard -
r911:9102bdac4611
parent child
Show More
@@ -1,71 +1,75
1 #ifndef SCIQLOP_DRAGDROPHELPER_H
1 #ifndef SCIQLOP_DRAGDROPHELPER_H
2 #define SCIQLOP_DRAGDROPHELPER_H
2 #define SCIQLOP_DRAGDROPHELPER_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 #include <QLoggingCategory>
6 #include <QWidget>
6 #include <QWidget>
7
7
8 class QVBoxLayout;
8 class QVBoxLayout;
9 class QScrollArea;
9 class QScrollArea;
10 class QTabBar;
10 class QTabBar;
11 class VisualizationDragWidget;
11 class VisualizationDragWidget;
12 class VisualizationDragDropContainer;
12 class VisualizationDragDropContainer;
13 class QMimeData;
13 class QMimeData;
14
14
15 Q_DECLARE_LOGGING_CATEGORY(LOG_DragDropHelper)
15 Q_DECLARE_LOGGING_CATEGORY(LOG_DragDropHelper)
16
16
17 /**
17 /**
18 * @brief Helper class for drag&drop operations.
18 * @brief Helper class for drag&drop operations.
19 * @note The helper is accessible from the sqpApp singleton and has the same life as the whole
19 * @note The helper is accessible from the sqpApp singleton and has the same life as the whole
20 * application (like a controller). But contrary to a controller, it doesn't live in a thread and
20 * application (like a controller). But contrary to a controller, it doesn't live in a thread and
21 * can interect with the gui.
21 * can interect with the gui.
22 * @see SqpApplication
22 * @see SqpApplication
23 */
23 */
24 class DragDropHelper {
24 class DragDropHelper {
25 public:
25 public:
26 static const QString MIME_TYPE_GRAPH;
26 static const QString MIME_TYPE_GRAPH;
27 static const QString MIME_TYPE_ZONE;
27 static const QString MIME_TYPE_ZONE;
28
28
29 enum class PlaceHolderType { Default, Graph, Zone };
29 enum class PlaceHolderType { Default, Graph, Zone };
30
30
31 DragDropHelper();
31 DragDropHelper();
32 virtual ~DragDropHelper();
32 virtual ~DragDropHelper();
33
33
34 /// Resets some internal variables. Must be called before any new drag&drop operation.
34 /// Resets some internal variables. Must be called before any new drag&drop operation.
35 void resetDragAndDrop();
35 void resetDragAndDrop();
36
36
37 /// Sets the visualization widget currently being drag on the visualization.
37 /// Sets the visualization widget currently being drag on the visualization.
38 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
38 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
39
39
40 /// Returns the visualization widget currently being drag on the visualization.
40 /// Returns the visualization widget currently being drag on the visualization.
41 /// Can be null if a new visualization widget is intended to be created by the drag&drop
41 /// Can be null if a new visualization widget is intended to be created by the drag&drop
42 /// operation.
42 /// operation.
43 VisualizationDragWidget *getCurrentDragWidget() const;
43 VisualizationDragWidget *getCurrentDragWidget() const;
44
44
45 QWidget &placeHolder() const;
45 QWidget &placeHolder() const;
46 void insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
46 void insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
47 const QString &topLabelText);
47 const QString &topLabelText);
48 void removePlaceHolder();
48 void removePlaceHolder();
49 bool isPlaceHolderSet() const;
49 bool isPlaceHolderSet() const;
50
50
51 /// Checks if the specified mime data is valid for a drop in the visualization
51 /// Checks if the specified mime data is valid for a drop in the visualization
52 bool checkMimeDataForVisualization(const QMimeData *mimeData,
52 bool checkMimeDataForVisualization(const QMimeData *mimeData,
53 VisualizationDragDropContainer *dropContainer);
53 VisualizationDragDropContainer *dropContainer);
54
54
55 void addDragDropScrollArea(QScrollArea *scrollArea);
55 void addDragDropScrollArea(QScrollArea *scrollArea);
56 void removeDragDropScrollArea(QScrollArea *scrollArea);
56 void removeDragDropScrollArea(QScrollArea *scrollArea);
57
57
58 void addDragDropTabBar(QTabBar *tabBar);
58 void addDragDropTabBar(QTabBar *tabBar);
59 void removeDragDropTabBar(QTabBar *tabBar);
59 void removeDragDropTabBar(QTabBar *tabBar);
60
60
61 QUrl imageTemporaryUrl(const QImage &image) const;
61 QUrl imageTemporaryUrl(const QImage &image) const;
62
62
63 void setHightlightedDragWidget(VisualizationDragWidget *dragWidget);
63 void setHightlightedDragWidget(VisualizationDragWidget *dragWidget);
64 VisualizationDragWidget *getHightlightedDragWidget() const;
64 VisualizationDragWidget *getHightlightedDragWidget() const;
65
65
66 /// Delays the closing of a widget during a drag&drop operation
67 void delayedCloseWidget(QWidget *widget);
68 void doCloseWidgets();
69
66 private:
70 private:
67 class DragDropHelperPrivate;
71 class DragDropHelperPrivate;
68 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
72 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
69 };
73 };
70
74
71 #endif // SCIQLOP_DRAGDROPHELPER_H
75 #endif // SCIQLOP_DRAGDROPHELPER_H
@@ -1,275 +1,292
1 #include "DragAndDrop/DragDropHelper.h"
1 #include "DragAndDrop/DragDropHelper.h"
2 #include "DragAndDrop/DragDropScroller.h"
2 #include "DragAndDrop/DragDropScroller.h"
3 #include "DragAndDrop/DragDropTabSwitcher.h"
3 #include "DragAndDrop/DragDropTabSwitcher.h"
4 #include "SqpApplication.h"
4 #include "SqpApplication.h"
5 #include "Visualization/VisualizationDragDropContainer.h"
5 #include "Visualization/VisualizationDragDropContainer.h"
6 #include "Visualization/VisualizationDragWidget.h"
6 #include "Visualization/VisualizationDragWidget.h"
7 #include "Visualization/VisualizationWidget.h"
7 #include "Visualization/VisualizationWidget.h"
8 #include "Visualization/operations/FindVariableOperation.h"
8 #include "Visualization/operations/FindVariableOperation.h"
9
9
10 #include "Variable/Variable.h"
10 #include "Variable/Variable.h"
11 #include "Variable/VariableController.h"
11 #include "Variable/VariableController.h"
12
12
13 #include "Common/MimeTypesDef.h"
13 #include "Common/MimeTypesDef.h"
14 #include "Common/VisualizationDef.h"
14 #include "Common/VisualizationDef.h"
15
15
16 #include <QDir>
16 #include <QDir>
17 #include <QLabel>
17 #include <QLabel>
18 #include <QUrl>
18 #include <QUrl>
19 #include <QVBoxLayout>
19 #include <QVBoxLayout>
20
20
21
21
22 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDropHelper")
22 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDropHelper")
23
23
24
24
25 struct DragDropHelper::DragDropHelperPrivate {
25 struct DragDropHelper::DragDropHelperPrivate {
26
26
27 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
27 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
28 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
28 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
29 QLabel *m_PlaceHolderLabel;
29 QLabel *m_PlaceHolderLabel;
30 QWidget *m_PlaceBackground;
30 QWidget *m_PlaceBackground;
31 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
31 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
32 std::unique_ptr<DragDropTabSwitcher> m_DragDropTabSwitcher = nullptr;
32 std::unique_ptr<DragDropTabSwitcher> m_DragDropTabSwitcher = nullptr;
33 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
33 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
34 // QTemporaryFile to have a name which is not generated.
34 // QTemporaryFile to have a name which is not generated.
35
35
36 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
36 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
37
37
38 QMetaObject::Connection m_DragWidgetDestroyedConnection;
38 QMetaObject::Connection m_DragWidgetDestroyedConnection;
39 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
39 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
40
40
41 QList<QWidget *> m_WidgetToClose;
42
41 explicit DragDropHelperPrivate()
43 explicit DragDropHelperPrivate()
42 : m_PlaceHolder{std::make_unique<QWidget>()},
44 : m_PlaceHolder{std::make_unique<QWidget>()},
43 m_DragDropScroller{std::make_unique<DragDropScroller>()},
45 m_DragDropScroller{std::make_unique<DragDropScroller>()},
44 m_DragDropTabSwitcher{std::make_unique<DragDropTabSwitcher>()}
46 m_DragDropTabSwitcher{std::make_unique<DragDropTabSwitcher>()}
45 {
47 {
46
48
47 auto layout = new QVBoxLayout{m_PlaceHolder.get()};
49 auto layout = new QVBoxLayout{m_PlaceHolder.get()};
48 layout->setSpacing(0);
50 layout->setSpacing(0);
49 layout->setContentsMargins(0, 0, 0, 0);
51 layout->setContentsMargins(0, 0, 0, 0);
50
52
51 m_PlaceHolderLabel = new QLabel{"", m_PlaceHolder.get()};
53 m_PlaceHolderLabel = new QLabel{"", m_PlaceHolder.get()};
52 m_PlaceHolderLabel->setMinimumHeight(25);
54 m_PlaceHolderLabel->setMinimumHeight(25);
53 layout->addWidget(m_PlaceHolderLabel);
55 layout->addWidget(m_PlaceHolderLabel);
54
56
55 m_PlaceBackground = new QWidget{m_PlaceHolder.get()};
57 m_PlaceBackground = new QWidget{m_PlaceHolder.get()};
56 m_PlaceBackground->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
58 m_PlaceBackground->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
57 layout->addWidget(m_PlaceBackground);
59 layout->addWidget(m_PlaceBackground);
58
60
59 sqpApp->installEventFilter(m_DragDropScroller.get());
61 sqpApp->installEventFilter(m_DragDropScroller.get());
60 sqpApp->installEventFilter(m_DragDropTabSwitcher.get());
62 sqpApp->installEventFilter(m_DragDropTabSwitcher.get());
61
63
62 m_ImageTempUrl = QDir::temp().absoluteFilePath("Sciqlop_graph.png");
64 m_ImageTempUrl = QDir::temp().absoluteFilePath("Sciqlop_graph.png");
63 }
65 }
64
66
65 void preparePlaceHolder(DragDropHelper::PlaceHolderType type, const QString &topLabelText) const
67 void preparePlaceHolder(DragDropHelper::PlaceHolderType type, const QString &topLabelText) const
66 {
68 {
67 if (m_CurrentDragWidget) {
69 if (m_CurrentDragWidget) {
68 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
70 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
69 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
71 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
70 }
72 }
71 else {
73 else {
72 // Configuration of the placeHolder when there is no dragWidget
74 // Configuration of the placeHolder when there is no dragWidget
73 // (for instance with a drag from a variable)
75 // (for instance with a drag from a variable)
74
76
75 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
77 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
76 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
78 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
77 }
79 }
78
80
79 switch (type) {
81 switch (type) {
80 case DragDropHelper::PlaceHolderType::Graph:
82 case DragDropHelper::PlaceHolderType::Graph:
81 m_PlaceBackground->setStyleSheet(
83 m_PlaceBackground->setStyleSheet(
82 "background-color: #BBD5EE; border: 1px solid #2A7FD4");
84 "background-color: #BBD5EE; border: 1px solid #2A7FD4");
83 break;
85 break;
84 case DragDropHelper::PlaceHolderType::Zone:
86 case DragDropHelper::PlaceHolderType::Zone:
85 case DragDropHelper::PlaceHolderType::Default:
87 case DragDropHelper::PlaceHolderType::Default:
86 m_PlaceBackground->setStyleSheet(
88 m_PlaceBackground->setStyleSheet(
87 "background-color: #BBD5EE; border: 2px solid #2A7FD4");
89 "background-color: #BBD5EE; border: 2px solid #2A7FD4");
88 m_PlaceHolderLabel->setStyleSheet("color: #2A7FD4");
90 m_PlaceHolderLabel->setStyleSheet("color: #2A7FD4");
89 break;
91 break;
90 }
92 }
91
93
92 m_PlaceHolderLabel->setText(topLabelText);
94 m_PlaceHolderLabel->setText(topLabelText);
93 m_PlaceHolderLabel->setVisible(!topLabelText.isEmpty());
95 m_PlaceHolderLabel->setVisible(!topLabelText.isEmpty());
94 }
96 }
95 };
97 };
96
98
97
99
98 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()} {}
100 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()} {}
99
101
100 DragDropHelper::~DragDropHelper()
102 DragDropHelper::~DragDropHelper()
101 {
103 {
102 QFile::remove(impl->m_ImageTempUrl);
104 QFile::remove(impl->m_ImageTempUrl);
103 }
105 }
104
106
105 void DragDropHelper::resetDragAndDrop()
107 void DragDropHelper::resetDragAndDrop()
106 {
108 {
107 setCurrentDragWidget(nullptr);
109 setCurrentDragWidget(nullptr);
108 impl->m_HighlightedDragWidget = nullptr;
110 impl->m_HighlightedDragWidget = nullptr;
109 }
111 }
110
112
111 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
113 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
112 {
114 {
113 if (impl->m_CurrentDragWidget) {
115 if (impl->m_CurrentDragWidget) {
114
116
115 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
117 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
116 }
118 }
117
119
118 if (dragWidget) {
120 if (dragWidget) {
119 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
121 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
120 impl->m_DragWidgetDestroyedConnection
122 impl->m_DragWidgetDestroyedConnection
121 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
123 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
122 [this]() { impl->m_CurrentDragWidget = nullptr; });
124 [this]() { impl->m_CurrentDragWidget = nullptr; });
123 }
125 }
124
126
125 impl->m_CurrentDragWidget = dragWidget;
127 impl->m_CurrentDragWidget = dragWidget;
126 }
128 }
127
129
128 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
130 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
129 {
131 {
130 return impl->m_CurrentDragWidget;
132 return impl->m_CurrentDragWidget;
131 }
133 }
132
134
133 QWidget &DragDropHelper::placeHolder() const
135 QWidget &DragDropHelper::placeHolder() const
134 {
136 {
135 return *impl->m_PlaceHolder;
137 return *impl->m_PlaceHolder;
136 }
138 }
137
139
138 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
140 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
139 const QString &topLabelText)
141 const QString &topLabelText)
140 {
142 {
141 removePlaceHolder();
143 removePlaceHolder();
142 impl->preparePlaceHolder(type, topLabelText);
144 impl->preparePlaceHolder(type, topLabelText);
143 layout->insertWidget(index, impl->m_PlaceHolder.get());
145 layout->insertWidget(index, impl->m_PlaceHolder.get());
144 impl->m_PlaceHolder->show();
146 impl->m_PlaceHolder->show();
145 }
147 }
146
148
147 void DragDropHelper::removePlaceHolder()
149 void DragDropHelper::removePlaceHolder()
148 {
150 {
149 auto parentWidget = impl->m_PlaceHolder->parentWidget();
151 auto parentWidget = impl->m_PlaceHolder->parentWidget();
150 if (parentWidget) {
152 if (parentWidget) {
151 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
153 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
152 impl->m_PlaceHolder->setParent(nullptr);
154 impl->m_PlaceHolder->setParent(nullptr);
153 impl->m_PlaceHolder->hide();
155 impl->m_PlaceHolder->hide();
154 }
156 }
155 }
157 }
156
158
157 bool DragDropHelper::isPlaceHolderSet() const
159 bool DragDropHelper::isPlaceHolderSet() const
158 {
160 {
159 return impl->m_PlaceHolder->parentWidget();
161 return impl->m_PlaceHolder->parentWidget();
160 }
162 }
161
163
162 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
164 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
163 {
165 {
164 impl->m_DragDropScroller->addScrollArea(scrollArea);
166 impl->m_DragDropScroller->addScrollArea(scrollArea);
165 }
167 }
166
168
167 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
169 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
168 {
170 {
169 impl->m_DragDropScroller->removeScrollArea(scrollArea);
171 impl->m_DragDropScroller->removeScrollArea(scrollArea);
170 }
172 }
171
173
172 void DragDropHelper::addDragDropTabBar(QTabBar *tabBar)
174 void DragDropHelper::addDragDropTabBar(QTabBar *tabBar)
173 {
175 {
174 impl->m_DragDropTabSwitcher->addTabBar(tabBar);
176 impl->m_DragDropTabSwitcher->addTabBar(tabBar);
175 }
177 }
176
178
177 void DragDropHelper::removeDragDropTabBar(QTabBar *tabBar)
179 void DragDropHelper::removeDragDropTabBar(QTabBar *tabBar)
178 {
180 {
179 impl->m_DragDropTabSwitcher->removeTabBar(tabBar);
181 impl->m_DragDropTabSwitcher->removeTabBar(tabBar);
180 }
182 }
181
183
182 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
184 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
183 {
185 {
184 image.save(impl->m_ImageTempUrl);
186 image.save(impl->m_ImageTempUrl);
185 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
187 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
186 }
188 }
187
189
188 void DragDropHelper::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
190 void DragDropHelper::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
189 {
191 {
190 if (impl->m_HighlightedDragWidget) {
192 if (impl->m_HighlightedDragWidget) {
191 impl->m_HighlightedDragWidget->highlightForMerge(false);
193 impl->m_HighlightedDragWidget->highlightForMerge(false);
192 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
194 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
193 }
195 }
194
196
195 if (dragWidget) {
197 if (dragWidget) {
196 dragWidget->highlightForMerge(true);
198 dragWidget->highlightForMerge(true);
197
199
198 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
200 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
199 impl->m_DragWidgetDestroyedConnection
201 impl->m_DragWidgetDestroyedConnection
200 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
202 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
201 [this]() { impl->m_HighlightedDragWidget = nullptr; });
203 [this]() { impl->m_HighlightedDragWidget = nullptr; });
202 }
204 }
203
205
204 impl->m_HighlightedDragWidget = dragWidget;
206 impl->m_HighlightedDragWidget = dragWidget;
205 }
207 }
206
208
207 VisualizationDragWidget *DragDropHelper::getHightlightedDragWidget() const
209 VisualizationDragWidget *DragDropHelper::getHightlightedDragWidget() const
208 {
210 {
209 return impl->m_HighlightedDragWidget;
211 return impl->m_HighlightedDragWidget;
210 }
212 }
211
213
214 void DragDropHelper::delayedCloseWidget(QWidget *widget)
215 {
216 widget->hide();
217 impl->m_WidgetToClose << widget;
218 }
219
220 void DragDropHelper::doCloseWidgets()
221 {
222 for (auto widget : impl->m_WidgetToClose) {
223 widget->close();
224 }
225
226 impl->m_WidgetToClose.clear();
227 }
228
212 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
229 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
213 VisualizationDragDropContainer *dropContainer)
230 VisualizationDragDropContainer *dropContainer)
214 {
231 {
215 if (!mimeData || !dropContainer) {
232 if (!mimeData || !dropContainer) {
216 qCWarning(LOG_DragDropHelper()) << QObject::tr(
233 qCWarning(LOG_DragDropHelper()) << QObject::tr(
217 "DragDropHelper::checkMimeDataForVisualization, invalid input parameters.");
234 "DragDropHelper::checkMimeDataForVisualization, invalid input parameters.");
218 Q_ASSERT(false);
235 Q_ASSERT(false);
219 return false;
236 return false;
220 }
237 }
221
238
222 auto result = false;
239 auto result = false;
223
240
224 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
241 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
225 auto variables = sqpApp->variableController().variablesForMimeData(
242 auto variables = sqpApp->variableController().variablesForMimeData(
226 mimeData->data(MIME_TYPE_VARIABLE_LIST));
243 mimeData->data(MIME_TYPE_VARIABLE_LIST));
227
244
228 if (variables.count() == 1) {
245 if (variables.count() == 1) {
229
246
230 auto variable = variables.first();
247 auto variable = variables.first();
231 if (variable->dataSeries() != nullptr) {
248 if (variable->dataSeries() != nullptr) {
232
249
233 // Check that the variable is not already in a graph
250 // Check that the variable is not already in a graph
234
251
235 auto parent = dropContainer->parentWidget();
252 auto parent = dropContainer->parentWidget();
236 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
253 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
237 parent = parent->parentWidget(); // Search for the top level VisualizationWidget
254 parent = parent->parentWidget(); // Search for the top level VisualizationWidget
238 }
255 }
239
256
240 if (parent) {
257 if (parent) {
241 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
258 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
242
259
243 FindVariableOperation findVariableOperation{variable};
260 FindVariableOperation findVariableOperation{variable};
244 visualizationWidget->accept(&findVariableOperation);
261 visualizationWidget->accept(&findVariableOperation);
245 auto variableContainers = findVariableOperation.result();
262 auto variableContainers = findVariableOperation.result();
246 if (variableContainers.empty()) {
263 if (variableContainers.empty()) {
247 result = true;
264 result = true;
248 }
265 }
249 else {
266 else {
250 // result = false: the variable already exist in the visualisation
267 // result = false: the variable already exist in the visualisation
251 }
268 }
252 }
269 }
253 else {
270 else {
254 qCWarning(LOG_DragDropHelper()) << QObject::tr(
271 qCWarning(LOG_DragDropHelper()) << QObject::tr(
255 "DragDropHelper::checkMimeDataForVisualization, the parent "
272 "DragDropHelper::checkMimeDataForVisualization, the parent "
256 "VisualizationWidget cannot be found. Cannot check if the variable is "
273 "VisualizationWidget cannot be found. Cannot check if the variable is "
257 "already used or not.");
274 "already used or not.");
258 }
275 }
259 }
276 }
260 else {
277 else {
261 // result = false: the variable is not fully loaded
278 // result = false: the variable is not fully loaded
262 }
279 }
263 }
280 }
264 else {
281 else {
265 // result = false: cannot drop multiple variables in the visualisation
282 // result = false: cannot drop multiple variables in the visualisation
266 }
283 }
267 }
284 }
268 else {
285 else {
269 // Other MIME data
286 // Other MIME data
270 // no special rules, accepted by default
287 // no special rules, accepted by default
271 result = true;
288 result = true;
272 }
289 }
273
290
274 return result;
291 return result;
275 }
292 }
@@ -1,452 +1,453
1 #include "Visualization/VisualizationDragDropContainer.h"
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragAndDrop/DragDropHelper.h"
2 #include "DragAndDrop/DragDropHelper.h"
3 #include "SqpApplication.h"
3 #include "SqpApplication.h"
4 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5
5
6 #include "Common/VisualizationDef.h"
6 #include "Common/VisualizationDef.h"
7
7
8 #include <QDrag>
8 #include <QDrag>
9 #include <QDragEnterEvent>
9 #include <QDragEnterEvent>
10 #include <QVBoxLayout>
10 #include <QVBoxLayout>
11
11
12 #include <cmath>
12 #include <cmath>
13 #include <memory>
13 #include <memory>
14
14
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
16
16
17 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
17 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
18
18
19 QVBoxLayout *m_Layout;
19 QVBoxLayout *m_Layout;
20 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
20 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
21 QString m_PlaceHolderText;
21 QString m_PlaceHolderText;
22 DragDropHelper::PlaceHolderType m_PlaceHolderType = DragDropHelper::PlaceHolderType::Graph;
22 DragDropHelper::PlaceHolderType m_PlaceHolderType = DragDropHelper::PlaceHolderType::Graph;
23
23
24 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
24 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
25 = [](auto mimeData) { return true; };
25 = [](auto mimeData) { return true; };
26
26
27 int m_MinContainerHeight = 0;
27 int m_MinContainerHeight = 0;
28
28
29 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
29 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
30 {
30 {
31 m_Layout = new QVBoxLayout(widget);
31 m_Layout = new QVBoxLayout(widget);
32 m_Layout->setContentsMargins(0, 0, 0, 0);
32 m_Layout->setContentsMargins(0, 0, 0, 0);
33 }
33 }
34
34
35 bool acceptMimeData(const QMimeData *data) const
35 bool acceptMimeData(const QMimeData *data) const
36 {
36 {
37 for (const auto &type : m_AcceptedMimeTypes.keys()) {
37 for (const auto &type : m_AcceptedMimeTypes.keys()) {
38 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
38 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
39 return true;
39 return true;
40 }
40 }
41 }
41 }
42
42
43 return false;
43 return false;
44 }
44 }
45
45
46 bool allowMergeForMimeData(const QMimeData *data) const
46 bool allowMergeForMimeData(const QMimeData *data) const
47 {
47 {
48 bool result = false;
48 bool result = false;
49 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
49 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
50 ++it) {
50 ++it) {
51
51
52 if (data->hasFormat(it.key())
52 if (data->hasFormat(it.key())
53 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
53 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
54 || it.value()
54 || it.value()
55 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
55 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
56 result = true;
56 result = true;
57 }
57 }
58 else if (data->hasFormat(it.key())
58 else if (data->hasFormat(it.key())
59 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
59 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
60 // Merge is forbidden if the mime data contain an acceptable type which cannot be
60 // Merge is forbidden if the mime data contain an acceptable type which cannot be
61 // merged
61 // merged
62 result = false;
62 result = false;
63 break;
63 break;
64 }
64 }
65 }
65 }
66
66
67 return result;
67 return result;
68 }
68 }
69
69
70 bool allowInsertForMimeData(const QMimeData *data) const
70 bool allowInsertForMimeData(const QMimeData *data) const
71 {
71 {
72 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
72 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
73 ++it) {
73 ++it) {
74 if (data->hasFormat(it.key())
74 if (data->hasFormat(it.key())
75 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
75 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
76 || it.value()
76 || it.value()
77 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
77 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
78 return true;
78 return true;
79 }
79 }
80 }
80 }
81
81
82 return false;
82 return false;
83 }
83 }
84
84
85 bool hasPlaceHolder() const
85 bool hasPlaceHolder() const
86 {
86 {
87 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
87 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
88 }
88 }
89
89
90 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
90 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
91 {
91 {
92 VisualizationDragWidget *dragWidget = nullptr;
92 VisualizationDragWidget *dragWidget = nullptr;
93
93
94 for (auto child : parent->children()) {
94 for (auto child : parent->children()) {
95 auto widget = qobject_cast<VisualizationDragWidget *>(child);
95 auto widget = qobject_cast<VisualizationDragWidget *>(child);
96 if (widget && widget->isVisible()) {
96 if (widget && widget->isVisible()) {
97 if (widget->frameGeometry().contains(pos)) {
97 if (widget->frameGeometry().contains(pos)) {
98 dragWidget = widget;
98 dragWidget = widget;
99 break;
99 break;
100 }
100 }
101 }
101 }
102 }
102 }
103
103
104 return dragWidget;
104 return dragWidget;
105 }
105 }
106
106
107 bool cursorIsInContainer(QWidget *container) const
107 bool cursorIsInContainer(QWidget *container) const
108 {
108 {
109 return container->isAncestorOf(sqpApp->widgetAt(QCursor::pos()));
109 return container->isAncestorOf(sqpApp->widgetAt(QCursor::pos()));
110 }
110 }
111
111
112 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
112 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
113 {
113 {
114 auto nbGraph = 0;
114 auto nbGraph = 0;
115 for (auto child : parent->children()) {
115 for (auto child : parent->children()) {
116 if (qobject_cast<VisualizationDragWidget *>(child)) {
116 if (qobject_cast<VisualizationDragWidget *>(child)) {
117 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
117 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
118 nbGraph += 1;
118 nbGraph += 1;
119 }
119 }
120 }
120 }
121 }
121 }
122
122
123 return nbGraph;
123 return nbGraph;
124 }
124 }
125
125
126 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
126 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
127 const VisualizationDragDropContainer *container);
127 const VisualizationDragDropContainer *container);
128 };
128 };
129
129
130 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
130 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
131 : QFrame{parent},
131 : QFrame{parent},
132 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
132 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
133 {
133 {
134 setAcceptDrops(true);
134 setAcceptDrops(true);
135 }
135 }
136
136
137 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
137 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
138 {
138 {
139 impl->m_Layout->addWidget(dragWidget);
139 impl->m_Layout->addWidget(dragWidget);
140 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
140 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
141 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
141 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
142 &VisualizationDragDropContainer::startDrag);
142 &VisualizationDragDropContainer::startDrag);
143 }
143 }
144
144
145 void VisualizationDragDropContainer::insertDragWidget(int index,
145 void VisualizationDragDropContainer::insertDragWidget(int index,
146 VisualizationDragWidget *dragWidget)
146 VisualizationDragWidget *dragWidget)
147 {
147 {
148 impl->m_Layout->insertWidget(index, dragWidget);
148 impl->m_Layout->insertWidget(index, dragWidget);
149 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
149 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
150 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
150 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
151 &VisualizationDragDropContainer::startDrag);
151 &VisualizationDragDropContainer::startDrag);
152 }
152 }
153
153
154 void VisualizationDragDropContainer::addAcceptedMimeType(
154 void VisualizationDragDropContainer::addAcceptedMimeType(
155 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
155 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
156 {
156 {
157 impl->m_AcceptedMimeTypes[mimeType] = behavior;
157 impl->m_AcceptedMimeTypes[mimeType] = behavior;
158 }
158 }
159
159
160 int VisualizationDragDropContainer::countDragWidget() const
160 int VisualizationDragDropContainer::countDragWidget() const
161 {
161 {
162 return impl->countDragWidget(this);
162 return impl->countDragWidget(this);
163 }
163 }
164
164
165 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
165 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
166 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
166 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
167 {
167 {
168 impl->m_AcceptMimeDataFun = fun;
168 impl->m_AcceptMimeDataFun = fun;
169 }
169 }
170
170
171 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
171 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
172 const QString &placeHolderText)
172 const QString &placeHolderText)
173 {
173 {
174 impl->m_PlaceHolderType = type;
174 impl->m_PlaceHolderType = type;
175 impl->m_PlaceHolderText = placeHolderText;
175 impl->m_PlaceHolderText = placeHolderText;
176 }
176 }
177
177
178 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
178 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
179 const QPoint &dragPosition)
179 const QPoint &dragPosition)
180 {
180 {
181 auto &helper = sqpApp->dragDropHelper();
181 auto &helper = sqpApp->dragDropHelper();
182 helper.resetDragAndDrop();
182 helper.resetDragAndDrop();
183
183
184 // Note: The management of the drag object is done by Qt
184 // Note: The management of the drag object is done by Qt
185 auto drag = new QDrag{dragWidget};
185 auto drag = new QDrag{dragWidget};
186 drag->setHotSpot(dragPosition);
186 drag->setHotSpot(dragPosition);
187
187
188 auto mimeData = dragWidget->mimeData();
188 auto mimeData = dragWidget->mimeData();
189 drag->setMimeData(mimeData);
189 drag->setMimeData(mimeData);
190
190
191 auto pixmap = QPixmap(dragWidget->size());
191 auto pixmap = QPixmap(dragWidget->size());
192 dragWidget->render(&pixmap);
192 dragWidget->render(&pixmap);
193 drag->setPixmap(pixmap);
193 drag->setPixmap(pixmap);
194
194
195 auto image = pixmap.toImage();
195 auto image = pixmap.toImage();
196 mimeData->setImageData(image);
196 mimeData->setImageData(image);
197 mimeData->setUrls({helper.imageTemporaryUrl(image)});
197 mimeData->setUrls({helper.imageTemporaryUrl(image)});
198
198
199 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
199 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
200 helper.setCurrentDragWidget(dragWidget);
200 helper.setCurrentDragWidget(dragWidget);
201
201
202 if (impl->cursorIsInContainer(this)) {
202 if (impl->cursorIsInContainer(this)) {
203 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
203 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
204 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
204 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
205 impl->m_PlaceHolderText);
205 impl->m_PlaceHolderText);
206 dragWidget->setVisible(false);
206 dragWidget->setVisible(false);
207 }
207 }
208 else {
208 else {
209 // The drag starts directly outside the drop zone
209 // The drag starts directly outside the drop zone
210 // do not add the placeHolder
210 // do not add the placeHolder
211 }
211 }
212
212
213 // Note: The exec() is blocking on windows but not on linux and macOS
213 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
214 drag->exec(Qt::MoveAction | Qt::CopyAction);
214
215 helper.doCloseWidgets();
215 }
216 }
216 else {
217 else {
217 qCWarning(LOG_VisualizationDragDropContainer())
218 qCWarning(LOG_VisualizationDragDropContainer())
218 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
219 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
219 "VisualizationDragWidget is not found in this container.");
220 "VisualizationDragWidget is not found in this container.");
220 }
221 }
221 }
222 }
222
223
223 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
224 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
224 {
225 {
225 if (impl->acceptMimeData(event->mimeData())) {
226 if (impl->acceptMimeData(event->mimeData())) {
226 event->acceptProposedAction();
227 event->acceptProposedAction();
227
228
228 auto &helper = sqpApp->dragDropHelper();
229 auto &helper = sqpApp->dragDropHelper();
229
230
230 if (!impl->hasPlaceHolder()) {
231 if (!impl->hasPlaceHolder()) {
231 auto dragWidget = helper.getCurrentDragWidget();
232 auto dragWidget = helper.getCurrentDragWidget();
232
233
233 if (dragWidget) {
234 if (dragWidget) {
234 // If the drag&drop is internal to the visualization, entering the container hide
235 // If the drag&drop is internal to the visualization, entering the container hide
235 // the dragWidget which was made visible by the dragLeaveEvent
236 // the dragWidget which was made visible by the dragLeaveEvent
236 auto parentWidget
237 auto parentWidget
237 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
238 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
238 if (parentWidget) {
239 if (parentWidget) {
239 dragWidget->setVisible(false);
240 dragWidget->setVisible(false);
240 }
241 }
241 }
242 }
242
243
243 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
244 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
244 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
245 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
245 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
246 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
246 }
247 }
247 else {
248 else {
248 // do nothing
249 // do nothing
249 }
250 }
250 }
251 }
251 else {
252 else {
252 event->ignore();
253 event->ignore();
253 }
254 }
254
255
255 QWidget::dragEnterEvent(event);
256 QWidget::dragEnterEvent(event);
256 }
257 }
257
258
258 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
259 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
259 {
260 {
260 Q_UNUSED(event);
261 Q_UNUSED(event);
261
262
262 auto &helper = sqpApp->dragDropHelper();
263 auto &helper = sqpApp->dragDropHelper();
263
264
264 if (!impl->cursorIsInContainer(this)) {
265 if (!impl->cursorIsInContainer(this)) {
265 helper.removePlaceHolder();
266 helper.removePlaceHolder();
266 helper.setHightlightedDragWidget(nullptr);
267 helper.setHightlightedDragWidget(nullptr);
267 impl->m_MinContainerHeight = 0;
268 impl->m_MinContainerHeight = 0;
268
269
269 auto dragWidget = helper.getCurrentDragWidget();
270 auto dragWidget = helper.getCurrentDragWidget();
270 if (dragWidget) {
271 if (dragWidget) {
271 // dragWidget has a value only if the drag is started from the visualization
272 // dragWidget has a value only if the drag is started from the visualization
272 // In that case, shows the drag widget at its original place
273 // In that case, shows the drag widget at its original place
273 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
274 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
274 // drop zone (It is not possible to catch a drop event outside of the application)
275 // drop zone (It is not possible to catch a drop event outside of the application)
275
276
276 if (dragWidget) {
277 if (dragWidget) {
277 dragWidget->setVisible(true);
278 dragWidget->setVisible(true);
278 }
279 }
279 }
280 }
280 }
281 }
281 else {
282 else {
282 // Leave event probably received for a child widget.
283 // Leave event probably received for a child widget.
283 // Do nothing.
284 // Do nothing.
284 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
285 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
285 }
286 }
286
287
287 QWidget::dragLeaveEvent(event);
288 QWidget::dragLeaveEvent(event);
288 }
289 }
289
290
290 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
291 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
291 {
292 {
292 if (impl->acceptMimeData(event->mimeData())) {
293 if (impl->acceptMimeData(event->mimeData())) {
293 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
294 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
294 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
295 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
295 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
296 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
296 }
297 }
297 else {
298 else {
298 event->ignore();
299 event->ignore();
299 }
300 }
300
301
301 QWidget::dragMoveEvent(event);
302 QWidget::dragMoveEvent(event);
302 }
303 }
303
304
304 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
305 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
305 {
306 {
306 auto &helper = sqpApp->dragDropHelper();
307 auto &helper = sqpApp->dragDropHelper();
307
308
308 if (impl->acceptMimeData(event->mimeData())) {
309 if (impl->acceptMimeData(event->mimeData())) {
309 auto dragWidget = helper.getCurrentDragWidget();
310 auto dragWidget = helper.getCurrentDragWidget();
310 if (impl->hasPlaceHolder()) {
311 if (impl->hasPlaceHolder()) {
311 // drop where the placeHolder is located
312 // drop where the placeHolder is located
312
313
313 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
314 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
314 if (canInsert) {
315 if (canInsert) {
315 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
316 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
316
317
317 if (dragWidget) {
318 if (dragWidget) {
318 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
319 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
319 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
320 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
320 // Correction of the index if the drop occurs in the same container
321 // Correction of the index if the drop occurs in the same container
321 // and if the drag is started from the visualization (in that case, the
322 // and if the drag is started from the visualization (in that case, the
322 // dragWidget is hidden)
323 // dragWidget is hidden)
323 droppedIndex -= 1;
324 droppedIndex -= 1;
324 }
325 }
325
326
326 dragWidget->setVisible(true);
327 dragWidget->setVisible(true);
327 }
328 }
328
329
329 event->acceptProposedAction();
330 event->acceptProposedAction();
330
331
331 helper.removePlaceHolder();
332 helper.removePlaceHolder();
332
333
333 emit dropOccuredInContainer(droppedIndex, event->mimeData());
334 emit dropOccuredInContainer(droppedIndex, event->mimeData());
334 }
335 }
335 else {
336 else {
336 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
337 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
337 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
338 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
338 "the insertion is forbidden.");
339 "the insertion is forbidden.");
339 Q_ASSERT(false);
340 Q_ASSERT(false);
340 }
341 }
341 }
342 }
342 else if (helper.getHightlightedDragWidget()) {
343 else if (helper.getHightlightedDragWidget()) {
343 // drop on the highlighted widget
344 // drop on the highlighted widget
344
345
345 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
346 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
346 if (canMerge) {
347 if (canMerge) {
347 event->acceptProposedAction();
348 event->acceptProposedAction();
348 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
349 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
349 }
350 }
350 else {
351 else {
351 qCWarning(LOG_VisualizationDragDropContainer())
352 qCWarning(LOG_VisualizationDragDropContainer())
352 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
353 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
353 "the merge is forbidden.");
354 "the merge is forbidden.");
354 Q_ASSERT(false);
355 Q_ASSERT(false);
355 }
356 }
356 }
357 }
357 }
358 }
358 else {
359 else {
359 event->ignore();
360 event->ignore();
360 }
361 }
361
362
362 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
363 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
363 impl->m_MinContainerHeight = 0;
364 impl->m_MinContainerHeight = 0;
364
365
365 QWidget::dropEvent(event);
366 QWidget::dropEvent(event);
366 }
367 }
367
368
368
369
369 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
370 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
370 const QPoint &pos, bool canInsert, bool canMerge,
371 const QPoint &pos, bool canInsert, bool canMerge,
371 const VisualizationDragDropContainer *container)
372 const VisualizationDragDropContainer *container)
372 {
373 {
373 auto &helper = sqpApp->dragDropHelper();
374 auto &helper = sqpApp->dragDropHelper();
374
375
375 auto absPos = container->mapToGlobal(pos);
376 auto absPos = container->mapToGlobal(pos);
376 auto isOnPlaceHolder = sqpApp->widgetAt(absPos) == &(helper.placeHolder());
377 auto isOnPlaceHolder = sqpApp->widgetAt(absPos) == &(helper.placeHolder());
377
378
378 if (countDragWidget(container, true) == 0) {
379 if (countDragWidget(container, true) == 0) {
379 // Drop on an empty container, just add the placeHolder at the top
380 // Drop on an empty container, just add the placeHolder at the top
380 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
381 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
381 }
382 }
382 else if (!isOnPlaceHolder) {
383 else if (!isOnPlaceHolder) {
383 auto nbDragWidget = countDragWidget(container);
384 auto nbDragWidget = countDragWidget(container);
384 if (nbDragWidget > 0) {
385 if (nbDragWidget > 0) {
385
386
386 if (m_MinContainerHeight == 0) {
387 if (m_MinContainerHeight == 0) {
387 m_MinContainerHeight = container->size().height();
388 m_MinContainerHeight = container->size().height();
388 }
389 }
389
390
390 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
391 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
391 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
392 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
392
393
393 auto posY = pos.y();
394 auto posY = pos.y();
394 auto dropIndex = floor(posY / graphHeight);
395 auto dropIndex = floor(posY / graphHeight);
395 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
396 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
396
397
397
398
398 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
399 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
399 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
400 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
400
401
401 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
402 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
402
403
403 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
404 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
404
405
405 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
406 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
406 if (isOnBottom) {
407 if (isOnBottom) {
407 dropIndex += 1;
408 dropIndex += 1;
408 }
409 }
409
410
410 if (helper.getCurrentDragWidget()) {
411 if (helper.getCurrentDragWidget()) {
411 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
412 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
412 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
413 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
413 // Correction of the index if the drop occurs in the same container
414 // Correction of the index if the drop occurs in the same container
414 // and if the drag is started from the visualization (in that case, the
415 // and if the drag is started from the visualization (in that case, the
415 // dragWidget is hidden)
416 // dragWidget is hidden)
416 dropIndex += 1;
417 dropIndex += 1;
417 }
418 }
418 }
419 }
419
420
420 if (dropIndex != placeHolderIndex) {
421 if (dropIndex != placeHolderIndex) {
421 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
422 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
422 m_PlaceHolderText);
423 m_PlaceHolderText);
423 }
424 }
424
425
425 helper.setHightlightedDragWidget(nullptr);
426 helper.setHightlightedDragWidget(nullptr);
426 }
427 }
427 else if (canMerge && dragWidgetHovered) {
428 else if (canMerge && dragWidgetHovered) {
428 // drop on the middle -> merge
429 // drop on the middle -> merge
429 if (hasPlaceHolder()) {
430 if (hasPlaceHolder()) {
430 helper.removePlaceHolder();
431 helper.removePlaceHolder();
431 }
432 }
432
433
433 helper.setHightlightedDragWidget(dragWidgetHovered);
434 helper.setHightlightedDragWidget(dragWidgetHovered);
434 }
435 }
435 else {
436 else {
436 qCWarning(LOG_VisualizationDragDropContainer())
437 qCWarning(LOG_VisualizationDragDropContainer())
437 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
438 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
438 "action.");
439 "action.");
439 }
440 }
440 }
441 }
441 else {
442 else {
442 qCWarning(LOG_VisualizationDragDropContainer())
443 qCWarning(LOG_VisualizationDragDropContainer())
443 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
444 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
444 "found in the "
445 "found in the "
445 "container");
446 "container");
446 }
447 }
447 }
448 }
448 else {
449 else {
449 // the mouse is hover the placeHolder
450 // the mouse is hover the placeHolder
450 // Do nothing
451 // Do nothing
451 }
452 }
452 }
453 }
@@ -1,309 +1,309
1 #include "Visualization/VisualizationTabWidget.h"
1 #include "Visualization/VisualizationTabWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "ui_VisualizationTabWidget.h"
3 #include "ui_VisualizationTabWidget.h"
4
4
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7
7
8 #include "Variable/VariableController.h"
8 #include "Variable/VariableController.h"
9
9
10 #include "Common/MimeTypesDef.h"
10 #include "Common/MimeTypesDef.h"
11
11
12 #include "DragAndDrop/DragDropHelper.h"
12 #include "DragAndDrop/DragDropHelper.h"
13 #include "SqpApplication.h"
13 #include "SqpApplication.h"
14
14
15 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
15 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
16
16
17 namespace {
17 namespace {
18
18
19 /// Generates a default name for a new zone, according to the number of zones already displayed in
19 /// Generates a default name for a new zone, according to the number of zones already displayed in
20 /// the tab
20 /// the tab
21 QString defaultZoneName(const QLayout &layout)
21 QString defaultZoneName(const QLayout &layout)
22 {
22 {
23 auto count = 0;
23 auto count = 0;
24 for (auto i = 0; i < layout.count(); ++i) {
24 for (auto i = 0; i < layout.count(); ++i) {
25 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
25 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
26 count++;
26 count++;
27 }
27 }
28 }
28 }
29
29
30 return QObject::tr("Zone %1").arg(count + 1);
30 return QObject::tr("Zone %1").arg(count + 1);
31 }
31 }
32
32
33 /**
33 /**
34 * Applies a function to all zones of the tab represented by its layout
34 * Applies a function to all zones of the tab represented by its layout
35 * @param layout the layout that contains zones
35 * @param layout the layout that contains zones
36 * @param fun the function to apply to each zone
36 * @param fun the function to apply to each zone
37 */
37 */
38 template <typename Fun>
38 template <typename Fun>
39 void processZones(QLayout &layout, Fun fun)
39 void processZones(QLayout &layout, Fun fun)
40 {
40 {
41 for (auto i = 0; i < layout.count(); ++i) {
41 for (auto i = 0; i < layout.count(); ++i) {
42 if (auto item = layout.itemAt(i)) {
42 if (auto item = layout.itemAt(i)) {
43 if (auto visualizationZoneWidget
43 if (auto visualizationZoneWidget
44 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
44 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
45 fun(*visualizationZoneWidget);
45 fun(*visualizationZoneWidget);
46 }
46 }
47 }
47 }
48 }
48 }
49 }
49 }
50
50
51 } // namespace
51 } // namespace
52
52
53 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
53 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
54 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
54 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
55
55
56 QString m_Name;
56 QString m_Name;
57
57
58 void dropGraph(int index, VisualizationTabWidget *tabWidget);
58 void dropGraph(int index, VisualizationTabWidget *tabWidget);
59 void dropZone(int index, VisualizationTabWidget *tabWidget);
59 void dropZone(int index, VisualizationTabWidget *tabWidget);
60 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
60 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
61 VisualizationTabWidget *tabWidget);
61 VisualizationTabWidget *tabWidget);
62 };
62 };
63
63
64 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
64 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
65 : QWidget{parent},
65 : QWidget{parent},
66 ui{new Ui::VisualizationTabWidget},
66 ui{new Ui::VisualizationTabWidget},
67 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
67 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
68 {
68 {
69 ui->setupUi(this);
69 ui->setupUi(this);
70
70
71 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Zone, "Zone");
71 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Zone, "Zone");
72 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 5);
72 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 5);
73 ui->dragDropContainer->addAcceptedMimeType(
73 ui->dragDropContainer->addAcceptedMimeType(
74 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
74 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
75 ui->dragDropContainer->addAcceptedMimeType(
75 ui->dragDropContainer->addAcceptedMimeType(
76 MIME_TYPE_ZONE, VisualizationDragDropContainer::DropBehavior::Inserted);
76 MIME_TYPE_ZONE, VisualizationDragDropContainer::DropBehavior::Inserted);
77 ui->dragDropContainer->addAcceptedMimeType(
77 ui->dragDropContainer->addAcceptedMimeType(
78 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::Inserted);
78 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::Inserted);
79
79
80 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
80 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
81 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
81 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
82 ui->dragDropContainer);
82 ui->dragDropContainer);
83 });
83 });
84
84
85 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
85 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
86 &VisualizationTabWidget::dropMimeData);
86 &VisualizationTabWidget::dropMimeData);
87
87
88 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
88 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
89
89
90 // Widget is deleted when closed
90 // Widget is deleted when closed
91 setAttribute(Qt::WA_DeleteOnClose);
91 setAttribute(Qt::WA_DeleteOnClose);
92 }
92 }
93
93
94 VisualizationTabWidget::~VisualizationTabWidget()
94 VisualizationTabWidget::~VisualizationTabWidget()
95 {
95 {
96 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
96 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
97 delete ui;
97 delete ui;
98 }
98 }
99
99
100 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
100 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
101 {
101 {
102 ui->dragDropContainer->addDragWidget(zoneWidget);
102 ui->dragDropContainer->addDragWidget(zoneWidget);
103 }
103 }
104
104
105 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
105 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
106 {
106 {
107 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
107 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
108 }
108 }
109
109
110 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
110 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
111 {
111 {
112 return createZone({variable}, -1);
112 return createZone({variable}, -1);
113 }
113 }
114
114
115 VisualizationZoneWidget *
115 VisualizationZoneWidget *
116 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
116 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
117 {
117 {
118 auto zoneWidget = createEmptyZone(index);
118 auto zoneWidget = createEmptyZone(index);
119
119
120 // Creates a new graph into the zone
120 // Creates a new graph into the zone
121 zoneWidget->createGraph(variables, index);
121 zoneWidget->createGraph(variables, index);
122
122
123 return zoneWidget;
123 return zoneWidget;
124 }
124 }
125
125
126 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
126 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
127 {
127 {
128 auto zoneWidget
128 auto zoneWidget
129 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
129 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
130 this->insertZone(index, zoneWidget);
130 this->insertZone(index, zoneWidget);
131
131
132 return zoneWidget;
132 return zoneWidget;
133 }
133 }
134
134
135 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
135 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
136 {
136 {
137 if (visitor) {
137 if (visitor) {
138 visitor->visitEnter(this);
138 visitor->visitEnter(this);
139
139
140 // Apply visitor to zone children: widgets different from zones are not visited (no action)
140 // Apply visitor to zone children: widgets different from zones are not visited (no action)
141 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
141 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
142 zoneWidget.accept(visitor);
142 zoneWidget.accept(visitor);
143 });
143 });
144
144
145 visitor->visitLeave(this);
145 visitor->visitLeave(this);
146 }
146 }
147 else {
147 else {
148 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
148 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
149 }
149 }
150 }
150 }
151
151
152 bool VisualizationTabWidget::canDrop(const Variable &variable) const
152 bool VisualizationTabWidget::canDrop(const Variable &variable) const
153 {
153 {
154 // A tab can always accomodate a variable
154 // A tab can always accomodate a variable
155 Q_UNUSED(variable);
155 Q_UNUSED(variable);
156 return true;
156 return true;
157 }
157 }
158
158
159 bool VisualizationTabWidget::contains(const Variable &variable) const
159 bool VisualizationTabWidget::contains(const Variable &variable) const
160 {
160 {
161 Q_UNUSED(variable);
161 Q_UNUSED(variable);
162 return false;
162 return false;
163 }
163 }
164
164
165 QString VisualizationTabWidget::name() const
165 QString VisualizationTabWidget::name() const
166 {
166 {
167 return impl->m_Name;
167 return impl->m_Name;
168 }
168 }
169
169
170 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
170 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
171 {
171 {
172 // Closes zones in the tab
172 // Closes zones in the tab
173 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
173 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
174
174
175 QWidget::closeEvent(event);
175 QWidget::closeEvent(event);
176 }
176 }
177
177
178 QLayout &VisualizationTabWidget::tabLayout() const noexcept
178 QLayout &VisualizationTabWidget::tabLayout() const noexcept
179 {
179 {
180 return *ui->dragDropContainer->layout();
180 return *ui->dragDropContainer->layout();
181 }
181 }
182
182
183 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
183 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
184 {
184 {
185 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
185 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
186 impl->dropGraph(index, this);
186 impl->dropGraph(index, this);
187 }
187 }
188 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
188 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
189 impl->dropZone(index, this);
189 impl->dropZone(index, this);
190 }
190 }
191 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
191 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
192 auto variables = sqpApp->variableController().variablesForMimeData(
192 auto variables = sqpApp->variableController().variablesForMimeData(
193 mimeData->data(MIME_TYPE_VARIABLE_LIST));
193 mimeData->data(MIME_TYPE_VARIABLE_LIST));
194 impl->dropVariables(variables, index, this);
194 impl->dropVariables(variables, index, this);
195 }
195 }
196 else {
196 else {
197 qCWarning(LOG_VisualizationZoneWidget())
197 qCWarning(LOG_VisualizationZoneWidget())
198 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
198 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
199 }
199 }
200 }
200 }
201
201
202 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
202 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
203 int index, VisualizationTabWidget *tabWidget)
203 int index, VisualizationTabWidget *tabWidget)
204 {
204 {
205 auto &helper = sqpApp->dragDropHelper();
205 auto &helper = sqpApp->dragDropHelper();
206
206
207 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
207 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
208 if (!graphWidget) {
208 if (!graphWidget) {
209 qCWarning(LOG_VisualizationZoneWidget())
209 qCWarning(LOG_VisualizationZoneWidget())
210 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
210 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
211 "found or invalid.");
211 "found or invalid.");
212 Q_ASSERT(false);
212 Q_ASSERT(false);
213 return;
213 return;
214 }
214 }
215
215
216 auto parentDragDropContainer
216 auto parentDragDropContainer
217 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
217 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
218 if (!parentDragDropContainer) {
218 if (!parentDragDropContainer) {
219 qCWarning(LOG_VisualizationZoneWidget())
219 qCWarning(LOG_VisualizationZoneWidget())
220 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
220 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
221 "the dropped graph is not found.");
221 "the dropped graph is not found.");
222 Q_ASSERT(false);
222 Q_ASSERT(false);
223 return;
223 return;
224 }
224 }
225
225
226 auto nbGraph = parentDragDropContainer->countDragWidget();
226 auto nbGraph = parentDragDropContainer->countDragWidget();
227
227
228 const auto &variables = graphWidget->variables();
228 const auto &variables = graphWidget->variables();
229
229
230 if (!variables.isEmpty()) {
230 if (!variables.isEmpty()) {
231 // Abort the requests for the variables (if any)
231 // Abort the requests for the variables (if any)
232 // Commented, because it's not sure if it's needed or not
232 // Commented, because it's not sure if it's needed or not
233 // for (const auto& var : variables)
233 // for (const auto& var : variables)
234 //{
234 //{
235 // sqpApp->variableController().onAbortProgressRequested(var);
235 // sqpApp->variableController().onAbortProgressRequested(var);
236 //}
236 //}
237
237
238 if (nbGraph == 1) {
238 if (nbGraph == 1) {
239 // This is the only graph in the previous zone, close the zone
239 // This is the only graph in the previous zone, close the zone
240 graphWidget->parentZoneWidget()->close();
240 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
241 }
241 }
242 else {
242 else {
243 // Close the graph
243 // Close the graph
244 graphWidget->close();
244 helper.delayedCloseWidget(graphWidget);
245 }
245 }
246
246
247 tabWidget->createZone(variables, index);
247 tabWidget->createZone(variables, index);
248 }
248 }
249 else {
249 else {
250 // The graph is empty, create an empty zone and move the graph inside
250 // The graph is empty, create an empty zone and move the graph inside
251
251
252 auto parentZoneWidget = graphWidget->parentZoneWidget();
252 auto parentZoneWidget = graphWidget->parentZoneWidget();
253
253
254 parentDragDropContainer->layout()->removeWidget(graphWidget);
254 parentDragDropContainer->layout()->removeWidget(graphWidget);
255
255
256 auto zoneWidget = tabWidget->createEmptyZone(index);
256 auto zoneWidget = tabWidget->createEmptyZone(index);
257 zoneWidget->addGraph(graphWidget);
257 zoneWidget->addGraph(graphWidget);
258
258
259 // Close the old zone if it was the only graph inside
259 // Close the old zone if it was the only graph inside
260 if (nbGraph == 1) {
260 if (nbGraph == 1) {
261 parentZoneWidget->close();
261 helper.delayedCloseWidget(parentZoneWidget);
262 }
262 }
263 }
263 }
264 }
264 }
265
265
266 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
266 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
267 int index, VisualizationTabWidget *tabWidget)
267 int index, VisualizationTabWidget *tabWidget)
268 {
268 {
269 auto &helper = sqpApp->dragDropHelper();
269 auto &helper = sqpApp->dragDropHelper();
270
270
271 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
271 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
272 if (!zoneWidget) {
272 if (!zoneWidget) {
273 qCWarning(LOG_VisualizationZoneWidget())
273 qCWarning(LOG_VisualizationZoneWidget())
274 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
274 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
275 "found or invalid.");
275 "found or invalid.");
276 Q_ASSERT(false);
276 Q_ASSERT(false);
277 return;
277 return;
278 }
278 }
279
279
280 auto parentDragDropContainer
280 auto parentDragDropContainer
281 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
281 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
282 if (!parentDragDropContainer) {
282 if (!parentDragDropContainer) {
283 qCWarning(LOG_VisualizationZoneWidget())
283 qCWarning(LOG_VisualizationZoneWidget())
284 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
284 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
285 "the dropped zone is not found.");
285 "the dropped zone is not found.");
286 Q_ASSERT(false);
286 Q_ASSERT(false);
287 return;
287 return;
288 }
288 }
289
289
290 // Simple move of the zone, no variable operation associated
290 // Simple move of the zone, no variable operation associated
291 parentDragDropContainer->layout()->removeWidget(zoneWidget);
291 parentDragDropContainer->layout()->removeWidget(zoneWidget);
292 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
292 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
293 }
293 }
294
294
295 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
295 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
296 const QList<std::shared_ptr<Variable> > &variables, int index,
296 const QList<std::shared_ptr<Variable> > &variables, int index,
297 VisualizationTabWidget *tabWidget)
297 VisualizationTabWidget *tabWidget)
298 {
298 {
299 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
299 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
300 // compatible variable here
300 // compatible variable here
301 if (variables.count() > 1) {
301 if (variables.count() > 1) {
302 qCWarning(LOG_VisualizationZoneWidget())
302 qCWarning(LOG_VisualizationZoneWidget())
303 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
303 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
304 "aborted.");
304 "aborted.");
305 return;
305 return;
306 }
306 }
307
307
308 tabWidget->createZone(variables, index);
308 tabWidget->createZone(variables, index);
309 }
309 }
@@ -1,500 +1,500
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/VisualizationWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
8
8
9 #include "Common/MimeTypesDef.h"
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
10 #include "Common/VisualizationDef.h"
11
11
12 #include <Data/SqpRange.h>
12 #include <Data/SqpRange.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14 #include <Variable/Variable.h>
14 #include <Variable/Variable.h>
15 #include <Variable/VariableController.h>
15 #include <Variable/VariableController.h>
16
16
17 #include <Visualization/operations/FindVariableOperation.h>
17 #include <Visualization/operations/FindVariableOperation.h>
18
18
19 #include <DragAndDrop/DragDropHelper.h>
19 #include <DragAndDrop/DragDropHelper.h>
20 #include <QUuid>
20 #include <QUuid>
21 #include <SqpApplication.h>
21 #include <SqpApplication.h>
22 #include <cmath>
22 #include <cmath>
23
23
24 #include <QLayout>
24 #include <QLayout>
25
25
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27
27
28 namespace {
28 namespace {
29
29
30
30
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
32 /// the zone
32 /// the zone
33 QString defaultGraphName(const QLayout &layout)
33 QString defaultGraphName(const QLayout &layout)
34 {
34 {
35 auto count = 0;
35 auto count = 0;
36 for (auto i = 0; i < layout.count(); ++i) {
36 for (auto i = 0; i < layout.count(); ++i) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
38 count++;
38 count++;
39 }
39 }
40 }
40 }
41
41
42 return QObject::tr("Graph %1").arg(count + 1);
42 return QObject::tr("Graph %1").arg(count + 1);
43 }
43 }
44
44
45 /**
45 /**
46 * Applies a function to all graphs of the zone represented by its layout
46 * Applies a function to all graphs of the zone represented by its layout
47 * @param layout the layout that contains graphs
47 * @param layout the layout that contains graphs
48 * @param fun the function to apply to each graph
48 * @param fun the function to apply to each graph
49 */
49 */
50 template <typename Fun>
50 template <typename Fun>
51 void processGraphs(QLayout &layout, Fun fun)
51 void processGraphs(QLayout &layout, Fun fun)
52 {
52 {
53 for (auto i = 0; i < layout.count(); ++i) {
53 for (auto i = 0; i < layout.count(); ++i) {
54 if (auto item = layout.itemAt(i)) {
54 if (auto item = layout.itemAt(i)) {
55 if (auto visualizationGraphWidget
55 if (auto visualizationGraphWidget
56 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
56 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
57 fun(*visualizationGraphWidget);
57 fun(*visualizationGraphWidget);
58 }
58 }
59 }
59 }
60 }
60 }
61 }
61 }
62
62
63 } // namespace
63 } // namespace
64
64
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
66
66
67 explicit VisualizationZoneWidgetPrivate()
67 explicit VisualizationZoneWidgetPrivate()
68 : m_SynchronisationGroupId{QUuid::createUuid()},
68 : m_SynchronisationGroupId{QUuid::createUuid()},
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
70 {
70 {
71 }
71 }
72 QUuid m_SynchronisationGroupId;
72 QUuid m_SynchronisationGroupId;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
74
74
75 // Returns the first graph in the zone or nullptr if there is no graph inside
75 // Returns the first graph in the zone or nullptr if there is no graph inside
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
77 {
77 {
78 VisualizationGraphWidget *firstGraph = nullptr;
78 VisualizationGraphWidget *firstGraph = nullptr;
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
80 if (layout->count() > 0) {
80 if (layout->count() > 0) {
81 if (auto visualizationGraphWidget
81 if (auto visualizationGraphWidget
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
83 firstGraph = visualizationGraphWidget;
83 firstGraph = visualizationGraphWidget;
84 }
84 }
85 }
85 }
86
86
87 return firstGraph;
87 return firstGraph;
88 }
88 }
89
89
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
92 VisualizationZoneWidget *zoneWidget);
92 VisualizationZoneWidget *zoneWidget);
93 };
93 };
94
94
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
96 : VisualizationDragWidget{parent},
96 : VisualizationDragWidget{parent},
97 ui{new Ui::VisualizationZoneWidget},
97 ui{new Ui::VisualizationZoneWidget},
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
99 {
99 {
100 ui->setupUi(this);
100 ui->setupUi(this);
101
101
102 ui->zoneNameLabel->setText(name);
102 ui->zoneNameLabel->setText(name);
103
103
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
105 ui->dragDropContainer->addAcceptedMimeType(
105 ui->dragDropContainer->addAcceptedMimeType(
106 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
106 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
107 ui->dragDropContainer->addAcceptedMimeType(
107 ui->dragDropContainer->addAcceptedMimeType(
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
109 ui->dragDropContainer->addAcceptedMimeType(
109 ui->dragDropContainer->addAcceptedMimeType(
110 MIME_TYPE_TIME_RANGE, VisualizationDragDropContainer::DropBehavior::Merged);
110 MIME_TYPE_TIME_RANGE, VisualizationDragDropContainer::DropBehavior::Merged);
111 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
111 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
112 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
112 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
113 ui->dragDropContainer);
113 ui->dragDropContainer);
114 });
114 });
115
115
116 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
116 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
117 &VisualizationZoneWidget::dropMimeData);
117 &VisualizationZoneWidget::dropMimeData);
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
119 &VisualizationZoneWidget::dropMimeDataOnGraph);
119 &VisualizationZoneWidget::dropMimeDataOnGraph);
120
120
121 // 'Close' options : widget is deleted when closed
121 // 'Close' options : widget is deleted when closed
122 setAttribute(Qt::WA_DeleteOnClose);
122 setAttribute(Qt::WA_DeleteOnClose);
123 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
123 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
124 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
124 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
125
125
126 // Synchronisation id
126 // Synchronisation id
127 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
127 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
128 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
128 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
129 }
129 }
130
130
131 VisualizationZoneWidget::~VisualizationZoneWidget()
131 VisualizationZoneWidget::~VisualizationZoneWidget()
132 {
132 {
133 delete ui;
133 delete ui;
134 }
134 }
135
135
136 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
136 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
137 {
137 {
138 // Synchronize new graph with others in the zone
138 // Synchronize new graph with others in the zone
139 impl->m_Synchronizer->addGraph(*graphWidget);
139 impl->m_Synchronizer->addGraph(*graphWidget);
140
140
141 ui->dragDropContainer->addDragWidget(graphWidget);
141 ui->dragDropContainer->addDragWidget(graphWidget);
142 }
142 }
143
143
144 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
144 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
145 {
145 {
146 // Synchronize new graph with others in the zone
146 // Synchronize new graph with others in the zone
147 impl->m_Synchronizer->addGraph(*graphWidget);
147 impl->m_Synchronizer->addGraph(*graphWidget);
148
148
149 ui->dragDropContainer->insertDragWidget(index, graphWidget);
149 ui->dragDropContainer->insertDragWidget(index, graphWidget);
150 }
150 }
151
151
152 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
152 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
153 {
153 {
154 return createGraph(variable, -1);
154 return createGraph(variable, -1);
155 }
155 }
156
156
157 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
157 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
158 int index)
158 int index)
159 {
159 {
160 auto graphWidget
160 auto graphWidget
161 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
161 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
162
162
163
163
164 // Set graph properties
164 // Set graph properties
165 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
165 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
166 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
166 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
167
167
168
168
169 // Lambda to synchronize zone widget
169 // Lambda to synchronize zone widget
170 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
170 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
171 const SqpRange &oldGraphRange) {
171 const SqpRange &oldGraphRange) {
172
172
173 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
173 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
174 auto frameLayout = ui->dragDropContainer->layout();
174 auto frameLayout = ui->dragDropContainer->layout();
175 for (auto i = 0; i < frameLayout->count(); ++i) {
175 for (auto i = 0; i < frameLayout->count(); ++i) {
176 auto graphChild
176 auto graphChild
177 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
177 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
178 if (graphChild && (graphChild != graphWidget)) {
178 if (graphChild && (graphChild != graphWidget)) {
179
179
180 auto graphChildRange = graphChild->graphRange();
180 auto graphChildRange = graphChild->graphRange();
181 switch (zoomType) {
181 switch (zoomType) {
182 case AcquisitionZoomType::ZoomIn: {
182 case AcquisitionZoomType::ZoomIn: {
183 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
183 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
184 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
184 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
185 graphChildRange.m_TStart += deltaLeft;
185 graphChildRange.m_TStart += deltaLeft;
186 graphChildRange.m_TEnd -= deltaRight;
186 graphChildRange.m_TEnd -= deltaRight;
187 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
187 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
188 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
188 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
189 << deltaLeft;
189 << deltaLeft;
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
191 << deltaRight;
191 << deltaRight;
192 qCDebug(LOG_VisualizationZoneWidget())
192 qCDebug(LOG_VisualizationZoneWidget())
193 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
193 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
194
194
195 break;
195 break;
196 }
196 }
197
197
198 case AcquisitionZoomType::ZoomOut: {
198 case AcquisitionZoomType::ZoomOut: {
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
200 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
200 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
201 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
201 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
203 << deltaLeft;
203 << deltaLeft;
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
205 << deltaRight;
205 << deltaRight;
206 qCDebug(LOG_VisualizationZoneWidget())
206 qCDebug(LOG_VisualizationZoneWidget())
207 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
207 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
208 graphChildRange.m_TStart -= deltaLeft;
208 graphChildRange.m_TStart -= deltaLeft;
209 graphChildRange.m_TEnd += deltaRight;
209 graphChildRange.m_TEnd += deltaRight;
210 break;
210 break;
211 }
211 }
212 case AcquisitionZoomType::PanRight: {
212 case AcquisitionZoomType::PanRight: {
213 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
213 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
214 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
214 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
215 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
215 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
216 graphChildRange.m_TStart += deltaLeft;
216 graphChildRange.m_TStart += deltaLeft;
217 graphChildRange.m_TEnd += deltaRight;
217 graphChildRange.m_TEnd += deltaRight;
218 qCDebug(LOG_VisualizationZoneWidget())
218 qCDebug(LOG_VisualizationZoneWidget())
219 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
219 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
220 break;
220 break;
221 }
221 }
222 case AcquisitionZoomType::PanLeft: {
222 case AcquisitionZoomType::PanLeft: {
223 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
223 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
224 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
224 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
225 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
225 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
226 graphChildRange.m_TStart -= deltaLeft;
226 graphChildRange.m_TStart -= deltaLeft;
227 graphChildRange.m_TEnd -= deltaRight;
227 graphChildRange.m_TEnd -= deltaRight;
228 break;
228 break;
229 }
229 }
230 case AcquisitionZoomType::Unknown: {
230 case AcquisitionZoomType::Unknown: {
231 qCDebug(LOG_VisualizationZoneWidget())
231 qCDebug(LOG_VisualizationZoneWidget())
232 << tr("Impossible to synchronize: zoom type unknown");
232 << tr("Impossible to synchronize: zoom type unknown");
233 break;
233 break;
234 }
234 }
235 default:
235 default:
236 qCCritical(LOG_VisualizationZoneWidget())
236 qCCritical(LOG_VisualizationZoneWidget())
237 << tr("Impossible to synchronize: zoom type not take into account");
237 << tr("Impossible to synchronize: zoom type not take into account");
238 // No action
238 // No action
239 break;
239 break;
240 }
240 }
241 graphChild->enableAcquisition(false);
241 graphChild->enableAcquisition(false);
242 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
242 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
243 << graphChild->graphRange();
243 << graphChild->graphRange();
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
245 << graphChildRange;
245 << graphChildRange;
246 qCDebug(LOG_VisualizationZoneWidget())
246 qCDebug(LOG_VisualizationZoneWidget())
247 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
247 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
248 graphChild->setGraphRange(graphChildRange);
248 graphChild->setGraphRange(graphChildRange);
249 graphChild->enableAcquisition(true);
249 graphChild->enableAcquisition(true);
250 }
250 }
251 }
251 }
252 };
252 };
253
253
254 // connection for synchronization
254 // connection for synchronization
255 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
255 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
256 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
256 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
257 &VisualizationZoneWidget::onVariableAdded);
257 &VisualizationZoneWidget::onVariableAdded);
258 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
258 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
259 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
259 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
260
260
261 auto range = SqpRange{};
261 auto range = SqpRange{};
262 if (auto firstGraph = impl->firstGraph(this)) {
262 if (auto firstGraph = impl->firstGraph(this)) {
263 // Case of a new graph in a existant zone
263 // Case of a new graph in a existant zone
264 range = firstGraph->graphRange();
264 range = firstGraph->graphRange();
265 }
265 }
266 else {
266 else {
267 // Case of a new graph as the first of the zone
267 // Case of a new graph as the first of the zone
268 range = variable->range();
268 range = variable->range();
269 }
269 }
270
270
271 this->insertGraph(index, graphWidget);
271 this->insertGraph(index, graphWidget);
272
272
273 graphWidget->addVariable(variable, range);
273 graphWidget->addVariable(variable, range);
274 graphWidget->setYRange(variable);
274 graphWidget->setYRange(variable);
275
275
276 return graphWidget;
276 return graphWidget;
277 }
277 }
278
278
279 VisualizationGraphWidget *
279 VisualizationGraphWidget *
280 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
280 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
281 {
281 {
282 if (variables.isEmpty()) {
282 if (variables.isEmpty()) {
283 return nullptr;
283 return nullptr;
284 }
284 }
285
285
286 auto graphWidget = createGraph(variables.first(), index);
286 auto graphWidget = createGraph(variables.first(), index);
287 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
287 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
288 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
288 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
289 }
289 }
290
290
291 return graphWidget;
291 return graphWidget;
292 }
292 }
293
293
294 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
294 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
295 {
295 {
296 if (visitor) {
296 if (visitor) {
297 visitor->visitEnter(this);
297 visitor->visitEnter(this);
298
298
299 // Apply visitor to graph children: widgets different from graphs are not visited (no
299 // Apply visitor to graph children: widgets different from graphs are not visited (no
300 // action)
300 // action)
301 processGraphs(
301 processGraphs(
302 *ui->dragDropContainer->layout(),
302 *ui->dragDropContainer->layout(),
303 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
303 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
304
304
305 visitor->visitLeave(this);
305 visitor->visitLeave(this);
306 }
306 }
307 else {
307 else {
308 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
308 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
309 }
309 }
310 }
310 }
311
311
312 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
312 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
313 {
313 {
314 // A tab can always accomodate a variable
314 // A tab can always accomodate a variable
315 Q_UNUSED(variable);
315 Q_UNUSED(variable);
316 return true;
316 return true;
317 }
317 }
318
318
319 bool VisualizationZoneWidget::contains(const Variable &variable) const
319 bool VisualizationZoneWidget::contains(const Variable &variable) const
320 {
320 {
321 Q_UNUSED(variable);
321 Q_UNUSED(variable);
322 return false;
322 return false;
323 }
323 }
324
324
325 QString VisualizationZoneWidget::name() const
325 QString VisualizationZoneWidget::name() const
326 {
326 {
327 return ui->zoneNameLabel->text();
327 return ui->zoneNameLabel->text();
328 }
328 }
329
329
330 QMimeData *VisualizationZoneWidget::mimeData() const
330 QMimeData *VisualizationZoneWidget::mimeData() const
331 {
331 {
332 auto mimeData = new QMimeData;
332 auto mimeData = new QMimeData;
333 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
333 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
334
334
335 return mimeData;
335 return mimeData;
336 }
336 }
337
337
338 bool VisualizationZoneWidget::isDragAllowed() const
338 bool VisualizationZoneWidget::isDragAllowed() const
339 {
339 {
340 return true;
340 return true;
341 }
341 }
342
342
343 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
343 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
344 {
344 {
345 // Closes graphs in the zone
345 // Closes graphs in the zone
346 processGraphs(*ui->dragDropContainer->layout(),
346 processGraphs(*ui->dragDropContainer->layout(),
347 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
347 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
348
348
349 // Delete synchronization group from variable controller
349 // Delete synchronization group from variable controller
350 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
350 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
351 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
351 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
352
352
353 QWidget::closeEvent(event);
353 QWidget::closeEvent(event);
354 }
354 }
355
355
356 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
356 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
357 {
357 {
358 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
358 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
359 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
359 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
360 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
360 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
361 }
361 }
362
362
363 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
363 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
364 {
364 {
365 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
365 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
366 Q_ARG(std::shared_ptr<Variable>, variable),
366 Q_ARG(std::shared_ptr<Variable>, variable),
367 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
367 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
368 }
368 }
369
369
370 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
370 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
371 {
371 {
372 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
372 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
373 impl->dropGraph(index, this);
373 impl->dropGraph(index, this);
374 }
374 }
375 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
375 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
376 auto variables = sqpApp->variableController().variablesForMimeData(
376 auto variables = sqpApp->variableController().variablesForMimeData(
377 mimeData->data(MIME_TYPE_VARIABLE_LIST));
377 mimeData->data(MIME_TYPE_VARIABLE_LIST));
378 impl->dropVariables(variables, index, this);
378 impl->dropVariables(variables, index, this);
379 }
379 }
380 else {
380 else {
381 qCWarning(LOG_VisualizationZoneWidget())
381 qCWarning(LOG_VisualizationZoneWidget())
382 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
382 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
383 }
383 }
384 }
384 }
385
385
386 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
386 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
387 const QMimeData *mimeData)
387 const QMimeData *mimeData)
388 {
388 {
389 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
389 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
390 if (!graphWidget) {
390 if (!graphWidget) {
391 qCWarning(LOG_VisualizationZoneWidget())
391 qCWarning(LOG_VisualizationZoneWidget())
392 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
392 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
393 "drop aborted");
393 "drop aborted");
394 Q_ASSERT(false);
394 Q_ASSERT(false);
395 return;
395 return;
396 }
396 }
397
397
398 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
398 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
399 auto variables = sqpApp->variableController().variablesForMimeData(
399 auto variables = sqpApp->variableController().variablesForMimeData(
400 mimeData->data(MIME_TYPE_VARIABLE_LIST));
400 mimeData->data(MIME_TYPE_VARIABLE_LIST));
401 for (const auto &var : variables) {
401 for (const auto &var : variables) {
402 graphWidget->addVariable(var, graphWidget->graphRange());
402 graphWidget->addVariable(var, graphWidget->graphRange());
403 }
403 }
404 }
404 }
405 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
405 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
406 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
406 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
407 graphWidget->setGraphRange(range);
407 graphWidget->setGraphRange(range);
408 }
408 }
409 else {
409 else {
410 qCWarning(LOG_VisualizationZoneWidget())
410 qCWarning(LOG_VisualizationZoneWidget())
411 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
411 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
412 }
412 }
413 }
413 }
414
414
415 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
415 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
416 int index, VisualizationZoneWidget *zoneWidget)
416 int index, VisualizationZoneWidget *zoneWidget)
417 {
417 {
418 auto &helper = sqpApp->dragDropHelper();
418 auto &helper = sqpApp->dragDropHelper();
419
419
420 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
420 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
421 if (!graphWidget) {
421 if (!graphWidget) {
422 qCWarning(LOG_VisualizationZoneWidget())
422 qCWarning(LOG_VisualizationZoneWidget())
423 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
423 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
424 "found or invalid.");
424 "found or invalid.");
425 Q_ASSERT(false);
425 Q_ASSERT(false);
426 return;
426 return;
427 }
427 }
428
428
429 auto parentDragDropContainer
429 auto parentDragDropContainer
430 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
430 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
431 if (!parentDragDropContainer) {
431 if (!parentDragDropContainer) {
432 qCWarning(LOG_VisualizationZoneWidget())
432 qCWarning(LOG_VisualizationZoneWidget())
433 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
433 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
434 "the dropped graph is not found.");
434 "the dropped graph is not found.");
435 Q_ASSERT(false);
435 Q_ASSERT(false);
436 return;
436 return;
437 }
437 }
438
438
439 const auto &variables = graphWidget->variables();
439 const auto &variables = graphWidget->variables();
440
440
441 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
441 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
442 // The drop didn't occur in the same zone
442 // The drop didn't occur in the same zone
443
443
444 // Abort the requests for the variables (if any)
444 // Abort the requests for the variables (if any)
445 // Commented, because it's not sure if it's needed or not
445 // Commented, because it's not sure if it's needed or not
446 // for (const auto& var : variables)
446 // for (const auto& var : variables)
447 //{
447 //{
448 // sqpApp->variableController().onAbortProgressRequested(var);
448 // sqpApp->variableController().onAbortProgressRequested(var);
449 //}
449 //}
450
450
451 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
451 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
452 auto nbGraph = parentDragDropContainer->countDragWidget();
452 auto nbGraph = parentDragDropContainer->countDragWidget();
453 if (nbGraph == 1) {
453 if (nbGraph == 1) {
454 // This is the only graph in the previous zone, close the zone
454 // This is the only graph in the previous zone, close the zone
455 previousParentZoneWidget->close();
455 helper.delayedCloseWidget(previousParentZoneWidget);
456 }
456 }
457 else {
457 else {
458 // Close the graph
458 // Close the graph
459 graphWidget->close();
459 helper.delayedCloseWidget(graphWidget);
460 }
460 }
461
461
462 // Creates the new graph in the zone
462 // Creates the new graph in the zone
463 zoneWidget->createGraph(variables, index);
463 zoneWidget->createGraph(variables, index);
464 }
464 }
465 else {
465 else {
466 // The drop occurred in the same zone or the graph is empty
466 // The drop occurred in the same zone or the graph is empty
467 // Simple move of the graph, no variable operation associated
467 // Simple move of the graph, no variable operation associated
468 parentDragDropContainer->layout()->removeWidget(graphWidget);
468 parentDragDropContainer->layout()->removeWidget(graphWidget);
469
469
470 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
470 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
471 // The graph is empty and dropped in a different zone.
471 // The graph is empty and dropped in a different zone.
472 // Take the range of the first graph in the zone (if existing).
472 // Take the range of the first graph in the zone (if existing).
473 auto layout = zoneWidget->ui->dragDropContainer->layout();
473 auto layout = zoneWidget->ui->dragDropContainer->layout();
474 if (layout->count() > 0) {
474 if (layout->count() > 0) {
475 if (auto visualizationGraphWidget
475 if (auto visualizationGraphWidget
476 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
476 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
477 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
477 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
478 }
478 }
479 }
479 }
480 }
480 }
481
481
482 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
482 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
483 }
483 }
484 }
484 }
485
485
486 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
486 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
487 const QList<std::shared_ptr<Variable> > &variables, int index,
487 const QList<std::shared_ptr<Variable> > &variables, int index,
488 VisualizationZoneWidget *zoneWidget)
488 VisualizationZoneWidget *zoneWidget)
489 {
489 {
490 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
490 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
491 // compatible variable here
491 // compatible variable here
492 if (variables.count() > 1) {
492 if (variables.count() > 1) {
493 qCWarning(LOG_VisualizationZoneWidget())
493 qCWarning(LOG_VisualizationZoneWidget())
494 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
494 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
495 "aborted.");
495 "aborted.");
496 return;
496 return;
497 }
497 }
498
498
499 zoneWidget->createGraph(variables, index);
499 zoneWidget->createGraph(variables, index);
500 }
500 }
General Comments 0
You need to be logged in to leave comments. Login now