@@ -53,6 +53,8 public: | |||||
53 |
|
53 | |||
54 | QUrl imageTemporaryUrl(const QImage &image) const; |
|
54 | QUrl imageTemporaryUrl(const QImage &image) const; | |
55 |
|
55 | |||
|
56 | void setHightlightedDragWidget(VisualizationDragWidget *dragWidget); | |||
|
57 | ||||
56 | private: |
|
58 | private: | |
57 | class DragDropHelperPrivate; |
|
59 | class DragDropHelperPrivate; | |
58 | spimpl::unique_impl_ptr<DragDropHelperPrivate> impl; |
|
60 | spimpl::unique_impl_ptr<DragDropHelperPrivate> impl; |
@@ -13,6 +13,7 public: | |||||
13 |
|
13 | |||
14 | virtual QMimeData *mimeData() const = 0; |
|
14 | virtual QMimeData *mimeData() const = 0; | |
15 | virtual bool isDragAllowed() const = 0; |
|
15 | virtual bool isDragAllowed() const = 0; | |
|
16 | virtual void highlightForMerge(bool highlighted) { Q_UNUSED(highlighted); }; | |||
16 |
|
17 | |||
17 | protected: |
|
18 | protected: | |
18 | virtual void mousePressEvent(QMouseEvent *event) override; |
|
19 | virtual void mousePressEvent(QMouseEvent *event) override; |
@@ -59,6 +59,7 public: | |||||
59 | // VisualisationDragWidget |
|
59 | // VisualisationDragWidget | |
60 | QMimeData *mimeData() const override; |
|
60 | QMimeData *mimeData() const override; | |
61 | bool isDragAllowed() const override; |
|
61 | bool isDragAllowed() const override; | |
|
62 | void highlightForMerge(bool highlighted) override; | |||
62 |
|
63 | |||
63 | signals: |
|
64 | signals: | |
64 | void synchronize(const SqpRange &range, const SqpRange &oldRange); |
|
65 | void synchronize(const SqpRange &range, const SqpRange &oldRange); |
@@ -29,7 +29,6 struct DragDropScroller::DragDropScrollerPrivate { | |||||
29 | QScrollArea *m_CurrentScrollArea = nullptr; |
|
29 | QScrollArea *m_CurrentScrollArea = nullptr; | |
30 | std::unique_ptr<QTimer> m_Timer = nullptr; |
|
30 | std::unique_ptr<QTimer> m_Timer = nullptr; | |
31 |
|
31 | |||
32 |
|
||||
33 | enum class ScrollDirection { up, down, unknown }; |
|
32 | enum class ScrollDirection { up, down, unknown }; | |
34 | ScrollDirection m_Direction = ScrollDirection::unknown; |
|
33 | ScrollDirection m_Direction = ScrollDirection::unknown; | |
35 |
|
34 | |||
@@ -148,6 +147,8 struct DragDropHelper::DragDropHelperPrivate { | |||||
148 | QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using |
|
147 | QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using | |
149 | // QTemporaryFile to have a name which is not generated. |
|
148 | // QTemporaryFile to have a name which is not generated. | |
150 |
|
149 | |||
|
150 | VisualizationDragWidget *m_HighlightedDragWidget = nullptr; | |||
|
151 | ||||
151 | explicit DragDropHelperPrivate() |
|
152 | explicit DragDropHelperPrivate() | |
152 | : m_PlaceHolder{std::make_unique<QWidget>()}, |
|
153 | : m_PlaceHolder{std::make_unique<QWidget>()}, | |
153 | m_DragDropScroller{std::make_unique<DragDropScroller>()} |
|
154 | m_DragDropScroller{std::make_unique<DragDropScroller>()} | |
@@ -188,6 +189,7 DragDropHelper::~DragDropHelper() | |||||
188 | void DragDropHelper::resetDragAndDrop() |
|
189 | void DragDropHelper::resetDragAndDrop() | |
189 | { |
|
190 | { | |
190 | setCurrentDragWidget(nullptr); |
|
191 | setCurrentDragWidget(nullptr); | |
|
192 | impl->m_HighlightedDragWidget = nullptr; | |||
191 | } |
|
193 | } | |
192 |
|
194 | |||
193 | void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget) |
|
195 | void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget) | |
@@ -245,6 +247,18 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const | |||||
245 | return QUrl::fromLocalFile(impl->m_ImageTempUrl); |
|
247 | return QUrl::fromLocalFile(impl->m_ImageTempUrl); | |
246 | } |
|
248 | } | |
247 |
|
249 | |||
|
250 | void DragDropHelper::setHightlightedDragWidget(VisualizationDragWidget *dragWidget) | |||
|
251 | { | |||
|
252 | if (impl->m_HighlightedDragWidget) { | |||
|
253 | impl->m_HighlightedDragWidget->highlightForMerge(false); | |||
|
254 | } | |||
|
255 | ||||
|
256 | if (dragWidget) { | |||
|
257 | impl->m_HighlightedDragWidget = dragWidget; | |||
|
258 | impl->m_HighlightedDragWidget->highlightForMerge(true); | |||
|
259 | } | |||
|
260 | } | |||
|
261 | ||||
248 | bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData, |
|
262 | bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData, | |
249 | VisualizationDragDropContainer *dropContainer) |
|
263 | VisualizationDragDropContainer *dropContainer) | |
250 | { |
|
264 | { |
@@ -21,6 +21,7 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate { | |||||
21 | QStringList m_MergeAllowedMimeTypes; |
|
21 | QStringList m_MergeAllowedMimeTypes; | |
22 | VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun |
|
22 | VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun | |
23 | = [](auto mimeData) { return true; }; |
|
23 | = [](auto mimeData) { return true; }; | |
|
24 | int m_MinContainerHeight = 0; | |||
24 |
|
25 | |||
25 | explicit VisualizationDragDropContainerPrivate(QWidget *widget) |
|
26 | explicit VisualizationDragDropContainerPrivate(QWidget *widget) | |
26 | { |
|
27 | { | |
@@ -55,7 +56,7 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate { | |||||
55 | return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget(); |
|
56 | return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget(); | |
56 | } |
|
57 | } | |
57 |
|
58 | |||
58 | VisualizationDragWidget *getChildDragWidgetAt(QWidget *parent, const QPoint &pos) const |
|
59 | VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const | |
59 | { |
|
60 | { | |
60 | VisualizationDragWidget *dragWidget = nullptr; |
|
61 | VisualizationDragWidget *dragWidget = nullptr; | |
61 |
|
62 | |||
@@ -79,6 +80,21 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate { | |||||
79 | .adjusted(adustNum, adustNum, -adustNum, -adustNum); |
|
80 | .adjusted(adustNum, adustNum, -adustNum, -adustNum); | |
80 | return containerRect.contains(container->mapFromGlobal(QCursor::pos())); |
|
81 | return containerRect.contains(container->mapFromGlobal(QCursor::pos())); | |
81 | } |
|
82 | } | |
|
83 | ||||
|
84 | int countDragWidget(const QWidget *parent) const | |||
|
85 | { | |||
|
86 | auto nbGraph = 0; | |||
|
87 | for (auto child : parent->children()) { | |||
|
88 | if (qobject_cast<VisualizationDragWidget *>(child)) { | |||
|
89 | nbGraph += 1; | |||
|
90 | } | |||
|
91 | } | |||
|
92 | ||||
|
93 | return nbGraph; | |||
|
94 | } | |||
|
95 | ||||
|
96 | void findPlaceHolderPosition(const QPoint &pos, bool canMerge, | |||
|
97 | const VisualizationDragDropContainer *container); | |||
82 | }; |
|
98 | }; | |
83 |
|
99 | |||
84 | VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent) |
|
100 | VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent) | |
@@ -117,14 +133,7 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList | |||||
117 |
|
133 | |||
118 | int VisualizationDragDropContainer::countDragWidget() const |
|
134 | int VisualizationDragDropContainer::countDragWidget() const | |
119 | { |
|
135 | { | |
120 | auto nbGraph = 0; |
|
136 | return impl->countDragWidget(this); | |
121 | for (auto child : children()) { |
|
|||
122 | if (qobject_cast<VisualizationDragWidget *>(child)) { |
|
|||
123 | nbGraph += 1; |
|
|||
124 | } |
|
|||
125 | } |
|
|||
126 |
|
||||
127 | return nbGraph; |
|
|||
128 | } |
|
137 | } | |
129 |
|
138 | |||
130 | void VisualizationDragDropContainer::setAcceptMimeDataFunction( |
|
139 | void VisualizationDragDropContainer::setAcceptMimeDataFunction( | |
@@ -185,7 +194,7 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event) | |||||
185 |
|
194 | |||
186 | if (dragWidget) { |
|
195 | if (dragWidget) { | |
187 | // If the drag&drop is internal to the visualization, entering the container hide |
|
196 | // If the drag&drop is internal to the visualization, entering the container hide | |
188 |
// the dragWidget which was |
|
197 | // the dragWidget which was made visible by the dragLeaveEvent | |
189 | auto parentWidget |
|
198 | auto parentWidget | |
190 | = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget()); |
|
199 | = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget()); | |
191 | if (parentWidget) { |
|
200 | if (parentWidget) { | |
@@ -193,26 +202,8 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event) | |||||
193 | } |
|
202 | } | |
194 | } |
|
203 | } | |
195 |
|
204 | |||
196 | auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos()); |
|
205 | auto canMerge = impl->allowMergeMimeData(event->mimeData()); | |
197 |
|
206 | impl->findPlaceHolderPosition(event->pos(), canMerge, this); | ||
198 | if (dragWidgetHovered) { |
|
|||
199 | auto hoveredWidgetIndex = impl->m_Layout->indexOf(dragWidgetHovered); |
|
|||
200 |
|
||||
201 | if (dragWidget) { |
|
|||
202 | auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget()); |
|
|||
203 | if (dragWidgetIndex >= 0 && dragWidgetIndex <= hoveredWidgetIndex) { |
|
|||
204 | // Correction of the index if the drop occurs in the same container |
|
|||
205 | // and if the drag is started from the visualization (in that case, the |
|
|||
206 | // dragWidget is hidden) |
|
|||
207 | hoveredWidgetIndex += 1; |
|
|||
208 | } |
|
|||
209 | } |
|
|||
210 |
|
||||
211 | helper.insertPlaceHolder(impl->m_Layout, hoveredWidgetIndex); |
|
|||
212 | } |
|
|||
213 | else { |
|
|||
214 | helper.insertPlaceHolder(impl->m_Layout, 0); |
|
|||
215 | } |
|
|||
216 | } |
|
207 | } | |
217 | else { |
|
208 | else { | |
218 | // do nothing |
|
209 | // do nothing | |
@@ -233,6 +224,8 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event) | |||||
233 |
|
224 | |||
234 | if (!impl->cursorIsInContainer(this)) { |
|
225 | if (!impl->cursorIsInContainer(this)) { | |
235 | helper.removePlaceHolder(); |
|
226 | helper.removePlaceHolder(); | |
|
227 | helper.setHightlightedDragWidget(nullptr); | |||
|
228 | impl->m_MinContainerHeight = 0; | |||
236 |
|
229 | |||
237 | auto dragWidget = helper.getCurrentDragWidget(); |
|
230 | auto dragWidget = helper.getCurrentDragWidget(); | |
238 | if (dragWidget) { |
|
231 | if (dragWidget) { | |
@@ -258,60 +251,8 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event) | |||||
258 | void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event) |
|
251 | void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event) | |
259 | { |
|
252 | { | |
260 | if (impl->acceptMimeData(event->mimeData())) { |
|
253 | if (impl->acceptMimeData(event->mimeData())) { | |
261 | auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos()); |
|
254 | auto canMerge = impl->allowMergeMimeData(event->mimeData()); | |
262 | if (dragWidgetHovered) { |
|
255 | impl->findPlaceHolderPosition(event->pos(), canMerge, this); | |
263 | auto canMerge = impl->allowMergeMimeData(event->mimeData()); |
|
|||
264 |
|
||||
265 | auto nbDragWidget = countDragWidget(); |
|
|||
266 | if (nbDragWidget > 0) { |
|
|||
267 | auto graphHeight = qMax(size().height() / nbDragWidget, GRAPH_MINIMUM_HEIGHT); |
|
|||
268 |
|
||||
269 | auto dropIndex = floor(event->pos().y() / graphHeight); |
|
|||
270 | auto zoneSize = qMin(graphHeight / 3.0, 150.0); |
|
|||
271 |
|
||||
272 | auto isOnTop = event->pos().y() < dropIndex * graphHeight + zoneSize; |
|
|||
273 | auto isOnBottom = event->pos().y() > (dropIndex + 1) * graphHeight - zoneSize; |
|
|||
274 |
|
||||
275 | auto &helper = sqpApp->dragDropHelper(); |
|
|||
276 | auto placeHolderIndex = impl->m_Layout->indexOf(&(helper.placeHolder())); |
|
|||
277 |
|
||||
278 | if (isOnTop || isOnBottom) { |
|
|||
279 | if (isOnBottom) { |
|
|||
280 | dropIndex += 1; |
|
|||
281 | } |
|
|||
282 |
|
||||
283 | if (helper.getCurrentDragWidget()) { |
|
|||
284 | auto dragWidgetIndex |
|
|||
285 | = impl->m_Layout->indexOf(helper.getCurrentDragWidget()); |
|
|||
286 | if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) { |
|
|||
287 | // Correction of the index if the drop occurs in the same container |
|
|||
288 | // and if the drag is started from the visualization (in that case, the |
|
|||
289 | // dragWidget is hidden) |
|
|||
290 | dropIndex += 1; |
|
|||
291 | } |
|
|||
292 | } |
|
|||
293 |
|
||||
294 | if (dropIndex != placeHolderIndex) { |
|
|||
295 | helper.insertPlaceHolder(impl->m_Layout, dropIndex); |
|
|||
296 | } |
|
|||
297 | } |
|
|||
298 | else if (canMerge) { |
|
|||
299 | // drop on the middle -> merge |
|
|||
300 | if (impl->hasPlaceHolder()) { |
|
|||
301 | helper.removePlaceHolder(); |
|
|||
302 | } |
|
|||
303 | } |
|
|||
304 | } |
|
|||
305 | else { |
|
|||
306 | qCWarning(LOG_VisualizationDragDropContainer()) |
|
|||
307 | << tr("VisualizationDragDropContainer::dragMoveEvent, no widget found in the " |
|
|||
308 | "container"); |
|
|||
309 | } |
|
|||
310 | } |
|
|||
311 | else { |
|
|||
312 | // No hovered drag widget, the mouse is probably hover the placeHolder |
|
|||
313 | // Do nothing |
|
|||
314 | } |
|
|||
315 | } |
|
256 | } | |
316 | else { |
|
257 | else { | |
317 | event->ignore(); |
|
258 | event->ignore(); | |
@@ -351,12 +292,89 void VisualizationDragDropContainer::dropEvent(QDropEvent *event) | |||||
351 | qCWarning(LOG_VisualizationDragDropContainer()) |
|
292 | qCWarning(LOG_VisualizationDragDropContainer()) | |
352 | << tr("VisualizationDragDropContainer::dropEvent, couldn't drop because the " |
|
293 | << tr("VisualizationDragDropContainer::dropEvent, couldn't drop because the " | |
353 | "placeHolder is not found."); |
|
294 | "placeHolder is not found."); | |
354 | Q_ASSERT(false); |
|
295 | // Q_ASSERT(false); | |
355 | } |
|
296 | } | |
356 | } |
|
297 | } | |
357 | else { |
|
298 | else { | |
358 | event->ignore(); |
|
299 | event->ignore(); | |
359 | } |
|
300 | } | |
360 |
|
301 | |||
|
302 | sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr); | |||
|
303 | impl->m_MinContainerHeight = 0; | |||
|
304 | ||||
361 | QWidget::dropEvent(event); |
|
305 | QWidget::dropEvent(event); | |
362 | } |
|
306 | } | |
|
307 | ||||
|
308 | ||||
|
309 | void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition( | |||
|
310 | const QPoint &pos, bool canMerge, const VisualizationDragDropContainer *container) | |||
|
311 | { | |||
|
312 | auto &helper = sqpApp->dragDropHelper(); | |||
|
313 | ||||
|
314 | auto dragWidgetHovered = getChildDragWidgetAt(container, pos); | |||
|
315 | if (dragWidgetHovered) { | |||
|
316 | auto nbDragWidget = countDragWidget(container); | |||
|
317 | if (nbDragWidget > 0) { | |||
|
318 | ||||
|
319 | if (m_MinContainerHeight == 0) { | |||
|
320 | m_MinContainerHeight = container->size().height(); | |||
|
321 | } | |||
|
322 | ||||
|
323 | m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height()); | |||
|
324 | auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT); | |||
|
325 | ||||
|
326 | auto posY = pos.y(); | |||
|
327 | auto dropIndex = floor(posY / graphHeight); | |||
|
328 | auto zoneSize = qMin(graphHeight / 4.0, 75.0); | |||
|
329 | ||||
|
330 | ||||
|
331 | auto isOnTop = posY < dropIndex * graphHeight + zoneSize; | |||
|
332 | auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize; | |||
|
333 | ||||
|
334 | auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder())); | |||
|
335 | ||||
|
336 | if (isOnTop || isOnBottom || !canMerge) { | |||
|
337 | if (isOnBottom) { | |||
|
338 | dropIndex += 1; | |||
|
339 | } | |||
|
340 | ||||
|
341 | if (helper.getCurrentDragWidget()) { | |||
|
342 | auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget()); | |||
|
343 | if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) { | |||
|
344 | // Correction of the index if the drop occurs in the same container | |||
|
345 | // and if the drag is started from the visualization (in that case, the | |||
|
346 | // dragWidget is hidden) | |||
|
347 | dropIndex += 1; | |||
|
348 | } | |||
|
349 | } | |||
|
350 | ||||
|
351 | if (dropIndex != placeHolderIndex) { | |||
|
352 | helper.insertPlaceHolder(m_Layout, dropIndex); | |||
|
353 | } | |||
|
354 | ||||
|
355 | helper.setHightlightedDragWidget(nullptr); | |||
|
356 | } | |||
|
357 | else if (canMerge) { | |||
|
358 | // drop on the middle -> merge | |||
|
359 | if (hasPlaceHolder()) { | |||
|
360 | helper.removePlaceHolder(); | |||
|
361 | } | |||
|
362 | ||||
|
363 | helper.setHightlightedDragWidget(dragWidgetHovered); | |||
|
364 | } | |||
|
365 | } | |||
|
366 | else { | |||
|
367 | qCWarning(LOG_VisualizationDragDropContainer()) | |||
|
368 | << tr("VisualizationDragDropContainer::dragMoveEvent, no widget found in the " | |||
|
369 | "container"); | |||
|
370 | } | |||
|
371 | } | |||
|
372 | else if (!hasPlaceHolder()) { | |||
|
373 | // Drop on an empty container, just add the placeHolder at the top | |||
|
374 | helper.insertPlaceHolder(m_Layout, 0); | |||
|
375 | } | |||
|
376 | else { | |||
|
377 | // No hovered drag widget, the mouse is probably hover the placeHolder | |||
|
378 | // Do nothing | |||
|
379 | } | |||
|
380 | } |
@@ -243,6 +243,18 bool VisualizationGraphWidget::isDragAllowed() const | |||||
243 | return true; |
|
243 | return true; | |
244 | } |
|
244 | } | |
245 |
|
245 | |||
|
246 | void VisualizationGraphWidget::highlightForMerge(bool highlighted) | |||
|
247 | { | |||
|
248 | if (highlighted) { | |||
|
249 | plot().setBackground(QBrush(QColor("#BBD5EE"))); | |||
|
250 | } | |||
|
251 | else { | |||
|
252 | plot().setBackground(QBrush(Qt::white)); | |||
|
253 | } | |||
|
254 | ||||
|
255 | plot().update(); | |||
|
256 | } | |||
|
257 | ||||
246 | void VisualizationGraphWidget::closeEvent(QCloseEvent *event) |
|
258 | void VisualizationGraphWidget::closeEvent(QCloseEvent *event) | |
247 | { |
|
259 | { | |
248 | Q_UNUSED(event); |
|
260 | Q_UNUSED(event); |
@@ -86,6 +86,7 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *p | |||||
86 | ui->zoneNameLabel->setText(name); |
|
86 | ui->zoneNameLabel->setText(name); | |
87 |
|
87 | |||
88 | ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST}); |
|
88 | ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST}); | |
|
89 | ui->dragDropContainer->setMergeAllowedMimeTypes({MIME_TYPE_VARIABLE_LIST}); | |||
89 | ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) { |
|
90 | ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) { | |
90 | return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData, |
|
91 | return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData, | |
91 | ui->dragDropContainer); |
|
92 | ui->dragDropContainer); |
General Comments 0
You need to be logged in to leave comments.
Login now