##// END OF EJS Templates
Fix some glitches which occurred when dragging in the visualization something from the sides.
trabillard -
r886:4ed691514436
parent child
Show More
@@ -1,52 +1,52
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 <QLoggingCategory>
6 #include <QLoggingCategory>
6 #include <QMimeData>
7 #include <QMimeData>
7 #include <QVBoxLayout>
8 #include <QVBoxLayout>
8 #include <QWidget>
9
9
10 #include <functional>
10 #include <functional>
11
11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
13
13
14 class VisualizationDragWidget;
14 class VisualizationDragWidget;
15
15
16 class VisualizationDragDropContainer : public QWidget {
16 class VisualizationDragDropContainer : public QFrame {
17 Q_OBJECT
17 Q_OBJECT
18
18
19 signals:
19 signals:
20 void dropOccuredInContainer(int dropIndex, const QMimeData *mimeData);
20 void dropOccuredInContainer(int dropIndex, const QMimeData *mimeData);
21 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
21 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
22
22
23 public:
23 public:
24 enum class DropBehavior { Inserted, Merged, InsertedAndMerged };
24 enum class DropBehavior { Inserted, Merged, InsertedAndMerged };
25 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
25 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
26
26
27 VisualizationDragDropContainer(QWidget *parent = nullptr);
27 VisualizationDragDropContainer(QWidget *parent = nullptr);
28
28
29 void addDragWidget(VisualizationDragWidget *dragWidget);
29 void addDragWidget(VisualizationDragWidget *dragWidget);
30 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
30 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
31
31
32 void addAcceptedMimeType(const QString &mimeType, DropBehavior behavior);
32 void addAcceptedMimeType(const QString &mimeType, DropBehavior behavior);
33
33
34 int countDragWidget() const;
34 int countDragWidget() const;
35
35
36 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
36 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
37
37
38 protected:
38 protected:
39 void dragEnterEvent(QDragEnterEvent *event);
39 void dragEnterEvent(QDragEnterEvent *event);
40 void dragLeaveEvent(QDragLeaveEvent *event);
40 void dragLeaveEvent(QDragLeaveEvent *event);
41 void dragMoveEvent(QDragMoveEvent *event);
41 void dragMoveEvent(QDragMoveEvent *event);
42 void dropEvent(QDropEvent *event);
42 void dropEvent(QDropEvent *event);
43
43
44 private:
44 private:
45 class VisualizationDragDropContainerPrivate;
45 class VisualizationDragDropContainerPrivate;
46 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
46 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
47
47
48 private slots:
48 private slots:
49 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
49 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
50 };
50 };
51
51
52 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
52 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
@@ -1,435 +1,442
1 #include "Visualization/VisualizationDragDropContainer.h"
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragDropHelper.h"
2 #include "DragDropHelper.h"
3 #include "SqpApplication.h"
3 #include "SqpApplication.h"
4 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5
5
6 #include "Common/VisualizationDef.h"
6 #include "Common/VisualizationDef.h"
7
7
8 #include <QDrag>
8 #include <QDrag>
9 #include <QDragEnterEvent>
9 #include <QDragEnterEvent>
10 #include <QVBoxLayout>
10 #include <QVBoxLayout>
11
11
12 #include <cmath>
12 #include <cmath>
13 #include <memory>
13 #include <memory>
14
14
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
16
16
17 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
17 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
18
18
19 QVBoxLayout *m_Layout;
19 QVBoxLayout *m_Layout;
20 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
20 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
21
21
22 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
22 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
23 = [](auto mimeData) { return true; };
23 = [](auto mimeData) { return true; };
24
24
25 int m_MinContainerHeight = 0;
25 int m_MinContainerHeight = 0;
26
26
27 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
27 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
28 {
28 {
29 m_Layout = new QVBoxLayout(widget);
29 m_Layout = new QVBoxLayout(widget);
30 m_Layout->setContentsMargins(0, 0, 0, 0);
30 m_Layout->setContentsMargins(0, 0, 0, 0);
31 }
31 }
32
32
33 bool acceptMimeData(const QMimeData *data) const
33 bool acceptMimeData(const QMimeData *data) const
34 {
34 {
35 for (const auto &type : m_AcceptedMimeTypes.keys()) {
35 for (const auto &type : m_AcceptedMimeTypes.keys()) {
36 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
36 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
37 return true;
37 return true;
38 }
38 }
39 }
39 }
40
40
41 return false;
41 return false;
42 }
42 }
43
43
44 bool allowMergeForMimeData(const QMimeData *data) const
44 bool allowMergeForMimeData(const QMimeData *data) const
45 {
45 {
46 bool result = false;
46 bool result = false;
47 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
47 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
48 ++it) {
48 ++it) {
49
49
50 if (data->hasFormat(it.key())
50 if (data->hasFormat(it.key())
51 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
51 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
52 || it.value()
52 || it.value()
53 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
53 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
54 result = true;
54 result = true;
55 }
55 }
56 else if (data->hasFormat(it.key())
56 else if (data->hasFormat(it.key())
57 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
57 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
58 // Merge is forbidden if the mime data contain an acceptable type which cannot be
58 // Merge is forbidden if the mime data contain an acceptable type which cannot be
59 // merged
59 // merged
60 result = false;
60 result = false;
61 break;
61 break;
62 }
62 }
63 }
63 }
64
64
65 return result;
65 return result;
66 }
66 }
67
67
68 bool allowInsertForMimeData(const QMimeData *data) const
68 bool allowInsertForMimeData(const QMimeData *data) const
69 {
69 {
70 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
70 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
71 ++it) {
71 ++it) {
72 if (data->hasFormat(it.key())
72 if (data->hasFormat(it.key())
73 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
73 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
74 || it.value()
74 || it.value()
75 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
75 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
76 return true;
76 return true;
77 }
77 }
78 }
78 }
79
79
80 return false;
80 return false;
81 }
81 }
82
82
83 bool hasPlaceHolder() const
83 bool hasPlaceHolder() const
84 {
84 {
85 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
85 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
86 }
86 }
87
87
88 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
88 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
89 {
89 {
90 VisualizationDragWidget *dragWidget = nullptr;
90 VisualizationDragWidget *dragWidget = nullptr;
91
91
92 for (auto child : parent->children()) {
92 for (auto child : parent->children()) {
93 auto widget = qobject_cast<VisualizationDragWidget *>(child);
93 auto widget = qobject_cast<VisualizationDragWidget *>(child);
94 if (widget && widget->isVisible()) {
94 if (widget && widget->isVisible()) {
95 if (widget->frameGeometry().contains(pos)) {
95 if (widget->frameGeometry().contains(pos)) {
96 dragWidget = widget;
96 dragWidget = widget;
97 break;
97 break;
98 }
98 }
99 }
99 }
100 }
100 }
101
101
102 return dragWidget;
102 return dragWidget;
103 }
103 }
104
104
105 bool cursorIsInContainer(QWidget *container) const
105 bool cursorIsInContainer(QWidget *container) const
106 {
106 {
107 return container->isAncestorOf(sqpApp->widgetAt(QCursor::pos()));
107 return container->isAncestorOf(sqpApp->widgetAt(QCursor::pos()));
108 }
108 }
109
109
110 int countDragWidget(const QWidget *parent) const
110 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
111 {
111 {
112 auto nbGraph = 0;
112 auto nbGraph = 0;
113 for (auto child : parent->children()) {
113 for (auto child : parent->children()) {
114 if (qobject_cast<VisualizationDragWidget *>(child)) {
114 if (qobject_cast<VisualizationDragWidget *>(child)) {
115 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
115 nbGraph += 1;
116 nbGraph += 1;
116 }
117 }
117 }
118 }
119 }
118
120
119 return nbGraph;
121 return nbGraph;
120 }
122 }
121
123
122 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
124 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
123 const VisualizationDragDropContainer *container);
125 const VisualizationDragDropContainer *container);
124 };
126 };
125
127
126 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
128 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
127 : QWidget{parent},
129 : QFrame{parent},
128 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
130 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
129 {
131 {
130 setAcceptDrops(true);
132 setAcceptDrops(true);
131 }
133 }
132
134
133 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
135 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
134 {
136 {
135 impl->m_Layout->addWidget(dragWidget);
137 impl->m_Layout->addWidget(dragWidget);
136 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
138 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
137 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
139 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
138 &VisualizationDragDropContainer::startDrag);
140 &VisualizationDragDropContainer::startDrag);
139 }
141 }
140
142
141 void VisualizationDragDropContainer::insertDragWidget(int index,
143 void VisualizationDragDropContainer::insertDragWidget(int index,
142 VisualizationDragWidget *dragWidget)
144 VisualizationDragWidget *dragWidget)
143 {
145 {
144 impl->m_Layout->insertWidget(index, dragWidget);
146 impl->m_Layout->insertWidget(index, dragWidget);
145 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
147 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
146 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
148 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
147 &VisualizationDragDropContainer::startDrag);
149 &VisualizationDragDropContainer::startDrag);
148 }
150 }
149
151
150 void VisualizationDragDropContainer::addAcceptedMimeType(
152 void VisualizationDragDropContainer::addAcceptedMimeType(
151 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
153 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
152 {
154 {
153 impl->m_AcceptedMimeTypes[mimeType] = behavior;
155 impl->m_AcceptedMimeTypes[mimeType] = behavior;
154 }
156 }
155
157
156 int VisualizationDragDropContainer::countDragWidget() const
158 int VisualizationDragDropContainer::countDragWidget() const
157 {
159 {
158 return impl->countDragWidget(this);
160 return impl->countDragWidget(this);
159 }
161 }
160
162
161 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
163 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
162 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
164 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
163 {
165 {
164 impl->m_AcceptMimeDataFun = fun;
166 impl->m_AcceptMimeDataFun = fun;
165 }
167 }
166
168
167 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
169 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
168 const QPoint &dragPosition)
170 const QPoint &dragPosition)
169 {
171 {
170 auto &helper = sqpApp->dragDropHelper();
172 auto &helper = sqpApp->dragDropHelper();
171 helper.resetDragAndDrop();
173 helper.resetDragAndDrop();
172
174
173 // Note: The management of the drag object is done by Qt
175 // Note: The management of the drag object is done by Qt
174 auto drag = new QDrag{dragWidget};
176 auto drag = new QDrag{dragWidget};
175 drag->setHotSpot(dragPosition);
177 drag->setHotSpot(dragPosition);
176
178
177 auto mimeData = dragWidget->mimeData();
179 auto mimeData = dragWidget->mimeData();
178 drag->setMimeData(mimeData);
180 drag->setMimeData(mimeData);
179
181
180 auto pixmap = QPixmap(dragWidget->size());
182 auto pixmap = QPixmap(dragWidget->size());
181 dragWidget->render(&pixmap);
183 dragWidget->render(&pixmap);
182 drag->setPixmap(pixmap);
184 drag->setPixmap(pixmap);
183
185
184 auto image = pixmap.toImage();
186 auto image = pixmap.toImage();
185 mimeData->setImageData(image);
187 mimeData->setImageData(image);
186 mimeData->setUrls({helper.imageTemporaryUrl(image)});
188 mimeData->setUrls({helper.imageTemporaryUrl(image)});
187
189
188 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
190 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
189 helper.setCurrentDragWidget(dragWidget);
191 helper.setCurrentDragWidget(dragWidget);
190
192
191 if (impl->cursorIsInContainer(this)) {
193 if (impl->cursorIsInContainer(this)) {
192 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
194 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
193 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
195 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
194 dragWidget->setVisible(false);
196 dragWidget->setVisible(false);
195 }
197 }
196 else {
198 else {
197 // The drag starts directly outside the drop zone
199 // The drag starts directly outside the drop zone
198 // do not add the placeHolder
200 // do not add the placeHolder
199 }
201 }
200
202
201 // Note: The exec() is blocking on windows but not on linux and macOS
203 // Note: The exec() is blocking on windows but not on linux and macOS
202 drag->exec(Qt::MoveAction | Qt::CopyAction);
204 drag->exec(Qt::MoveAction | Qt::CopyAction);
203 }
205 }
204 else {
206 else {
205 qCWarning(LOG_VisualizationDragDropContainer())
207 qCWarning(LOG_VisualizationDragDropContainer())
206 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
208 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
207 "VisualizationDragWidget is not found in this container.");
209 "VisualizationDragWidget is not found in this container.");
208 }
210 }
209 }
211 }
210
212
211 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
213 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
212 {
214 {
213 if (impl->acceptMimeData(event->mimeData())) {
215 if (impl->acceptMimeData(event->mimeData())) {
214 event->acceptProposedAction();
216 event->acceptProposedAction();
215
217
216 auto &helper = sqpApp->dragDropHelper();
218 auto &helper = sqpApp->dragDropHelper();
217
219
218 if (!impl->hasPlaceHolder()) {
220 if (!impl->hasPlaceHolder()) {
219 auto dragWidget = helper.getCurrentDragWidget();
221 auto dragWidget = helper.getCurrentDragWidget();
220
222
221 if (dragWidget) {
223 if (dragWidget) {
222 // If the drag&drop is internal to the visualization, entering the container hide
224 // If the drag&drop is internal to the visualization, entering the container hide
223 // the dragWidget which was made visible by the dragLeaveEvent
225 // the dragWidget which was made visible by the dragLeaveEvent
224 auto parentWidget
226 auto parentWidget
225 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
227 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
226 if (parentWidget) {
228 if (parentWidget) {
227 dragWidget->setVisible(false);
229 dragWidget->setVisible(false);
228 }
230 }
229 }
231 }
230
232
231 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
233 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
232 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
234 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
233 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
235 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
234 }
236 }
235 else {
237 else {
236 // do nothing
238 // do nothing
237 }
239 }
238 }
240 }
239 else {
241 else {
240 event->ignore();
242 event->ignore();
241 }
243 }
242
244
243 QWidget::dragEnterEvent(event);
245 QWidget::dragEnterEvent(event);
244 }
246 }
245
247
246 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
248 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
247 {
249 {
248 Q_UNUSED(event);
250 Q_UNUSED(event);
249
251
250 auto &helper = sqpApp->dragDropHelper();
252 auto &helper = sqpApp->dragDropHelper();
251
253
252 if (!impl->cursorIsInContainer(this)) {
254 if (!impl->cursorIsInContainer(this)) {
253 helper.removePlaceHolder();
255 helper.removePlaceHolder();
254 helper.setHightlightedDragWidget(nullptr);
256 helper.setHightlightedDragWidget(nullptr);
255 impl->m_MinContainerHeight = 0;
257 impl->m_MinContainerHeight = 0;
256
258
257 auto dragWidget = helper.getCurrentDragWidget();
259 auto dragWidget = helper.getCurrentDragWidget();
258 if (dragWidget) {
260 if (dragWidget) {
259 // dragWidget has a value only if the drag is started from the visualization
261 // dragWidget has a value only if the drag is started from the visualization
260 // In that case, shows the drag widget at its original place
262 // In that case, shows the drag widget at its original place
261 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
263 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
262 // drop zone (It is not possible to catch a drop event outside of the application)
264 // drop zone (It is not possible to catch a drop event outside of the application)
263
265
264 if (dragWidget) {
266 if (dragWidget) {
265 dragWidget->setVisible(true);
267 dragWidget->setVisible(true);
266 }
268 }
267 }
269 }
268 }
270 }
269 else {
271 else {
270 // Leave event probably received for a child widget.
272 // Leave event probably received for a child widget.
271 // Do nothing.
273 // Do nothing.
272 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
274 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
273 }
275 }
274
276
275 QWidget::dragLeaveEvent(event);
277 QWidget::dragLeaveEvent(event);
276 }
278 }
277
279
278 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
280 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
279 {
281 {
280 if (impl->acceptMimeData(event->mimeData())) {
282 if (impl->acceptMimeData(event->mimeData())) {
281 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
283 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
282 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
284 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
283 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
285 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
284 }
286 }
285 else {
287 else {
286 event->ignore();
288 event->ignore();
287 }
289 }
288
290
289 QWidget::dragMoveEvent(event);
291 QWidget::dragMoveEvent(event);
290 }
292 }
291
293
292 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
294 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
293 {
295 {
294 auto &helper = sqpApp->dragDropHelper();
296 auto &helper = sqpApp->dragDropHelper();
295
297
296 if (impl->acceptMimeData(event->mimeData())) {
298 if (impl->acceptMimeData(event->mimeData())) {
297 auto dragWidget = helper.getCurrentDragWidget();
299 auto dragWidget = helper.getCurrentDragWidget();
298 if (impl->hasPlaceHolder()) {
300 if (impl->hasPlaceHolder()) {
299 // drop where the placeHolder is located
301 // drop where the placeHolder is located
300
302
301 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
303 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
302 if (canInsert) {
304 if (canInsert) {
303 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
305 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
304
306
305 if (dragWidget) {
307 if (dragWidget) {
306 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
308 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
307 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
309 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
308 // Correction of the index if the drop occurs in the same container
310 // Correction of the index if the drop occurs in the same container
309 // and if the drag is started from the visualization (in that case, the
311 // and if the drag is started from the visualization (in that case, the
310 // dragWidget is hidden)
312 // dragWidget is hidden)
311 droppedIndex -= 1;
313 droppedIndex -= 1;
312 }
314 }
313
315
314 dragWidget->setVisible(true);
316 dragWidget->setVisible(true);
315 }
317 }
316
318
317 event->acceptProposedAction();
319 event->acceptProposedAction();
318
320
319 helper.removePlaceHolder();
321 helper.removePlaceHolder();
320
322
321 emit dropOccuredInContainer(droppedIndex, event->mimeData());
323 emit dropOccuredInContainer(droppedIndex, event->mimeData());
322 }
324 }
323 else {
325 else {
324 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
326 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
325 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
327 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
326 "the insertion is forbidden.");
328 "the insertion is forbidden.");
327 Q_ASSERT(false);
329 Q_ASSERT(false);
328 }
330 }
329 }
331 }
330 else if (helper.getHightlightedDragWidget()) {
332 else if (helper.getHightlightedDragWidget()) {
331 // drop on the highlighted widget
333 // drop on the highlighted widget
332
334
333 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
335 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
334 if (canMerge) {
336 if (canMerge) {
335 event->acceptProposedAction();
337 event->acceptProposedAction();
336 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
338 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
337 }
339 }
338 else {
340 else {
339 qCWarning(LOG_VisualizationDragDropContainer())
341 qCWarning(LOG_VisualizationDragDropContainer())
340 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
342 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
341 "the merge is forbidden.");
343 "the merge is forbidden.");
342 Q_ASSERT(false);
344 Q_ASSERT(false);
343 }
345 }
344 }
346 }
345 }
347 }
346 else {
348 else {
347 event->ignore();
349 event->ignore();
348 }
350 }
349
351
350 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
352 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
351 impl->m_MinContainerHeight = 0;
353 impl->m_MinContainerHeight = 0;
352
354
353 QWidget::dropEvent(event);
355 QWidget::dropEvent(event);
354 }
356 }
355
357
356
358
357 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
359 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
358 const QPoint &pos, bool canInsert, bool canMerge,
360 const QPoint &pos, bool canInsert, bool canMerge,
359 const VisualizationDragDropContainer *container)
361 const VisualizationDragDropContainer *container)
360 {
362 {
361 auto &helper = sqpApp->dragDropHelper();
363 auto &helper = sqpApp->dragDropHelper();
362
364
363 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
365 auto absPos = container->mapToGlobal(pos);
364 if (dragWidgetHovered) {
366 auto isOnPlaceHolder = sqpApp->widgetAt(absPos) == &(helper.placeHolder());
367
368 if (countDragWidget(container, true) == 0) {
369 // Drop on an empty container, just add the placeHolder at the top
370 helper.insertPlaceHolder(m_Layout, 0);
371 }
372 else if (!isOnPlaceHolder) {
365 auto nbDragWidget = countDragWidget(container);
373 auto nbDragWidget = countDragWidget(container);
366 if (nbDragWidget > 0) {
374 if (nbDragWidget > 0) {
367
375
368 if (m_MinContainerHeight == 0) {
376 if (m_MinContainerHeight == 0) {
369 m_MinContainerHeight = container->size().height();
377 m_MinContainerHeight = container->size().height();
370 }
378 }
371
379
372 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
380 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
373 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
381 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
374
382
375 auto posY = pos.y();
383 auto posY = pos.y();
376 auto dropIndex = floor(posY / graphHeight);
384 auto dropIndex = floor(posY / graphHeight);
377 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
385 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
378
386
379
387
380 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
388 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
381 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
389 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
382
390
383 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
391 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
384
392
393 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
394
385 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
395 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
386 if (isOnBottom) {
396 if (isOnBottom) {
387 dropIndex += 1;
397 dropIndex += 1;
388 }
398 }
389
399
390 if (helper.getCurrentDragWidget()) {
400 if (helper.getCurrentDragWidget()) {
391 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
401 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
392 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
402 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
393 // Correction of the index if the drop occurs in the same container
403 // Correction of the index if the drop occurs in the same container
394 // and if the drag is started from the visualization (in that case, the
404 // and if the drag is started from the visualization (in that case, the
395 // dragWidget is hidden)
405 // dragWidget is hidden)
396 dropIndex += 1;
406 dropIndex += 1;
397 }
407 }
398 }
408 }
399
409
400 if (dropIndex != placeHolderIndex) {
410 if (dropIndex != placeHolderIndex) {
401 helper.insertPlaceHolder(m_Layout, dropIndex);
411 helper.insertPlaceHolder(m_Layout, dropIndex);
402 }
412 }
403
413
404 helper.setHightlightedDragWidget(nullptr);
414 helper.setHightlightedDragWidget(nullptr);
405 }
415 }
406 else if (canMerge) {
416 else if (canMerge && dragWidgetHovered) {
407 // drop on the middle -> merge
417 // drop on the middle -> merge
408 if (hasPlaceHolder()) {
418 if (hasPlaceHolder()) {
409 helper.removePlaceHolder();
419 helper.removePlaceHolder();
410 }
420 }
411
421
412 helper.setHightlightedDragWidget(dragWidgetHovered);
422 helper.setHightlightedDragWidget(dragWidgetHovered);
413 }
423 }
414 else {
424 else {
415 qCWarning(LOG_VisualizationDragDropContainer())
425 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
416 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
426 "VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
417 "action.");
427 "action.");
418 Q_ASSERT(false);
428 Q_ASSERT(false);
419 }
429 }
420 }
430 }
421 else {
431 else {
422 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
432 qCWarning(LOG_VisualizationDragDropContainer())
423 "VisualizationDragDropContainer::findPlaceHolderPosition, no widget found in the "
433 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
434 "found in the "
424 "container");
435 "container");
425 }
436 }
426 }
437 }
427 else if (!hasPlaceHolder() && canInsert) {
428 // Drop on an empty container, just add the placeHolder at the top
429 helper.insertPlaceHolder(m_Layout, 0);
430 }
431 else {
438 else {
432 // No hovered drag widget, the mouse is probably hover the placeHolder
439 // the mouse is hover the placeHolder
433 // Do nothing
440 // Do nothing
434 }
441 }
435 }
442 }
@@ -1,84 +1,88
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>VisualizationTabWidget</class>
3 <class>VisualizationTabWidget</class>
4 <widget class="QWidget" name="VisualizationTabWidget">
4 <widget class="QWidget" name="VisualizationTabWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>400</width>
9 <width>400</width>
10 <height>300</height>
10 <height>300</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="windowTitle">
13 <property name="windowTitle">
14 <string>Form</string>
14 <string>Form</string>
15 </property>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout">
16 <layout class="QVBoxLayout" name="verticalLayout">
17 <property name="leftMargin">
17 <property name="leftMargin">
18 <number>0</number>
18 <number>0</number>
19 </property>
19 </property>
20 <property name="topMargin">
20 <property name="topMargin">
21 <number>0</number>
21 <number>0</number>
22 </property>
22 </property>
23 <property name="rightMargin">
23 <property name="rightMargin">
24 <number>0</number>
24 <number>0</number>
25 </property>
25 </property>
26 <property name="bottomMargin">
26 <property name="bottomMargin">
27 <number>0</number>
27 <number>0</number>
28 </property>
28 </property>
29 <item>
29 <item>
30 <widget class="QScrollArea" name="scrollArea">
30 <widget class="QScrollArea" name="scrollArea">
31 <property name="frameShape">
31 <property name="frameShape">
32 <enum>QFrame::NoFrame</enum>
32 <enum>QFrame::NoFrame</enum>
33 </property>
33 </property>
34 <property name="frameShadow">
34 <property name="frameShadow">
35 <enum>QFrame::Sunken</enum>
35 <enum>QFrame::Sunken</enum>
36 </property>
36 </property>
37 <property name="widgetResizable">
37 <property name="widgetResizable">
38 <bool>true</bool>
38 <bool>true</bool>
39 </property>
39 </property>
40 <widget class="QWidget" name="scrollAreaWidgetContents">
40 <widget class="QWidget" name="scrollAreaWidgetContents">
41 <property name="geometry">
41 <property name="geometry">
42 <rect>
42 <rect>
43 <x>0</x>
43 <x>0</x>
44 <y>0</y>
44 <y>0</y>
45 <width>400</width>
45 <width>400</width>
46 <height>300</height>
46 <height>300</height>
47 </rect>
47 </rect>
48 </property>
48 </property>
49 <layout class="QVBoxLayout" name="verticalLayout_3">
49 <layout class="QVBoxLayout" name="verticalLayout_3">
50 <property name="spacing">
50 <property name="spacing">
51 <number>3</number>
51 <number>3</number>
52 </property>
52 </property>
53 <property name="leftMargin">
53 <property name="leftMargin">
54 <number>0</number>
54 <number>0</number>
55 </property>
55 </property>
56 <property name="topMargin">
56 <property name="topMargin">
57 <number>0</number>
57 <number>0</number>
58 </property>
58 </property>
59 <property name="rightMargin">
59 <property name="rightMargin">
60 <number>0</number>
60 <number>0</number>
61 </property>
61 </property>
62 <property name="bottomMargin">
62 <property name="bottomMargin">
63 <number>0</number>
63 <number>0</number>
64 </property>
64 </property>
65 <item>
65 <item>
66 <widget class="VisualizationDragDropContainer" name="dragDropContainer" native="true"/>
66 <widget class="VisualizationDragDropContainer" name="dragDropContainer">
67 <property name="lineWidth">
68 <number>0</number>
69 </property>
70 </widget>
67 </item>
71 </item>
68 </layout>
72 </layout>
69 </widget>
73 </widget>
70 </widget>
74 </widget>
71 </item>
75 </item>
72 </layout>
76 </layout>
73 </widget>
77 </widget>
74 <customwidgets>
78 <customwidgets>
75 <customwidget>
79 <customwidget>
76 <class>VisualizationDragDropContainer</class>
80 <class>VisualizationDragDropContainer</class>
77 <extends>QWidget</extends>
81 <extends>QFrame</extends>
78 <header>Visualization/VisualizationDragDropContainer.h</header>
82 <header>Visualization/VisualizationDragDropContainer.h</header>
79 <container>1</container>
83 <container>1</container>
80 </customwidget>
84 </customwidget>
81 </customwidgets>
85 </customwidgets>
82 <resources/>
86 <resources/>
83 <connections/>
87 <connections/>
84 </ui>
88 </ui>
@@ -1,128 +1,125
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>VisualizationZoneWidget</class>
3 <class>VisualizationZoneWidget</class>
4 <widget class="QWidget" name="VisualizationZoneWidget">
4 <widget class="QWidget" name="VisualizationZoneWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>400</width>
9 <width>400</width>
10 <height>300</height>
10 <height>300</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="windowTitle">
13 <property name="windowTitle">
14 <string>Form</string>
14 <string>Form</string>
15 </property>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout_2">
16 <layout class="QVBoxLayout" name="verticalLayout_2">
17 <property name="spacing">
17 <property name="spacing">
18 <number>0</number>
18 <number>0</number>
19 </property>
19 </property>
20 <property name="leftMargin">
20 <property name="leftMargin">
21 <number>0</number>
21 <number>0</number>
22 </property>
22 </property>
23 <property name="topMargin">
23 <property name="topMargin">
24 <number>0</number>
24 <number>0</number>
25 </property>
25 </property>
26 <property name="rightMargin">
26 <property name="rightMargin">
27 <number>0</number>
27 <number>0</number>
28 </property>
28 </property>
29 <property name="bottomMargin">
29 <property name="bottomMargin">
30 <number>0</number>
30 <number>0</number>
31 </property>
31 </property>
32 <item>
32 <item>
33 <widget class="QWidget" name="infobar" native="true">
33 <widget class="QWidget" name="infobar" native="true">
34 <property name="sizePolicy">
34 <property name="sizePolicy">
35 <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
35 <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
36 <horstretch>0</horstretch>
36 <horstretch>0</horstretch>
37 <verstretch>0</verstretch>
37 <verstretch>0</verstretch>
38 </sizepolicy>
38 </sizepolicy>
39 </property>
39 </property>
40 <layout class="QHBoxLayout" name="horizontalLayout">
40 <layout class="QHBoxLayout" name="horizontalLayout">
41 <property name="spacing">
41 <property name="spacing">
42 <number>0</number>
42 <number>0</number>
43 </property>
43 </property>
44 <property name="leftMargin">
44 <property name="leftMargin">
45 <number>0</number>
45 <number>0</number>
46 </property>
46 </property>
47 <property name="topMargin">
47 <property name="topMargin">
48 <number>0</number>
48 <number>0</number>
49 </property>
49 </property>
50 <property name="rightMargin">
50 <property name="rightMargin">
51 <number>0</number>
51 <number>0</number>
52 </property>
52 </property>
53 <property name="bottomMargin">
53 <property name="bottomMargin">
54 <number>0</number>
54 <number>0</number>
55 </property>
55 </property>
56 <item>
56 <item>
57 <widget class="QLabel" name="zoneNameLabel">
57 <widget class="QLabel" name="zoneNameLabel">
58 <property name="styleSheet">
58 <property name="styleSheet">
59 <string notr="true">color: rgb(127, 127, 127);
59 <string notr="true">color: rgb(127, 127, 127);
60 </string>
60 </string>
61 </property>
61 </property>
62 <property name="text">
62 <property name="text">
63 <string>TextLabel</string>
63 <string>TextLabel</string>
64 </property>
64 </property>
65 </widget>
65 </widget>
66 </item>
66 </item>
67 <item>
67 <item>
68 <widget class="QToolButton" name="closeButton">
68 <widget class="QToolButton" name="closeButton">
69 <property name="styleSheet">
69 <property name="styleSheet">
70 <string notr="true">background-color: transparent;</string>
70 <string notr="true">background-color: transparent;</string>
71 </property>
71 </property>
72 <property name="text">
72 <property name="text">
73 <string>Close</string>
73 <string>Close</string>
74 </property>
74 </property>
75 </widget>
75 </widget>
76 </item>
76 </item>
77 </layout>
77 </layout>
78 </widget>
78 </widget>
79 </item>
79 </item>
80 <item>
80 <item>
81 <widget class="QFrame" name="visualizationZoneFrame">
81 <widget class="VisualizationDragDropContainer" name="dragDropContainer">
82 <property name="sizePolicy">
82 <property name="sizePolicy">
83 <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
83 <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
84 <horstretch>0</horstretch>
84 <horstretch>0</horstretch>
85 <verstretch>0</verstretch>
85 <verstretch>0</verstretch>
86 </sizepolicy>
86 </sizepolicy>
87 </property>
87 </property>
88 <property name="frameShape">
88 <property name="frameShape">
89 <enum>QFrame::Box</enum>
89 <enum>QFrame::Box</enum>
90 </property>
90 </property>
91 <property name="frameShadow">
91 <property name="frameShadow">
92 <enum>QFrame::Raised</enum>
92 <enum>QFrame::Raised</enum>
93 </property>
93 </property>
94 <property name="lineWidth">
94 <property name="lineWidth">
95 <number>1</number>
95 <number>1</number>
96 </property>
96 </property>
97 <layout class="QVBoxLayout" name="verticalLayout">
97 <layout class="QVBoxLayout" name="verticalLayout">
98 <property name="leftMargin">
98 <property name="leftMargin">
99 <number>0</number>
99 <number>0</number>
100 </property>
100 </property>
101 <property name="topMargin">
101 <property name="topMargin">
102 <number>0</number>
102 <number>0</number>
103 </property>
103 </property>
104 <property name="rightMargin">
104 <property name="rightMargin">
105 <number>0</number>
105 <number>0</number>
106 </property>
106 </property>
107 <property name="bottomMargin">
107 <property name="bottomMargin">
108 <number>0</number>
108 <number>0</number>
109 </property>
109 </property>
110 <item>
111 <widget class="VisualizationDragDropContainer" name="dragDropContainer" native="true"/>
112 </item>
113 </layout>
110 </layout>
114 </widget>
111 </widget>
115 </item>
112 </item>
116 </layout>
113 </layout>
117 </widget>
114 </widget>
118 <customwidgets>
115 <customwidgets>
119 <customwidget>
116 <customwidget>
120 <class>VisualizationDragDropContainer</class>
117 <class>VisualizationDragDropContainer</class>
121 <extends>QWidget</extends>
118 <extends>QFrame</extends>
122 <header>Visualization/VisualizationDragDropContainer.h</header>
119 <header>Visualization/VisualizationDragDropContainer.h</header>
123 <container>1</container>
120 <container>1</container>
124 </customwidget>
121 </customwidget>
125 </customwidgets>
122 </customwidgets>
126 <resources/>
123 <resources/>
127 <connections/>
124 <connections/>
128 </ui>
125 </ui>
General Comments 3
Under Review
author

Pull request updated. Auto status change to "Under Review"

Changed commits:
  * 1 added
  * 0 removed

Changed files:
  * A core/tests/meson.build
You need to be logged in to leave comments. Login now