##// END OF EJS Templates
drag of selection zones
trabillard -
r1047:d404ba4b75e5
parent child
Show More
@@ -14,6 +14,7 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_ZONE;
14 14 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_VARIABLE_LIST;
15 15 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_PRODUCT_LIST;
16 16 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_TIME_RANGE;
17 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_SELECTION_ZONE;
17 18
18 19
19 20 #endif // SCIQLOP_MIMETYPESDEF_H
@@ -5,3 +5,4 const QString MIME_TYPE_ZONE = QStringLiteral("sciqlop/zone");
5 5 const QString MIME_TYPE_VARIABLE_LIST = QStringLiteral("sciqlop/var-list");
6 6 const QString MIME_TYPE_PRODUCT_LIST = QStringLiteral("sciqlop/product-list");
7 7 const QString MIME_TYPE_TIME_RANGE = QStringLiteral("sciqlop/time-range");
8 const QString MIME_TYPE_SELECTION_ZONE = QStringLiteral("sciqlop/selection-zone");
@@ -11,9 +11,13 class VisualizationDragWidget : public QWidget {
11 11 public:
12 12 VisualizationDragWidget(QWidget *parent = nullptr);
13 13
14 virtual QMimeData *mimeData() const = 0;
14 virtual QMimeData *mimeData(const QPoint &position) const = 0;
15 15 virtual bool isDragAllowed() const = 0;
16 virtual void highlightForMerge(bool highlighted) { Q_UNUSED(highlighted); };
16 virtual void highlightForMerge(bool highlighted) { Q_UNUSED(highlighted); }
17
18 /// Custom pixmap to display during a drag operation.
19 /// If the provided pixmap is null, a pixmap of the entire widget is used.
20 virtual QPixmap customDragPixmap(const QPoint &dragPosition);
17 21
18 22 protected:
19 23 virtual void mousePressEvent(QMouseEvent *event) override;
@@ -61,7 +61,8 public:
61 61 QString name() const override;
62 62
63 63 // VisualisationDragWidget
64 QMimeData *mimeData() const override;
64 QMimeData *mimeData(const QPoint &position) const override;
65 QPixmap customDragPixmap(const QPoint &dragPosition) override;
65 66 bool isDragAllowed() const override;
66 67 void highlightForMerge(bool highlighted) override;
67 68
@@ -92,7 +93,7 protected:
92 93 void enterEvent(QEvent *event) override;
93 94 void leaveEvent(QEvent *event) override;
94 95
95 QCustomPlot &plot() noexcept;
96 QCustomPlot &plot() const noexcept;
96 97
97 98 private:
98 99 Ui::VisualizationGraphWidget *ui;
@@ -67,7 +67,7 public:
67 67 QString name() const override;
68 68
69 69 // VisualisationDragWidget
70 QMimeData *mimeData() const override;
70 QMimeData *mimeData(const QPoint &position) const override;
71 71 bool isDragAllowed() const override;
72 72
73 73 void notifyMouseMoveInGraph(const QPointF &graphPosition, const QPointF &plotPosition,
@@ -212,11 +212,15 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidg
212 212 // Note: The management of the drag object is done by Qt
213 213 auto drag = new QDrag{dragWidget};
214 214
215 auto mimeData = dragWidget->mimeData();
215 auto mimeData = dragWidget->mimeData(dragPosition);
216 216 drag->setMimeData(mimeData);
217 217
218 auto pixmap = QPixmap(dragWidget->size());
219 dragWidget->render(&pixmap);
218 auto pixmap = dragWidget->customDragPixmap(dragPosition);
219 if (pixmap.isNull()) {
220 pixmap = QPixmap{dragWidget->size()};
221 dragWidget->render(&pixmap);
222 }
223
220 224 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
221 225 Qt::KeepAspectRatio, Qt::SmoothTransformation));
222 226
@@ -225,17 +229,20 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidg
225 229 mimeData->setUrls({helper.imageTemporaryUrl(image)});
226 230
227 231 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
228 helper.setCurrentDragWidget(dragWidget);
229 232
230 if (impl->cursorIsInContainer(this)) {
231 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
232 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
233 impl->m_PlaceHolderText);
234 dragWidget->setVisible(false);
235 }
236 else {
237 // The drag starts directly outside the drop zone
238 // do not add the placeHolder
233 if (impl->acceptMimeData(mimeData) && impl->allowInsertForMimeData(mimeData)) {
234 helper.setCurrentDragWidget(dragWidget);
235
236 if (impl->cursorIsInContainer(this)) {
237 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
238 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
239 impl->m_PlaceHolderText);
240 dragWidget->setVisible(false);
241 }
242 else {
243 // The drag starts directly outside the drop zone
244 // do not add the placeHolder
245 }
239 246 }
240 247
241 248 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
@@ -19,6 +19,12 VisualizationDragWidget::VisualizationDragWidget(QWidget *parent)
19 19 {
20 20 }
21 21
22 virtual QPixmap VisualizationDragWidget::customDragPixmap(const QPoint &dragPosition)
23 {
24 Q_UNUSED(dragPosition);
25 return QPixmap();
26 }
27
22 28 void VisualizationDragWidget::mousePressEvent(QMouseEvent *event)
23 29 {
24 30 if (event->button() == Qt::LeftButton) {
@@ -25,6 +25,9 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
25 25
26 26 namespace {
27 27
28 /// Key pressed to enable drag&drop in all modes
29 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
30
28 31 /// Key pressed to enable zoom on horizontal axis
29 32 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
30 33
@@ -141,6 +144,22 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
141 144 }
142 145 }
143 146
147 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
148 const QCustomPlot &plot) const
149 {
150 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
151 auto minDistanceToZone = -1;
152 for (auto zone : m_SelectionZones) {
153 auto distanceToZone = zone->selectTest(pos, false);
154 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
155 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
156 selectionZoneItemUnderCursor = zone;
157 }
158 }
159
160 return selectionZoneItemUnderCursor;
161 }
162
144 163 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
145 164 {
146 165 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
@@ -371,17 +390,50 QString VisualizationGraphWidget::name() const
371 390 return impl->m_Name;
372 391 }
373 392
374 QMimeData *VisualizationGraphWidget::mimeData() const
393 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
375 394 {
376 395 auto mimeData = new QMimeData;
377 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
378 396
379 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
380 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
397 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
398 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
399 && selectionZoneItemUnderCursor) {
400 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
401 selectionZoneItemUnderCursor->range()));
402 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
403 selectionZoneItemUnderCursor->range()));
404 }
405 else {
406 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
407
408 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
409 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
410 }
381 411
382 412 return mimeData;
383 413 }
384 414
415 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
416 {
417 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
418 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
419 && selectionZoneItemUnderCursor) {
420
421 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
422 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
423
424 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
425 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
426 .toSize();
427
428 auto pixmap = QPixmap(zoneSize);
429 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
430
431 return pixmap;
432 }
433
434 return QPixmap();
435 }
436
385 437 bool VisualizationGraphWidget::isDragAllowed() const
386 438 {
387 439 return true;
@@ -482,7 +534,7 void VisualizationGraphWidget::leaveEvent(QEvent *event)
482 534 }
483 535 }
484 536
485 QCustomPlot &VisualizationGraphWidget::plot() noexcept
537 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
486 538 {
487 539 return *ui->widget;
488 540 }
@@ -590,16 +642,7 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
590 642 }
591 643
592 644 // Search for the selection zone under the mouse
593 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
594 auto minDistanceToZone = -1;
595 for (auto zone : impl->m_SelectionZones) {
596 auto distanceToZone = zone->selectTest(event->pos(), true);
597 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone) && distanceToZone >= 0
598 && distanceToZone < plot().selectionTolerance()) {
599 selectionZoneItemUnderCursor = zone;
600 }
601 }
602
645 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
603 646 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
604 647 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
605 648
@@ -663,16 +706,21 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
663 706
664 707 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
665 708 {
666 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
667 // Starts a zoom box
668 impl->startDrawingRect(event->pos(), plot());
669 }
670 else if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
671 && impl->m_DrawingZone == nullptr) {
672 // Starts a new selection zone
673 auto itemAtPos = plot().itemAt(event->pos(), true);
674 if (!itemAtPos) {
675 impl->startDrawingZone(event->pos(), plot());
709 bool isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
710
711 if (!isDragDropClick) {
712 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
713 // Starts a zoom box
714 impl->startDrawingRect(event->pos(), plot());
715 }
716 else if (sqpApp->plotsInteractionMode()
717 == SqpApplication::PlotsInteractionMode::SelectionZones
718 && impl->m_DrawingZone == nullptr) {
719 // Starts a new selection zone
720 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
721 if (!zoneAtPos) {
722 impl->startDrawingZone(event->pos(), plot());
723 }
676 724 }
677 725 }
678 726 else if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::None) {
@@ -681,11 +729,13 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
681 729
682 730 // Allows mouse panning only in default mode
683 731 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
684 == SqpApplication::PlotsInteractionMode::None);
732 == SqpApplication::PlotsInteractionMode::None
733 && !isDragDropClick);
685 734
686 // Allows zone edition only in selection zone mode
687 impl->setSelectionZonesEditionEnabled(sqpApp->plotsInteractionMode()
688 == SqpApplication::PlotsInteractionMode::SelectionZones);
735 // Allows zone edition only in selection zone mode without ALT pressed (ALT is for drag&drop)
736 impl->setSelectionZonesEditionEnabled(
737 sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
738 && !isDragDropClick);
689 739
690 740 VisualizationDragWidget::mousePressEvent(event);
691 741 }
@@ -33,7 +33,7 struct VisualizationSelectionZoneItem::VisualizationSelectionZoneItemPrivate {
33 33 {
34 34 auto distanceLeft = m_LeftLine->selectTest(pos, false);
35 35 auto distanceRight = m_RightLine->selectTest(pos, false);
36 auto distance = zoneItem->selectTest(pos, true);
36 auto distance = zoneItem->selectTest(pos, false);
37 37
38 38 if (distanceRight <= distance) {
39 39 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight;
@@ -173,6 +173,7 void VisualizationSelectionZoneItem::setEditionEnabled(bool value)
173 173 setSelectable(value);
174 174 if (!value) {
175 175 setSelected(false);
176 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
176 177 }
177 178 }
178 179
@@ -110,6 +110,8 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *p
110 110 VisualizationDragDropContainer::DropBehavior::Merged);
111 111 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
112 112 VisualizationDragDropContainer::DropBehavior::Forbidden);
113 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
114 VisualizationDragDropContainer::DropBehavior::Forbidden);
113 115 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
114 116 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
115 117 ui->dragDropContainer);
@@ -352,8 +354,10 QString VisualizationZoneWidget::name() const
352 354 return ui->zoneNameLabel->text();
353 355 }
354 356
355 QMimeData *VisualizationZoneWidget::mimeData() const
357 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
356 358 {
359 Q_UNUSED(position);
360
357 361 auto mimeData = new QMimeData;
358 362 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
359 363
General Comments 0
You need to be logged in to leave comments. Login now