##// END OF EJS Templates
Handle the previous prohibition for drag and drop
Alexandre Leroux -
r1064:1b1ede101ec5
parent child
Show More
@@ -1,57 +1,61
1 #ifndef SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
1 #ifndef SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QFrame>
5 #include <QFrame>
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QMimeData>
7 #include <QMimeData>
8 #include <QVBoxLayout>
8 #include <QVBoxLayout>
9
9
10 #include <functional>
10 #include <functional>
11
11
12 #include <DragAndDrop/DragDropHelper.h>
12 #include <DragAndDrop/DragDropHelper.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
15
15
16 class VisualizationDragWidget;
16 class VisualizationDragWidget;
17
17
18 class VisualizationDragDropContainer : public QFrame {
18 class VisualizationDragDropContainer : public QFrame {
19 Q_OBJECT
19 Q_OBJECT
20
20
21 signals:
21 signals:
22 void dropOccuredInContainer(int dropIndex, const QMimeData *mimeData);
22 void dropOccuredInContainer(int dropIndex, const QMimeData *mimeData);
23 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
23 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
24
24
25 public:
25 public:
26 enum class DropBehavior { Inserted, Merged, InsertedAndMerged, Forbidden };
26 enum class DropBehavior { Inserted, Merged, InsertedAndMerged, Forbidden };
27 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
27 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
28 using AcceptDragWidgetFunction
29 = std::function<bool(const VisualizationDragWidget *dragWidget, const QMimeData *mimeData)>;
28
30
29 VisualizationDragDropContainer(QWidget *parent = nullptr);
31 VisualizationDragDropContainer(QWidget *parent = nullptr);
30
32
31 void addDragWidget(VisualizationDragWidget *dragWidget);
33 void addDragWidget(VisualizationDragWidget *dragWidget);
32 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
34 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
33
35
34 void setMimeType(const QString &mimeType, DropBehavior behavior);
36 void setMimeType(const QString &mimeType, DropBehavior behavior);
35
37
36 int countDragWidget() const;
38 int countDragWidget() const;
37
39
38 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
40 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
39
41
42 void setAcceptDragWidgetFunction(AcceptDragWidgetFunction fun);
43
40 void setPlaceHolderType(DragDropHelper::PlaceHolderType type,
44 void setPlaceHolderType(DragDropHelper::PlaceHolderType type,
41 const QString &placeHolderText = QString());
45 const QString &placeHolderText = QString());
42
46
43 protected:
47 protected:
44 void dragEnterEvent(QDragEnterEvent *event);
48 void dragEnterEvent(QDragEnterEvent *event);
45 void dragLeaveEvent(QDragLeaveEvent *event);
49 void dragLeaveEvent(QDragLeaveEvent *event);
46 void dragMoveEvent(QDragMoveEvent *event);
50 void dragMoveEvent(QDragMoveEvent *event);
47 void dropEvent(QDropEvent *event);
51 void dropEvent(QDropEvent *event);
48
52
49 private:
53 private:
50 class VisualizationDragDropContainerPrivate;
54 class VisualizationDragDropContainerPrivate;
51 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
55 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
52
56
53 private slots:
57 private slots:
54 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
58 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
55 };
59 };
56
60
57 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
61 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
@@ -1,473 +1,492
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 auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels
17 auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels
18
18
19 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
19 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
20
20
21 QVBoxLayout *m_Layout;
21 QVBoxLayout *m_Layout;
22 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
22 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
23 QString m_PlaceHolderText;
23 QString m_PlaceHolderText;
24 DragDropHelper::PlaceHolderType m_PlaceHolderType;
24 DragDropHelper::PlaceHolderType m_PlaceHolderType;
25
25
26 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
26 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
27 = [](auto mimeData) { return true; };
27 = [](auto mimeData) { return true; };
28 VisualizationDragDropContainer::AcceptDragWidgetFunction m_AcceptDragWidgetFun
29 = [](auto dragWidget, auto mimeData) { return true; };
28
30
29 int m_MinContainerHeight = 0;
31 int m_MinContainerHeight = 0;
30
32
31 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
33 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
32 : m_PlaceHolderType(DragDropHelper::PlaceHolderType::Graph)
34 : m_PlaceHolderType(DragDropHelper::PlaceHolderType::Graph)
33 {
35 {
34 m_Layout = new QVBoxLayout(widget);
36 m_Layout = new QVBoxLayout(widget);
35 m_Layout->setContentsMargins(0, 0, 0, 0);
37 m_Layout->setContentsMargins(0, 0, 0, 0);
36 }
38 }
37
39
38 bool acceptMimeData(const QMimeData *data) const
40 bool acceptMimeData(const QMimeData *data) const
39 {
41 {
40 auto accepted = false;
42 auto accepted = false;
41 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
43 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
42 ++it) {
44 ++it) {
43 const auto &type = it.key();
45 const auto &type = it.key();
44 const auto &behavior = it.value();
46 const auto &behavior = it.value();
45
47
46 if (data->hasFormat(type)) {
48 if (data->hasFormat(type)) {
47 if (behavior != DropBehavior::Forbidden) {
49 if (behavior != DropBehavior::Forbidden) {
48 accepted = true;
50 accepted = true;
49 }
51 }
50 else {
52 else {
51 accepted = false;
53 accepted = false;
52 break;
54 break;
53 }
55 }
54 }
56 }
55 }
57 }
56
58
57 if (accepted) {
59 if (accepted) {
58 accepted = m_AcceptMimeDataFun(data);
60 accepted = m_AcceptMimeDataFun(data);
59 }
61 }
60
62
61 return accepted;
63 return accepted;
62 }
64 }
63
65
64 bool allowMergeForMimeData(const QMimeData *data) const
66 bool allowMergeForMimeData(const QMimeData *data) const
65 {
67 {
66 auto result = false;
68 auto result = false;
67 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
69 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
68 ++it) {
70 ++it) {
69
71
70 if (data->hasFormat(it.key())
72 if (data->hasFormat(it.key())
71 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
73 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
72 || it.value()
74 || it.value()
73 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
75 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
74 result = true;
76 result = true;
75 }
77 }
76 else if (data->hasFormat(it.key())
78 else if (data->hasFormat(it.key())
77 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
79 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
78 // Merge is forbidden if the mime data contain an acceptable type which cannot be
80 // Merge is forbidden if the mime data contain an acceptable type which cannot be
79 // merged
81 // merged
80 result = false;
82 result = false;
81 break;
83 break;
82 }
84 }
83 }
85 }
84
86
85 return result;
87 return result;
86 }
88 }
87
89
88 bool allowInsertForMimeData(const QMimeData *data) const
90 bool allowInsertForMimeData(const QMimeData *data) const
89 {
91 {
90 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
92 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
91 ++it) {
93 ++it) {
92 if (data->hasFormat(it.key())
94 if (data->hasFormat(it.key())
93 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
95 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
94 || it.value()
96 || it.value()
95 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
97 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
96 return true;
98 return true;
97 }
99 }
98 }
100 }
99
101
100 return false;
102 return false;
101 }
103 }
102
104
103 bool hasPlaceHolder() const
105 bool hasPlaceHolder() const
104 {
106 {
105 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
107 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
106 }
108 }
107
109
108 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
110 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
109 {
111 {
110 VisualizationDragWidget *dragWidget = nullptr;
112 VisualizationDragWidget *dragWidget = nullptr;
111
113
112 for (auto child : parent->children()) {
114 for (auto child : parent->children()) {
113 auto widget = qobject_cast<VisualizationDragWidget *>(child);
115 auto widget = qobject_cast<VisualizationDragWidget *>(child);
114 if (widget && widget->isVisible()) {
116 if (widget && widget->isVisible()) {
115 if (widget->frameGeometry().contains(pos)) {
117 if (widget->frameGeometry().contains(pos)) {
116 dragWidget = widget;
118 dragWidget = widget;
117 break;
119 break;
118 }
120 }
119 }
121 }
120 }
122 }
121
123
122 return dragWidget;
124 return dragWidget;
123 }
125 }
124
126
125 bool cursorIsInContainer(QWidget *container) const
127 bool cursorIsInContainer(QWidget *container) const
126 {
128 {
127 auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos());
129 auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos());
128 return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container
130 return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container
129 && sqpApp->dragDropHelper().placeHolder().isAncestorOf(widgetUnderMouse);
131 && sqpApp->dragDropHelper().placeHolder().isAncestorOf(widgetUnderMouse);
130 }
132 }
131
133
132 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
134 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
133 {
135 {
134 auto nbGraph = 0;
136 auto nbGraph = 0;
135 for (auto child : parent->children()) {
137 for (auto child : parent->children()) {
136 if (qobject_cast<VisualizationDragWidget *>(child)) {
138 if (qobject_cast<VisualizationDragWidget *>(child)) {
137 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
139 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
138 nbGraph += 1;
140 nbGraph += 1;
139 }
141 }
140 }
142 }
141 }
143 }
142
144
143 return nbGraph;
145 return nbGraph;
144 }
146 }
145
147
146 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
148 bool findPlaceHolderPosition(const QPoint &pos, const QMimeData *mimeData, bool canInsert,
147 const VisualizationDragDropContainer *container);
149 bool canMerge, const VisualizationDragDropContainer *container);
148 };
150 };
149
151
150 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
152 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
151 : QFrame{parent},
153 : QFrame{parent},
152 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
154 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
153 {
155 {
154 setAcceptDrops(true);
156 setAcceptDrops(true);
155 }
157 }
156
158
157 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
159 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
158 {
160 {
159 impl->m_Layout->addWidget(dragWidget);
161 impl->m_Layout->addWidget(dragWidget);
160 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
162 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
161 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
163 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
162 &VisualizationDragDropContainer::startDrag);
164 &VisualizationDragDropContainer::startDrag);
163 }
165 }
164
166
165 void VisualizationDragDropContainer::insertDragWidget(int index,
167 void VisualizationDragDropContainer::insertDragWidget(int index,
166 VisualizationDragWidget *dragWidget)
168 VisualizationDragWidget *dragWidget)
167 {
169 {
168 impl->m_Layout->insertWidget(index, dragWidget);
170 impl->m_Layout->insertWidget(index, dragWidget);
169 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
171 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
170 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
172 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
171 &VisualizationDragDropContainer::startDrag);
173 &VisualizationDragDropContainer::startDrag);
172 }
174 }
173
175
174 void VisualizationDragDropContainer::setMimeType(
176 void VisualizationDragDropContainer::setMimeType(
175 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
177 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
176 {
178 {
177 impl->m_AcceptedMimeTypes[mimeType] = behavior;
179 impl->m_AcceptedMimeTypes[mimeType] = behavior;
178 }
180 }
179
181
180 int VisualizationDragDropContainer::countDragWidget() const
182 int VisualizationDragDropContainer::countDragWidget() const
181 {
183 {
182 return impl->countDragWidget(this);
184 return impl->countDragWidget(this);
183 }
185 }
184
186
185 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
187 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
186 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
188 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
187 {
189 {
188 impl->m_AcceptMimeDataFun = fun;
190 impl->m_AcceptMimeDataFun = fun;
189 }
191 }
190
192
193 void VisualizationDragDropContainer::setAcceptDragWidgetFunction(
194 VisualizationDragDropContainer::AcceptDragWidgetFunction fun)
195 {
196 impl->m_AcceptDragWidgetFun = fun;
197 }
198
191 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
199 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
192 const QString &placeHolderText)
200 const QString &placeHolderText)
193 {
201 {
194 impl->m_PlaceHolderType = type;
202 impl->m_PlaceHolderType = type;
195 impl->m_PlaceHolderText = placeHolderText;
203 impl->m_PlaceHolderText = placeHolderText;
196 }
204 }
197
205
198 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
206 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
199 const QPoint &dragPosition)
207 const QPoint &dragPosition)
200 {
208 {
201 auto &helper = sqpApp->dragDropHelper();
209 auto &helper = sqpApp->dragDropHelper();
202 helper.resetDragAndDrop();
210 helper.resetDragAndDrop();
203
211
204 // Note: The management of the drag object is done by Qt
212 // Note: The management of the drag object is done by Qt
205 auto drag = new QDrag{dragWidget};
213 auto drag = new QDrag{dragWidget};
206
214
207 auto mimeData = dragWidget->mimeData();
215 auto mimeData = dragWidget->mimeData();
208 drag->setMimeData(mimeData);
216 drag->setMimeData(mimeData);
209
217
210 auto pixmap = QPixmap(dragWidget->size());
218 auto pixmap = QPixmap(dragWidget->size());
211 dragWidget->render(&pixmap);
219 dragWidget->render(&pixmap);
212 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
220 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
213 Qt::KeepAspectRatio, Qt::SmoothTransformation));
221 Qt::KeepAspectRatio, Qt::SmoothTransformation));
214
222
215 auto image = pixmap.toImage();
223 auto image = pixmap.toImage();
216 mimeData->setImageData(image);
224 mimeData->setImageData(image);
217 mimeData->setUrls({helper.imageTemporaryUrl(image)});
225 mimeData->setUrls({helper.imageTemporaryUrl(image)});
218
226
219 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
227 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
220 helper.setCurrentDragWidget(dragWidget);
228 helper.setCurrentDragWidget(dragWidget);
221
229
222 if (impl->cursorIsInContainer(this)) {
230 if (impl->cursorIsInContainer(this)) {
223 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
231 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
224 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
232 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
225 impl->m_PlaceHolderText);
233 impl->m_PlaceHolderText);
226 dragWidget->setVisible(false);
234 dragWidget->setVisible(false);
227 }
235 }
228 else {
236 else {
229 // The drag starts directly outside the drop zone
237 // The drag starts directly outside the drop zone
230 // do not add the placeHolder
238 // do not add the placeHolder
231 }
239 }
232
240
233 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
241 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
234
242
235 helper.doCloseWidgets();
243 helper.doCloseWidgets();
236 }
244 }
237 else {
245 else {
238 qCWarning(LOG_VisualizationDragDropContainer())
246 qCWarning(LOG_VisualizationDragDropContainer())
239 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
247 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
240 "VisualizationDragWidget is not found in this container.");
248 "VisualizationDragWidget is not found in this container.");
241 }
249 }
242 }
250 }
243
251
244 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
252 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
245 {
253 {
246 if (impl->acceptMimeData(event->mimeData())) {
254 if (impl->acceptMimeData(event->mimeData())) {
247 event->acceptProposedAction();
255 event->acceptProposedAction();
248
256
249 auto &helper = sqpApp->dragDropHelper();
257 auto &helper = sqpApp->dragDropHelper();
250
258
251 if (!impl->hasPlaceHolder()) {
259 if (!impl->hasPlaceHolder()) {
252 auto dragWidget = helper.getCurrentDragWidget();
260 auto dragWidget = helper.getCurrentDragWidget();
253
261
254 if (dragWidget) {
262 if (dragWidget) {
255 // If the drag&drop is internal to the visualization, entering the container hide
263 // If the drag&drop is internal to the visualization, entering the container hide
256 // the dragWidget which was made visible by the dragLeaveEvent
264 // the dragWidget which was made visible by the dragLeaveEvent
257 auto parentWidget
265 auto parentWidget
258 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
266 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
259 if (parentWidget) {
267 if (parentWidget) {
260 dragWidget->setVisible(false);
268 dragWidget->setVisible(false);
261 }
269 }
262 }
270 }
263
271
264 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
272 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
265 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
273 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
266 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
274 if (!impl->findPlaceHolderPosition(event->pos(), event->mimeData(), canInsert, canMerge,
275 this)) {
276 event->ignore();
277 }
267 }
278 }
268 else {
279 else {
269 // do nothing
280 // do nothing
270 }
281 }
271 }
282 }
272 else {
283 else {
273 event->ignore();
284 event->ignore();
274 }
285 }
275
286
276 QWidget::dragEnterEvent(event);
287 QWidget::dragEnterEvent(event);
277 }
288 }
278
289
279 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
290 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
280 {
291 {
281 Q_UNUSED(event);
292 Q_UNUSED(event);
282
293
283 auto &helper = sqpApp->dragDropHelper();
294 auto &helper = sqpApp->dragDropHelper();
284
295
285 if (!impl->cursorIsInContainer(this)) {
296 if (!impl->cursorIsInContainer(this)) {
286 helper.removePlaceHolder();
297 helper.removePlaceHolder();
287 helper.setHightlightedDragWidget(nullptr);
298 helper.setHightlightedDragWidget(nullptr);
288 impl->m_MinContainerHeight = 0;
299 impl->m_MinContainerHeight = 0;
289
300
290 auto dragWidget = helper.getCurrentDragWidget();
301 auto dragWidget = helper.getCurrentDragWidget();
291 if (dragWidget) {
302 if (dragWidget) {
292 // dragWidget has a value only if the drag is started from the visualization
303 // dragWidget has a value only if the drag is started from the visualization
293 // In that case, shows the drag widget at its original place
304 // In that case, shows the drag widget at its original place
294 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
305 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
295 // drop zone (It is not possible to catch a drop event outside of the application)
306 // drop zone (It is not possible to catch a drop event outside of the application)
296
307
297 if (dragWidget) {
308 if (dragWidget) {
298 dragWidget->setVisible(true);
309 dragWidget->setVisible(true);
299 }
310 }
300 }
311 }
301 }
312 }
302 else {
313 else {
303 // Leave event probably received for a child widget.
314 // Leave event probably received for a child widget.
304 // Do nothing.
315 // Do nothing.
305 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
316 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
306 }
317 }
307
318
308 QWidget::dragLeaveEvent(event);
319 QWidget::dragLeaveEvent(event);
309 }
320 }
310
321
311 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
322 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
312 {
323 {
313 if (impl->acceptMimeData(event->mimeData())) {
324 if (impl->acceptMimeData(event->mimeData())) {
314 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
325 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
315 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
326 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
316 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
327 impl->findPlaceHolderPosition(event->pos(), event->mimeData(), canInsert, canMerge, this);
317 }
328 }
318 else {
329 else {
319 event->ignore();
330 event->ignore();
320 }
331 }
321
332
322 QWidget::dragMoveEvent(event);
333 QWidget::dragMoveEvent(event);
323 }
334 }
324
335
325 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
336 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
326 {
337 {
327 auto &helper = sqpApp->dragDropHelper();
338 auto &helper = sqpApp->dragDropHelper();
328
339
329 if (impl->acceptMimeData(event->mimeData())) {
340 if (impl->acceptMimeData(event->mimeData())) {
330 auto dragWidget = helper.getCurrentDragWidget();
341 auto dragWidget = helper.getCurrentDragWidget();
331 if (impl->hasPlaceHolder()) {
342 if (impl->hasPlaceHolder()) {
332 // drop where the placeHolder is located
343 // drop where the placeHolder is located
333
344
334 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
345 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
335 if (canInsert) {
346 if (canInsert) {
336 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
347 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
337
348
338 if (dragWidget) {
349 if (dragWidget) {
339 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
350 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
340 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
351 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
341 // Correction of the index if the drop occurs in the same container
352 // Correction of the index if the drop occurs in the same container
342 // and if the drag is started from the visualization (in that case, the
353 // and if the drag is started from the visualization (in that case, the
343 // dragWidget is hidden)
354 // dragWidget is hidden)
344 droppedIndex -= 1;
355 droppedIndex -= 1;
345 }
356 }
346
357
347 dragWidget->setVisible(true);
358 dragWidget->setVisible(true);
348 }
359 }
349
360
350 event->acceptProposedAction();
361 event->acceptProposedAction();
351
362
352 helper.removePlaceHolder();
363 helper.removePlaceHolder();
353
364
354 emit dropOccuredInContainer(droppedIndex, event->mimeData());
365 emit dropOccuredInContainer(droppedIndex, event->mimeData());
355 }
366 }
356 else {
367 else {
357 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
368 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
358 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
369 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
359 "the insertion is forbidden.");
370 "the insertion is forbidden.");
360 Q_ASSERT(false);
371 Q_ASSERT(false);
361 }
372 }
362 }
373 }
363 else if (helper.getHightlightedDragWidget()) {
374 else if (helper.getHightlightedDragWidget()) {
364 // drop on the highlighted widget
375 // drop on the highlighted widget
365
376
366 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
377 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
367 if (canMerge) {
378 if (canMerge) {
368 event->acceptProposedAction();
379 event->acceptProposedAction();
369 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
380 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
370 }
381 }
371 else {
382 else {
372 qCWarning(LOG_VisualizationDragDropContainer())
383 qCWarning(LOG_VisualizationDragDropContainer())
373 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
384 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
374 "the merge is forbidden.");
385 "the merge is forbidden.");
375 Q_ASSERT(false);
386 Q_ASSERT(false);
376 }
387 }
377 }
388 }
378 }
389 }
379 else {
390 else {
380 event->ignore();
391 event->ignore();
381 }
392 }
382
393
383 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
394 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
384 impl->m_MinContainerHeight = 0;
395 impl->m_MinContainerHeight = 0;
385
396
386 QWidget::dropEvent(event);
397 QWidget::dropEvent(event);
387 }
398 }
388
399
389
400
390 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
401 bool VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
391 const QPoint &pos, bool canInsert, bool canMerge,
402 const QPoint &pos, const QMimeData *mimeData, bool canInsert, bool canMerge,
392 const VisualizationDragDropContainer *container)
403 const VisualizationDragDropContainer *container)
393 {
404 {
394 auto &helper = sqpApp->dragDropHelper();
405 auto &helper = sqpApp->dragDropHelper();
395
406
396 auto absPos = container->mapToGlobal(pos);
407 auto absPos = container->mapToGlobal(pos);
397 auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos));
408 auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos));
398
409
399 if (countDragWidget(container, true) == 0) {
410 if (countDragWidget(container, true) == 0) {
400 // Drop on an empty container, just add the placeHolder at the top
411 // Drop on an empty container, just add the placeHolder at the top
401 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
412 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
402 }
413 }
403 else if (!isOnPlaceHolder) {
414 else if (!isOnPlaceHolder) {
404 auto nbDragWidget = countDragWidget(container);
415 auto nbDragWidget = countDragWidget(container);
405 if (nbDragWidget > 0) {
416 if (nbDragWidget > 0) {
406
417
407 if (m_MinContainerHeight == 0) {
418 if (m_MinContainerHeight == 0) {
408 m_MinContainerHeight = container->size().height();
419 m_MinContainerHeight = container->size().height();
409 }
420 }
410
421
411 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
422 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
412 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
423 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
413
424
414 auto posY = pos.y();
425 auto posY = pos.y();
415 auto dropIndex = floor(posY / graphHeight);
426 auto dropIndex = floor(posY / graphHeight);
416 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
427 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
417
428
418
429
419 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
430 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
420 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
431 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
421
432
422 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
433 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
423
434
424 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
435 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
425
436
426 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
437 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
427 if (isOnBottom) {
438 if (isOnBottom) {
428 dropIndex += 1;
439 dropIndex += 1;
429 }
440 }
430
441
431 if (helper.getCurrentDragWidget()) {
442 if (helper.getCurrentDragWidget()) {
432 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
443 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
433 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
444 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
434 // Correction of the index if the drop occurs in the same container
445 // Correction of the index if the drop occurs in the same container
435 // and if the drag is started from the visualization (in that case, the
446 // and if the drag is started from the visualization (in that case, the
436 // dragWidget is hidden)
447 // dragWidget is hidden)
437 dropIndex += 1;
448 dropIndex += 1;
438 }
449 }
439 }
450 }
440
451
441 if (dropIndex != placeHolderIndex) {
452 if (dropIndex != placeHolderIndex) {
442 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
453 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
443 m_PlaceHolderText);
454 m_PlaceHolderText);
444 }
455 }
445
456
446 helper.setHightlightedDragWidget(nullptr);
457 helper.setHightlightedDragWidget(nullptr);
447 }
458 }
448 else if (canMerge && dragWidgetHovered) {
459 else if (canMerge && dragWidgetHovered) {
449 // drop on the middle -> merge
460 // drop on the middle -> merge
450 if (hasPlaceHolder()) {
461 if (hasPlaceHolder()) {
451 helper.removePlaceHolder();
462 helper.removePlaceHolder();
452 }
463 }
453
464
454 helper.setHightlightedDragWidget(dragWidgetHovered);
465 if (m_AcceptDragWidgetFun(dragWidgetHovered, mimeData)) {
466 helper.setHightlightedDragWidget(dragWidgetHovered);
467 return true;
468 }
469 else {
470 return false;
471 }
455 }
472 }
456 else {
473 else {
457 qCWarning(LOG_VisualizationDragDropContainer())
474 qCWarning(LOG_VisualizationDragDropContainer())
458 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
475 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
459 "action.");
476 "action.");
460 }
477 }
461 }
478 }
462 else {
479 else {
463 qCWarning(LOG_VisualizationDragDropContainer())
480 qCWarning(LOG_VisualizationDragDropContainer())
464 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
481 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
465 "found in the "
482 "found in the "
466 "container");
483 "container");
467 }
484 }
468 }
485 }
469 else {
486 else {
470 // the mouse is hover the placeHolder
487 // the mouse is hover the placeHolder
471 // Do nothing
488 // Do nothing
472 }
489 }
490
491 return true;
473 }
492 }
@@ -1,560 +1,583
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 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
56 = qobject_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->setMimeType(MIME_TYPE_GRAPH,
105 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
106 VisualizationDragDropContainer::DropBehavior::Inserted);
106 VisualizationDragDropContainer::DropBehavior::Inserted);
107 ui->dragDropContainer->setMimeType(
107 ui->dragDropContainer->setMimeType(
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
109 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
109 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
110 VisualizationDragDropContainer::DropBehavior::Merged);
110 VisualizationDragDropContainer::DropBehavior::Merged);
111 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
111 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
112 VisualizationDragDropContainer::DropBehavior::Forbidden);
112 VisualizationDragDropContainer::DropBehavior::Forbidden);
113 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
113 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
114 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
114 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
115 ui->dragDropContainer);
115 ui->dragDropContainer);
116 });
116 });
117
117
118 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
119 if (!mimeData) {
120 return false;
121 }
122
123 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
124 auto variables = sqpApp->variableController().variablesForMimeData(
125 mimeData->data(MIME_TYPE_VARIABLE_LIST));
126
127 if (variables.count() != 1) {
128 return false;
129 }
130 auto variable = variables.first();
131
132 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
133 return graphWidget->canDrop(*variable);
134 }
135 }
136
137 return true;
138 };
139 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
140
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
141 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
119 &VisualizationZoneWidget::dropMimeData);
142 &VisualizationZoneWidget::dropMimeData);
120 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
143 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
121 &VisualizationZoneWidget::dropMimeDataOnGraph);
144 &VisualizationZoneWidget::dropMimeDataOnGraph);
122
145
123 // 'Close' options : widget is deleted when closed
146 // 'Close' options : widget is deleted when closed
124 setAttribute(Qt::WA_DeleteOnClose);
147 setAttribute(Qt::WA_DeleteOnClose);
125 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
148 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
126 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
149 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
127
150
128 // Synchronisation id
151 // Synchronisation id
129 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
152 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
130 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
153 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
131 }
154 }
132
155
133 VisualizationZoneWidget::~VisualizationZoneWidget()
156 VisualizationZoneWidget::~VisualizationZoneWidget()
134 {
157 {
135 delete ui;
158 delete ui;
136 }
159 }
137
160
138 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
161 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
139 {
162 {
140 // Synchronize new graph with others in the zone
163 // Synchronize new graph with others in the zone
141 impl->m_Synchronizer->addGraph(*graphWidget);
164 impl->m_Synchronizer->addGraph(*graphWidget);
142
165
143 ui->dragDropContainer->addDragWidget(graphWidget);
166 ui->dragDropContainer->addDragWidget(graphWidget);
144 }
167 }
145
168
146 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
169 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
147 {
170 {
148 // Synchronize new graph with others in the zone
171 // Synchronize new graph with others in the zone
149 impl->m_Synchronizer->addGraph(*graphWidget);
172 impl->m_Synchronizer->addGraph(*graphWidget);
150
173
151 ui->dragDropContainer->insertDragWidget(index, graphWidget);
174 ui->dragDropContainer->insertDragWidget(index, graphWidget);
152 }
175 }
153
176
154 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
177 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
155 {
178 {
156 return createGraph(variable, -1);
179 return createGraph(variable, -1);
157 }
180 }
158
181
159 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
182 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
160 int index)
183 int index)
161 {
184 {
162 auto graphWidget
185 auto graphWidget
163 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
186 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
164
187
165
188
166 // Set graph properties
189 // Set graph properties
167 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
190 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
168 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
191 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
169
192
170
193
171 // Lambda to synchronize zone widget
194 // Lambda to synchronize zone widget
172 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
195 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
173 const SqpRange &oldGraphRange) {
196 const SqpRange &oldGraphRange) {
174
197
175 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
198 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
176 auto frameLayout = ui->dragDropContainer->layout();
199 auto frameLayout = ui->dragDropContainer->layout();
177 for (auto i = 0; i < frameLayout->count(); ++i) {
200 for (auto i = 0; i < frameLayout->count(); ++i) {
178 auto graphChild
201 auto graphChild
179 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
202 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
180 if (graphChild && (graphChild != graphWidget)) {
203 if (graphChild && (graphChild != graphWidget)) {
181
204
182 auto graphChildRange = graphChild->graphRange();
205 auto graphChildRange = graphChild->graphRange();
183 switch (zoomType) {
206 switch (zoomType) {
184 case AcquisitionZoomType::ZoomIn: {
207 case AcquisitionZoomType::ZoomIn: {
185 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
208 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
186 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
209 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
187 graphChildRange.m_TStart += deltaLeft;
210 graphChildRange.m_TStart += deltaLeft;
188 graphChildRange.m_TEnd -= deltaRight;
211 graphChildRange.m_TEnd -= deltaRight;
189 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
212 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
213 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
191 << deltaLeft;
214 << deltaLeft;
192 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
215 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
193 << deltaRight;
216 << deltaRight;
194 qCDebug(LOG_VisualizationZoneWidget())
217 qCDebug(LOG_VisualizationZoneWidget())
195 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
218 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
196
219
197 break;
220 break;
198 }
221 }
199
222
200 case AcquisitionZoomType::ZoomOut: {
223 case AcquisitionZoomType::ZoomOut: {
201 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
224 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
202 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
225 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
203 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
226 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
227 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
205 << deltaLeft;
228 << deltaLeft;
206 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
229 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
207 << deltaRight;
230 << deltaRight;
208 qCDebug(LOG_VisualizationZoneWidget())
231 qCDebug(LOG_VisualizationZoneWidget())
209 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
232 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
210 graphChildRange.m_TStart -= deltaLeft;
233 graphChildRange.m_TStart -= deltaLeft;
211 graphChildRange.m_TEnd += deltaRight;
234 graphChildRange.m_TEnd += deltaRight;
212 break;
235 break;
213 }
236 }
214 case AcquisitionZoomType::PanRight: {
237 case AcquisitionZoomType::PanRight: {
215 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
238 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
216 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
239 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
217 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
240 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
218 graphChildRange.m_TStart += deltaLeft;
241 graphChildRange.m_TStart += deltaLeft;
219 graphChildRange.m_TEnd += deltaRight;
242 graphChildRange.m_TEnd += deltaRight;
220 qCDebug(LOG_VisualizationZoneWidget())
243 qCDebug(LOG_VisualizationZoneWidget())
221 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
244 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
222 break;
245 break;
223 }
246 }
224 case AcquisitionZoomType::PanLeft: {
247 case AcquisitionZoomType::PanLeft: {
225 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
248 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
226 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
249 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
227 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
250 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
228 graphChildRange.m_TStart -= deltaLeft;
251 graphChildRange.m_TStart -= deltaLeft;
229 graphChildRange.m_TEnd -= deltaRight;
252 graphChildRange.m_TEnd -= deltaRight;
230 break;
253 break;
231 }
254 }
232 case AcquisitionZoomType::Unknown: {
255 case AcquisitionZoomType::Unknown: {
233 qCDebug(LOG_VisualizationZoneWidget())
256 qCDebug(LOG_VisualizationZoneWidget())
234 << tr("Impossible to synchronize: zoom type unknown");
257 << tr("Impossible to synchronize: zoom type unknown");
235 break;
258 break;
236 }
259 }
237 default:
260 default:
238 qCCritical(LOG_VisualizationZoneWidget())
261 qCCritical(LOG_VisualizationZoneWidget())
239 << tr("Impossible to synchronize: zoom type not take into account");
262 << tr("Impossible to synchronize: zoom type not take into account");
240 // No action
263 // No action
241 break;
264 break;
242 }
265 }
243 graphChild->enableAcquisition(false);
266 graphChild->enableAcquisition(false);
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
267 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
245 << graphChild->graphRange();
268 << graphChild->graphRange();
246 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
269 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
247 << graphChildRange;
270 << graphChildRange;
248 qCDebug(LOG_VisualizationZoneWidget())
271 qCDebug(LOG_VisualizationZoneWidget())
249 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
272 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
250 graphChild->setGraphRange(graphChildRange);
273 graphChild->setGraphRange(graphChildRange);
251 graphChild->enableAcquisition(true);
274 graphChild->enableAcquisition(true);
252 }
275 }
253 }
276 }
254 };
277 };
255
278
256 // connection for synchronization
279 // connection for synchronization
257 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
280 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
258 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
281 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
259 &VisualizationZoneWidget::onVariableAdded);
282 &VisualizationZoneWidget::onVariableAdded);
260 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
283 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
261 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
284 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
262
285
263 auto range = SqpRange{};
286 auto range = SqpRange{};
264 if (auto firstGraph = impl->firstGraph(this)) {
287 if (auto firstGraph = impl->firstGraph(this)) {
265 // Case of a new graph in a existant zone
288 // Case of a new graph in a existant zone
266 range = firstGraph->graphRange();
289 range = firstGraph->graphRange();
267 }
290 }
268 else {
291 else {
269 // Case of a new graph as the first of the zone
292 // Case of a new graph as the first of the zone
270 range = variable->range();
293 range = variable->range();
271 }
294 }
272
295
273 this->insertGraph(index, graphWidget);
296 this->insertGraph(index, graphWidget);
274
297
275 graphWidget->addVariable(variable, range);
298 graphWidget->addVariable(variable, range);
276 graphWidget->setYRange(variable);
299 graphWidget->setYRange(variable);
277
300
278 return graphWidget;
301 return graphWidget;
279 }
302 }
280
303
281 VisualizationGraphWidget *
304 VisualizationGraphWidget *
282 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
305 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
283 {
306 {
284 if (variables.isEmpty()) {
307 if (variables.isEmpty()) {
285 return nullptr;
308 return nullptr;
286 }
309 }
287
310
288 auto graphWidget = createGraph(variables.first(), index);
311 auto graphWidget = createGraph(variables.first(), index);
289 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
312 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
290 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
313 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
291 }
314 }
292
315
293 return graphWidget;
316 return graphWidget;
294 }
317 }
295
318
296 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
319 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
297 {
320 {
298 if (visitor) {
321 if (visitor) {
299 visitor->visitEnter(this);
322 visitor->visitEnter(this);
300
323
301 // Apply visitor to graph children: widgets different from graphs are not visited (no
324 // Apply visitor to graph children: widgets different from graphs are not visited (no
302 // action)
325 // action)
303 processGraphs(
326 processGraphs(
304 *ui->dragDropContainer->layout(),
327 *ui->dragDropContainer->layout(),
305 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
328 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
306
329
307 visitor->visitLeave(this);
330 visitor->visitLeave(this);
308 }
331 }
309 else {
332 else {
310 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
333 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
311 }
334 }
312 }
335 }
313
336
314 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
337 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
315 {
338 {
316 // A tab can always accomodate a variable
339 // A tab can always accomodate a variable
317 Q_UNUSED(variable);
340 Q_UNUSED(variable);
318 return true;
341 return true;
319 }
342 }
320
343
321 bool VisualizationZoneWidget::contains(const Variable &variable) const
344 bool VisualizationZoneWidget::contains(const Variable &variable) const
322 {
345 {
323 Q_UNUSED(variable);
346 Q_UNUSED(variable);
324 return false;
347 return false;
325 }
348 }
326
349
327 QString VisualizationZoneWidget::name() const
350 QString VisualizationZoneWidget::name() const
328 {
351 {
329 return ui->zoneNameLabel->text();
352 return ui->zoneNameLabel->text();
330 }
353 }
331
354
332 QMimeData *VisualizationZoneWidget::mimeData() const
355 QMimeData *VisualizationZoneWidget::mimeData() const
333 {
356 {
334 auto mimeData = new QMimeData;
357 auto mimeData = new QMimeData;
335 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
358 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
336
359
337 if (auto firstGraph = impl->firstGraph(this)) {
360 if (auto firstGraph = impl->firstGraph(this)) {
338 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
361 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
339 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
362 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
340 }
363 }
341
364
342 return mimeData;
365 return mimeData;
343 }
366 }
344
367
345 bool VisualizationZoneWidget::isDragAllowed() const
368 bool VisualizationZoneWidget::isDragAllowed() const
346 {
369 {
347 return true;
370 return true;
348 }
371 }
349
372
350 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
373 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
351 const QPointF &plotPosition,
374 const QPointF &plotPosition,
352 VisualizationGraphWidget *graphWidget)
375 VisualizationGraphWidget *graphWidget)
353 {
376 {
354 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
377 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
355 VisualizationGraphWidget &processedGraph) {
378 VisualizationGraphWidget &processedGraph) {
356
379
357 switch (sqpApp->plotsCursorMode()) {
380 switch (sqpApp->plotsCursorMode()) {
358 case SqpApplication::PlotsCursorMode::Vertical:
381 case SqpApplication::PlotsCursorMode::Vertical:
359 processedGraph.removeHorizontalCursor();
382 processedGraph.removeHorizontalCursor();
360 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
383 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
361 break;
384 break;
362 case SqpApplication::PlotsCursorMode::Temporal:
385 case SqpApplication::PlotsCursorMode::Temporal:
363 processedGraph.addVerticalCursor(plotPosition.x());
386 processedGraph.addVerticalCursor(plotPosition.x());
364 processedGraph.removeHorizontalCursor();
387 processedGraph.removeHorizontalCursor();
365 break;
388 break;
366 case SqpApplication::PlotsCursorMode::Horizontal:
389 case SqpApplication::PlotsCursorMode::Horizontal:
367 processedGraph.removeVerticalCursor();
390 processedGraph.removeVerticalCursor();
368 if (&processedGraph == graphWidget) {
391 if (&processedGraph == graphWidget) {
369 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
392 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
370 }
393 }
371 else {
394 else {
372 processedGraph.removeHorizontalCursor();
395 processedGraph.removeHorizontalCursor();
373 }
396 }
374 break;
397 break;
375 case SqpApplication::PlotsCursorMode::Cross:
398 case SqpApplication::PlotsCursorMode::Cross:
376 if (&processedGraph == graphWidget) {
399 if (&processedGraph == graphWidget) {
377 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
400 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
378 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
401 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
379 }
402 }
380 else {
403 else {
381 processedGraph.removeHorizontalCursor();
404 processedGraph.removeHorizontalCursor();
382 processedGraph.removeVerticalCursor();
405 processedGraph.removeVerticalCursor();
383 }
406 }
384 break;
407 break;
385 case SqpApplication::PlotsCursorMode::NoCursor:
408 case SqpApplication::PlotsCursorMode::NoCursor:
386 processedGraph.removeHorizontalCursor();
409 processedGraph.removeHorizontalCursor();
387 processedGraph.removeVerticalCursor();
410 processedGraph.removeVerticalCursor();
388 break;
411 break;
389 }
412 }
390
413
391
414
392 });
415 });
393 }
416 }
394
417
395 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
418 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
396 {
419 {
397 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
420 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
398 processedGraph.removeHorizontalCursor();
421 processedGraph.removeHorizontalCursor();
399 processedGraph.removeVerticalCursor();
422 processedGraph.removeVerticalCursor();
400 });
423 });
401 }
424 }
402
425
403 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
426 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
404 {
427 {
405 // Closes graphs in the zone
428 // Closes graphs in the zone
406 processGraphs(*ui->dragDropContainer->layout(),
429 processGraphs(*ui->dragDropContainer->layout(),
407 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
430 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
408
431
409 // Delete synchronization group from variable controller
432 // Delete synchronization group from variable controller
410 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
433 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
411 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
434 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
412
435
413 QWidget::closeEvent(event);
436 QWidget::closeEvent(event);
414 }
437 }
415
438
416 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
439 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
417 {
440 {
418 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
441 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
419 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
442 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
420 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
443 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
421 }
444 }
422
445
423 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
446 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
424 {
447 {
425 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
448 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
426 Q_ARG(std::shared_ptr<Variable>, variable),
449 Q_ARG(std::shared_ptr<Variable>, variable),
427 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
450 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
428 }
451 }
429
452
430 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
453 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
431 {
454 {
432 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
455 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
433 impl->dropGraph(index, this);
456 impl->dropGraph(index, this);
434 }
457 }
435 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
458 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
436 auto variables = sqpApp->variableController().variablesForMimeData(
459 auto variables = sqpApp->variableController().variablesForMimeData(
437 mimeData->data(MIME_TYPE_VARIABLE_LIST));
460 mimeData->data(MIME_TYPE_VARIABLE_LIST));
438 impl->dropVariables(variables, index, this);
461 impl->dropVariables(variables, index, this);
439 }
462 }
440 else {
463 else {
441 qCWarning(LOG_VisualizationZoneWidget())
464 qCWarning(LOG_VisualizationZoneWidget())
442 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
465 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
443 }
466 }
444 }
467 }
445
468
446 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
469 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
447 const QMimeData *mimeData)
470 const QMimeData *mimeData)
448 {
471 {
449 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
472 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
450 if (!graphWidget) {
473 if (!graphWidget) {
451 qCWarning(LOG_VisualizationZoneWidget())
474 qCWarning(LOG_VisualizationZoneWidget())
452 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
475 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
453 "drop aborted");
476 "drop aborted");
454 Q_ASSERT(false);
477 Q_ASSERT(false);
455 return;
478 return;
456 }
479 }
457
480
458 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
481 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
459 auto variables = sqpApp->variableController().variablesForMimeData(
482 auto variables = sqpApp->variableController().variablesForMimeData(
460 mimeData->data(MIME_TYPE_VARIABLE_LIST));
483 mimeData->data(MIME_TYPE_VARIABLE_LIST));
461 for (const auto &var : variables) {
484 for (const auto &var : variables) {
462 graphWidget->addVariable(var, graphWidget->graphRange());
485 graphWidget->addVariable(var, graphWidget->graphRange());
463 }
486 }
464 }
487 }
465 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
488 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
466 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
489 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
467 graphWidget->setGraphRange(range);
490 graphWidget->setGraphRange(range);
468 }
491 }
469 else {
492 else {
470 qCWarning(LOG_VisualizationZoneWidget())
493 qCWarning(LOG_VisualizationZoneWidget())
471 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
494 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
472 }
495 }
473 }
496 }
474
497
475 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
498 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
476 int index, VisualizationZoneWidget *zoneWidget)
499 int index, VisualizationZoneWidget *zoneWidget)
477 {
500 {
478 auto &helper = sqpApp->dragDropHelper();
501 auto &helper = sqpApp->dragDropHelper();
479
502
480 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
503 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
481 if (!graphWidget) {
504 if (!graphWidget) {
482 qCWarning(LOG_VisualizationZoneWidget())
505 qCWarning(LOG_VisualizationZoneWidget())
483 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
506 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
484 "found or invalid.");
507 "found or invalid.");
485 Q_ASSERT(false);
508 Q_ASSERT(false);
486 return;
509 return;
487 }
510 }
488
511
489 auto parentDragDropContainer
512 auto parentDragDropContainer
490 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
513 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
491 if (!parentDragDropContainer) {
514 if (!parentDragDropContainer) {
492 qCWarning(LOG_VisualizationZoneWidget())
515 qCWarning(LOG_VisualizationZoneWidget())
493 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
516 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
494 "the dropped graph is not found.");
517 "the dropped graph is not found.");
495 Q_ASSERT(false);
518 Q_ASSERT(false);
496 return;
519 return;
497 }
520 }
498
521
499 const auto &variables = graphWidget->variables();
522 const auto &variables = graphWidget->variables();
500
523
501 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
524 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
502 // The drop didn't occur in the same zone
525 // The drop didn't occur in the same zone
503
526
504 // Abort the requests for the variables (if any)
527 // Abort the requests for the variables (if any)
505 // Commented, because it's not sure if it's needed or not
528 // Commented, because it's not sure if it's needed or not
506 // for (const auto& var : variables)
529 // for (const auto& var : variables)
507 //{
530 //{
508 // sqpApp->variableController().onAbortProgressRequested(var);
531 // sqpApp->variableController().onAbortProgressRequested(var);
509 //}
532 //}
510
533
511 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
534 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
512 auto nbGraph = parentDragDropContainer->countDragWidget();
535 auto nbGraph = parentDragDropContainer->countDragWidget();
513 if (nbGraph == 1) {
536 if (nbGraph == 1) {
514 // This is the only graph in the previous zone, close the zone
537 // This is the only graph in the previous zone, close the zone
515 helper.delayedCloseWidget(previousParentZoneWidget);
538 helper.delayedCloseWidget(previousParentZoneWidget);
516 }
539 }
517 else {
540 else {
518 // Close the graph
541 // Close the graph
519 helper.delayedCloseWidget(graphWidget);
542 helper.delayedCloseWidget(graphWidget);
520 }
543 }
521
544
522 // Creates the new graph in the zone
545 // Creates the new graph in the zone
523 zoneWidget->createGraph(variables, index);
546 zoneWidget->createGraph(variables, index);
524 }
547 }
525 else {
548 else {
526 // The drop occurred in the same zone or the graph is empty
549 // The drop occurred in the same zone or the graph is empty
527 // Simple move of the graph, no variable operation associated
550 // Simple move of the graph, no variable operation associated
528 parentDragDropContainer->layout()->removeWidget(graphWidget);
551 parentDragDropContainer->layout()->removeWidget(graphWidget);
529
552
530 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
553 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
531 // The graph is empty and dropped in a different zone.
554 // The graph is empty and dropped in a different zone.
532 // Take the range of the first graph in the zone (if existing).
555 // Take the range of the first graph in the zone (if existing).
533 auto layout = zoneWidget->ui->dragDropContainer->layout();
556 auto layout = zoneWidget->ui->dragDropContainer->layout();
534 if (layout->count() > 0) {
557 if (layout->count() > 0) {
535 if (auto visualizationGraphWidget
558 if (auto visualizationGraphWidget
536 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
559 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
537 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
560 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
538 }
561 }
539 }
562 }
540 }
563 }
541
564
542 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
565 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
543 }
566 }
544 }
567 }
545
568
546 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
569 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
547 const QList<std::shared_ptr<Variable> > &variables, int index,
570 const QList<std::shared_ptr<Variable> > &variables, int index,
548 VisualizationZoneWidget *zoneWidget)
571 VisualizationZoneWidget *zoneWidget)
549 {
572 {
550 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
573 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
551 // compatible variable here
574 // compatible variable here
552 if (variables.count() > 1) {
575 if (variables.count() > 1) {
553 qCWarning(LOG_VisualizationZoneWidget())
576 qCWarning(LOG_VisualizationZoneWidget())
554 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
577 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
555 "aborted.");
578 "aborted.");
556 return;
579 return;
557 }
580 }
558
581
559 zoneWidget->createGraph(variables, index);
582 zoneWidget->createGraph(variables, index);
560 }
583 }
General Comments 0
You need to be logged in to leave comments. Login now