##// 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 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_VARIABLE_LIST;
14 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_VARIABLE_LIST;
15 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_PRODUCT_LIST;
15 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_PRODUCT_LIST;
16 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_TIME_RANGE;
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 #endif // SCIQLOP_MIMETYPESDEF_H
20 #endif // SCIQLOP_MIMETYPESDEF_H
@@ -5,3 +5,4 const QString MIME_TYPE_ZONE = QStringLiteral("sciqlop/zone");
5 const QString MIME_TYPE_VARIABLE_LIST = QStringLiteral("sciqlop/var-list");
5 const QString MIME_TYPE_VARIABLE_LIST = QStringLiteral("sciqlop/var-list");
6 const QString MIME_TYPE_PRODUCT_LIST = QStringLiteral("sciqlop/product-list");
6 const QString MIME_TYPE_PRODUCT_LIST = QStringLiteral("sciqlop/product-list");
7 const QString MIME_TYPE_TIME_RANGE = QStringLiteral("sciqlop/time-range");
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 public:
11 public:
12 VisualizationDragWidget(QWidget *parent = nullptr);
12 VisualizationDragWidget(QWidget *parent = nullptr);
13
13
14 virtual QMimeData *mimeData() const = 0;
14 virtual QMimeData *mimeData(const QPoint &position) const = 0;
15 virtual bool isDragAllowed() const = 0;
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 protected:
22 protected:
19 virtual void mousePressEvent(QMouseEvent *event) override;
23 virtual void mousePressEvent(QMouseEvent *event) override;
@@ -61,7 +61,8 public:
61 QString name() const override;
61 QString name() const override;
62
62
63 // VisualisationDragWidget
63 // VisualisationDragWidget
64 QMimeData *mimeData() const override;
64 QMimeData *mimeData(const QPoint &position) const override;
65 QPixmap customDragPixmap(const QPoint &dragPosition) override;
65 bool isDragAllowed() const override;
66 bool isDragAllowed() const override;
66 void highlightForMerge(bool highlighted) override;
67 void highlightForMerge(bool highlighted) override;
67
68
@@ -92,7 +93,7 protected:
92 void enterEvent(QEvent *event) override;
93 void enterEvent(QEvent *event) override;
93 void leaveEvent(QEvent *event) override;
94 void leaveEvent(QEvent *event) override;
94
95
95 QCustomPlot &plot() noexcept;
96 QCustomPlot &plot() const noexcept;
96
97
97 private:
98 private:
98 Ui::VisualizationGraphWidget *ui;
99 Ui::VisualizationGraphWidget *ui;
@@ -67,7 +67,7 public:
67 QString name() const override;
67 QString name() const override;
68
68
69 // VisualisationDragWidget
69 // VisualisationDragWidget
70 QMimeData *mimeData() const override;
70 QMimeData *mimeData(const QPoint &position) const override;
71 bool isDragAllowed() const override;
71 bool isDragAllowed() const override;
72
72
73 void notifyMouseMoveInGraph(const QPointF &graphPosition, const QPointF &plotPosition,
73 void notifyMouseMoveInGraph(const QPointF &graphPosition, const QPointF &plotPosition,
@@ -212,11 +212,15 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidg
212 // Note: The management of the drag object is done by Qt
212 // Note: The management of the drag object is done by Qt
213 auto drag = new QDrag{dragWidget};
213 auto drag = new QDrag{dragWidget};
214
214
215 auto mimeData = dragWidget->mimeData();
215 auto mimeData = dragWidget->mimeData(dragPosition);
216 drag->setMimeData(mimeData);
216 drag->setMimeData(mimeData);
217
217
218 auto pixmap = QPixmap(dragWidget->size());
218 auto pixmap = dragWidget->customDragPixmap(dragPosition);
219 dragWidget->render(&pixmap);
219 if (pixmap.isNull()) {
220 pixmap = QPixmap{dragWidget->size()};
221 dragWidget->render(&pixmap);
222 }
223
220 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
224 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
221 Qt::KeepAspectRatio, Qt::SmoothTransformation));
225 Qt::KeepAspectRatio, Qt::SmoothTransformation));
222
226
@@ -225,17 +229,20 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidg
225 mimeData->setUrls({helper.imageTemporaryUrl(image)});
229 mimeData->setUrls({helper.imageTemporaryUrl(image)});
226
230
227 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
231 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
228 helper.setCurrentDragWidget(dragWidget);
229
232
230 if (impl->cursorIsInContainer(this)) {
233 if (impl->acceptMimeData(mimeData) && impl->allowInsertForMimeData(mimeData)) {
231 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
234 helper.setCurrentDragWidget(dragWidget);
232 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
235
233 impl->m_PlaceHolderText);
236 if (impl->cursorIsInContainer(this)) {
234 dragWidget->setVisible(false);
237 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
235 }
238 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
236 else {
239 impl->m_PlaceHolderText);
237 // The drag starts directly outside the drop zone
240 dragWidget->setVisible(false);
238 // do not add the placeHolder
241 }
242 else {
243 // The drag starts directly outside the drop zone
244 // do not add the placeHolder
245 }
239 }
246 }
240
247
241 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
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 void VisualizationDragWidget::mousePressEvent(QMouseEvent *event)
28 void VisualizationDragWidget::mousePressEvent(QMouseEvent *event)
23 {
29 {
24 if (event->button() == Qt::LeftButton) {
30 if (event->button() == Qt::LeftButton) {
@@ -25,6 +25,9 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
25
25
26 namespace {
26 namespace {
27
27
28 /// Key pressed to enable drag&drop in all modes
29 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
30
28 /// Key pressed to enable zoom on horizontal axis
31 /// Key pressed to enable zoom on horizontal axis
29 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
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 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
163 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
145 {
164 {
146 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
165 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
@@ -371,17 +390,50 QString VisualizationGraphWidget::name() const
371 return impl->m_Name;
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 auto mimeData = new QMimeData;
395 auto mimeData = new QMimeData;
377 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
378
396
379 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
397 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
380 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
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 return mimeData;
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 bool VisualizationGraphWidget::isDragAllowed() const
437 bool VisualizationGraphWidget::isDragAllowed() const
386 {
438 {
387 return true;
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 return *ui->widget;
539 return *ui->widget;
488 }
540 }
@@ -590,16 +642,7 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
590 }
642 }
591
643
592 // Search for the selection zone under the mouse
644 // Search for the selection zone under the mouse
593 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
645 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
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
603 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
646 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
604 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
647 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
605
648
@@ -663,16 +706,21 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
663
706
664 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
707 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
665 {
708 {
666 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
709 bool isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
667 // Starts a zoom box
710
668 impl->startDrawingRect(event->pos(), plot());
711 if (!isDragDropClick) {
669 }
712 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
670 else if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
713 // Starts a zoom box
671 && impl->m_DrawingZone == nullptr) {
714 impl->startDrawingRect(event->pos(), plot());
672 // Starts a new selection zone
715 }
673 auto itemAtPos = plot().itemAt(event->pos(), true);
716 else if (sqpApp->plotsInteractionMode()
674 if (!itemAtPos) {
717 == SqpApplication::PlotsInteractionMode::SelectionZones
675 impl->startDrawingZone(event->pos(), plot());
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 else if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::None) {
726 else if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::None) {
@@ -681,11 +729,13 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
681
729
682 // Allows mouse panning only in default mode
730 // Allows mouse panning only in default mode
683 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
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
735 // Allows zone edition only in selection zone mode without ALT pressed (ALT is for drag&drop)
687 impl->setSelectionZonesEditionEnabled(sqpApp->plotsInteractionMode()
736 impl->setSelectionZonesEditionEnabled(
688 == SqpApplication::PlotsInteractionMode::SelectionZones);
737 sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
738 && !isDragDropClick);
689
739
690 VisualizationDragWidget::mousePressEvent(event);
740 VisualizationDragWidget::mousePressEvent(event);
691 }
741 }
@@ -33,7 +33,7 struct VisualizationSelectionZoneItem::VisualizationSelectionZoneItemPrivate {
33 {
33 {
34 auto distanceLeft = m_LeftLine->selectTest(pos, false);
34 auto distanceLeft = m_LeftLine->selectTest(pos, false);
35 auto distanceRight = m_RightLine->selectTest(pos, false);
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 if (distanceRight <= distance) {
38 if (distanceRight <= distance) {
39 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight;
39 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight;
@@ -173,6 +173,7 void VisualizationSelectionZoneItem::setEditionEnabled(bool value)
173 setSelectable(value);
173 setSelectable(value);
174 if (!value) {
174 if (!value) {
175 setSelected(false);
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 VisualizationDragDropContainer::DropBehavior::Merged);
110 VisualizationDragDropContainer::DropBehavior::Merged);
111 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
111 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
112 VisualizationDragDropContainer::DropBehavior::Forbidden);
112 VisualizationDragDropContainer::DropBehavior::Forbidden);
113 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
114 VisualizationDragDropContainer::DropBehavior::Forbidden);
113 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
115 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
114 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
116 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
115 ui->dragDropContainer);
117 ui->dragDropContainer);
@@ -352,8 +354,10 QString VisualizationZoneWidget::name() const
352 return ui->zoneNameLabel->text();
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 auto mimeData = new QMimeData;
361 auto mimeData = new QMimeData;
358 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
362 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
359
363
General Comments 0
You need to be logged in to leave comments. Login now