Please modify qDebug to qCDebug
@@ -0,0 +1,45 | |||
|
1 | #ifndef VISUALIZATIONDRAGDROPCONTAINER_H | |
|
2 | #define VISUALIZATIONDRAGDROPCONTAINER_H | |
|
3 | ||
|
4 | #include <QWidget> | |
|
5 | #include <QVBoxLayout> | |
|
6 | #include <QMimeData> | |
|
7 | #include <Common/spimpl.h> | |
|
8 | ||
|
9 | class VisualizationDragWidget; | |
|
10 | ||
|
11 | class VisualizationDragDropContainer : public QWidget | |
|
12 | { | |
|
13 | Q_OBJECT | |
|
14 | ||
|
15 | signals: | |
|
16 | void dropOccured(int dropIndex, const QMimeData* mimeData); | |
|
17 | ||
|
18 | public: | |
|
19 | VisualizationDragDropContainer(QWidget* parent = nullptr); | |
|
20 | ||
|
21 | void addDragWidget(VisualizationDragWidget* dragWidget); | |
|
22 | void insertDragWidget(int index, VisualizationDragWidget* dragWidget); | |
|
23 | ||
|
24 | void setAcceptedMimeTypes(const QStringList& mimeTypes); | |
|
25 | void setMergeAllowedMimeTypes(const QStringList& mimeTypes); | |
|
26 | ||
|
27 | int countDragWidget() const; | |
|
28 | ||
|
29 | protected: | |
|
30 | void dragEnterEvent(QDragEnterEvent *event); | |
|
31 | void dragLeaveEvent(QDragLeaveEvent *event); | |
|
32 | void dragMoveEvent(QDragMoveEvent *event); | |
|
33 | void dropEvent(QDropEvent *event); | |
|
34 | ||
|
35 | private: | |
|
36 | ||
|
37 | ||
|
38 | class VisualizationDragDropContainerPrivate; | |
|
39 | spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl; | |
|
40 | ||
|
41 | private slots: | |
|
42 | void startDrag(VisualizationDragWidget* dragWidget, const QPoint& dragPosition); | |
|
43 | }; | |
|
44 | ||
|
45 | #endif // VISUALIZATIONDRAGDROPCONTAINER_H |
@@ -0,0 +1,30 | |||
|
1 | #ifndef VISUALIZATIONDRAGWIDGET_H | |
|
2 | #define VISUALIZATIONDRAGWIDGET_H | |
|
3 | ||
|
4 | #include <QWidget> | |
|
5 | #include <QMimeData> | |
|
6 | #include <Common/spimpl.h> | |
|
7 | ||
|
8 | class VisualizationDragWidget : public QWidget | |
|
9 | { | |
|
10 | Q_OBJECT | |
|
11 | ||
|
12 | public: | |
|
13 | VisualizationDragWidget(QWidget* parent = nullptr); | |
|
14 | ||
|
15 | virtual QMimeData* mimeData() const = 0; | |
|
16 | virtual bool isDragAllowed() const = 0; | |
|
17 | ||
|
18 | protected: | |
|
19 | virtual void mousePressEvent(QMouseEvent *event) override; | |
|
20 | virtual void mouseMoveEvent(QMouseEvent *event) override; | |
|
21 | ||
|
22 | private: | |
|
23 | class VisualizationDragWidgetPrivate; | |
|
24 | spimpl::unique_impl_ptr<VisualizationDragWidgetPrivate> impl; | |
|
25 | ||
|
26 | signals: | |
|
27 | void dragDetected(VisualizationDragWidget* dragWidget, const QPoint& dragPosition); | |
|
28 | }; | |
|
29 | ||
|
30 | #endif // VISUALIZATIONDRAGWIDGET_H |
@@ -0,0 +1,312 | |||
|
1 | #include "Visualization/VisualizationDragDropContainer.h" | |
|
2 | #include "Visualization/VisualizationDragWidget.h" | |
|
3 | #include "SqpApplication.h" | |
|
4 | #include "DragDropHelper.h" | |
|
5 | ||
|
6 | #include <QDrag> | |
|
7 | #include <QVBoxLayout> | |
|
8 | #include <QDragEnterEvent> | |
|
9 | ||
|
10 | #include <memory> | |
|
11 | ||
|
12 | struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate { | |
|
13 | ||
|
14 | QVBoxLayout* m_layout; | |
|
15 | QStringList m_acceptedMimeTypes; | |
|
16 | QStringList m_mergeAllowedMimeTypes; | |
|
17 | ||
|
18 | explicit VisualizationDragDropContainerPrivate(QWidget* widget) | |
|
19 | { | |
|
20 | m_layout = new QVBoxLayout(widget); | |
|
21 | m_layout->setContentsMargins(0,0,0,0); | |
|
22 | } | |
|
23 | ||
|
24 | bool acceptMimeData(const QMimeData* data) const | |
|
25 | { | |
|
26 | for (const auto& type : m_acceptedMimeTypes) | |
|
27 | { | |
|
28 | if (data->hasFormat(type)) | |
|
29 | return true; | |
|
30 | } | |
|
31 | ||
|
32 | return false; | |
|
33 | } | |
|
34 | ||
|
35 | bool allowMergeMimeData(const QMimeData* data) const | |
|
36 | { | |
|
37 | for (const auto& type : m_mergeAllowedMimeTypes) | |
|
38 | { | |
|
39 | if (data->hasFormat(type)) | |
|
40 | return true; | |
|
41 | } | |
|
42 | ||
|
43 | return false; | |
|
44 | } | |
|
45 | ||
|
46 | bool hasPlaceHolder() const | |
|
47 | { | |
|
48 | return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_layout->parentWidget(); | |
|
49 | } | |
|
50 | ||
|
51 | VisualizationDragWidget* getChildDragWidgetAt(QWidget* parent, const QPoint &pos) const | |
|
52 | { | |
|
53 | VisualizationDragWidget* dragWidget = nullptr; | |
|
54 | ||
|
55 | for (auto child : parent->children()) | |
|
56 | { | |
|
57 | auto widget = qobject_cast<VisualizationDragWidget*>(child); | |
|
58 | if (widget && widget->isVisible()) | |
|
59 | { | |
|
60 | if (widget->frameGeometry().contains(pos)) | |
|
61 | { | |
|
62 | dragWidget = widget; | |
|
63 | break; | |
|
64 | } | |
|
65 | } | |
|
66 | } | |
|
67 | ||
|
68 | return dragWidget; | |
|
69 | } | |
|
70 | ||
|
71 | bool cursorIsInContainer(QWidget* container) const | |
|
72 | { | |
|
73 | auto adustNum = 18; //to be safe, in case of scrollbar on the side | |
|
74 | auto containerRect = QRect(QPoint(), container->contentsRect().size()).adjusted(adustNum, adustNum, -adustNum, -adustNum); | |
|
75 |
qDebug() << containerRect << container->mapFromGlobal(QCursor::pos());
|
|
|
76 | return containerRect.contains(container->mapFromGlobal(QCursor::pos())); | |
|
77 | } | |
|
78 | ||
|
79 | }; | |
|
80 | ||
|
81 | VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent) | |
|
82 | : QWidget{parent}, impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)} | |
|
83 | { | |
|
84 | setAcceptDrops(true); | |
|
85 | } | |
|
86 | ||
|
87 | void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget) | |
|
88 | { | |
|
89 | impl->m_layout->addWidget(dragWidget); | |
|
90 | disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr); | |
|
91 | connect(dragWidget, &VisualizationDragWidget::dragDetected, this, &VisualizationDragDropContainer::startDrag); | |
|
92 | } | |
|
93 | ||
|
94 | void VisualizationDragDropContainer::insertDragWidget(int index, VisualizationDragWidget *dragWidget) | |
|
95 | { | |
|
96 | impl->m_layout->insertWidget(index, dragWidget); | |
|
97 | disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr); | |
|
98 | connect(dragWidget, &VisualizationDragWidget::dragDetected, this, &VisualizationDragDropContainer::startDrag); | |
|
99 | } | |
|
100 | ||
|
101 | void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes) | |
|
102 | { | |
|
103 | impl->m_acceptedMimeTypes = mimeTypes; | |
|
104 | } | |
|
105 | ||
|
106 | void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes) | |
|
107 | { | |
|
108 | impl->m_mergeAllowedMimeTypes = mimeTypes; | |
|
109 | } | |
|
110 | ||
|
111 | int VisualizationDragDropContainer::countDragWidget() const | |
|
112 | { | |
|
113 | auto nbGraph = 0; | |
|
114 | for (auto child : children()) | |
|
115 | { | |
|
116 | auto widget = qobject_cast<VisualizationDragWidget*>(child); | |
|
117 |
if (widget)
if(dynami...) to remove widget local variable |
|
|
118 | { | |
|
119 | nbGraph += 1; | |
|
120 | } | |
|
121 | } | |
|
122 | ||
|
123 | return nbGraph; | |
|
124 | } | |
|
125 | ||
|
126 | void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition) | |
|
127 | { | |
|
128 | auto& helper = sqpApp->dragDropHelper(); | |
|
129 | ||
|
130 | //Note: The management of the drag object is done by Qt | |
|
131 |
auto *drag = new QDrag{dragWidget};
auto drag |
|
|
132 | drag->setHotSpot(dragPosition); | |
|
133 | ||
|
134 | auto mimeData = dragWidget->mimeData(); | |
|
135 | drag->setMimeData(mimeData); | |
|
136 | ||
|
137 | auto pixmap = QPixmap(dragWidget->size()); | |
|
138 | dragWidget->render(&pixmap); | |
|
139 | drag->setPixmap(pixmap); | |
|
140 | ||
|
141 | auto image = pixmap.toImage(); | |
|
142 | mimeData->setImageData(image); | |
|
143 | mimeData->setUrls({helper.imageTemporaryUrl(image)}); | |
|
144 | ||
|
145 | if (impl->m_layout->indexOf(dragWidget) >= 0) | |
|
146 | { | |
|
147 | helper.setCurrentDragWidget(dragWidget); | |
|
148 | ||
|
149 | if (impl->cursorIsInContainer(this)) | |
|
150 | { | |
|
151 | auto dragWidgetIndex = impl->m_layout->indexOf(dragWidget); | |
|
152 | helper.insertPlaceHolder(impl->m_layout, dragWidgetIndex); | |
|
153 | dragWidget->setVisible(false); | |
|
154 | } | |
|
155 | } | |
|
156 | ||
|
157 | //Note: The exec() is blocking on windows but not on linux and macOS | |
|
158 | drag->exec(Qt::MoveAction | Qt::CopyAction); | |
|
159 | } | |
|
160 | ||
|
161 | void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event) | |
|
162 | { | |
|
163 | if (impl->acceptMimeData(event->mimeData())) | |
|
164 | { | |
|
165 | event->acceptProposedAction(); | |
|
166 | ||
|
167 |
auto& helper = sqpApp->dragDropHelper();
auto helper |
|
|
168 | ||
|
169 | if (!impl->hasPlaceHolder()) | |
|
170 | { | |
|
171 | auto dragWidget = helper.getCurrentDragWidget(); | |
|
172 | auto parentWidget = qobject_cast<VisualizationDragDropContainer*>(dragWidget->parentWidget()); | |
|
173 | if (parentWidget) | |
|
174 | { | |
|
175 | dragWidget->setVisible(false); | |
|
176 | } | |
|
177 | ||
|
178 | auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos()); | |
|
179 | ||
|
180 | if (dragWidgetHovered) | |
|
181 | { | |
|
182 | auto hoveredWidgetIndex = impl->m_layout->indexOf(dragWidgetHovered); | |
|
183 | auto dragWidgetIndex = impl->m_layout->indexOf(helper.getCurrentDragWidget()); | |
|
184 | if (dragWidgetIndex >= 0 && dragWidgetIndex <= hoveredWidgetIndex) | |
|
185 | hoveredWidgetIndex += 1; //Correction of the index if the drop occurs in the same container | |
|
186 | ||
|
187 | helper.insertPlaceHolder(impl->m_layout, hoveredWidgetIndex); | |
|
188 | } | |
|
189 | else | |
|
190 | { | |
|
191 | helper.insertPlaceHolder(impl->m_layout, 0); | |
|
192 | } | |
|
193 | } | |
|
194 | } | |
|
195 | else | |
|
196 | event->ignore(); | |
|
197 | ||
|
198 | QWidget::dragEnterEvent(event); | |
|
199 | } | |
|
200 | ||
|
201 | void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event) | |
|
202 | { | |
|
203 | Q_UNUSED(event); | |
|
204 | ||
|
205 |
auto& helper = sqpApp->dragDropHelper();
auto helper |
|
|
206 | ||
|
207 | if (!impl->cursorIsInContainer(this)) | |
|
208 | { | |
|
209 | helper.removePlaceHolder(); | |
|
210 | ||
|
211 | bool isInternal = true; | |
|
212 | if (isInternal) | |
|
213 | { | |
|
214 | //Only if the drag is strated from the visualization | |
|
215 | //Show the drag widget at its original place | |
|
216 | //So the drag widget doesn't stay hidden if the drop occurs outside the visualization drop zone | |
|
217 | //(It is not possible to catch a drop event outside of the application) | |
|
218 | ||
|
219 | auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget(); | |
|
220 | if (dragWidget) | |
|
221 | { | |
|
222 | dragWidget->setVisible(true); | |
|
223 | } | |
|
224 | } | |
|
225 | } | |
|
226 | ||
|
227 | QWidget::dragLeaveEvent(event); | |
|
228 | } | |
|
229 | ||
|
230 | void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event) | |
|
231 | { | |
|
232 | if (impl->acceptMimeData(event->mimeData())) | |
|
233 | { | |
|
234 | auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos()); | |
|
235 | if (dragWidgetHovered) | |
|
236 | { | |
|
237 | auto canMerge = impl->allowMergeMimeData(event->mimeData()); | |
|
238 | ||
|
239 | auto nbDragWidget = countDragWidget(); | |
|
240 | if (nbDragWidget > 0) | |
|
241 | { | |
|
242 | auto graphHeight = size().height() / nbDragWidget; | |
|
243 | auto dropIndex = floor(event->pos().y() / graphHeight); | |
|
244 | auto zoneSize = qMin(graphHeight / 3.0, 150.0); | |
|
245 | ||
|
246 | auto isOnTop = event->pos().y() < dropIndex * graphHeight + zoneSize; | |
|
247 | auto isOnBottom = event->pos().y() > (dropIndex + 1) * graphHeight - zoneSize; | |
|
248 | ||
|
249 | auto& helper = sqpApp->dragDropHelper(); | |
|
250 | auto placeHolderIndex = impl->m_layout->indexOf(&(helper.placeHolder())); | |
|
251 | ||
|
252 | if (isOnTop || isOnBottom) | |
|
253 | { | |
|
254 | if (isOnBottom) | |
|
255 | dropIndex += 1; | |
|
256 | ||
|
257 | auto dragWidgetIndex = impl->m_layout->indexOf(helper.getCurrentDragWidget()); | |
|
258 | if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) | |
|
259 | dropIndex += 1; //Correction of the index if the drop occurs in the same container | |
|
260 | ||
|
261 | if (dropIndex != placeHolderIndex) | |
|
262 | { | |
|
263 | helper.insertPlaceHolder(impl->m_layout, dropIndex); | |
|
264 | } | |
|
265 | } | |
|
266 | else if (canMerge) | |
|
267 | { | |
|
268 | //drop on the middle -> merge | |
|
269 | if (impl->hasPlaceHolder()) | |
|
270 | { | |
|
271 | helper.removePlaceHolder(); | |
|
272 | } | |
|
273 | } | |
|
274 | } | |
|
275 | } | |
|
276 | } | |
|
277 | else | |
|
278 | event->ignore(); | |
|
279 | ||
|
280 | QWidget::dragMoveEvent(event); | |
|
281 | } | |
|
282 | ||
|
283 | void VisualizationDragDropContainer::dropEvent(QDropEvent *event) | |
|
284 | { | |
|
285 | if (impl->acceptMimeData(event->mimeData())) | |
|
286 | { | |
|
287 | auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget(); | |
|
288 | if (impl->hasPlaceHolder() && dragWidget) | |
|
289 | { | |
|
290 | auto& helper = sqpApp->dragDropHelper(); | |
|
291 | ||
|
292 | auto droppedIndex = impl->m_layout->indexOf(&helper.placeHolder()); | |
|
293 | ||
|
294 | auto dragWidgetIndex = impl->m_layout->indexOf(dragWidget); | |
|
295 | if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) | |
|
296 | droppedIndex -= 1; //Correction of the index if the drop occurs in the same container | |
|
297 | ||
|
298 | dragWidget->setVisible(true); | |
|
299 | dragWidget->setStyleSheet(""); | |
|
300 | ||
|
301 | event->acceptProposedAction(); | |
|
302 | ||
|
303 | helper.removePlaceHolder(); | |
|
304 | ||
|
305 | emit dropOccured(droppedIndex, event->mimeData()); | |
|
306 | } | |
|
307 | } | |
|
308 | else | |
|
309 |
event->ignore();
else { } |
|
|
310 | ||
|
311 | QWidget::dropEvent(event); | |
|
312 | } |
@@ -0,0 +1,50 | |||
|
1 | #include "Visualization/VisualizationDragWidget.h" | |
|
2 | #include "Visualization/VisualizationDragDropContainer.h" | |
|
3 | ||
|
4 | #include <QMouseEvent> | |
|
5 | #include <QApplication> | |
|
6 | ||
|
7 | struct VisualizationDragWidget::VisualizationDragWidgetPrivate { | |
|
8 | ||
|
9 | QPoint m_dragStartPosition; | |
|
10 | bool m_dragStartPositionValid = false; | |
|
11 | ||
|
12 | explicit VisualizationDragWidgetPrivate() | |
|
13 | { | |
|
14 | } | |
|
15 | }; | |
|
16 | ||
|
17 | VisualizationDragWidget::VisualizationDragWidget(QWidget* parent) | |
|
18 | : QWidget{parent}, impl{spimpl::make_unique_impl<VisualizationDragWidgetPrivate>()} | |
|
19 | { | |
|
20 | ||
|
21 | } | |
|
22 | ||
|
23 | void VisualizationDragWidget::mousePressEvent(QMouseEvent *event) | |
|
24 | { | |
|
25 | if (event->button() == Qt::LeftButton) | |
|
26 | impl->m_dragStartPosition = event->pos(); | |
|
27 | ||
|
28 | impl->m_dragStartPositionValid = isDragAllowed(); | |
|
29 | ||
|
30 | QWidget::mousePressEvent(event); | |
|
31 | } | |
|
32 | ||
|
33 | void VisualizationDragWidget::mouseMoveEvent(QMouseEvent *event) | |
|
34 | { | |
|
35 | if (!impl->m_dragStartPositionValid || !isDragAllowed()) | |
|
36 | return; | |
|
37 | ||
|
38 | if (!(event->buttons() & Qt::LeftButton)) | |
|
39 | return; | |
|
40 | ||
|
41 | if (!event->modifiers().testFlag(Qt::AltModifier)) | |
|
42 | return; | |
|
43 | ||
|
44 | if ((event->pos() - impl->m_dragStartPosition).manhattanLength() < QApplication::startDragDistance()) | |
|
45 | return; | |
|
46 | ||
|
47 | emit dragDetected(this, impl->m_dragStartPosition); | |
|
48 | ||
|
49 | QWidget::mouseMoveEvent(event); | |
|
50 | } |
General Comments 6
Pull request updated. Auto status change to "Under Review"
Changed commits: * 1 added * 0 removed Changed files: * M gui/include/Visualization/VisualizationDragDropContainer.h * M gui/include/Visualization/VisualizationDragWidget.h * M gui/src/Visualization/VisualizationDragDropContainer.cpp * M gui/src/Visualization/VisualizationGraphWidget.cpp * M gui/src/Visualization/VisualizationZoneWidget.cpp
Status change > Approved
You need to be logged in to leave comments.
Login now