##// END OF EJS Templates
Drag of the time widget on a graph
trabillard -
r879:be7e4409e91c
parent child
Show More
@@ -5,6 +5,8
5
5
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 #include <Common/spimpl.h>
9
8 namespace Ui {
10 namespace Ui {
9 class TimeWidget;
11 class TimeWidget;
10 } // Ui
12 } // Ui
@@ -17,6 +19,7 public:
17 virtual ~TimeWidget();
19 virtual ~TimeWidget();
18
20
19 void setTimeRange(SqpRange time);
21 void setTimeRange(SqpRange time);
22 SqpRange timeRange() const;
20
23
21 signals:
24 signals:
22 /// Signal emitted when the time parameters has beed updated
25 /// Signal emitted when the time parameters has beed updated
@@ -31,9 +34,14 protected:
31 void dragLeaveEvent(QDragLeaveEvent *event) override;
34 void dragLeaveEvent(QDragLeaveEvent *event) override;
32 void dropEvent(QDropEvent *event) override;
35 void dropEvent(QDropEvent *event) override;
33
36
37 void mousePressEvent(QMouseEvent *event) override;
38 void mouseMoveEvent(QMouseEvent *event) override;
34
39
35 private:
40 private:
36 Ui::TimeWidget *ui;
41 Ui::TimeWidget *ui;
42
43 class TimeWidgetPrivate;
44 spimpl::unique_impl_ptr<TimeWidgetPrivate> impl;
37 };
45 };
38
46
39 #endif // SCIQLOP_ SQPSIDEPANE_H
47 #endif // SCIQLOP_ SQPSIDEPANE_H
@@ -21,6 +21,7 signals:
21 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
21 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
22
22
23 public:
23 public:
24 enum class DropBehavior { Inserted, Merged, InsertedAndMerged };
24 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
25 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
25
26
26 VisualizationDragDropContainer(QWidget *parent = nullptr);
27 VisualizationDragDropContainer(QWidget *parent = nullptr);
@@ -28,8 +29,7 public:
28 void addDragWidget(VisualizationDragWidget *dragWidget);
29 void addDragWidget(VisualizationDragWidget *dragWidget);
29 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
30 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
30
31
31 void setAcceptedMimeTypes(const QStringList &mimeTypes);
32 void addAcceptedMimeType(const QString &mimeType, DropBehavior behavior);
32 void setMergeAllowedMimeTypes(const QStringList &mimeTypes);
33
33
34 int countDragWidget() const;
34 int countDragWidget() const;
35
35
@@ -4,14 +4,27
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5 #include <Common/MimeTypesDef.h>
5 #include <Common/MimeTypesDef.h>
6
6
7 #include <DragDropHelper.h>
7 #include <SqpApplication.h>
8 #include <SqpApplication.h>
8 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
9
10
11 #include <QDrag>
10 #include <QDragEnterEvent>
12 #include <QDragEnterEvent>
11 #include <QDropEvent>
13 #include <QDropEvent>
12 #include <QMimeData>
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 ui->setupUi(this);
29 ui->setupUi(this);
17
30
@@ -56,11 +69,15 void TimeWidget::setTimeRange(SqpRange time)
56 ui->endDateTimeEdit->setDateTime(endDateTime);
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()),
74 return SqpRange{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
62 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
75 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
76 }
63
77
78 void TimeWidget::onTimeUpdateRequested()
79 {
80 auto dateTime = timeRange();
64 emit timeUpdated(std::move(dateTime));
81 emit timeUpdated(std::move(dateTime));
65 }
82 }
66
83
@@ -94,3 +111,46 void TimeWidget::dropEvent(QDropEvent *event)
94
111
95 setStyleSheet(QString());
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 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
17 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
18
18
19 QVBoxLayout *m_Layout;
19 QVBoxLayout *m_Layout;
20 QStringList m_AcceptedMimeTypes;
20 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
21 QStringList m_MergeAllowedMimeTypes;
21
22 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
22 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
23 = [](auto mimeData) { return true; };
23 = [](auto mimeData) { return true; };
24
24 int m_MinContainerHeight = 0;
25 int m_MinContainerHeight = 0;
25
26
26 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
27 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
@@ -31,7 +32,7 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
31
32
32 bool acceptMimeData(const QMimeData *data) const
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 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
36 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
36 return true;
37 return true;
37 }
38 }
@@ -40,10 +41,38 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
40 return false;
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 bool result = false;
46 if (data->hasFormat(type)) {
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 return true;
76 return true;
48 }
77 }
49 }
78 }
@@ -90,7 +119,7 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
90 return nbGraph;
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 const VisualizationDragDropContainer *container);
123 const VisualizationDragDropContainer *container);
95 };
124 };
96
125
@@ -118,14 +147,10 void VisualizationDragDropContainer::insertDragWidget(int index,
118 &VisualizationDragDropContainer::startDrag);
147 &VisualizationDragDropContainer::startDrag);
119 }
148 }
120
149
121 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
150 void VisualizationDragDropContainer::addAcceptedMimeType(
122 {
151 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
123 impl->m_AcceptedMimeTypes = mimeTypes;
124 }
125
126 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
127 {
152 {
128 impl->m_MergeAllowedMimeTypes = mimeTypes;
153 impl->m_AcceptedMimeTypes[mimeType] = behavior;
129 }
154 }
130
155
131 int VisualizationDragDropContainer::countDragWidget() const
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());
231 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
207 impl->findPlaceHolderPosition(event->pos(), canMerge, this);
232 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
233 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
208 }
234 }
209 else {
235 else {
210 // do nothing
236 // do nothing
@@ -252,8 +278,9 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
252 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
278 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
253 {
279 {
254 if (impl->acceptMimeData(event->mimeData())) {
280 if (impl->acceptMimeData(event->mimeData())) {
255 auto canMerge = impl->allowMergeMimeData(event->mimeData());
281 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
256 impl->findPlaceHolderPosition(event->pos(), canMerge, this);
282 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
283 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
257 }
284 }
258 else {
285 else {
259 event->ignore();
286 event->ignore();
@@ -271,30 +298,39 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
271 if (impl->hasPlaceHolder()) {
298 if (impl->hasPlaceHolder()) {
272 // drop where the placeHolder is located
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) {
305 if (dragWidget) {
277 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
306 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
278 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
307 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
279 // Correction of the index if the drop occurs in the same container
308 // 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
309 // and if the drag is started from the visualization (in that case, the
281 // dragWidget is hidden)
310 // dragWidget is hidden)
282 droppedIndex -= 1;
311 droppedIndex -= 1;
283 }
312 }
284
313
285 dragWidget->setVisible(true);
314 dragWidget->setVisible(true);
286 }
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 else if (helper.getHightlightedDragWidget()) {
330 else if (helper.getHightlightedDragWidget()) {
295 // drop on the highlighted widget
331 // drop on the highlighted widget
296
332
297 auto canMerge = impl->allowMergeMimeData(event->mimeData());
333 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
298 if (canMerge) {
334 if (canMerge) {
299 event->acceptProposedAction();
335 event->acceptProposedAction();
300 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
336 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
@@ -319,7 +355,8 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
319
355
320
356
321 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
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 auto &helper = sqpApp->dragDropHelper();
361 auto &helper = sqpApp->dragDropHelper();
325
362
@@ -345,7 +382,7 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::find
345
382
346 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
383 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
347
384
348 if (isOnTop || isOnBottom || !canMerge) {
385 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
349 if (isOnBottom) {
386 if (isOnBottom) {
350 dropIndex += 1;
387 dropIndex += 1;
351 }
388 }
@@ -374,14 +411,20 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::find
374
411
375 helper.setHightlightedDragWidget(dragWidgetHovered);
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 else {
421 else {
379 qCWarning(LOG_VisualizationDragDropContainer())
422 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
380 << tr("VisualizationDragDropContainer::dragMoveEvent, no widget found in the "
423 "VisualizationDragDropContainer::findPlaceHolderPosition, no widget found in the "
381 "container");
424 "container");
382 }
425 }
383 }
426 }
384 else if (!hasPlaceHolder()) {
427 else if (!hasPlaceHolder() && canInsert) {
385 // Drop on an empty container, just add the placeHolder at the top
428 // Drop on an empty container, just add the placeHolder at the top
386 helper.insertPlaceHolder(m_Layout, 0);
429 helper.insertPlaceHolder(m_Layout, 0);
387 }
430 }
@@ -68,14 +68,21 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *par
68 {
68 {
69 ui->setupUi(this);
69 ui->setupUi(this);
70
70
71 ui->dragDropContainer->setAcceptedMimeTypes(
71 ui->dragDropContainer->addAcceptedMimeType(
72 {MIME_TYPE_GRAPH, MIME_TYPE_ZONE, MIME_TYPE_VARIABLE_LIST});
72 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
73 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
73 ui->dragDropContainer->addAcceptedMimeType(
74 &VisualizationTabWidget::dropMimeData);
74 MIME_TYPE_ZONE, VisualizationDragDropContainer::DropBehavior::Inserted);
75 ui->dragDropContainer->addAcceptedMimeType(
76 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::Inserted);
77
75 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
78 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
76 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
79 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
77 ui->dragDropContainer);
80 ui->dragDropContainer);
78 });
81 });
82
83 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
84 &VisualizationTabWidget::dropMimeData);
85
79 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
86 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
80
87
81 // Widget is deleted when closed
88 // Widget is deleted when closed
@@ -101,8 +101,12 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *p
101
101
102 ui->zoneNameLabel->setText(name);
102 ui->zoneNameLabel->setText(name);
103
103
104 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST});
104 ui->dragDropContainer->addAcceptedMimeType(
105 ui->dragDropContainer->setMergeAllowedMimeTypes({MIME_TYPE_VARIABLE_LIST});
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 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
110 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
107 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
111 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
108 ui->dragDropContainer);
112 ui->dragDropContainer);
@@ -343,11 +347,6 QMimeData *VisualizationZoneWidget::mimeData() const
343 auto mimeData = new QMimeData;
347 auto mimeData = new QMimeData;
344 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
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 return mimeData;
350 return mimeData;
352 }
351 }
353
352
@@ -418,6 +417,10 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragW
418 graphWidget->addVariable(var, graphWidget->graphRange());
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 else {
424 else {
422 qCWarning(LOG_VisualizationZoneWidget())
425 qCWarning(LOG_VisualizationZoneWidget())
423 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
426 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
General Comments 0
You need to be logged in to leave comments. Login now