##// END OF EJS Templates
Improves drag&drop with spectro
trabillard -
r1125:3bc886701554
parent child
Show More
@@ -1,500 +1,496
1 #include "Visualization/VisualizationDragDropContainer.h"
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragAndDrop/DragDropGuiController.h"
2 #include "DragAndDrop/DragDropGuiController.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 DragDropGuiController::PlaceHolderType m_PlaceHolderType;
24 DragDropGuiController::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
28 VisualizationDragDropContainer::AcceptDragWidgetFunction m_AcceptDragWidgetFun
29 = [](auto dragWidget, auto mimeData) { return true; };
29 = [](auto dragWidget, auto mimeData) { return true; };
30
30
31 int m_MinContainerHeight = 0;
31 int m_MinContainerHeight = 0;
32
32
33 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
33 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
34 : m_PlaceHolderType(DragDropGuiController::PlaceHolderType::Graph)
34 : m_PlaceHolderType(DragDropGuiController::PlaceHolderType::Graph)
35 {
35 {
36 m_Layout = new QVBoxLayout(widget);
36 m_Layout = new QVBoxLayout(widget);
37 m_Layout->setContentsMargins(0, 0, 0, 0);
37 m_Layout->setContentsMargins(0, 0, 0, 0);
38 }
38 }
39
39
40 bool acceptMimeData(const QMimeData *data) const
40 bool acceptMimeData(const QMimeData *data) const
41 {
41 {
42 auto accepted = false;
42 auto accepted = false;
43 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
43 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
44 ++it) {
44 ++it) {
45 const auto &type = it.key();
45 const auto &type = it.key();
46 const auto &behavior = it.value();
46 const auto &behavior = it.value();
47
47
48 if (data->hasFormat(type)) {
48 if (data->hasFormat(type)) {
49 if (behavior != DropBehavior::Forbidden) {
49 if (behavior != DropBehavior::Forbidden) {
50 accepted = true;
50 accepted = true;
51 }
51 }
52 else {
52 else {
53 accepted = false;
53 accepted = false;
54 break;
54 break;
55 }
55 }
56 }
56 }
57 }
57 }
58
58
59 if (accepted) {
59 if (accepted) {
60 accepted = m_AcceptMimeDataFun(data);
60 accepted = m_AcceptMimeDataFun(data);
61 }
61 }
62
62
63 return accepted;
63 return accepted;
64 }
64 }
65
65
66 bool allowMergeForMimeData(const QMimeData *data) const
66 bool allowMergeForMimeData(const QMimeData *data) const
67 {
67 {
68 auto result = false;
68 auto result = false;
69 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
69 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
70 ++it) {
70 ++it) {
71
71
72 if (data->hasFormat(it.key())
72 if (data->hasFormat(it.key())
73 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
73 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
74 || it.value()
74 || it.value()
75 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
75 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
76 result = true;
76 result = true;
77 }
77 }
78 else if (data->hasFormat(it.key())
78 else if (data->hasFormat(it.key())
79 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
79 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
80 // 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
81 // merged
81 // merged
82 result = false;
82 result = false;
83 break;
83 break;
84 }
84 }
85 }
85 }
86
86
87 return result;
87 return result;
88 }
88 }
89
89
90 bool allowInsertForMimeData(const QMimeData *data) const
90 bool allowInsertForMimeData(const QMimeData *data) const
91 {
91 {
92 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
92 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
93 ++it) {
93 ++it) {
94 if (data->hasFormat(it.key())
94 if (data->hasFormat(it.key())
95 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
95 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
96 || it.value()
96 || it.value()
97 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
97 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
98 return true;
98 return true;
99 }
99 }
100 }
100 }
101
101
102 return false;
102 return false;
103 }
103 }
104
104
105 bool hasPlaceHolder() const
105 bool hasPlaceHolder() const
106 {
106 {
107 return sqpApp->dragDropGuiController().placeHolder().parentWidget()
107 return sqpApp->dragDropGuiController().placeHolder().parentWidget()
108 == m_Layout->parentWidget();
108 == m_Layout->parentWidget();
109 }
109 }
110
110
111 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
111 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
112 {
112 {
113 VisualizationDragWidget *dragWidget = nullptr;
113 VisualizationDragWidget *dragWidget = nullptr;
114
114
115 for (auto child : parent->children()) {
115 for (auto child : parent->children()) {
116 auto widget = qobject_cast<VisualizationDragWidget *>(child);
116 auto widget = qobject_cast<VisualizationDragWidget *>(child);
117 if (widget && widget->isVisible()) {
117 if (widget && widget->isVisible()) {
118 if (widget->frameGeometry().contains(pos)) {
118 if (widget->frameGeometry().contains(pos)) {
119 dragWidget = widget;
119 dragWidget = widget;
120 break;
120 break;
121 }
121 }
122 }
122 }
123 }
123 }
124
124
125 return dragWidget;
125 return dragWidget;
126 }
126 }
127
127
128 bool cursorIsInContainer(QWidget *container) const
128 bool cursorIsInContainer(QWidget *container) const
129 {
129 {
130 auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos());
130 auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos());
131 return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container
131 return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container
132 && sqpApp->dragDropGuiController().placeHolder().isAncestorOf(widgetUnderMouse);
132 && sqpApp->dragDropGuiController().placeHolder().isAncestorOf(widgetUnderMouse);
133 }
133 }
134
134
135 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
135 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
136 {
136 {
137 auto nbGraph = 0;
137 auto nbGraph = 0;
138 for (auto child : parent->children()) {
138 for (auto child : parent->children()) {
139 if (qobject_cast<VisualizationDragWidget *>(child)) {
139 if (qobject_cast<VisualizationDragWidget *>(child)) {
140 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
140 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
141 nbGraph += 1;
141 nbGraph += 1;
142 }
142 }
143 }
143 }
144 }
144 }
145
145
146 return nbGraph;
146 return nbGraph;
147 }
147 }
148
148
149 bool findPlaceHolderPosition(const QPoint &pos, const QMimeData *mimeData, bool canInsert,
149 bool findPlaceHolderPosition(const QPoint &pos, const QMimeData *mimeData, bool canInsert,
150 bool canMerge, const VisualizationDragDropContainer *container);
150 bool canMerge, const VisualizationDragDropContainer *container);
151 };
151 };
152
152
153 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
153 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
154 : QFrame{parent},
154 : QFrame{parent},
155 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
155 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
156 {
156 {
157 setAcceptDrops(true);
157 setAcceptDrops(true);
158 }
158 }
159
159
160 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
160 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
161 {
161 {
162 impl->m_Layout->addWidget(dragWidget);
162 impl->m_Layout->addWidget(dragWidget);
163 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
163 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
164 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
164 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
165 &VisualizationDragDropContainer::startDrag);
165 &VisualizationDragDropContainer::startDrag);
166 }
166 }
167
167
168 void VisualizationDragDropContainer::insertDragWidget(int index,
168 void VisualizationDragDropContainer::insertDragWidget(int index,
169 VisualizationDragWidget *dragWidget)
169 VisualizationDragWidget *dragWidget)
170 {
170 {
171 impl->m_Layout->insertWidget(index, dragWidget);
171 impl->m_Layout->insertWidget(index, dragWidget);
172 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
172 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
173 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
173 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
174 &VisualizationDragDropContainer::startDrag);
174 &VisualizationDragDropContainer::startDrag);
175 }
175 }
176
176
177 void VisualizationDragDropContainer::setMimeType(
177 void VisualizationDragDropContainer::setMimeType(
178 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
178 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
179 {
179 {
180 impl->m_AcceptedMimeTypes[mimeType] = behavior;
180 impl->m_AcceptedMimeTypes[mimeType] = behavior;
181 }
181 }
182
182
183 int VisualizationDragDropContainer::countDragWidget() const
183 int VisualizationDragDropContainer::countDragWidget() const
184 {
184 {
185 return impl->countDragWidget(this);
185 return impl->countDragWidget(this);
186 }
186 }
187
187
188 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
188 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
189 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
189 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
190 {
190 {
191 impl->m_AcceptMimeDataFun = fun;
191 impl->m_AcceptMimeDataFun = fun;
192 }
192 }
193
193
194 void VisualizationDragDropContainer::setAcceptDragWidgetFunction(
194 void VisualizationDragDropContainer::setAcceptDragWidgetFunction(
195 VisualizationDragDropContainer::AcceptDragWidgetFunction fun)
195 VisualizationDragDropContainer::AcceptDragWidgetFunction fun)
196 {
196 {
197 impl->m_AcceptDragWidgetFun = fun;
197 impl->m_AcceptDragWidgetFun = fun;
198 }
198 }
199
199
200 void VisualizationDragDropContainer::setPlaceHolderType(DragDropGuiController::PlaceHolderType type,
200 void VisualizationDragDropContainer::setPlaceHolderType(DragDropGuiController::PlaceHolderType type,
201 const QString &placeHolderText)
201 const QString &placeHolderText)
202 {
202 {
203 impl->m_PlaceHolderType = type;
203 impl->m_PlaceHolderType = type;
204 impl->m_PlaceHolderText = placeHolderText;
204 impl->m_PlaceHolderText = placeHolderText;
205 }
205 }
206
206
207 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
207 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
208 const QPoint &dragPosition)
208 const QPoint &dragPosition)
209 {
209 {
210 auto &helper = sqpApp->dragDropGuiController();
210 auto &helper = sqpApp->dragDropGuiController();
211 helper.resetDragAndDrop();
211 helper.resetDragAndDrop();
212
212
213 // Note: The management of the drag object is done by Qt
213 // Note: The management of the drag object is done by Qt
214 auto drag = new QDrag{dragWidget};
214 auto drag = new QDrag{dragWidget};
215
215
216 auto mimeData = dragWidget->mimeData(dragPosition);
216 auto mimeData = dragWidget->mimeData(dragPosition);
217 drag->setMimeData(mimeData);
217 drag->setMimeData(mimeData);
218
218
219 auto pixmap = dragWidget->customDragPixmap(dragPosition);
219 auto pixmap = dragWidget->customDragPixmap(dragPosition);
220 if (pixmap.isNull()) {
220 if (pixmap.isNull()) {
221 pixmap = QPixmap{dragWidget->size()};
221 pixmap = QPixmap{dragWidget->size()};
222 dragWidget->render(&pixmap);
222 dragWidget->render(&pixmap);
223 }
223 }
224
224
225 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
225 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
226 Qt::KeepAspectRatio, Qt::SmoothTransformation));
226 Qt::KeepAspectRatio, Qt::SmoothTransformation));
227
227
228 auto image = pixmap.toImage();
228 auto image = pixmap.toImage();
229 mimeData->setImageData(image);
229 mimeData->setImageData(image);
230 mimeData->setUrls({helper.imageTemporaryUrl(image)});
230 mimeData->setUrls({helper.imageTemporaryUrl(image)});
231
231
232 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
232 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
233
233
234 if (impl->acceptMimeData(mimeData) && impl->allowInsertForMimeData(mimeData)) {
234 if (impl->acceptMimeData(mimeData) && impl->allowInsertForMimeData(mimeData)) {
235 helper.setCurrentDragWidget(dragWidget);
235 helper.setCurrentDragWidget(dragWidget);
236
236
237 if (impl->cursorIsInContainer(this)) {
237 if (impl->cursorIsInContainer(this)) {
238 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
238 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
239 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
239 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
240 impl->m_PlaceHolderText);
240 impl->m_PlaceHolderText);
241 dragWidget->setVisible(false);
241 dragWidget->setVisible(false);
242 }
242 }
243 else {
243 else {
244 // The drag starts directly outside the drop zone
244 // The drag starts directly outside the drop zone
245 // do not add the placeHolder
245 // do not add the placeHolder
246 }
246 }
247 }
247 }
248
248
249 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
249 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
250
250
251 helper.doCloseWidgets();
251 helper.doCloseWidgets();
252 }
252 }
253 else {
253 else {
254 qCWarning(LOG_VisualizationDragDropContainer())
254 qCWarning(LOG_VisualizationDragDropContainer())
255 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
255 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
256 "VisualizationDragWidget is not found in this container.");
256 "VisualizationDragWidget is not found in this container.");
257 }
257 }
258 }
258 }
259
259
260 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
260 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
261 {
261 {
262 if (impl->acceptMimeData(event->mimeData())) {
262 if (impl->acceptMimeData(event->mimeData())) {
263 event->acceptProposedAction();
263 event->acceptProposedAction();
264
264
265 auto &helper = sqpApp->dragDropGuiController();
265 auto &helper = sqpApp->dragDropGuiController();
266
266
267 if (!impl->hasPlaceHolder()) {
267 if (!impl->hasPlaceHolder()) {
268 auto dragWidget = helper.getCurrentDragWidget();
268 auto dragWidget = helper.getCurrentDragWidget();
269
269
270 if (dragWidget) {
270 if (dragWidget) {
271 // If the drag&drop is internal to the visualization, entering the container hide
271 // If the drag&drop is internal to the visualization, entering the container hide
272 // the dragWidget which was made visible by the dragLeaveEvent
272 // the dragWidget which was made visible by the dragLeaveEvent
273 auto parentWidget
273 auto parentWidget
274 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
274 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
275 if (parentWidget) {
275 if (parentWidget) {
276 dragWidget->setVisible(false);
276 dragWidget->setVisible(false);
277 }
277 }
278 }
278 }
279
279
280 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
280 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
281 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
281 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
282 if (!impl->findPlaceHolderPosition(event->pos(), event->mimeData(), canInsert, canMerge,
282 if (!impl->findPlaceHolderPosition(event->pos(), event->mimeData(), canInsert, canMerge,
283 this)) {
283 this)) {
284 event->ignore();
284 event->ignore();
285 }
285 }
286 }
286 }
287 else {
287 else {
288 // do nothing
288 // do nothing
289 }
289 }
290 }
290 }
291 else {
291 else {
292 event->ignore();
292 event->ignore();
293 }
293 }
294
294
295 QWidget::dragEnterEvent(event);
295 QWidget::dragEnterEvent(event);
296 }
296 }
297
297
298 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
298 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
299 {
299 {
300 Q_UNUSED(event);
300 Q_UNUSED(event);
301
301
302 auto &helper = sqpApp->dragDropGuiController();
302 auto &helper = sqpApp->dragDropGuiController();
303
303
304 if (!impl->cursorIsInContainer(this)) {
304 if (!impl->cursorIsInContainer(this)) {
305 helper.removePlaceHolder();
305 helper.removePlaceHolder();
306 helper.setHightlightedDragWidget(nullptr);
306 helper.setHightlightedDragWidget(nullptr);
307 impl->m_MinContainerHeight = 0;
307 impl->m_MinContainerHeight = 0;
308
308
309 auto dragWidget = helper.getCurrentDragWidget();
309 auto dragWidget = helper.getCurrentDragWidget();
310 if (dragWidget) {
310 if (dragWidget) {
311 // dragWidget has a value only if the drag is started from the visualization
311 // dragWidget has a value only if the drag is started from the visualization
312 // In that case, shows the drag widget at its original place
312 // In that case, shows the drag widget at its original place
313 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
313 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
314 // drop zone (It is not possible to catch a drop event outside of the application)
314 // drop zone (It is not possible to catch a drop event outside of the application)
315
315
316 if (dragWidget) {
316 if (dragWidget) {
317 dragWidget->setVisible(true);
317 dragWidget->setVisible(true);
318 }
318 }
319 }
319 }
320 }
320 }
321 else {
321 else {
322 // Leave event probably received for a child widget.
322 // Leave event probably received for a child widget.
323 // Do nothing.
323 // Do nothing.
324 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
324 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
325 }
325 }
326
326
327 QWidget::dragLeaveEvent(event);
327 QWidget::dragLeaveEvent(event);
328 }
328 }
329
329
330 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
330 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
331 {
331 {
332 if (impl->acceptMimeData(event->mimeData())) {
332 if (impl->acceptMimeData(event->mimeData())) {
333 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
333 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
334 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
334 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
335 impl->findPlaceHolderPosition(event->pos(), event->mimeData(), canInsert, canMerge, this);
335 impl->findPlaceHolderPosition(event->pos(), event->mimeData(), canInsert, canMerge, this);
336 }
336 }
337 else {
337 else {
338 event->ignore();
338 event->ignore();
339 }
339 }
340
340
341 QWidget::dragMoveEvent(event);
341 QWidget::dragMoveEvent(event);
342 }
342 }
343
343
344 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
344 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
345 {
345 {
346 auto &helper = sqpApp->dragDropGuiController();
346 auto &helper = sqpApp->dragDropGuiController();
347
347
348 if (impl->acceptMimeData(event->mimeData())) {
348 if (impl->acceptMimeData(event->mimeData())) {
349 auto dragWidget = helper.getCurrentDragWidget();
349 auto dragWidget = helper.getCurrentDragWidget();
350 if (impl->hasPlaceHolder()) {
350 if (impl->hasPlaceHolder()) {
351 // drop where the placeHolder is located
351 // drop where the placeHolder is located
352
352
353 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
353 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
354 if (canInsert) {
354 if (canInsert) {
355 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
355 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
356
356
357 if (dragWidget) {
357 if (dragWidget) {
358 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
358 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
359 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
359 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
360 // Correction of the index if the drop occurs in the same container
360 // Correction of the index if the drop occurs in the same container
361 // and if the drag is started from the visualization (in that case, the
361 // and if the drag is started from the visualization (in that case, the
362 // dragWidget is hidden)
362 // dragWidget is hidden)
363 droppedIndex -= 1;
363 droppedIndex -= 1;
364 }
364 }
365
365
366 dragWidget->setVisible(true);
366 dragWidget->setVisible(true);
367 }
367 }
368
368
369 event->acceptProposedAction();
369 event->acceptProposedAction();
370
370
371 helper.removePlaceHolder();
371 helper.removePlaceHolder();
372
372
373 emit dropOccuredInContainer(droppedIndex, event->mimeData());
373 emit dropOccuredInContainer(droppedIndex, event->mimeData());
374 }
374 }
375 else {
375 else {
376 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
376 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
377 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
377 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
378 "the insertion is forbidden.");
378 "the insertion is forbidden.");
379 Q_ASSERT(false);
379 Q_ASSERT(false);
380 }
380 }
381 }
381 }
382 else if (helper.getHightlightedDragWidget()) {
382 else if (helper.getHightlightedDragWidget()) {
383 // drop on the highlighted widget
383 // drop on the highlighted widget
384
384
385 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
385 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
386 if (canMerge) {
386 if (canMerge) {
387 event->acceptProposedAction();
387 event->acceptProposedAction();
388 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
388 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
389 }
389 }
390 else {
390 else {
391 qCWarning(LOG_VisualizationDragDropContainer())
391 qCWarning(LOG_VisualizationDragDropContainer())
392 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
392 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
393 "the merge is forbidden.");
393 "the merge is forbidden.");
394 Q_ASSERT(false);
394 Q_ASSERT(false);
395 }
395 }
396 }
396 }
397 }
397 }
398 else {
398 else {
399 event->ignore();
399 event->ignore();
400 }
400 }
401
401
402 sqpApp->dragDropGuiController().setHightlightedDragWidget(nullptr);
402 sqpApp->dragDropGuiController().setHightlightedDragWidget(nullptr);
403 impl->m_MinContainerHeight = 0;
403 impl->m_MinContainerHeight = 0;
404
404
405 QWidget::dropEvent(event);
405 QWidget::dropEvent(event);
406 }
406 }
407
407
408
408
409 bool VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
409 bool VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
410 const QPoint &pos, const QMimeData *mimeData, bool canInsert, bool canMerge,
410 const QPoint &pos, const QMimeData *mimeData, bool canInsert, bool canMerge,
411 const VisualizationDragDropContainer *container)
411 const VisualizationDragDropContainer *container)
412 {
412 {
413 auto &helper = sqpApp->dragDropGuiController();
413 auto &helper = sqpApp->dragDropGuiController();
414
414
415 auto absPos = container->mapToGlobal(pos);
415 auto absPos = container->mapToGlobal(pos);
416 auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos));
416 auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos));
417
417
418 if (countDragWidget(container, true) == 0) {
418 if (countDragWidget(container, true) == 0) {
419 // Drop on an empty container, just add the placeHolder at the top
419 // Drop on an empty container, just add the placeHolder at the top
420 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
420 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
421 }
421 }
422 else if (!isOnPlaceHolder) {
422 else if (!isOnPlaceHolder) {
423 auto nbDragWidget = countDragWidget(container);
423 auto nbDragWidget = countDragWidget(container);
424 if (nbDragWidget > 0) {
424 if (nbDragWidget > 0) {
425
425
426 if (m_MinContainerHeight == 0) {
426 if (m_MinContainerHeight == 0) {
427 m_MinContainerHeight = container->size().height();
427 m_MinContainerHeight = container->size().height();
428 }
428 }
429
429
430 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
430 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
431 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
431 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
432
432
433 auto posY = pos.y();
433 auto posY = pos.y();
434 auto dropIndex = floor(posY / graphHeight);
434 auto dropIndex = floor(posY / graphHeight);
435 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
435 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
436
436
437
437
438 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
438 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
439 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
439 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
440
440
441 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
441 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
442
442
443 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
443 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
444
444
445 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
445 auto acceptMerge = m_AcceptDragWidgetFun(dragWidgetHovered, mimeData);
446 if (isOnBottom) {
446
447 if (canInsert && (isOnTop || isOnBottom || !canMerge || !acceptMerge)) {
448 if (posY > (dropIndex + 1) * graphHeight - graphHeight / 2.0) {
447 dropIndex += 1;
449 dropIndex += 1;
448 }
450 }
449
451
450 if (helper.getCurrentDragWidget()) {
452 if (helper.getCurrentDragWidget()) {
451 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
453 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
452 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
454 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
453 // Correction of the index if the drop occurs in the same container
455 // Correction of the index if the drop occurs in the same container
454 // and if the drag is started from the visualization (in that case, the
456 // and if the drag is started from the visualization (in that case, the
455 // dragWidget is hidden)
457 // dragWidget is hidden)
456 dropIndex += 1;
458 dropIndex += 1;
457 }
459 }
458 }
460 }
459
461
460 if (dropIndex != placeHolderIndex) {
462 if (dropIndex != placeHolderIndex) {
461 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
463 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
462 m_PlaceHolderText);
464 m_PlaceHolderText);
463 }
465 }
464
466
465 helper.setHightlightedDragWidget(nullptr);
467 helper.setHightlightedDragWidget(nullptr);
466 }
468 }
467 else if (canMerge && dragWidgetHovered) {
469 else if (canMerge && dragWidgetHovered) {
468 // drop on the middle -> merge
470 // drop on the middle -> merge
469 if (hasPlaceHolder()) {
471 if (hasPlaceHolder()) {
470 helper.removePlaceHolder();
472 helper.removePlaceHolder();
471 }
473 }
472
474
473 if (m_AcceptDragWidgetFun(dragWidgetHovered, mimeData)) {
474 helper.setHightlightedDragWidget(dragWidgetHovered);
475 helper.setHightlightedDragWidget(dragWidgetHovered);
475 return true;
476 }
477 else {
478 return false;
479 }
480 }
476 }
481 else {
477 else {
482 qCWarning(LOG_VisualizationDragDropContainer())
478 qCWarning(LOG_VisualizationDragDropContainer())
483 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
479 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
484 "action.");
480 "action.");
485 }
481 }
486 }
482 }
487 else {
483 else {
488 qCWarning(LOG_VisualizationDragDropContainer())
484 qCWarning(LOG_VisualizationDragDropContainer())
489 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
485 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
490 "found in the "
486 "found in the "
491 "container");
487 "container");
492 }
488 }
493 }
489 }
494 else {
490 else {
495 // the mouse is hover the placeHolder
491 // the mouse is hover the placeHolder
496 // Do nothing
492 // Do nothing
497 }
493 }
498
494
499 return true;
495 return true;
500 }
496 }
General Comments 4
Under Review
author

Auto status change to "Under Review"

Approved

Status change > Approved

Approved

Status change > Approved

You need to be logged in to leave comments. Login now