##// END OF EJS Templates
Merge branch 'feature/DragAndDropVisualization' into develop
trabillard -
r846:56046db82688 merge
parent child
Show More
@@ -0,0 +1,67
1 #ifndef DRAGDROPHELPER_H
2 #define DRAGDROPHELPER_H
3
4 #include <Common/spimpl.h>
5 #include <QWidget>
6
7 class QVBoxLayout;
8 class QScrollArea;
9 class VisualizationDragWidget;
10 class QMimeData;
11
12 /**
13 * @brief Event filter class which manage the scroll of QScrollArea during a drag&drop operation.
14 * @note A QScrollArea inside an other QScrollArea is not fully supported.
15 */
16 class DragDropScroller : public QObject
17 {
18 Q_OBJECT
19
20 public:
21 DragDropScroller(QObject* parent = nullptr);
22
23 void addScrollArea(QScrollArea* scrollArea);
24 void removeScrollArea(QScrollArea* scrollArea);
25
26 protected:
27 bool eventFilter(QObject *obj, QEvent *event);
28
29 private:
30 class DragDropScrollerPrivate;
31 spimpl::unique_impl_ptr<DragDropScrollerPrivate> impl;
32
33 private slots:
34 void onTimer();
35 };
36
37 /**
38 * @brief Helper class for drag&drop operations.
39 */
40 class DragDropHelper
41 {
42 public:
43 DragDropHelper();
44 ~DragDropHelper();
45
46 static const QString MIME_TYPE_GRAPH;
47 static const QString MIME_TYPE_ZONE;
48
49 void setCurrentDragWidget(VisualizationDragWidget* dragWidget);
50 VisualizationDragWidget* getCurrentDragWidget() const;
51
52 QWidget &placeHolder() const;
53 void insertPlaceHolder(QVBoxLayout* layout, int index);
54 void removePlaceHolder();
55 bool isPlaceHolderSet() const;
56
57 void addDragDropScrollArea(QScrollArea* scrollArea);
58 void removeDragDropScrollArea(QScrollArea* scrollArea);
59
60 QUrl imageTemporaryUrl(const QImage& image) const;
61
62 private:
63 class DragDropHelperPrivate;
64 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
65 };
66
67 #endif // DRAGDROPHELPER_H
@@ -0,0 +1,45
1 #ifndef VISUALIZATIONDRAGDROPCONTAINER_H
2 #define VISUALIZATIONDRAGDROPCONTAINER_H
3
4 #include <QWidget>
5 #include <QVBoxLayout>
6 #include <QMimeData>
7 #include <Common/spimpl.h>
8
9 class VisualizationDragWidget;
10
11 class VisualizationDragDropContainer : public QWidget
12 {
13 Q_OBJECT
14
15 signals:
16 void dropOccured(int dropIndex, const QMimeData* mimeData);
17
18 public:
19 VisualizationDragDropContainer(QWidget* parent = nullptr);
20
21 void addDragWidget(VisualizationDragWidget* dragWidget);
22 void insertDragWidget(int index, VisualizationDragWidget* dragWidget);
23
24 void setAcceptedMimeTypes(const QStringList& mimeTypes);
25 void setMergeAllowedMimeTypes(const QStringList& mimeTypes);
26
27 int countDragWidget() const;
28
29 protected:
30 void dragEnterEvent(QDragEnterEvent *event);
31 void dragLeaveEvent(QDragLeaveEvent *event);
32 void dragMoveEvent(QDragMoveEvent *event);
33 void dropEvent(QDropEvent *event);
34
35 private:
36
37
38 class VisualizationDragDropContainerPrivate;
39 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
40
41 private slots:
42 void startDrag(VisualizationDragWidget* dragWidget, const QPoint& dragPosition);
43 };
44
45 #endif // VISUALIZATIONDRAGDROPCONTAINER_H
@@ -0,0 +1,30
1 #ifndef VISUALIZATIONDRAGWIDGET_H
2 #define VISUALIZATIONDRAGWIDGET_H
3
4 #include <QWidget>
5 #include <QMimeData>
6 #include <Common/spimpl.h>
7
8 class VisualizationDragWidget : public QWidget
9 {
10 Q_OBJECT
11
12 public:
13 VisualizationDragWidget(QWidget* parent = nullptr);
14
15 virtual QMimeData* mimeData() const = 0;
16 virtual bool isDragAllowed() const = 0;
17
18 protected:
19 virtual void mousePressEvent(QMouseEvent *event) override;
20 virtual void mouseMoveEvent(QMouseEvent *event) override;
21
22 private:
23 class VisualizationDragWidgetPrivate;
24 spimpl::unique_impl_ptr<VisualizationDragWidgetPrivate> impl;
25
26 signals:
27 void dragDetected(VisualizationDragWidget* dragWidget, const QPoint& dragPosition);
28 };
29
30 #endif // VISUALIZATIONDRAGWIDGET_H
@@ -0,0 +1,248
1 #include "DragDropHelper.h"
2 #include "Visualization/VisualizationDragWidget.h"
3 #include "SqpApplication.h"
4
5 #include <QDragMoveEvent>
6 #include <QDragEnterEvent>
7 #include <QScrollBar>
8 #include <QScrollArea>
9 #include <QVBoxLayout>
10 #include <QTimer>
11 #include <QDir>
12
13 const QString DragDropHelper::MIME_TYPE_GRAPH = "scqlop/graph";
14 const QString DragDropHelper::MIME_TYPE_ZONE = "scqlop/zone";
15
16 const int SCROLL_SPEED = 5;
17 const int SCROLL_ZONE_SIZE = 50;
18
19 struct DragDropScroller::DragDropScrollerPrivate {
20
21 QList<QScrollArea*> m_scrollAreas;
22 QScrollArea* m_currentScrollArea = nullptr;
23 std::unique_ptr<QTimer> m_timer = nullptr;
24
25
26 enum class ScrollDirection {up, down, unknown};
27 ScrollDirection m_direction = ScrollDirection::unknown;
28
29 explicit DragDropScrollerPrivate()
30 : m_timer{std::make_unique<QTimer>()}
31 {
32 m_timer->setInterval(0);
33 }
34 };
35
36 DragDropScroller::DragDropScroller(QObject* parent)
37 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
38 {
39 connect(impl->m_timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
40 }
41
42 void DragDropScroller::addScrollArea(QScrollArea* scrollArea)
43 {
44 impl->m_scrollAreas << scrollArea;
45 scrollArea->viewport()->setAcceptDrops(true);
46 }
47
48 void DragDropScroller::removeScrollArea(QScrollArea* scrollArea)
49 {
50 impl->m_scrollAreas.removeAll(scrollArea);
51 scrollArea->viewport()->setAcceptDrops(false);
52 }
53
54 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
55 {
56 if (event->type() == QEvent::DragMove)
57 {
58 auto w = static_cast<QWidget*>(obj);
59
60 if (impl->m_currentScrollArea && impl->m_currentScrollArea->isAncestorOf(w))
61 {
62 auto moveEvent = static_cast<QDragMoveEvent*>(event);
63
64 auto pos = moveEvent->pos();
65 if (impl->m_currentScrollArea->viewport() != w)
66 {
67 auto globalPos = w->mapToGlobal(moveEvent->pos());
68 pos = impl->m_currentScrollArea->viewport()->mapFromGlobal(globalPos);
69 }
70
71 auto isInTopZone = pos.y() > impl->m_currentScrollArea->viewport()->size().height() - SCROLL_ZONE_SIZE;
72 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
73
74 if (!isInTopZone && !isInBottomZone)
75 {
76 impl->m_direction = DragDropScrollerPrivate::ScrollDirection::unknown;
77 impl->m_timer->stop();
78 }
79 else if (!impl->m_timer->isActive())
80 {
81 impl->m_direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up : DragDropScrollerPrivate::ScrollDirection::down;
82 impl->m_timer->start();
83 }
84 }
85 }
86 else if (event->type() == QEvent::DragEnter)
87 {
88 auto w = static_cast<QWidget*>(obj);
89
90 for (auto scrollArea : impl-> m_scrollAreas)
91 {
92 if (impl->m_currentScrollArea != scrollArea && scrollArea->isAncestorOf(w))
93 {
94 auto enterEvent = static_cast<QDragEnterEvent*>(event);
95 enterEvent->acceptProposedAction();
96 enterEvent->setDropAction(Qt::IgnoreAction);
97 impl->m_currentScrollArea = scrollArea;
98 break;
99 }
100 }
101 }
102 else if (event->type() == QEvent::DragLeave)
103 {
104 auto w = static_cast<QWidget*>(obj);
105 if (impl->m_currentScrollArea)
106 {
107 if (!QRect(QPoint(), impl->m_currentScrollArea->size()).contains(impl->m_currentScrollArea->mapFromGlobal(QCursor::pos())))
108 {
109 impl->m_currentScrollArea = nullptr;
110 impl->m_direction = DragDropScrollerPrivate::ScrollDirection::unknown;
111 impl->m_timer->stop();
112 }
113 }
114 }
115 else if (event->type() == QEvent::Drop)
116 {
117 auto w = static_cast<QWidget*>(obj);
118 if (impl->m_currentScrollArea)
119 {
120 impl->m_currentScrollArea = nullptr;
121 impl->m_direction = DragDropScrollerPrivate::ScrollDirection::unknown;
122 impl->m_timer->stop();
123 }
124 }
125
126 return false;
127 }
128
129 void DragDropScroller::onTimer()
130 {
131 if (impl->m_currentScrollArea)
132 {
133 auto mvt = 0;
134 switch (impl->m_direction)
135 {
136 case DragDropScrollerPrivate::ScrollDirection::up:
137 mvt = SCROLL_SPEED;
138 break;
139 case DragDropScrollerPrivate::ScrollDirection::down:
140 mvt = -SCROLL_SPEED;
141 break;
142 default:
143 break;
144 }
145
146 impl->m_currentScrollArea->verticalScrollBar()->setValue(impl->m_currentScrollArea->verticalScrollBar()->value() + mvt);
147 }
148 }
149
150 struct DragDropHelper::DragDropHelperPrivate {
151
152 VisualizationDragWidget* m_currentDragWidget = nullptr;
153 std::unique_ptr<QWidget> m_placeHolder = nullptr;
154 std::unique_ptr<DragDropScroller> m_dragDropScroller = nullptr;
155 QString m_imageTempUrl; //Temporary file for image url generated by the drag & drop. Not using QTemporaryFile to have a name which is not generated.
156
157 explicit DragDropHelperPrivate()
158 : m_placeHolder{std::make_unique<QWidget>()},
159 m_dragDropScroller{std::make_unique<DragDropScroller>()}
160 {
161 m_placeHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
162 sqpApp->installEventFilter(m_dragDropScroller.get());
163
164
165 m_imageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
166 }
167
168 void preparePlaceHolder() const
169 {
170 if (m_currentDragWidget)
171 {
172 m_placeHolder->setMinimumSize(m_currentDragWidget->size());
173 m_placeHolder->setSizePolicy(m_currentDragWidget->sizePolicy());
174 }
175 else
176 {
177 m_placeHolder->setMinimumSize(200, 200);
178 }
179 }
180 };
181
182
183 DragDropHelper::DragDropHelper() :
184 impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
185 {
186 }
187
188 DragDropHelper::~DragDropHelper()
189 {
190 QFile::remove(impl->m_imageTempUrl);
191 }
192
193 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
194 {
195 impl->m_currentDragWidget = dragWidget;
196 }
197
198 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
199 {
200 return impl->m_currentDragWidget;
201 }
202
203
204 QWidget& DragDropHelper::placeHolder() const
205 {
206 return *impl->m_placeHolder;
207 }
208
209 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
210 {
211 removePlaceHolder();
212 impl->preparePlaceHolder();
213 layout->insertWidget(index, impl->m_placeHolder.get());
214 impl->m_placeHolder->show();
215 }
216
217 void DragDropHelper::removePlaceHolder()
218 {
219 auto parentWidget = impl->m_placeHolder->parentWidget();
220 if (parentWidget)
221 {
222 parentWidget->layout()->removeWidget(impl->m_placeHolder.get());
223 impl->m_placeHolder->setParent(nullptr);
224 impl->m_placeHolder->hide();
225 }
226 }
227
228 bool DragDropHelper::isPlaceHolderSet() const
229 {
230 return impl->m_placeHolder->parentWidget();
231 }
232
233 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
234 {
235 impl->m_dragDropScroller->addScrollArea(scrollArea);
236 }
237
238 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
239 {
240 impl->m_dragDropScroller->removeScrollArea(scrollArea);
241 }
242
243 QUrl DragDropHelper::imageTemporaryUrl(const QImage& image) const
244 {
245 image.save(impl->m_imageTempUrl);
246 return QUrl::fromLocalFile(impl->m_imageTempUrl);
247 }
248
@@ -0,0 +1,312
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "Visualization/VisualizationDragWidget.h"
3 #include "SqpApplication.h"
4 #include "DragDropHelper.h"
5
6 #include <QDrag>
7 #include <QVBoxLayout>
8 #include <QDragEnterEvent>
9
10 #include <memory>
11
12 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
13
14 QVBoxLayout* m_layout;
15 QStringList m_acceptedMimeTypes;
16 QStringList m_mergeAllowedMimeTypes;
17
18 explicit VisualizationDragDropContainerPrivate(QWidget* widget)
19 {
20 m_layout = new QVBoxLayout(widget);
21 m_layout->setContentsMargins(0,0,0,0);
22 }
23
24 bool acceptMimeData(const QMimeData* data) const
25 {
26 for (const auto& type : m_acceptedMimeTypes)
27 {
28 if (data->hasFormat(type))
29 return true;
30 }
31
32 return false;
33 }
34
35 bool allowMergeMimeData(const QMimeData* data) const
36 {
37 for (const auto& type : m_mergeAllowedMimeTypes)
38 {
39 if (data->hasFormat(type))
40 return true;
41 }
42
43 return false;
44 }
45
46 bool hasPlaceHolder() const
47 {
48 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_layout->parentWidget();
49 }
50
51 VisualizationDragWidget* getChildDragWidgetAt(QWidget* parent, const QPoint &pos) const
52 {
53 VisualizationDragWidget* dragWidget = nullptr;
54
55 for (auto child : parent->children())
56 {
57 auto widget = qobject_cast<VisualizationDragWidget*>(child);
58 if (widget && widget->isVisible())
59 {
60 if (widget->frameGeometry().contains(pos))
61 {
62 dragWidget = widget;
63 break;
64 }
65 }
66 }
67
68 return dragWidget;
69 }
70
71 bool cursorIsInContainer(QWidget* container) const
72 {
73 auto adustNum = 18; //to be safe, in case of scrollbar on the side
74 auto containerRect = QRect(QPoint(), container->contentsRect().size()).adjusted(adustNum, adustNum, -adustNum, -adustNum);
75 qDebug() << containerRect << container->mapFromGlobal(QCursor::pos());
76 return containerRect.contains(container->mapFromGlobal(QCursor::pos()));
77 }
78
79 };
80
81 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
82 : QWidget{parent}, impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
83 {
84 setAcceptDrops(true);
85 }
86
87 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
88 {
89 impl->m_layout->addWidget(dragWidget);
90 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
91 connect(dragWidget, &VisualizationDragWidget::dragDetected, this, &VisualizationDragDropContainer::startDrag);
92 }
93
94 void VisualizationDragDropContainer::insertDragWidget(int index, VisualizationDragWidget *dragWidget)
95 {
96 impl->m_layout->insertWidget(index, dragWidget);
97 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
98 connect(dragWidget, &VisualizationDragWidget::dragDetected, this, &VisualizationDragDropContainer::startDrag);
99 }
100
101 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
102 {
103 impl->m_acceptedMimeTypes = mimeTypes;
104 }
105
106 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
107 {
108 impl->m_mergeAllowedMimeTypes = mimeTypes;
109 }
110
111 int VisualizationDragDropContainer::countDragWidget() const
112 {
113 auto nbGraph = 0;
114 for (auto child : children())
115 {
116 auto widget = qobject_cast<VisualizationDragWidget*>(child);
117 if (widget)
118 {
119 nbGraph += 1;
120 }
121 }
122
123 return nbGraph;
124 }
125
126 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition)
127 {
128 auto& helper = sqpApp->dragDropHelper();
129
130 //Note: The management of the drag object is done by Qt
131 auto *drag = new QDrag{dragWidget};
132 drag->setHotSpot(dragPosition);
133
134 auto mimeData = dragWidget->mimeData();
135 drag->setMimeData(mimeData);
136
137 auto pixmap = QPixmap(dragWidget->size());
138 dragWidget->render(&pixmap);
139 drag->setPixmap(pixmap);
140
141 auto image = pixmap.toImage();
142 mimeData->setImageData(image);
143 mimeData->setUrls({helper.imageTemporaryUrl(image)});
144
145 if (impl->m_layout->indexOf(dragWidget) >= 0)
146 {
147 helper.setCurrentDragWidget(dragWidget);
148
149 if (impl->cursorIsInContainer(this))
150 {
151 auto dragWidgetIndex = impl->m_layout->indexOf(dragWidget);
152 helper.insertPlaceHolder(impl->m_layout, dragWidgetIndex);
153 dragWidget->setVisible(false);
154 }
155 }
156
157 //Note: The exec() is blocking on windows but not on linux and macOS
158 drag->exec(Qt::MoveAction | Qt::CopyAction);
159 }
160
161 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
162 {
163 if (impl->acceptMimeData(event->mimeData()))
164 {
165 event->acceptProposedAction();
166
167 auto& helper = sqpApp->dragDropHelper();
168
169 if (!impl->hasPlaceHolder())
170 {
171 auto dragWidget = helper.getCurrentDragWidget();
172 auto parentWidget = qobject_cast<VisualizationDragDropContainer*>(dragWidget->parentWidget());
173 if (parentWidget)
174 {
175 dragWidget->setVisible(false);
176 }
177
178 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
179
180 if (dragWidgetHovered)
181 {
182 auto hoveredWidgetIndex = impl->m_layout->indexOf(dragWidgetHovered);
183 auto dragWidgetIndex = impl->m_layout->indexOf(helper.getCurrentDragWidget());
184 if (dragWidgetIndex >= 0 && dragWidgetIndex <= hoveredWidgetIndex)
185 hoveredWidgetIndex += 1; //Correction of the index if the drop occurs in the same container
186
187 helper.insertPlaceHolder(impl->m_layout, hoveredWidgetIndex);
188 }
189 else
190 {
191 helper.insertPlaceHolder(impl->m_layout, 0);
192 }
193 }
194 }
195 else
196 event->ignore();
197
198 QWidget::dragEnterEvent(event);
199 }
200
201 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
202 {
203 Q_UNUSED(event);
204
205 auto& helper = sqpApp->dragDropHelper();
206
207 if (!impl->cursorIsInContainer(this))
208 {
209 helper.removePlaceHolder();
210
211 bool isInternal = true;
212 if (isInternal)
213 {
214 //Only if the drag is strated from the visualization
215 //Show the drag widget at its original place
216 //So the drag widget doesn't stay hidden if the drop occurs outside the visualization drop zone
217 //(It is not possible to catch a drop event outside of the application)
218
219 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
220 if (dragWidget)
221 {
222 dragWidget->setVisible(true);
223 }
224 }
225 }
226
227 QWidget::dragLeaveEvent(event);
228 }
229
230 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
231 {
232 if (impl->acceptMimeData(event->mimeData()))
233 {
234 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
235 if (dragWidgetHovered)
236 {
237 auto canMerge = impl->allowMergeMimeData(event->mimeData());
238
239 auto nbDragWidget = countDragWidget();
240 if (nbDragWidget > 0)
241 {
242 auto graphHeight = size().height() / nbDragWidget;
243 auto dropIndex = floor(event->pos().y() / graphHeight);
244 auto zoneSize = qMin(graphHeight / 3.0, 150.0);
245
246 auto isOnTop = event->pos().y() < dropIndex * graphHeight + zoneSize;
247 auto isOnBottom = event->pos().y() > (dropIndex + 1) * graphHeight - zoneSize;
248
249 auto& helper = sqpApp->dragDropHelper();
250 auto placeHolderIndex = impl->m_layout->indexOf(&(helper.placeHolder()));
251
252 if (isOnTop || isOnBottom)
253 {
254 if (isOnBottom)
255 dropIndex += 1;
256
257 auto dragWidgetIndex = impl->m_layout->indexOf(helper.getCurrentDragWidget());
258 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex)
259 dropIndex += 1; //Correction of the index if the drop occurs in the same container
260
261 if (dropIndex != placeHolderIndex)
262 {
263 helper.insertPlaceHolder(impl->m_layout, dropIndex);
264 }
265 }
266 else if (canMerge)
267 {
268 //drop on the middle -> merge
269 if (impl->hasPlaceHolder())
270 {
271 helper.removePlaceHolder();
272 }
273 }
274 }
275 }
276 }
277 else
278 event->ignore();
279
280 QWidget::dragMoveEvent(event);
281 }
282
283 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
284 {
285 if (impl->acceptMimeData(event->mimeData()))
286 {
287 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
288 if (impl->hasPlaceHolder() && dragWidget)
289 {
290 auto& helper = sqpApp->dragDropHelper();
291
292 auto droppedIndex = impl->m_layout->indexOf(&helper.placeHolder());
293
294 auto dragWidgetIndex = impl->m_layout->indexOf(dragWidget);
295 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex)
296 droppedIndex -= 1; //Correction of the index if the drop occurs in the same container
297
298 dragWidget->setVisible(true);
299 dragWidget->setStyleSheet("");
300
301 event->acceptProposedAction();
302
303 helper.removePlaceHolder();
304
305 emit dropOccured(droppedIndex, event->mimeData());
306 }
307 }
308 else
309 event->ignore();
310
311 QWidget::dropEvent(event);
312 }
@@ -0,0 +1,50
1 #include "Visualization/VisualizationDragWidget.h"
2 #include "Visualization/VisualizationDragDropContainer.h"
3
4 #include <QMouseEvent>
5 #include <QApplication>
6
7 struct VisualizationDragWidget::VisualizationDragWidgetPrivate {
8
9 QPoint m_dragStartPosition;
10 bool m_dragStartPositionValid = false;
11
12 explicit VisualizationDragWidgetPrivate()
13 {
14 }
15 };
16
17 VisualizationDragWidget::VisualizationDragWidget(QWidget* parent)
18 : QWidget{parent}, impl{spimpl::make_unique_impl<VisualizationDragWidgetPrivate>()}
19 {
20
21 }
22
23 void VisualizationDragWidget::mousePressEvent(QMouseEvent *event)
24 {
25 if (event->button() == Qt::LeftButton)
26 impl->m_dragStartPosition = event->pos();
27
28 impl->m_dragStartPositionValid = isDragAllowed();
29
30 QWidget::mousePressEvent(event);
31 }
32
33 void VisualizationDragWidget::mouseMoveEvent(QMouseEvent *event)
34 {
35 if (!impl->m_dragStartPositionValid || !isDragAllowed())
36 return;
37
38 if (!(event->buttons() & Qt::LeftButton))
39 return;
40
41 if (!event->modifiers().testFlag(Qt::AltModifier))
42 return;
43
44 if ((event->pos() - impl->m_dragStartPosition).manhattanLength() < QApplication::startDragDistance())
45 return;
46
47 emit dragDetected(this, impl->m_dragStartPosition);
48
49 QWidget::mouseMoveEvent(event);
50 }
@@ -20,6 +20,7 class NetworkController;
20 class TimeController;
20 class TimeController;
21 class VariableController;
21 class VariableController;
22 class VisualizationController;
22 class VisualizationController;
23 class DragDropHelper;
23
24
24 /**
25 /**
25 * @brief The SqpApplication class aims to make the link between SciQlop
26 * @brief The SqpApplication class aims to make the link between SciQlop
@@ -44,6 +45,9 public:
44 VariableController &variableController() noexcept;
45 VariableController &variableController() noexcept;
45 VisualizationController &visualizationController() noexcept;
46 VisualizationController &visualizationController() noexcept;
46
47
48 /// Accessors for the differents sciqlop helpers
49 DragDropHelper &dragDropHelper() noexcept;
50
47 private:
51 private:
48 class SqpApplicationPrivate;
52 class SqpApplicationPrivate;
49 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
53 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
@@ -2,6 +2,7
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
5
6
6 #include <QLoggingCategory>
7 #include <QLoggingCategory>
7 #include <QWidget>
8 #include <QWidget>
@@ -16,12 +17,13 class QCPRange;
16 class QCustomPlot;
17 class QCustomPlot;
17 class SqpRange;
18 class SqpRange;
18 class Variable;
19 class Variable;
20 class VisualizationZoneWidget;
19
21
20 namespace Ui {
22 namespace Ui {
21 class VisualizationGraphWidget;
23 class VisualizationGraphWidget;
22 } // namespace Ui
24 } // namespace Ui
23
25
24 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
26 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
25 Q_OBJECT
27 Q_OBJECT
26
28
27 friend class QCustomPlotSynchronizer;
29 friend class QCustomPlotSynchronizer;
@@ -31,6 +33,8 public:
31 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
33 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
32 virtual ~VisualizationGraphWidget();
34 virtual ~VisualizationGraphWidget();
33
35
36 VisualizationZoneWidget* parentZoneWidget() const noexcept;
37
34 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
38 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
35 void enableAcquisition(bool enable);
39 void enableAcquisition(bool enable);
36
40
@@ -39,6 +43,9 public:
39 /// Removes a variable from the graph
43 /// Removes a variable from the graph
40 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
44 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
41
45
46 /// Returns the list of all variables used in the graph
47 QList<std::shared_ptr<Variable>> variables() const;
48
42 void setYRange(const SqpRange &range);
49 void setYRange(const SqpRange &range);
43 SqpRange graphRange() const noexcept;
50 SqpRange graphRange() const noexcept;
44 void setGraphRange(const SqpRange &range);
51 void setGraphRange(const SqpRange &range);
@@ -49,6 +56,9 public:
49 bool contains(const Variable &variable) const override;
56 bool contains(const Variable &variable) const override;
50 QString name() const override;
57 QString name() const override;
51
58
59 // VisualisationDragWidget
60 QMimeData* mimeData() const override;
61 bool isDragAllowed() const override;
52
62
53 signals:
63 signals:
54 void synchronize(const SqpRange &range, const SqpRange &oldRange);
64 void synchronize(const SqpRange &range, const SqpRange &oldRange);
@@ -7,6 +7,7
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QWidget>
9 #include <QWidget>
10 #include <QMimeData>
10
11
11 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget)
12
13
@@ -27,14 +28,32 public:
27 /// Add a zone widget
28 /// Add a zone widget
28 void addZone(VisualizationZoneWidget *zoneWidget);
29 void addZone(VisualizationZoneWidget *zoneWidget);
29
30
31 void insertZone(int index, VisualizationZoneWidget *zoneWidget);
32
30 /**
33 /**
31 * Creates a zone using a variable. The variable will be displayed in a new graph of the new
34 * Creates a zone using a variable. The variable will be displayed in a new graph of the new
32 * zone.
35 * zone. The zone is added at the end.
33 * @param variable the variable for which to create the zone
36 * @param variable the variable for which to create the zone
34 * @return the pointer to the created zone
37 * @return the pointer to the created zone
35 */
38 */
36 VisualizationZoneWidget *createZone(std::shared_ptr<Variable> variable);
39 VisualizationZoneWidget *createZone(std::shared_ptr<Variable> variable);
37
40
41 /**
42 * Creates a zone using a list of variables. The variables will be displayed in a new graph of the new
43 * zone. The zone is inserted at the specified index.
44 * @param variables the variables for which to create the zone
45 * @param index The index where the zone should be inserted in the layout
46 * @return the pointer to the created zone
47 */
48 VisualizationZoneWidget *createZone(const QList<std::shared_ptr<Variable>>& variables, int index);
49
50 /**
51 * Creates a zone which is empty (no variables). The zone is inserted at the specified index.
52 * @param index The index where the zone should be inserted in the layout
53 * @return the pointer to the created zone
54 */
55 VisualizationZoneWidget *createEmptyZone(int index);
56
38 // IVisualizationWidget interface
57 // IVisualizationWidget interface
39 void accept(IVisualizationWidgetVisitor *visitor) override;
58 void accept(IVisualizationWidgetVisitor *visitor) override;
40 bool canDrop(const Variable &variable) const override;
59 bool canDrop(const Variable &variable) const override;
@@ -52,6 +71,9 private:
52
71
53 class VisualizationTabWidgetPrivate;
72 class VisualizationTabWidgetPrivate;
54 spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl;
73 spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl;
74
75 private slots:
76 void dropMimeData(int index, const QMimeData *mimeData);
55 };
77 };
56
78
57 #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H
79 #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H
@@ -2,6 +2,7
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
5
6
6 #include <QLoggingCategory>
7 #include <QLoggingCategory>
7 #include <QWidget>
8 #include <QWidget>
@@ -19,29 +20,55 class VisualizationZoneWidget;
19 class Variable;
20 class Variable;
20 class VisualizationGraphWidget;
21 class VisualizationGraphWidget;
21
22
22 class VisualizationZoneWidget : public QWidget, public IVisualizationWidget {
23 class VisualizationZoneWidget : public VisualizationDragWidget, public IVisualizationWidget {
23 Q_OBJECT
24 Q_OBJECT
24
25
25 public:
26 public:
26 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
27 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
27 virtual ~VisualizationZoneWidget();
28 virtual ~VisualizationZoneWidget();
28
29
29 /// Add a graph widget
30 /// Adds a graph widget
30 void addGraph(VisualizationGraphWidget *graphWidget);
31 void addGraph(VisualizationGraphWidget *graphWidget);
31
32
33 /// Inserts a graph widget
34 void insertGraph(int index, VisualizationGraphWidget *graphWidget);
35
32 /**
36 /**
33 * Creates a graph using a variable. The variable will be displayed in the new graph.
37 * Creates a graph using a variable. The variable will be displayed in the new graph.
38 * The graph is added at the end.
34 * @param variable the variable for which to create the graph
39 * @param variable the variable for which to create the graph
35 * @return the pointer to the created graph
40 * @return the pointer to the created graph
36 */
41 */
37 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
42 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
38
43
44 /**
45 * Creates a graph using a variable. The variable will be displayed in the new graph.
46 * The graph is inserted at the specified index.
47 * @param variable the variable for which to create the graph
48 * @param index The index where the graph should be inserted in the layout
49 * @return the pointer to the created graph
50 */
51 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable, int index);
52
53 /**
54 * Creates a graph using a list of variables. The variables will be displayed in the new graph.
55 * The graph is inserted at the specified index.
56 * @param variables List of variables to be added to the graph
57 * @param index The index where the graph should be inserted in the layout
58 * @return the pointer to the created graph
59 */
60 VisualizationGraphWidget *createGraph(const QList<std::shared_ptr<Variable>> variables, int index);
61
39 // IVisualizationWidget interface
62 // IVisualizationWidget interface
40 void accept(IVisualizationWidgetVisitor *visitor) override;
63 void accept(IVisualizationWidgetVisitor *visitor) override;
41 bool canDrop(const Variable &variable) const override;
64 bool canDrop(const Variable &variable) const override;
42 bool contains(const Variable &variable) const override;
65 bool contains(const Variable &variable) const override;
43 QString name() const override;
66 QString name() const override;
44
67
68 // VisualisationDragWidget
69 QMimeData* mimeData() const override;
70 bool isDragAllowed() const override;
71
45 protected:
72 protected:
46 void closeEvent(QCloseEvent *event) override;
73 void closeEvent(QCloseEvent *event) override;
47
74
@@ -55,6 +82,8 private slots:
55 void onVariableAdded(std::shared_ptr<Variable> variable);
82 void onVariableAdded(std::shared_ptr<Variable> variable);
56 /// Slot called when a variable is about to be removed from a graph contained in the zone
83 /// Slot called when a variable is about to be removed from a graph contained in the zone
57 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
84 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
85
86 void dropMimeData(int index, const QMimeData* mimeData);
58 };
87 };
59
88
60 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
89 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -8,6 +8,7
8 #include <Variable/Variable.h>
8 #include <Variable/Variable.h>
9 #include <Variable/VariableController.h>
9 #include <Variable/VariableController.h>
10 #include <Visualization/VisualizationController.h>
10 #include <Visualization/VisualizationController.h>
11 #include <DragDropHelper.h>
11
12
12 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
13 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
13
14
@@ -18,7 +19,8 public:
18 m_NetworkController{std::make_unique<NetworkController>()},
19 m_NetworkController{std::make_unique<NetworkController>()},
19 m_TimeController{std::make_unique<TimeController>()},
20 m_TimeController{std::make_unique<TimeController>()},
20 m_VariableController{std::make_unique<VariableController>()},
21 m_VariableController{std::make_unique<VariableController>()},
21 m_VisualizationController{std::make_unique<VisualizationController>()}
22 m_VisualizationController{std::make_unique<VisualizationController>()},
23 m_DragDropHelper{std::make_unique<DragDropHelper>()}
22 {
24 {
23 // /////////////////////////////// //
25 // /////////////////////////////// //
24 // Connections between controllers //
26 // Connections between controllers //
@@ -82,6 +84,8 public:
82 QThread m_NetworkControllerThread;
84 QThread m_NetworkControllerThread;
83 QThread m_VariableControllerThread;
85 QThread m_VariableControllerThread;
84 QThread m_VisualizationControllerThread;
86 QThread m_VisualizationControllerThread;
87
88 std::unique_ptr<DragDropHelper> m_DragDropHelper;
85 };
89 };
86
90
87
91
@@ -148,3 +152,8 VisualizationController &SqpApplication::visualizationController() noexcept
148 {
152 {
149 return *impl->m_VisualizationController;
153 return *impl->m_VisualizationController;
150 }
154 }
155
156 DragDropHelper &SqpApplication::dragDropHelper() noexcept
157 {
158 return *impl->m_DragDropHelper;
159 }
@@ -3,12 +3,14
3 #include "Visualization/VisualizationDefs.h"
3 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationGraphHelper.h"
4 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "ui_VisualizationGraphWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
7
8
8 #include <Data/ArrayData.h>
9 #include <Data/ArrayData.h>
9 #include <Data/IDataSeries.h>
10 #include <Data/IDataSeries.h>
10 #include <Settings/SqpSettingsDefs.h>
11 #include <Settings/SqpSettingsDefs.h>
11 #include <SqpApplication.h>
12 #include <SqpApplication.h>
13 #include <DragDropHelper.h>
12 #include <Variable/Variable.h>
14 #include <Variable/Variable.h>
13 #include <Variable/VariableController.h>
15 #include <Variable/VariableController.h>
14
16
@@ -47,7 +49,7 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
47 };
49 };
48
50
49 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
51 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
50 : QWidget{parent},
52 : VisualizationDragWidget{parent},
51 ui{new Ui::VisualizationGraphWidget},
53 ui{new Ui::VisualizationGraphWidget},
52 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
54 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
53 {
55 {
@@ -92,6 +94,17 VisualizationGraphWidget::~VisualizationGraphWidget()
92 delete ui;
94 delete ui;
93 }
95 }
94
96
97 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
98 {
99 auto parent = parentWidget();
100 do
101 {
102 parent = parent->parentWidget();
103 } while (parent != nullptr && !qobject_cast<VisualizationZoneWidget*>(parent));
104
105 return qobject_cast<VisualizationZoneWidget*>(parent);
106 }
107
95 void VisualizationGraphWidget::enableAcquisition(bool enable)
108 void VisualizationGraphWidget::enableAcquisition(bool enable)
96 {
109 {
97 impl->m_DoAcquisition = enable;
110 impl->m_DoAcquisition = enable;
@@ -152,6 +165,17 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable
152 ui->widget->replot();
165 ui->widget->replot();
153 }
166 }
154
167
168 QList<std::shared_ptr<Variable>> VisualizationGraphWidget::variables() const
169 {
170 auto variables = QList<std::shared_ptr<Variable>>{};
171 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap); it != std::cend(impl->m_VariableToPlotMultiMap); ++it)
172 {
173 variables << it->first;
174 }
175
176 return variables;
177 }
178
155 void VisualizationGraphWidget::setYRange(const SqpRange &range)
179 void VisualizationGraphWidget::setYRange(const SqpRange &range)
156 {
180 {
157 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
181 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
@@ -206,6 +230,19 QString VisualizationGraphWidget::name() const
206 return impl->m_Name;
230 return impl->m_Name;
207 }
231 }
208
232
233 QMimeData *VisualizationGraphWidget::mimeData() const
234 {
235 auto *mimeData = new QMimeData;
236 mimeData->setData(DragDropHelper::MIME_TYPE_GRAPH, QByteArray());
237
238 return mimeData;
239 }
240
241 bool VisualizationGraphWidget::isDragAllowed() const
242 {
243 return true;
244 }
245
209 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
246 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
210 {
247 {
211 Q_UNUSED(event);
248 Q_UNUSED(event);
@@ -284,6 +321,8 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
284 {
321 {
285 // Handles plot rendering when mouse is moving
322 // Handles plot rendering when mouse is moving
286 impl->m_RenderingDelegate->onMouseMove(event);
323 impl->m_RenderingDelegate->onMouseMove(event);
324
325 VisualizationDragWidget::mouseMoveEvent(event);
287 }
326 }
288
327
289 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
328 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
@@ -307,6 +346,10 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
307 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
346 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
308 {
347 {
309 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
348 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
349
350 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
351
352 VisualizationDragWidget::mousePressEvent(event);
310 }
353 }
311
354
312 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
355 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
@@ -3,6 +3,12
3 #include "ui_VisualizationTabWidget.h"
3 #include "ui_VisualizationTabWidget.h"
4
4
5 #include "Visualization/VisualizationZoneWidget.h"
5 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationGraphWidget.h"
7
8 #include "Variable/VariableController.h"
9
10 #include "SqpApplication.h"
11 #include "DragDropHelper.h"
6
12
7 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
13 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
8
14
@@ -55,27 +61,49 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *par
55 {
61 {
56 ui->setupUi(this);
62 ui->setupUi(this);
57
63
64 ui->dragDropContainer->setAcceptedMimeTypes({DragDropHelper::MIME_TYPE_GRAPH, DragDropHelper::MIME_TYPE_ZONE});
65 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this, &VisualizationTabWidget::dropMimeData);
66 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
67
58 // Widget is deleted when closed
68 // Widget is deleted when closed
59 setAttribute(Qt::WA_DeleteOnClose);
69 setAttribute(Qt::WA_DeleteOnClose);
60 }
70 }
61
71
62 VisualizationTabWidget::~VisualizationTabWidget()
72 VisualizationTabWidget::~VisualizationTabWidget()
63 {
73 {
74 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
64 delete ui;
75 delete ui;
65 }
76 }
66
77
67 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
78 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
68 {
79 {
69 tabLayout().addWidget(zoneWidget);
80 ui->dragDropContainer->addDragWidget(zoneWidget);
81 }
82
83 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
84 {
85 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
70 }
86 }
71
87
72 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
88 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
73 {
89 {
74 auto zoneWidget = new VisualizationZoneWidget{defaultZoneName(tabLayout()), this};
90 return createZone({variable}, -1);
75 this->addZone(zoneWidget);
91 }
92
93 VisualizationZoneWidget *VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
94 {
95 auto zoneWidget = createEmptyZone(index);
76
96
77 // Creates a new graph into the zone
97 // Creates a new graph into the zone
78 zoneWidget->createGraph(variable);
98 zoneWidget->createGraph(variables, index);
99
100 return zoneWidget;
101 }
102
103 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
104 {
105 auto zoneWidget = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
106 this->insertZone(index, zoneWidget);
79
107
80 return zoneWidget;
108 return zoneWidget;
81 }
109 }
@@ -125,5 +153,67 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
125
153
126 QLayout &VisualizationTabWidget::tabLayout() const noexcept
154 QLayout &VisualizationTabWidget::tabLayout() const noexcept
127 {
155 {
128 return *ui->scrollAreaWidgetContents->layout();
156 return *ui->dragDropContainer->layout();
157 }
158
159 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
160 {
161 auto& helper = sqpApp->dragDropHelper();
162 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH))
163 {
164 auto graphWidget = static_cast<VisualizationGraphWidget*>(helper.getCurrentDragWidget());
165 auto parentDragDropContainer = qobject_cast<VisualizationDragDropContainer*>(graphWidget->parentWidget());
166 Q_ASSERT(parentDragDropContainer);
167
168 auto nbGraph = parentDragDropContainer->countDragWidget();
169
170 const auto& variables = graphWidget->variables();
171
172 if (!variables.isEmpty())
173 {
174 //Abort the requests for the variables (if any)
175 //Commented, because it's not sure if it's needed or not
176 //for (const auto& var : variables)
177 //{
178 // sqpApp->variableController().onAbortProgressRequested(var);
179 //}
180
181 if (nbGraph == 1)
182 {
183 //This is the only graph in the previous zone, close the zone
184 graphWidget->parentZoneWidget()->close();
185 }
186 else
187 {
188 //Close the graph
189 graphWidget->close();
190 }
191
192 createZone(variables, index);
193 }
194 else
195 {
196 //The graph is empty, create an empty zone and move the graph inside
197
198 auto parentZoneWidget = graphWidget->parentZoneWidget();
199
200 parentDragDropContainer->layout()->removeWidget(graphWidget);
201
202 auto zoneWidget = createEmptyZone(index);
203 zoneWidget->addGraph(graphWidget);
204
205 //Close the old zone if it was the only graph inside
206 if (nbGraph == 1)
207 parentZoneWidget->close();
208 }
209 }
210 else if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_ZONE))
211 {
212 //Simple move of the zone, no variable operation associated
213 auto zoneWidget = static_cast<VisualizationZoneWidget*>(helper.getCurrentDragWidget());
214 auto parentDragDropContainer = zoneWidget->parentWidget();
215 parentDragDropContainer->layout()->removeWidget(zoneWidget);
216
217 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
218 }
129 }
219 }
@@ -11,8 +11,11
11
11
12 #include <QUuid>
12 #include <QUuid>
13 #include <SqpApplication.h>
13 #include <SqpApplication.h>
14 #include <DragDropHelper.h>
14 #include <cmath>
15 #include <cmath>
15
16
17 #include <QLayout>
18
16 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
19 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
17
20
18 namespace {
21 namespace {
@@ -66,7 +69,7 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
66 };
69 };
67
70
68 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
71 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
69 : QWidget{parent},
72 : VisualizationDragWidget{parent},
70 ui{new Ui::VisualizationZoneWidget},
73 ui{new Ui::VisualizationZoneWidget},
71 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
74 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
72 {
75 {
@@ -74,6 +77,9 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *p
74
77
75 ui->zoneNameLabel->setText(name);
78 ui->zoneNameLabel->setText(name);
76
79
80 ui->dragDropContainer->setAcceptedMimeTypes({DragDropHelper::MIME_TYPE_GRAPH});
81 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this, &VisualizationZoneWidget::dropMimeData);
82
77 // 'Close' options : widget is deleted when closed
83 // 'Close' options : widget is deleted when closed
78 setAttribute(Qt::WA_DeleteOnClose);
84 setAttribute(Qt::WA_DeleteOnClose);
79 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
85 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
@@ -94,13 +100,26 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
94 // Synchronize new graph with others in the zone
100 // Synchronize new graph with others in the zone
95 impl->m_Synchronizer->addGraph(*graphWidget);
101 impl->m_Synchronizer->addGraph(*graphWidget);
96
102
97 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
103 ui->dragDropContainer->addDragWidget(graphWidget);
104 }
105
106 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
107 {
108 // Synchronize new graph with others in the zone
109 impl->m_Synchronizer->addGraph(*graphWidget);
110
111 ui->dragDropContainer->insertDragWidget(index, graphWidget);
98 }
112 }
99
113
100 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
114 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
101 {
115 {
116 return createGraph(variable, -1);
117 }
118
119 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable, int index)
120 {
102 auto graphWidget = new VisualizationGraphWidget{
121 auto graphWidget = new VisualizationGraphWidget{
103 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
122 defaultGraphName(*ui->dragDropContainer->layout()), this};
104
123
105
124
106 // Set graph properties
125 // Set graph properties
@@ -113,7 +132,7 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<V
113 const SqpRange &oldGraphRange) {
132 const SqpRange &oldGraphRange) {
114
133
115 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
134 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
116 auto frameLayout = ui->visualizationZoneFrame->layout();
135 auto frameLayout = ui->dragDropContainer->layout();
117 for (auto i = 0; i < frameLayout->count(); ++i) {
136 for (auto i = 0; i < frameLayout->count(); ++i) {
118 auto graphChild
137 auto graphChild
119 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
138 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
@@ -203,11 +222,11 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<V
203 auto range = SqpRange{};
222 auto range = SqpRange{};
204
223
205 // Apply visitor to graph children
224 // Apply visitor to graph children
206 auto layout = ui->visualizationZoneFrame->layout();
225 auto layout = ui->dragDropContainer->layout();
207 if (layout->count() > 0) {
226 if (layout->count() > 0) {
208 // Case of a new graph in a existant zone
227 // Case of a new graph in a existant zone
209 if (auto visualizationGraphWidget
228 if (auto visualizationGraphWidget
210 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
229 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
211 range = visualizationGraphWidget->graphRange();
230 range = visualizationGraphWidget->graphRange();
212 }
231 }
213 }
232 }
@@ -216,7 +235,7 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<V
216 range = variable->range();
235 range = variable->range();
217 }
236 }
218
237
219 this->addGraph(graphWidget);
238 this->insertGraph(index, graphWidget);
220
239
221 graphWidget->addVariable(variable, range);
240 graphWidget->addVariable(variable, range);
222
241
@@ -224,7 +243,7 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<V
224 if (auto dataSeries = variable->dataSeries()) {
243 if (auto dataSeries = variable->dataSeries()) {
225 dataSeries->lockRead();
244 dataSeries->lockRead();
226 auto valuesBounds
245 auto valuesBounds
227 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
246 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
228 auto end = dataSeries->cend();
247 auto end = dataSeries->cend();
229 if (valuesBounds.first != end && valuesBounds.second != end) {
248 if (valuesBounds.first != end && valuesBounds.second != end) {
230 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
249 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
@@ -240,6 +259,20 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<V
240 return graphWidget;
259 return graphWidget;
241 }
260 }
242
261
262 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
263 {
264 if (variables.isEmpty())
265 return nullptr;
266
267 auto graphWidget = createGraph(variables.first(), index);
268 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt)
269 {
270 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
271 }
272
273 return graphWidget;
274 }
275
243 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
276 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
244 {
277 {
245 if (visitor) {
278 if (visitor) {
@@ -248,7 +281,7 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
248 // Apply visitor to graph children: widgets different from graphs are not visited (no
281 // Apply visitor to graph children: widgets different from graphs are not visited (no
249 // action)
282 // action)
250 processGraphs(
283 processGraphs(
251 *ui->visualizationZoneFrame->layout(),
284 *ui->dragDropContainer->layout(),
252 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
285 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
253
286
254 visitor->visitLeave(this);
287 visitor->visitLeave(this);
@@ -276,10 +309,23 QString VisualizationZoneWidget::name() const
276 return ui->zoneNameLabel->text();
309 return ui->zoneNameLabel->text();
277 }
310 }
278
311
312 QMimeData *VisualizationZoneWidget::mimeData() const
313 {
314 auto *mimeData = new QMimeData;
315 mimeData->setData(DragDropHelper::MIME_TYPE_ZONE, QByteArray());
316
317 return mimeData;
318 }
319
320 bool VisualizationZoneWidget::isDragAllowed() const
321 {
322 return true;
323 }
324
279 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
325 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
280 {
326 {
281 // Closes graphs in the zone
327 // Closes graphs in the zone
282 processGraphs(*ui->visualizationZoneFrame->layout(),
328 processGraphs(*ui->dragDropContainer->layout(),
283 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
329 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
284
330
285 // Delete synchronization group from variable controller
331 // Delete synchronization group from variable controller
@@ -302,3 +348,66 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variabl
302 Q_ARG(std::shared_ptr<Variable>, variable),
348 Q_ARG(std::shared_ptr<Variable>, variable),
303 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
349 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
304 }
350 }
351
352 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
353 {
354 auto& helper = sqpApp->dragDropHelper();
355 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH))
356 {
357 auto graphWidget = static_cast<VisualizationGraphWidget*>(helper.getCurrentDragWidget());
358 auto parentDragDropContainer = qobject_cast<VisualizationDragDropContainer*>(graphWidget->parentWidget());
359 Q_ASSERT(parentDragDropContainer);
360
361 const auto& variables = graphWidget->variables();
362
363 if (parentDragDropContainer != ui->dragDropContainer && !variables.isEmpty())
364 {
365 //The drop didn't occur in the same zone
366
367 //Abort the requests for the variables (if any)
368 //Commented, because it's not sure if it's needed or not
369 //for (const auto& var : variables)
370 //{
371 // sqpApp->variableController().onAbortProgressRequested(var);
372 //}
373
374 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
375 auto nbGraph = parentDragDropContainer->countDragWidget();
376 if (nbGraph == 1)
377 {
378 //This is the only graph in the previous zone, close the zone
379 previousParentZoneWidget->close();
380 }
381 else
382 {
383 //Close the graph
384 graphWidget->close();
385 }
386
387 //Creates the new graph in the zone
388 createGraph(variables, index);
389 }
390 else
391 {
392 //The drop occurred in the same zone or the graph is empty
393 //Simple move of the graph, no variable operation associated
394 parentDragDropContainer->layout()->removeWidget(graphWidget);
395
396 if (variables.isEmpty() && parentDragDropContainer != ui->dragDropContainer)
397 {
398 // The graph is empty and dropped in a different zone.
399 // Take the range of the first graph in the zone (if existing).
400 auto layout = ui->dragDropContainer->layout();
401 if (layout->count() > 0)
402 {
403 if (auto visualizationGraphWidget = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget()))
404 {
405 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
406 }
407 }
408 }
409
410 ui->dragDropContainer->insertDragWidget(index, graphWidget);
411 }
412 }
413 }
@@ -62,12 +62,23
62 <property name="bottomMargin">
62 <property name="bottomMargin">
63 <number>0</number>
63 <number>0</number>
64 </property>
64 </property>
65 <item>
66 <widget class="VisualizationDragDropContainer" name="dragDropContainer" native="true"/>
67 </item>
65 </layout>
68 </layout>
66 </widget>
69 </widget>
67 </widget>
70 </widget>
68 </item>
71 </item>
69 </layout>
72 </layout>
70 </widget>
73 </widget>
74 <customwidgets>
75 <customwidget>
76 <class>VisualizationDragDropContainer</class>
77 <extends>QWidget</extends>
78 <header>Visualization/VisualizationDragDropContainer.h</header>
79 <container>1</container>
80 </customwidget>
81 </customwidgets>
71 <resources/>
82 <resources/>
72 <connections/>
83 <connections/>
73 </ui>
84 </ui>
@@ -107,11 +107,22
107 <property name="bottomMargin">
107 <property name="bottomMargin">
108 <number>0</number>
108 <number>0</number>
109 </property>
109 </property>
110 <item>
111 <widget class="VisualizationDragDropContainer" name="dragDropContainer" native="true"/>
112 </item>
110 </layout>
113 </layout>
111 </widget>
114 </widget>
112 </item>
115 </item>
113 </layout>
116 </layout>
114 </widget>
117 </widget>
118 <customwidgets>
119 <customwidget>
120 <class>VisualizationDragDropContainer</class>
121 <extends>QWidget</extends>
122 <header>Visualization/VisualizationDragDropContainer.h</header>
123 <container>1</container>
124 </customwidget>
125 </customwidgets>
115 <resources/>
126 <resources/>
116 <connections/>
127 <connections/>
117 </ui>
128 </ui>
General Comments 6
Approved

Status change > Approved

You need to be logged in to leave comments. Login now