##// END OF EJS Templates
Drag of the time widget on a graph
trabillard -
r885:be7e4409e91c
parent child
Show More
@@ -5,6 +5,8
5 5
6 6 #include <Data/SqpRange.h>
7 7
8 #include <Common/spimpl.h>
9
8 10 namespace Ui {
9 11 class TimeWidget;
10 12 } // Ui
@@ -17,6 +19,7 public:
17 19 virtual ~TimeWidget();
18 20
19 21 void setTimeRange(SqpRange time);
22 SqpRange timeRange() const;
20 23
21 24 signals:
22 25 /// Signal emitted when the time parameters has beed updated
@@ -31,9 +34,14 protected:
31 34 void dragLeaveEvent(QDragLeaveEvent *event) override;
32 35 void dropEvent(QDropEvent *event) override;
33 36
37 void mousePressEvent(QMouseEvent *event) override;
38 void mouseMoveEvent(QMouseEvent *event) override;
34 39
35 40 private:
36 41 Ui::TimeWidget *ui;
42
43 class TimeWidgetPrivate;
44 spimpl::unique_impl_ptr<TimeWidgetPrivate> impl;
37 45 };
38 46
39 47 #endif // SCIQLOP_ SQPSIDEPANE_H
@@ -21,6 +21,7 signals:
21 21 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
22 22
23 23 public:
24 enum class DropBehavior { Inserted, Merged, InsertedAndMerged };
24 25 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
25 26
26 27 VisualizationDragDropContainer(QWidget *parent = nullptr);
@@ -28,8 +29,7 public:
28 29 void addDragWidget(VisualizationDragWidget *dragWidget);
29 30 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
30 31
31 void setAcceptedMimeTypes(const QStringList &mimeTypes);
32 void setMergeAllowedMimeTypes(const QStringList &mimeTypes);
32 void addAcceptedMimeType(const QString &mimeType, DropBehavior behavior);
33 33
34 34 int countDragWidget() const;
35 35
@@ -4,14 +4,27
4 4 #include <Common/DateUtils.h>
5 5 #include <Common/MimeTypesDef.h>
6 6
7 #include <DragDropHelper.h>
7 8 #include <SqpApplication.h>
8 9 #include <Time/TimeController.h>
9 10
11 #include <QDrag>
10 12 #include <QDragEnterEvent>
11 13 #include <QDropEvent>
12 14 #include <QMimeData>
13 15
14 TimeWidget::TimeWidget(QWidget *parent) : QWidget{parent}, ui{new Ui::TimeWidget}
16
17 struct TimeWidget::TimeWidgetPrivate {
18
19 explicit TimeWidgetPrivate() {}
20
21 QPoint m_DragStartPosition;
22 };
23
24 TimeWidget::TimeWidget(QWidget *parent)
25 : QWidget{parent},
26 ui{new Ui::TimeWidget},
27 impl{spimpl::make_unique_impl<TimeWidgetPrivate>()}
15 28 {
16 29 ui->setupUi(this);
17 30
@@ -56,11 +69,15 void TimeWidget::setTimeRange(SqpRange time)
56 69 ui->endDateTimeEdit->setDateTime(endDateTime);
57 70 }
58 71
59 void TimeWidget::onTimeUpdateRequested()
72 SqpRange TimeWidget::timeRange() const
60 73 {
61 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
62 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
74 return SqpRange{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
75 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
76 }
63 77
78 void TimeWidget::onTimeUpdateRequested()
79 {
80 auto dateTime = timeRange();
64 81 emit timeUpdated(std::move(dateTime));
65 82 }
66 83
@@ -94,3 +111,46 void TimeWidget::dropEvent(QDropEvent *event)
94 111
95 112 setStyleSheet(QString());
96 113 }
114
115
116 void TimeWidget::mousePressEvent(QMouseEvent *event)
117 {
118 if (event->button() == Qt::LeftButton) {
119 impl->m_DragStartPosition = event->pos();
120 }
121
122 QWidget::mousePressEvent(event);
123 }
124
125 void TimeWidget::mouseMoveEvent(QMouseEvent *event)
126 {
127 if (!(event->buttons() & Qt::LeftButton)) {
128 return;
129 }
130
131 if ((event->pos() - impl->m_DragStartPosition).manhattanLength()
132 < QApplication::startDragDistance()) {
133 return;
134 }
135
136 // Note: The management of the drag object is done by Qt
137 auto drag = new QDrag{this};
138
139 auto mimeData = new QMimeData;
140 auto timeData = TimeController::mimeDataForTimeRange(timeRange());
141 mimeData->setData(MIME_TYPE_TIME_RANGE, timeData);
142
143 drag->setMimeData(mimeData);
144
145 auto pixmap = QPixmap(size());
146 render(&pixmap);
147 drag->setPixmap(pixmap);
148 drag->setHotSpot(impl->m_DragStartPosition);
149
150 sqpApp->dragDropHelper().resetDragAndDrop();
151
152 // Note: The exec() is blocking on windows but not on linux and macOS
153 drag->exec(Qt::MoveAction | Qt::CopyAction);
154
155 QWidget::mouseMoveEvent(event);
156 }
@@ -17,10 +17,11 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropCon
17 17 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
18 18
19 19 QVBoxLayout *m_Layout;
20 QStringList m_AcceptedMimeTypes;
21 QStringList m_MergeAllowedMimeTypes;
20 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
21
22 22 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
23 23 = [](auto mimeData) { return true; };
24
24 25 int m_MinContainerHeight = 0;
25 26
26 27 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
@@ -31,7 +32,7 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
31 32
32 33 bool acceptMimeData(const QMimeData *data) const
33 34 {
34 for (const auto &type : m_AcceptedMimeTypes) {
35 for (const auto &type : m_AcceptedMimeTypes.keys()) {
35 36 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
36 37 return true;
37 38 }
@@ -40,10 +41,38 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
40 41 return false;
41 42 }
42 43
43 bool allowMergeMimeData(const QMimeData *data) const
44 bool allowMergeForMimeData(const QMimeData *data) const
44 45 {
45 for (const auto &type : m_MergeAllowedMimeTypes) {
46 if (data->hasFormat(type)) {
46 bool result = false;
47 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
48 ++it) {
49
50 if (data->hasFormat(it.key())
51 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
52 || it.value()
53 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
54 result = true;
55 }
56 else if (data->hasFormat(it.key())
57 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
58 // Merge is forbidden if the mime data contain an acceptable type which cannot be
59 // merged
60 result = false;
61 break;
62 }
63 }
64
65 return result;
66 }
67
68 bool allowInsertForMimeData(const QMimeData *data) const
69 {
70 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
71 ++it) {
72 if (data->hasFormat(it.key())
73 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
74 || it.value()
75 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
47 76 return true;
48 77 }
49 78 }
@@ -90,7 +119,7 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
90 119 return nbGraph;
91 120 }
92 121
93 void findPlaceHolderPosition(const QPoint &pos, bool canMerge,
122 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
94 123 const VisualizationDragDropContainer *container);
95 124 };
96 125
@@ -118,14 +147,10 void VisualizationDragDropContainer::insertDragWidget(int index,
118 147 &VisualizationDragDropContainer::startDrag);
119 148 }
120 149
121 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
122 {
123 impl->m_AcceptedMimeTypes = mimeTypes;
124 }
125
126 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
150 void VisualizationDragDropContainer::addAcceptedMimeType(
151 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
127 152 {
128 impl->m_MergeAllowedMimeTypes = mimeTypes;
153 impl->m_AcceptedMimeTypes[mimeType] = behavior;
129 154 }
130 155
131 156 int VisualizationDragDropContainer::countDragWidget() const
@@ -203,8 +228,9 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
203 228 }
204 229 }
205 230
206 auto canMerge = impl->allowMergeMimeData(event->mimeData());
207 impl->findPlaceHolderPosition(event->pos(), canMerge, this);
231 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
232 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
233 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
208 234 }
209 235 else {
210 236 // do nothing
@@ -252,8 +278,9 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
252 278 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
253 279 {
254 280 if (impl->acceptMimeData(event->mimeData())) {
255 auto canMerge = impl->allowMergeMimeData(event->mimeData());
256 impl->findPlaceHolderPosition(event->pos(), canMerge, this);
281 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
282 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
283 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
257 284 }
258 285 else {
259 286 event->ignore();
@@ -271,30 +298,39 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
271 298 if (impl->hasPlaceHolder()) {
272 299 // drop where the placeHolder is located
273 300
274 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
301 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
302 if (canInsert) {
303 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
275 304
276 if (dragWidget) {
277 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
278 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
279 // Correction of the index if the drop occurs in the same container
280 // and if the drag is started from the visualization (in that case, the
281 // dragWidget is hidden)
282 droppedIndex -= 1;
283 }
305 if (dragWidget) {
306 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
307 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
308 // 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
310 // dragWidget is hidden)
311 droppedIndex -= 1;
312 }
284 313
285 dragWidget->setVisible(true);
286 }
314 dragWidget->setVisible(true);
315 }
287 316
288 event->acceptProposedAction();
317 event->acceptProposedAction();
289 318
290 helper.removePlaceHolder();
319 helper.removePlaceHolder();
291 320
292 emit dropOccuredInContainer(droppedIndex, event->mimeData());
321 emit dropOccuredInContainer(droppedIndex, event->mimeData());
322 }
323 else {
324 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
325 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
326 "the insertion is forbidden.");
327 Q_ASSERT(false);
328 }
293 329 }
294 330 else if (helper.getHightlightedDragWidget()) {
295 331 // drop on the highlighted widget
296 332
297 auto canMerge = impl->allowMergeMimeData(event->mimeData());
333 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
298 334 if (canMerge) {
299 335 event->acceptProposedAction();
300 336 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
@@ -319,7 +355,8 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
319 355
320 356
321 357 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
322 const QPoint &pos, bool canMerge, const VisualizationDragDropContainer *container)
358 const QPoint &pos, bool canInsert, bool canMerge,
359 const VisualizationDragDropContainer *container)
323 360 {
324 361 auto &helper = sqpApp->dragDropHelper();
325 362
@@ -345,7 +382,7 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::find
345 382
346 383 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
347 384
348 if (isOnTop || isOnBottom || !canMerge) {
385 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
349 386 if (isOnBottom) {
350 387 dropIndex += 1;
351 388 }
@@ -374,14 +411,20 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::find
374 411
375 412 helper.setHightlightedDragWidget(dragWidgetHovered);
376 413 }
414 else {
415 qCWarning(LOG_VisualizationDragDropContainer())
416 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
417 "action.");
418 Q_ASSERT(false);
419 }
377 420 }
378 421 else {
379 qCWarning(LOG_VisualizationDragDropContainer())
380 << tr("VisualizationDragDropContainer::dragMoveEvent, no widget found in the "
381 "container");
422 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
423 "VisualizationDragDropContainer::findPlaceHolderPosition, no widget found in the "
424 "container");
382 425 }
383 426 }
384 else if (!hasPlaceHolder()) {
427 else if (!hasPlaceHolder() && canInsert) {
385 428 // Drop on an empty container, just add the placeHolder at the top
386 429 helper.insertPlaceHolder(m_Layout, 0);
387 430 }
@@ -68,14 +68,21 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *par
68 68 {
69 69 ui->setupUi(this);
70 70
71 ui->dragDropContainer->setAcceptedMimeTypes(
72 {MIME_TYPE_GRAPH, MIME_TYPE_ZONE, MIME_TYPE_VARIABLE_LIST});
73 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
74 &VisualizationTabWidget::dropMimeData);
71 ui->dragDropContainer->addAcceptedMimeType(
72 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
73 ui->dragDropContainer->addAcceptedMimeType(
74 MIME_TYPE_ZONE, VisualizationDragDropContainer::DropBehavior::Inserted);
75 ui->dragDropContainer->addAcceptedMimeType(
76 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::Inserted);
77
75 78 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
76 79 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
77 80 ui->dragDropContainer);
78 81 });
82
83 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
84 &VisualizationTabWidget::dropMimeData);
85
79 86 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
80 87
81 88 // Widget is deleted when closed
@@ -101,8 +101,12 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *p
101 101
102 102 ui->zoneNameLabel->setText(name);
103 103
104 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST});
105 ui->dragDropContainer->setMergeAllowedMimeTypes({MIME_TYPE_VARIABLE_LIST});
104 ui->dragDropContainer->addAcceptedMimeType(
105 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
106 ui->dragDropContainer->addAcceptedMimeType(
107 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
108 ui->dragDropContainer->addAcceptedMimeType(
109 MIME_TYPE_TIME_RANGE, VisualizationDragDropContainer::DropBehavior::Merged);
106 110 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
107 111 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
108 112 ui->dragDropContainer);
@@ -343,11 +347,6 QMimeData *VisualizationZoneWidget::mimeData() const
343 347 auto mimeData = new QMimeData;
344 348 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
345 349
346 if (const auto firstGraph = impl->firstGraph(this)) {
347 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
348 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
349 }
350
351 350 return mimeData;
352 351 }
353 352
@@ -418,6 +417,10 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragW
418 417 graphWidget->addVariable(var, graphWidget->graphRange());
419 418 }
420 419 }
420 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
421 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
422 graphWidget->setGraphRange(range);
423 }
421 424 else {
422 425 qCWarning(LOG_VisualizationZoneWidget())
423 426 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
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