##// END OF EJS Templates
drop of zone on the time widget
trabillard -
r977:672c298824bc
parent child
Show More
@@ -1,57 +1,57
1 #ifndef SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
1 #ifndef SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QFrame>
5 #include <QFrame>
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QMimeData>
7 #include <QMimeData>
8 #include <QVBoxLayout>
8 #include <QVBoxLayout>
9
9
10 #include <functional>
10 #include <functional>
11
11
12 #include <DragAndDrop/DragDropHelper.h>
12 #include <DragAndDrop/DragDropHelper.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
15
15
16 class VisualizationDragWidget;
16 class VisualizationDragWidget;
17
17
18 class VisualizationDragDropContainer : public QFrame {
18 class VisualizationDragDropContainer : public QFrame {
19 Q_OBJECT
19 Q_OBJECT
20
20
21 signals:
21 signals:
22 void dropOccuredInContainer(int dropIndex, const QMimeData *mimeData);
22 void dropOccuredInContainer(int dropIndex, const QMimeData *mimeData);
23 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
23 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
24
24
25 public:
25 public:
26 enum class DropBehavior { Inserted, Merged, InsertedAndMerged };
26 enum class DropBehavior { Inserted, Merged, InsertedAndMerged, Forbidden };
27 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
27 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
28
28
29 VisualizationDragDropContainer(QWidget *parent = nullptr);
29 VisualizationDragDropContainer(QWidget *parent = nullptr);
30
30
31 void addDragWidget(VisualizationDragWidget *dragWidget);
31 void addDragWidget(VisualizationDragWidget *dragWidget);
32 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
32 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
33
33
34 void addAcceptedMimeType(const QString &mimeType, DropBehavior behavior);
34 void setMimeType(const QString &mimeType, DropBehavior behavior);
35
35
36 int countDragWidget() const;
36 int countDragWidget() const;
37
37
38 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
38 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
39
39
40 void setPlaceHolderType(DragDropHelper::PlaceHolderType type,
40 void setPlaceHolderType(DragDropHelper::PlaceHolderType type,
41 const QString &placeHolderText = QString());
41 const QString &placeHolderText = QString());
42
42
43 protected:
43 protected:
44 void dragEnterEvent(QDragEnterEvent *event);
44 void dragEnterEvent(QDragEnterEvent *event);
45 void dragLeaveEvent(QDragLeaveEvent *event);
45 void dragLeaveEvent(QDragLeaveEvent *event);
46 void dragMoveEvent(QDragMoveEvent *event);
46 void dragMoveEvent(QDragMoveEvent *event);
47 void dropEvent(QDropEvent *event);
47 void dropEvent(QDropEvent *event);
48
48
49 private:
49 private:
50 class VisualizationDragDropContainerPrivate;
50 class VisualizationDragDropContainerPrivate;
51 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
51 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
52
52
53 private slots:
53 private slots:
54 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
54 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
55 };
55 };
56
56
57 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
57 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
@@ -1,455 +1,470
1 #include "Visualization/VisualizationDragDropContainer.h"
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragAndDrop/DragDropHelper.h"
2 #include "DragAndDrop/DragDropHelper.h"
3 #include "SqpApplication.h"
3 #include "SqpApplication.h"
4 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5
5
6 #include "Common/VisualizationDef.h"
6 #include "Common/VisualizationDef.h"
7
7
8 #include <QDrag>
8 #include <QDrag>
9 #include <QDragEnterEvent>
9 #include <QDragEnterEvent>
10 #include <QVBoxLayout>
10 #include <QVBoxLayout>
11
11
12 #include <cmath>
12 #include <cmath>
13 #include <memory>
13 #include <memory>
14
14
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
16
16
17 auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels
17 auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels
18
18
19 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
19 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
20
20
21 QVBoxLayout *m_Layout;
21 QVBoxLayout *m_Layout;
22 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
22 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
23 QString m_PlaceHolderText;
23 QString m_PlaceHolderText;
24 DragDropHelper::PlaceHolderType m_PlaceHolderType = DragDropHelper::PlaceHolderType::Graph;
24 DragDropHelper::PlaceHolderType m_PlaceHolderType = DragDropHelper::PlaceHolderType::Graph;
25
25
26 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
26 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
27 = [](auto mimeData) { return true; };
27 = [](auto mimeData) { return true; };
28
28
29 int m_MinContainerHeight = 0;
29 int m_MinContainerHeight = 0;
30
30
31 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
31 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
32 {
32 {
33 m_Layout = new QVBoxLayout(widget);
33 m_Layout = new QVBoxLayout(widget);
34 m_Layout->setContentsMargins(0, 0, 0, 0);
34 m_Layout->setContentsMargins(0, 0, 0, 0);
35 }
35 }
36
36
37 bool acceptMimeData(const QMimeData *data) const
37 bool acceptMimeData(const QMimeData *data) const
38 {
38 {
39 for (const auto &type : m_AcceptedMimeTypes.keys()) {
39 auto accepted = false;
40 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
40 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
41 return true;
41 ++it) {
42 const auto &type = it.key();
43 const auto &behavior = it.value();
44
45 if (data->hasFormat(type)) {
46 if (behavior != DropBehavior::Forbidden) {
47 accepted = true;
48 }
49 else {
50 accepted = false;
51 break;
52 }
42 }
53 }
43 }
54 }
44
55
45 return false;
56 if (accepted) {
57 accepted = m_AcceptMimeDataFun(data);
58 }
59
60 return accepted;
46 }
61 }
47
62
48 bool allowMergeForMimeData(const QMimeData *data) const
63 bool allowMergeForMimeData(const QMimeData *data) const
49 {
64 {
50 bool result = false;
65 bool result = false;
51 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
66 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
52 ++it) {
67 ++it) {
53
68
54 if (data->hasFormat(it.key())
69 if (data->hasFormat(it.key())
55 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
70 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
56 || it.value()
71 || it.value()
57 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
72 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
58 result = true;
73 result = true;
59 }
74 }
60 else if (data->hasFormat(it.key())
75 else if (data->hasFormat(it.key())
61 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
76 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
62 // Merge is forbidden if the mime data contain an acceptable type which cannot be
77 // Merge is forbidden if the mime data contain an acceptable type which cannot be
63 // merged
78 // merged
64 result = false;
79 result = false;
65 break;
80 break;
66 }
81 }
67 }
82 }
68
83
69 return result;
84 return result;
70 }
85 }
71
86
72 bool allowInsertForMimeData(const QMimeData *data) const
87 bool allowInsertForMimeData(const QMimeData *data) const
73 {
88 {
74 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
89 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
75 ++it) {
90 ++it) {
76 if (data->hasFormat(it.key())
91 if (data->hasFormat(it.key())
77 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
92 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
78 || it.value()
93 || it.value()
79 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
94 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
80 return true;
95 return true;
81 }
96 }
82 }
97 }
83
98
84 return false;
99 return false;
85 }
100 }
86
101
87 bool hasPlaceHolder() const
102 bool hasPlaceHolder() const
88 {
103 {
89 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
104 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
90 }
105 }
91
106
92 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
107 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
93 {
108 {
94 VisualizationDragWidget *dragWidget = nullptr;
109 VisualizationDragWidget *dragWidget = nullptr;
95
110
96 for (auto child : parent->children()) {
111 for (auto child : parent->children()) {
97 auto widget = qobject_cast<VisualizationDragWidget *>(child);
112 auto widget = qobject_cast<VisualizationDragWidget *>(child);
98 if (widget && widget->isVisible()) {
113 if (widget && widget->isVisible()) {
99 if (widget->frameGeometry().contains(pos)) {
114 if (widget->frameGeometry().contains(pos)) {
100 dragWidget = widget;
115 dragWidget = widget;
101 break;
116 break;
102 }
117 }
103 }
118 }
104 }
119 }
105
120
106 return dragWidget;
121 return dragWidget;
107 }
122 }
108
123
109 bool cursorIsInContainer(QWidget *container) const
124 bool cursorIsInContainer(QWidget *container) const
110 {
125 {
111 return container->isAncestorOf(sqpApp->widgetAt(QCursor::pos()));
126 return container->isAncestorOf(sqpApp->widgetAt(QCursor::pos()));
112 }
127 }
113
128
114 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
129 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
115 {
130 {
116 auto nbGraph = 0;
131 auto nbGraph = 0;
117 for (auto child : parent->children()) {
132 for (auto child : parent->children()) {
118 if (qobject_cast<VisualizationDragWidget *>(child)) {
133 if (qobject_cast<VisualizationDragWidget *>(child)) {
119 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
134 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
120 nbGraph += 1;
135 nbGraph += 1;
121 }
136 }
122 }
137 }
123 }
138 }
124
139
125 return nbGraph;
140 return nbGraph;
126 }
141 }
127
142
128 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
143 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
129 const VisualizationDragDropContainer *container);
144 const VisualizationDragDropContainer *container);
130 };
145 };
131
146
132 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
147 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
133 : QFrame{parent},
148 : QFrame{parent},
134 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
149 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
135 {
150 {
136 setAcceptDrops(true);
151 setAcceptDrops(true);
137 }
152 }
138
153
139 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
154 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
140 {
155 {
141 impl->m_Layout->addWidget(dragWidget);
156 impl->m_Layout->addWidget(dragWidget);
142 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
157 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
143 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
158 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
144 &VisualizationDragDropContainer::startDrag);
159 &VisualizationDragDropContainer::startDrag);
145 }
160 }
146
161
147 void VisualizationDragDropContainer::insertDragWidget(int index,
162 void VisualizationDragDropContainer::insertDragWidget(int index,
148 VisualizationDragWidget *dragWidget)
163 VisualizationDragWidget *dragWidget)
149 {
164 {
150 impl->m_Layout->insertWidget(index, dragWidget);
165 impl->m_Layout->insertWidget(index, dragWidget);
151 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
166 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
152 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
167 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
153 &VisualizationDragDropContainer::startDrag);
168 &VisualizationDragDropContainer::startDrag);
154 }
169 }
155
170
156 void VisualizationDragDropContainer::addAcceptedMimeType(
171 void VisualizationDragDropContainer::setMimeType(
157 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
172 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
158 {
173 {
159 impl->m_AcceptedMimeTypes[mimeType] = behavior;
174 impl->m_AcceptedMimeTypes[mimeType] = behavior;
160 }
175 }
161
176
162 int VisualizationDragDropContainer::countDragWidget() const
177 int VisualizationDragDropContainer::countDragWidget() const
163 {
178 {
164 return impl->countDragWidget(this);
179 return impl->countDragWidget(this);
165 }
180 }
166
181
167 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
182 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
168 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
183 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
169 {
184 {
170 impl->m_AcceptMimeDataFun = fun;
185 impl->m_AcceptMimeDataFun = fun;
171 }
186 }
172
187
173 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
188 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
174 const QString &placeHolderText)
189 const QString &placeHolderText)
175 {
190 {
176 impl->m_PlaceHolderType = type;
191 impl->m_PlaceHolderType = type;
177 impl->m_PlaceHolderText = placeHolderText;
192 impl->m_PlaceHolderText = placeHolderText;
178 }
193 }
179
194
180 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
195 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
181 const QPoint &dragPosition)
196 const QPoint &dragPosition)
182 {
197 {
183 auto &helper = sqpApp->dragDropHelper();
198 auto &helper = sqpApp->dragDropHelper();
184 helper.resetDragAndDrop();
199 helper.resetDragAndDrop();
185
200
186 // Note: The management of the drag object is done by Qt
201 // Note: The management of the drag object is done by Qt
187 auto drag = new QDrag{dragWidget};
202 auto drag = new QDrag{dragWidget};
188
203
189 auto mimeData = dragWidget->mimeData();
204 auto mimeData = dragWidget->mimeData();
190 drag->setMimeData(mimeData);
205 drag->setMimeData(mimeData);
191
206
192 auto pixmap = QPixmap(dragWidget->size());
207 auto pixmap = QPixmap(dragWidget->size());
193 dragWidget->render(&pixmap);
208 dragWidget->render(&pixmap);
194 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
209 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
195 Qt::KeepAspectRatio, Qt::SmoothTransformation));
210 Qt::KeepAspectRatio, Qt::SmoothTransformation));
196
211
197 auto image = pixmap.toImage();
212 auto image = pixmap.toImage();
198 mimeData->setImageData(image);
213 mimeData->setImageData(image);
199 mimeData->setUrls({helper.imageTemporaryUrl(image)});
214 mimeData->setUrls({helper.imageTemporaryUrl(image)});
200
215
201 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
216 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
202 helper.setCurrentDragWidget(dragWidget);
217 helper.setCurrentDragWidget(dragWidget);
203
218
204 if (impl->cursorIsInContainer(this)) {
219 if (impl->cursorIsInContainer(this)) {
205 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
220 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
206 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
221 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
207 impl->m_PlaceHolderText);
222 impl->m_PlaceHolderText);
208 dragWidget->setVisible(false);
223 dragWidget->setVisible(false);
209 }
224 }
210 else {
225 else {
211 // The drag starts directly outside the drop zone
226 // The drag starts directly outside the drop zone
212 // do not add the placeHolder
227 // do not add the placeHolder
213 }
228 }
214
229
215 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
230 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
216
231
217 helper.doCloseWidgets();
232 helper.doCloseWidgets();
218 }
233 }
219 else {
234 else {
220 qCWarning(LOG_VisualizationDragDropContainer())
235 qCWarning(LOG_VisualizationDragDropContainer())
221 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
236 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
222 "VisualizationDragWidget is not found in this container.");
237 "VisualizationDragWidget is not found in this container.");
223 }
238 }
224 }
239 }
225
240
226 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
241 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
227 {
242 {
228 if (impl->acceptMimeData(event->mimeData())) {
243 if (impl->acceptMimeData(event->mimeData())) {
229 event->acceptProposedAction();
244 event->acceptProposedAction();
230
245
231 auto &helper = sqpApp->dragDropHelper();
246 auto &helper = sqpApp->dragDropHelper();
232
247
233 if (!impl->hasPlaceHolder()) {
248 if (!impl->hasPlaceHolder()) {
234 auto dragWidget = helper.getCurrentDragWidget();
249 auto dragWidget = helper.getCurrentDragWidget();
235
250
236 if (dragWidget) {
251 if (dragWidget) {
237 // If the drag&drop is internal to the visualization, entering the container hide
252 // If the drag&drop is internal to the visualization, entering the container hide
238 // the dragWidget which was made visible by the dragLeaveEvent
253 // the dragWidget which was made visible by the dragLeaveEvent
239 auto parentWidget
254 auto parentWidget
240 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
255 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
241 if (parentWidget) {
256 if (parentWidget) {
242 dragWidget->setVisible(false);
257 dragWidget->setVisible(false);
243 }
258 }
244 }
259 }
245
260
246 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
261 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
247 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
262 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
248 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
263 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
249 }
264 }
250 else {
265 else {
251 // do nothing
266 // do nothing
252 }
267 }
253 }
268 }
254 else {
269 else {
255 event->ignore();
270 event->ignore();
256 }
271 }
257
272
258 QWidget::dragEnterEvent(event);
273 QWidget::dragEnterEvent(event);
259 }
274 }
260
275
261 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
276 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
262 {
277 {
263 Q_UNUSED(event);
278 Q_UNUSED(event);
264
279
265 auto &helper = sqpApp->dragDropHelper();
280 auto &helper = sqpApp->dragDropHelper();
266
281
267 if (!impl->cursorIsInContainer(this)) {
282 if (!impl->cursorIsInContainer(this)) {
268 helper.removePlaceHolder();
283 helper.removePlaceHolder();
269 helper.setHightlightedDragWidget(nullptr);
284 helper.setHightlightedDragWidget(nullptr);
270 impl->m_MinContainerHeight = 0;
285 impl->m_MinContainerHeight = 0;
271
286
272 auto dragWidget = helper.getCurrentDragWidget();
287 auto dragWidget = helper.getCurrentDragWidget();
273 if (dragWidget) {
288 if (dragWidget) {
274 // dragWidget has a value only if the drag is started from the visualization
289 // dragWidget has a value only if the drag is started from the visualization
275 // In that case, shows the drag widget at its original place
290 // In that case, shows the drag widget at its original place
276 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
291 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
277 // drop zone (It is not possible to catch a drop event outside of the application)
292 // drop zone (It is not possible to catch a drop event outside of the application)
278
293
279 if (dragWidget) {
294 if (dragWidget) {
280 dragWidget->setVisible(true);
295 dragWidget->setVisible(true);
281 }
296 }
282 }
297 }
283 }
298 }
284 else {
299 else {
285 // Leave event probably received for a child widget.
300 // Leave event probably received for a child widget.
286 // Do nothing.
301 // Do nothing.
287 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
302 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
288 }
303 }
289
304
290 QWidget::dragLeaveEvent(event);
305 QWidget::dragLeaveEvent(event);
291 }
306 }
292
307
293 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
308 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
294 {
309 {
295 if (impl->acceptMimeData(event->mimeData())) {
310 if (impl->acceptMimeData(event->mimeData())) {
296 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
311 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
297 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
312 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
298 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
313 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
299 }
314 }
300 else {
315 else {
301 event->ignore();
316 event->ignore();
302 }
317 }
303
318
304 QWidget::dragMoveEvent(event);
319 QWidget::dragMoveEvent(event);
305 }
320 }
306
321
307 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
322 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
308 {
323 {
309 auto &helper = sqpApp->dragDropHelper();
324 auto &helper = sqpApp->dragDropHelper();
310
325
311 if (impl->acceptMimeData(event->mimeData())) {
326 if (impl->acceptMimeData(event->mimeData())) {
312 auto dragWidget = helper.getCurrentDragWidget();
327 auto dragWidget = helper.getCurrentDragWidget();
313 if (impl->hasPlaceHolder()) {
328 if (impl->hasPlaceHolder()) {
314 // drop where the placeHolder is located
329 // drop where the placeHolder is located
315
330
316 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
331 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
317 if (canInsert) {
332 if (canInsert) {
318 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
333 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
319
334
320 if (dragWidget) {
335 if (dragWidget) {
321 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
336 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
322 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
337 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
323 // Correction of the index if the drop occurs in the same container
338 // Correction of the index if the drop occurs in the same container
324 // and if the drag is started from the visualization (in that case, the
339 // and if the drag is started from the visualization (in that case, the
325 // dragWidget is hidden)
340 // dragWidget is hidden)
326 droppedIndex -= 1;
341 droppedIndex -= 1;
327 }
342 }
328
343
329 dragWidget->setVisible(true);
344 dragWidget->setVisible(true);
330 }
345 }
331
346
332 event->acceptProposedAction();
347 event->acceptProposedAction();
333
348
334 helper.removePlaceHolder();
349 helper.removePlaceHolder();
335
350
336 emit dropOccuredInContainer(droppedIndex, event->mimeData());
351 emit dropOccuredInContainer(droppedIndex, event->mimeData());
337 }
352 }
338 else {
353 else {
339 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
354 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
340 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
355 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
341 "the insertion is forbidden.");
356 "the insertion is forbidden.");
342 Q_ASSERT(false);
357 Q_ASSERT(false);
343 }
358 }
344 }
359 }
345 else if (helper.getHightlightedDragWidget()) {
360 else if (helper.getHightlightedDragWidget()) {
346 // drop on the highlighted widget
361 // drop on the highlighted widget
347
362
348 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
363 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
349 if (canMerge) {
364 if (canMerge) {
350 event->acceptProposedAction();
365 event->acceptProposedAction();
351 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
366 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
352 }
367 }
353 else {
368 else {
354 qCWarning(LOG_VisualizationDragDropContainer())
369 qCWarning(LOG_VisualizationDragDropContainer())
355 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
370 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
356 "the merge is forbidden.");
371 "the merge is forbidden.");
357 Q_ASSERT(false);
372 Q_ASSERT(false);
358 }
373 }
359 }
374 }
360 }
375 }
361 else {
376 else {
362 event->ignore();
377 event->ignore();
363 }
378 }
364
379
365 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
380 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
366 impl->m_MinContainerHeight = 0;
381 impl->m_MinContainerHeight = 0;
367
382
368 QWidget::dropEvent(event);
383 QWidget::dropEvent(event);
369 }
384 }
370
385
371
386
372 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
387 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
373 const QPoint &pos, bool canInsert, bool canMerge,
388 const QPoint &pos, bool canInsert, bool canMerge,
374 const VisualizationDragDropContainer *container)
389 const VisualizationDragDropContainer *container)
375 {
390 {
376 auto &helper = sqpApp->dragDropHelper();
391 auto &helper = sqpApp->dragDropHelper();
377
392
378 auto absPos = container->mapToGlobal(pos);
393 auto absPos = container->mapToGlobal(pos);
379 auto isOnPlaceHolder = sqpApp->widgetAt(absPos) == &(helper.placeHolder());
394 auto isOnPlaceHolder = sqpApp->widgetAt(absPos) == &(helper.placeHolder());
380
395
381 if (countDragWidget(container, true) == 0) {
396 if (countDragWidget(container, true) == 0) {
382 // Drop on an empty container, just add the placeHolder at the top
397 // Drop on an empty container, just add the placeHolder at the top
383 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
398 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
384 }
399 }
385 else if (!isOnPlaceHolder) {
400 else if (!isOnPlaceHolder) {
386 auto nbDragWidget = countDragWidget(container);
401 auto nbDragWidget = countDragWidget(container);
387 if (nbDragWidget > 0) {
402 if (nbDragWidget > 0) {
388
403
389 if (m_MinContainerHeight == 0) {
404 if (m_MinContainerHeight == 0) {
390 m_MinContainerHeight = container->size().height();
405 m_MinContainerHeight = container->size().height();
391 }
406 }
392
407
393 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
408 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
394 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
409 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
395
410
396 auto posY = pos.y();
411 auto posY = pos.y();
397 auto dropIndex = floor(posY / graphHeight);
412 auto dropIndex = floor(posY / graphHeight);
398 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
413 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
399
414
400
415
401 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
416 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
402 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
417 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
403
418
404 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
419 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
405
420
406 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
421 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
407
422
408 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
423 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
409 if (isOnBottom) {
424 if (isOnBottom) {
410 dropIndex += 1;
425 dropIndex += 1;
411 }
426 }
412
427
413 if (helper.getCurrentDragWidget()) {
428 if (helper.getCurrentDragWidget()) {
414 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
429 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
415 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
430 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
416 // Correction of the index if the drop occurs in the same container
431 // Correction of the index if the drop occurs in the same container
417 // and if the drag is started from the visualization (in that case, the
432 // and if the drag is started from the visualization (in that case, the
418 // dragWidget is hidden)
433 // dragWidget is hidden)
419 dropIndex += 1;
434 dropIndex += 1;
420 }
435 }
421 }
436 }
422
437
423 if (dropIndex != placeHolderIndex) {
438 if (dropIndex != placeHolderIndex) {
424 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
439 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
425 m_PlaceHolderText);
440 m_PlaceHolderText);
426 }
441 }
427
442
428 helper.setHightlightedDragWidget(nullptr);
443 helper.setHightlightedDragWidget(nullptr);
429 }
444 }
430 else if (canMerge && dragWidgetHovered) {
445 else if (canMerge && dragWidgetHovered) {
431 // drop on the middle -> merge
446 // drop on the middle -> merge
432 if (hasPlaceHolder()) {
447 if (hasPlaceHolder()) {
433 helper.removePlaceHolder();
448 helper.removePlaceHolder();
434 }
449 }
435
450
436 helper.setHightlightedDragWidget(dragWidgetHovered);
451 helper.setHightlightedDragWidget(dragWidgetHovered);
437 }
452 }
438 else {
453 else {
439 qCWarning(LOG_VisualizationDragDropContainer())
454 qCWarning(LOG_VisualizationDragDropContainer())
440 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
455 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
441 "action.");
456 "action.");
442 }
457 }
443 }
458 }
444 else {
459 else {
445 qCWarning(LOG_VisualizationDragDropContainer())
460 qCWarning(LOG_VisualizationDragDropContainer())
446 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
461 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
447 "found in the "
462 "found in the "
448 "container");
463 "container");
449 }
464 }
450 }
465 }
451 else {
466 else {
452 // the mouse is hover the placeHolder
467 // the mouse is hover the placeHolder
453 // Do nothing
468 // Do nothing
454 }
469 }
455 }
470 }
@@ -1,319 +1,319
1 #include "Visualization/VisualizationTabWidget.h"
1 #include "Visualization/VisualizationTabWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "ui_VisualizationTabWidget.h"
3 #include "ui_VisualizationTabWidget.h"
4
4
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7
7
8 #include "Visualization/MacScrollBarStyle.h"
8 #include "Visualization/MacScrollBarStyle.h"
9
9
10 #include "Variable/VariableController.h"
10 #include "Variable/VariableController.h"
11
11
12 #include "Common/MimeTypesDef.h"
12 #include "Common/MimeTypesDef.h"
13
13
14 #include "DragAndDrop/DragDropHelper.h"
14 #include "DragAndDrop/DragDropHelper.h"
15 #include "SqpApplication.h"
15 #include "SqpApplication.h"
16
16
17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
18
18
19 namespace {
19 namespace {
20
20
21 /// Generates a default name for a new zone, according to the number of zones already displayed in
21 /// Generates a default name for a new zone, according to the number of zones already displayed in
22 /// the tab
22 /// the tab
23 QString defaultZoneName(const QLayout &layout)
23 QString defaultZoneName(const QLayout &layout)
24 {
24 {
25 auto count = 0;
25 auto count = 0;
26 for (auto i = 0; i < layout.count(); ++i) {
26 for (auto i = 0; i < layout.count(); ++i) {
27 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
27 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
28 count++;
28 count++;
29 }
29 }
30 }
30 }
31
31
32 return QObject::tr("Zone %1").arg(count + 1);
32 return QObject::tr("Zone %1").arg(count + 1);
33 }
33 }
34
34
35 /**
35 /**
36 * Applies a function to all zones of the tab represented by its layout
36 * Applies a function to all zones of the tab represented by its layout
37 * @param layout the layout that contains zones
37 * @param layout the layout that contains zones
38 * @param fun the function to apply to each zone
38 * @param fun the function to apply to each zone
39 */
39 */
40 template <typename Fun>
40 template <typename Fun>
41 void processZones(QLayout &layout, Fun fun)
41 void processZones(QLayout &layout, Fun fun)
42 {
42 {
43 for (auto i = 0; i < layout.count(); ++i) {
43 for (auto i = 0; i < layout.count(); ++i) {
44 if (auto item = layout.itemAt(i)) {
44 if (auto item = layout.itemAt(i)) {
45 if (auto visualizationZoneWidget
45 if (auto visualizationZoneWidget
46 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
46 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
47 fun(*visualizationZoneWidget);
47 fun(*visualizationZoneWidget);
48 }
48 }
49 }
49 }
50 }
50 }
51 }
51 }
52
52
53 } // namespace
53 } // namespace
54
54
55 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
55 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
56 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
56 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
57
57
58 QString m_Name;
58 QString m_Name;
59
59
60 #ifdef Q_OS_MAC
60 #ifdef Q_OS_MAC
61 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
61 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
62 #endif
62 #endif
63
63
64 void dropGraph(int index, VisualizationTabWidget *tabWidget);
64 void dropGraph(int index, VisualizationTabWidget *tabWidget);
65 void dropZone(int index, VisualizationTabWidget *tabWidget);
65 void dropZone(int index, VisualizationTabWidget *tabWidget);
66 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
66 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
67 VisualizationTabWidget *tabWidget);
67 VisualizationTabWidget *tabWidget);
68 };
68 };
69
69
70 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
70 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
71 : QWidget{parent},
71 : QWidget{parent},
72 ui{new Ui::VisualizationTabWidget},
72 ui{new Ui::VisualizationTabWidget},
73 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
73 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
74 {
74 {
75 ui->setupUi(this);
75 ui->setupUi(this);
76
76
77 #ifdef Q_OS_MAC
77 #ifdef Q_OS_MAC
78 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
78 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
79 #endif
79 #endif
80
80
81 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Zone, "Zone");
81 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Zone, "Zone");
82 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 5);
82 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 5);
83 ui->dragDropContainer->addAcceptedMimeType(
83 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
84 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
84 VisualizationDragDropContainer::DropBehavior::Inserted);
85 ui->dragDropContainer->addAcceptedMimeType(
85 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
86 MIME_TYPE_ZONE, VisualizationDragDropContainer::DropBehavior::Inserted);
86 VisualizationDragDropContainer::DropBehavior::Inserted);
87 ui->dragDropContainer->addAcceptedMimeType(
87 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
88 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::Inserted);
88 VisualizationDragDropContainer::DropBehavior::Inserted);
89
89
90 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
90 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
91 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
91 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
92 ui->dragDropContainer);
92 ui->dragDropContainer);
93 });
93 });
94
94
95 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
95 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
96 &VisualizationTabWidget::dropMimeData);
96 &VisualizationTabWidget::dropMimeData);
97
97
98 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
98 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
99
99
100 // Widget is deleted when closed
100 // Widget is deleted when closed
101 setAttribute(Qt::WA_DeleteOnClose);
101 setAttribute(Qt::WA_DeleteOnClose);
102 }
102 }
103
103
104 VisualizationTabWidget::~VisualizationTabWidget()
104 VisualizationTabWidget::~VisualizationTabWidget()
105 {
105 {
106 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
106 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
107 delete ui;
107 delete ui;
108 }
108 }
109
109
110 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
110 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
111 {
111 {
112 ui->dragDropContainer->addDragWidget(zoneWidget);
112 ui->dragDropContainer->addDragWidget(zoneWidget);
113 }
113 }
114
114
115 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
115 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
116 {
116 {
117 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
117 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
118 }
118 }
119
119
120 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
120 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
121 {
121 {
122 return createZone({variable}, -1);
122 return createZone({variable}, -1);
123 }
123 }
124
124
125 VisualizationZoneWidget *
125 VisualizationZoneWidget *
126 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
126 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
127 {
127 {
128 auto zoneWidget = createEmptyZone(index);
128 auto zoneWidget = createEmptyZone(index);
129
129
130 // Creates a new graph into the zone
130 // Creates a new graph into the zone
131 zoneWidget->createGraph(variables, index);
131 zoneWidget->createGraph(variables, index);
132
132
133 return zoneWidget;
133 return zoneWidget;
134 }
134 }
135
135
136 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
136 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
137 {
137 {
138 auto zoneWidget
138 auto zoneWidget
139 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
139 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
140 this->insertZone(index, zoneWidget);
140 this->insertZone(index, zoneWidget);
141
141
142 return zoneWidget;
142 return zoneWidget;
143 }
143 }
144
144
145 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
145 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
146 {
146 {
147 if (visitor) {
147 if (visitor) {
148 visitor->visitEnter(this);
148 visitor->visitEnter(this);
149
149
150 // Apply visitor to zone children: widgets different from zones are not visited (no action)
150 // Apply visitor to zone children: widgets different from zones are not visited (no action)
151 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
151 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
152 zoneWidget.accept(visitor);
152 zoneWidget.accept(visitor);
153 });
153 });
154
154
155 visitor->visitLeave(this);
155 visitor->visitLeave(this);
156 }
156 }
157 else {
157 else {
158 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
158 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
159 }
159 }
160 }
160 }
161
161
162 bool VisualizationTabWidget::canDrop(const Variable &variable) const
162 bool VisualizationTabWidget::canDrop(const Variable &variable) const
163 {
163 {
164 // A tab can always accomodate a variable
164 // A tab can always accomodate a variable
165 Q_UNUSED(variable);
165 Q_UNUSED(variable);
166 return true;
166 return true;
167 }
167 }
168
168
169 bool VisualizationTabWidget::contains(const Variable &variable) const
169 bool VisualizationTabWidget::contains(const Variable &variable) const
170 {
170 {
171 Q_UNUSED(variable);
171 Q_UNUSED(variable);
172 return false;
172 return false;
173 }
173 }
174
174
175 QString VisualizationTabWidget::name() const
175 QString VisualizationTabWidget::name() const
176 {
176 {
177 return impl->m_Name;
177 return impl->m_Name;
178 }
178 }
179
179
180 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
180 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
181 {
181 {
182 // Closes zones in the tab
182 // Closes zones in the tab
183 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
183 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
184
184
185 QWidget::closeEvent(event);
185 QWidget::closeEvent(event);
186 }
186 }
187
187
188 QLayout &VisualizationTabWidget::tabLayout() const noexcept
188 QLayout &VisualizationTabWidget::tabLayout() const noexcept
189 {
189 {
190 return *ui->dragDropContainer->layout();
190 return *ui->dragDropContainer->layout();
191 }
191 }
192
192
193 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
193 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
194 {
194 {
195 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
195 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
196 impl->dropGraph(index, this);
196 impl->dropGraph(index, this);
197 }
197 }
198 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
198 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
199 impl->dropZone(index, this);
199 impl->dropZone(index, this);
200 }
200 }
201 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
201 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
202 auto variables = sqpApp->variableController().variablesForMimeData(
202 auto variables = sqpApp->variableController().variablesForMimeData(
203 mimeData->data(MIME_TYPE_VARIABLE_LIST));
203 mimeData->data(MIME_TYPE_VARIABLE_LIST));
204 impl->dropVariables(variables, index, this);
204 impl->dropVariables(variables, index, this);
205 }
205 }
206 else {
206 else {
207 qCWarning(LOG_VisualizationZoneWidget())
207 qCWarning(LOG_VisualizationZoneWidget())
208 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
208 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
209 }
209 }
210 }
210 }
211
211
212 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
212 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
213 int index, VisualizationTabWidget *tabWidget)
213 int index, VisualizationTabWidget *tabWidget)
214 {
214 {
215 auto &helper = sqpApp->dragDropHelper();
215 auto &helper = sqpApp->dragDropHelper();
216
216
217 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
217 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
218 if (!graphWidget) {
218 if (!graphWidget) {
219 qCWarning(LOG_VisualizationZoneWidget())
219 qCWarning(LOG_VisualizationZoneWidget())
220 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
220 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
221 "found or invalid.");
221 "found or invalid.");
222 Q_ASSERT(false);
222 Q_ASSERT(false);
223 return;
223 return;
224 }
224 }
225
225
226 auto parentDragDropContainer
226 auto parentDragDropContainer
227 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
227 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
228 if (!parentDragDropContainer) {
228 if (!parentDragDropContainer) {
229 qCWarning(LOG_VisualizationZoneWidget())
229 qCWarning(LOG_VisualizationZoneWidget())
230 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
230 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
231 "the dropped graph is not found.");
231 "the dropped graph is not found.");
232 Q_ASSERT(false);
232 Q_ASSERT(false);
233 return;
233 return;
234 }
234 }
235
235
236 auto nbGraph = parentDragDropContainer->countDragWidget();
236 auto nbGraph = parentDragDropContainer->countDragWidget();
237
237
238 const auto &variables = graphWidget->variables();
238 const auto &variables = graphWidget->variables();
239
239
240 if (!variables.isEmpty()) {
240 if (!variables.isEmpty()) {
241 // Abort the requests for the variables (if any)
241 // Abort the requests for the variables (if any)
242 // Commented, because it's not sure if it's needed or not
242 // Commented, because it's not sure if it's needed or not
243 // for (const auto& var : variables)
243 // for (const auto& var : variables)
244 //{
244 //{
245 // sqpApp->variableController().onAbortProgressRequested(var);
245 // sqpApp->variableController().onAbortProgressRequested(var);
246 //}
246 //}
247
247
248 if (nbGraph == 1) {
248 if (nbGraph == 1) {
249 // This is the only graph in the previous zone, close the zone
249 // This is the only graph in the previous zone, close the zone
250 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
250 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
251 }
251 }
252 else {
252 else {
253 // Close the graph
253 // Close the graph
254 helper.delayedCloseWidget(graphWidget);
254 helper.delayedCloseWidget(graphWidget);
255 }
255 }
256
256
257 tabWidget->createZone(variables, index);
257 tabWidget->createZone(variables, index);
258 }
258 }
259 else {
259 else {
260 // The graph is empty, create an empty zone and move the graph inside
260 // The graph is empty, create an empty zone and move the graph inside
261
261
262 auto parentZoneWidget = graphWidget->parentZoneWidget();
262 auto parentZoneWidget = graphWidget->parentZoneWidget();
263
263
264 parentDragDropContainer->layout()->removeWidget(graphWidget);
264 parentDragDropContainer->layout()->removeWidget(graphWidget);
265
265
266 auto zoneWidget = tabWidget->createEmptyZone(index);
266 auto zoneWidget = tabWidget->createEmptyZone(index);
267 zoneWidget->addGraph(graphWidget);
267 zoneWidget->addGraph(graphWidget);
268
268
269 // Close the old zone if it was the only graph inside
269 // Close the old zone if it was the only graph inside
270 if (nbGraph == 1) {
270 if (nbGraph == 1) {
271 helper.delayedCloseWidget(parentZoneWidget);
271 helper.delayedCloseWidget(parentZoneWidget);
272 }
272 }
273 }
273 }
274 }
274 }
275
275
276 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
276 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
277 int index, VisualizationTabWidget *tabWidget)
277 int index, VisualizationTabWidget *tabWidget)
278 {
278 {
279 auto &helper = sqpApp->dragDropHelper();
279 auto &helper = sqpApp->dragDropHelper();
280
280
281 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
281 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
282 if (!zoneWidget) {
282 if (!zoneWidget) {
283 qCWarning(LOG_VisualizationZoneWidget())
283 qCWarning(LOG_VisualizationZoneWidget())
284 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
284 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
285 "found or invalid.");
285 "found or invalid.");
286 Q_ASSERT(false);
286 Q_ASSERT(false);
287 return;
287 return;
288 }
288 }
289
289
290 auto parentDragDropContainer
290 auto parentDragDropContainer
291 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
291 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
292 if (!parentDragDropContainer) {
292 if (!parentDragDropContainer) {
293 qCWarning(LOG_VisualizationZoneWidget())
293 qCWarning(LOG_VisualizationZoneWidget())
294 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
294 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
295 "the dropped zone is not found.");
295 "the dropped zone is not found.");
296 Q_ASSERT(false);
296 Q_ASSERT(false);
297 return;
297 return;
298 }
298 }
299
299
300 // Simple move of the zone, no variable operation associated
300 // Simple move of the zone, no variable operation associated
301 parentDragDropContainer->layout()->removeWidget(zoneWidget);
301 parentDragDropContainer->layout()->removeWidget(zoneWidget);
302 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
302 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
303 }
303 }
304
304
305 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
305 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
306 const QList<std::shared_ptr<Variable> > &variables, int index,
306 const QList<std::shared_ptr<Variable> > &variables, int index,
307 VisualizationTabWidget *tabWidget)
307 VisualizationTabWidget *tabWidget)
308 {
308 {
309 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
309 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
310 // compatible variable here
310 // compatible variable here
311 if (variables.count() > 1) {
311 if (variables.count() > 1) {
312 qCWarning(LOG_VisualizationZoneWidget())
312 qCWarning(LOG_VisualizationZoneWidget())
313 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
313 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
314 "aborted.");
314 "aborted.");
315 return;
315 return;
316 }
316 }
317
317
318 tabWidget->createZone(variables, index);
318 tabWidget->createZone(variables, index);
319 }
319 }
@@ -1,500 +1,507
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/VisualizationWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
8
8
9 #include "Common/MimeTypesDef.h"
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
10 #include "Common/VisualizationDef.h"
11
11
12 #include <Data/SqpRange.h>
12 #include <Data/SqpRange.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14 #include <Variable/Variable.h>
14 #include <Variable/Variable.h>
15 #include <Variable/VariableController.h>
15 #include <Variable/VariableController.h>
16
16
17 #include <Visualization/operations/FindVariableOperation.h>
17 #include <Visualization/operations/FindVariableOperation.h>
18
18
19 #include <DragAndDrop/DragDropHelper.h>
19 #include <DragAndDrop/DragDropHelper.h>
20 #include <QUuid>
20 #include <QUuid>
21 #include <SqpApplication.h>
21 #include <SqpApplication.h>
22 #include <cmath>
22 #include <cmath>
23
23
24 #include <QLayout>
24 #include <QLayout>
25
25
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27
27
28 namespace {
28 namespace {
29
29
30
30
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
32 /// the zone
32 /// the zone
33 QString defaultGraphName(const QLayout &layout)
33 QString defaultGraphName(const QLayout &layout)
34 {
34 {
35 auto count = 0;
35 auto count = 0;
36 for (auto i = 0; i < layout.count(); ++i) {
36 for (auto i = 0; i < layout.count(); ++i) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
38 count++;
38 count++;
39 }
39 }
40 }
40 }
41
41
42 return QObject::tr("Graph %1").arg(count + 1);
42 return QObject::tr("Graph %1").arg(count + 1);
43 }
43 }
44
44
45 /**
45 /**
46 * Applies a function to all graphs of the zone represented by its layout
46 * Applies a function to all graphs of the zone represented by its layout
47 * @param layout the layout that contains graphs
47 * @param layout the layout that contains graphs
48 * @param fun the function to apply to each graph
48 * @param fun the function to apply to each graph
49 */
49 */
50 template <typename Fun>
50 template <typename Fun>
51 void processGraphs(QLayout &layout, Fun fun)
51 void processGraphs(QLayout &layout, Fun fun)
52 {
52 {
53 for (auto i = 0; i < layout.count(); ++i) {
53 for (auto i = 0; i < layout.count(); ++i) {
54 if (auto item = layout.itemAt(i)) {
54 if (auto item = layout.itemAt(i)) {
55 if (auto visualizationGraphWidget
55 if (auto visualizationGraphWidget
56 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
56 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
57 fun(*visualizationGraphWidget);
57 fun(*visualizationGraphWidget);
58 }
58 }
59 }
59 }
60 }
60 }
61 }
61 }
62
62
63 } // namespace
63 } // namespace
64
64
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
66
66
67 explicit VisualizationZoneWidgetPrivate()
67 explicit VisualizationZoneWidgetPrivate()
68 : m_SynchronisationGroupId{QUuid::createUuid()},
68 : m_SynchronisationGroupId{QUuid::createUuid()},
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
70 {
70 {
71 }
71 }
72 QUuid m_SynchronisationGroupId;
72 QUuid m_SynchronisationGroupId;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
74
74
75 // Returns the first graph in the zone or nullptr if there is no graph inside
75 // Returns the first graph in the zone or nullptr if there is no graph inside
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
77 {
77 {
78 VisualizationGraphWidget *firstGraph = nullptr;
78 VisualizationGraphWidget *firstGraph = nullptr;
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
80 if (layout->count() > 0) {
80 if (layout->count() > 0) {
81 if (auto visualizationGraphWidget
81 if (auto visualizationGraphWidget
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
83 firstGraph = visualizationGraphWidget;
83 firstGraph = visualizationGraphWidget;
84 }
84 }
85 }
85 }
86
86
87 return firstGraph;
87 return firstGraph;
88 }
88 }
89
89
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
92 VisualizationZoneWidget *zoneWidget);
92 VisualizationZoneWidget *zoneWidget);
93 };
93 };
94
94
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
96 : VisualizationDragWidget{parent},
96 : VisualizationDragWidget{parent},
97 ui{new Ui::VisualizationZoneWidget},
97 ui{new Ui::VisualizationZoneWidget},
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
99 {
99 {
100 ui->setupUi(this);
100 ui->setupUi(this);
101
101
102 ui->zoneNameLabel->setText(name);
102 ui->zoneNameLabel->setText(name);
103
103
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
105 ui->dragDropContainer->addAcceptedMimeType(
105 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
106 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
106 VisualizationDragDropContainer::DropBehavior::Inserted);
107 ui->dragDropContainer->addAcceptedMimeType(
107 ui->dragDropContainer->setMimeType(
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
109 ui->dragDropContainer->addAcceptedMimeType(
109 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
110 MIME_TYPE_TIME_RANGE, VisualizationDragDropContainer::DropBehavior::Merged);
110 VisualizationDragDropContainer::DropBehavior::Merged);
111 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
112 VisualizationDragDropContainer::DropBehavior::Forbidden);
111 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
113 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
112 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
114 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
113 ui->dragDropContainer);
115 ui->dragDropContainer);
114 });
116 });
115
117
116 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
117 &VisualizationZoneWidget::dropMimeData);
119 &VisualizationZoneWidget::dropMimeData);
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
120 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
119 &VisualizationZoneWidget::dropMimeDataOnGraph);
121 &VisualizationZoneWidget::dropMimeDataOnGraph);
120
122
121 // 'Close' options : widget is deleted when closed
123 // 'Close' options : widget is deleted when closed
122 setAttribute(Qt::WA_DeleteOnClose);
124 setAttribute(Qt::WA_DeleteOnClose);
123 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
125 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
124 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
126 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
125
127
126 // Synchronisation id
128 // Synchronisation id
127 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
129 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
128 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
130 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
129 }
131 }
130
132
131 VisualizationZoneWidget::~VisualizationZoneWidget()
133 VisualizationZoneWidget::~VisualizationZoneWidget()
132 {
134 {
133 delete ui;
135 delete ui;
134 }
136 }
135
137
136 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
138 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
137 {
139 {
138 // Synchronize new graph with others in the zone
140 // Synchronize new graph with others in the zone
139 impl->m_Synchronizer->addGraph(*graphWidget);
141 impl->m_Synchronizer->addGraph(*graphWidget);
140
142
141 ui->dragDropContainer->addDragWidget(graphWidget);
143 ui->dragDropContainer->addDragWidget(graphWidget);
142 }
144 }
143
145
144 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
146 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
145 {
147 {
146 // Synchronize new graph with others in the zone
148 // Synchronize new graph with others in the zone
147 impl->m_Synchronizer->addGraph(*graphWidget);
149 impl->m_Synchronizer->addGraph(*graphWidget);
148
150
149 ui->dragDropContainer->insertDragWidget(index, graphWidget);
151 ui->dragDropContainer->insertDragWidget(index, graphWidget);
150 }
152 }
151
153
152 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
154 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
153 {
155 {
154 return createGraph(variable, -1);
156 return createGraph(variable, -1);
155 }
157 }
156
158
157 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
159 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
158 int index)
160 int index)
159 {
161 {
160 auto graphWidget
162 auto graphWidget
161 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
163 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
162
164
163
165
164 // Set graph properties
166 // Set graph properties
165 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
167 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
166 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
168 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
167
169
168
170
169 // Lambda to synchronize zone widget
171 // Lambda to synchronize zone widget
170 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
172 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
171 const SqpRange &oldGraphRange) {
173 const SqpRange &oldGraphRange) {
172
174
173 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
175 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
174 auto frameLayout = ui->dragDropContainer->layout();
176 auto frameLayout = ui->dragDropContainer->layout();
175 for (auto i = 0; i < frameLayout->count(); ++i) {
177 for (auto i = 0; i < frameLayout->count(); ++i) {
176 auto graphChild
178 auto graphChild
177 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
179 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
178 if (graphChild && (graphChild != graphWidget)) {
180 if (graphChild && (graphChild != graphWidget)) {
179
181
180 auto graphChildRange = graphChild->graphRange();
182 auto graphChildRange = graphChild->graphRange();
181 switch (zoomType) {
183 switch (zoomType) {
182 case AcquisitionZoomType::ZoomIn: {
184 case AcquisitionZoomType::ZoomIn: {
183 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
185 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
184 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
186 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
185 graphChildRange.m_TStart += deltaLeft;
187 graphChildRange.m_TStart += deltaLeft;
186 graphChildRange.m_TEnd -= deltaRight;
188 graphChildRange.m_TEnd -= deltaRight;
187 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
189 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
188 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
189 << deltaLeft;
191 << deltaLeft;
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
192 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
191 << deltaRight;
193 << deltaRight;
192 qCDebug(LOG_VisualizationZoneWidget())
194 qCDebug(LOG_VisualizationZoneWidget())
193 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
195 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
194
196
195 break;
197 break;
196 }
198 }
197
199
198 case AcquisitionZoomType::ZoomOut: {
200 case AcquisitionZoomType::ZoomOut: {
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
201 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
200 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
202 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
201 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
203 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
203 << deltaLeft;
205 << deltaLeft;
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
206 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
205 << deltaRight;
207 << deltaRight;
206 qCDebug(LOG_VisualizationZoneWidget())
208 qCDebug(LOG_VisualizationZoneWidget())
207 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
209 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
208 graphChildRange.m_TStart -= deltaLeft;
210 graphChildRange.m_TStart -= deltaLeft;
209 graphChildRange.m_TEnd += deltaRight;
211 graphChildRange.m_TEnd += deltaRight;
210 break;
212 break;
211 }
213 }
212 case AcquisitionZoomType::PanRight: {
214 case AcquisitionZoomType::PanRight: {
213 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
215 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
214 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
216 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
215 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
217 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
216 graphChildRange.m_TStart += deltaLeft;
218 graphChildRange.m_TStart += deltaLeft;
217 graphChildRange.m_TEnd += deltaRight;
219 graphChildRange.m_TEnd += deltaRight;
218 qCDebug(LOG_VisualizationZoneWidget())
220 qCDebug(LOG_VisualizationZoneWidget())
219 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
221 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
220 break;
222 break;
221 }
223 }
222 case AcquisitionZoomType::PanLeft: {
224 case AcquisitionZoomType::PanLeft: {
223 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
225 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
224 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
226 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
225 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
227 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
226 graphChildRange.m_TStart -= deltaLeft;
228 graphChildRange.m_TStart -= deltaLeft;
227 graphChildRange.m_TEnd -= deltaRight;
229 graphChildRange.m_TEnd -= deltaRight;
228 break;
230 break;
229 }
231 }
230 case AcquisitionZoomType::Unknown: {
232 case AcquisitionZoomType::Unknown: {
231 qCDebug(LOG_VisualizationZoneWidget())
233 qCDebug(LOG_VisualizationZoneWidget())
232 << tr("Impossible to synchronize: zoom type unknown");
234 << tr("Impossible to synchronize: zoom type unknown");
233 break;
235 break;
234 }
236 }
235 default:
237 default:
236 qCCritical(LOG_VisualizationZoneWidget())
238 qCCritical(LOG_VisualizationZoneWidget())
237 << tr("Impossible to synchronize: zoom type not take into account");
239 << tr("Impossible to synchronize: zoom type not take into account");
238 // No action
240 // No action
239 break;
241 break;
240 }
242 }
241 graphChild->enableAcquisition(false);
243 graphChild->enableAcquisition(false);
242 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
243 << graphChild->graphRange();
245 << graphChild->graphRange();
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
246 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
245 << graphChildRange;
247 << graphChildRange;
246 qCDebug(LOG_VisualizationZoneWidget())
248 qCDebug(LOG_VisualizationZoneWidget())
247 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
249 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
248 graphChild->setGraphRange(graphChildRange);
250 graphChild->setGraphRange(graphChildRange);
249 graphChild->enableAcquisition(true);
251 graphChild->enableAcquisition(true);
250 }
252 }
251 }
253 }
252 };
254 };
253
255
254 // connection for synchronization
256 // connection for synchronization
255 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
257 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
256 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
258 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
257 &VisualizationZoneWidget::onVariableAdded);
259 &VisualizationZoneWidget::onVariableAdded);
258 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
260 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
259 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
261 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
260
262
261 auto range = SqpRange{};
263 auto range = SqpRange{};
262 if (auto firstGraph = impl->firstGraph(this)) {
264 if (auto firstGraph = impl->firstGraph(this)) {
263 // Case of a new graph in a existant zone
265 // Case of a new graph in a existant zone
264 range = firstGraph->graphRange();
266 range = firstGraph->graphRange();
265 }
267 }
266 else {
268 else {
267 // Case of a new graph as the first of the zone
269 // Case of a new graph as the first of the zone
268 range = variable->range();
270 range = variable->range();
269 }
271 }
270
272
271 this->insertGraph(index, graphWidget);
273 this->insertGraph(index, graphWidget);
272
274
273 graphWidget->addVariable(variable, range);
275 graphWidget->addVariable(variable, range);
274 graphWidget->setYRange(variable);
276 graphWidget->setYRange(variable);
275
277
276 return graphWidget;
278 return graphWidget;
277 }
279 }
278
280
279 VisualizationGraphWidget *
281 VisualizationGraphWidget *
280 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
282 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
281 {
283 {
282 if (variables.isEmpty()) {
284 if (variables.isEmpty()) {
283 return nullptr;
285 return nullptr;
284 }
286 }
285
287
286 auto graphWidget = createGraph(variables.first(), index);
288 auto graphWidget = createGraph(variables.first(), index);
287 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
289 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
288 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
290 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
289 }
291 }
290
292
291 return graphWidget;
293 return graphWidget;
292 }
294 }
293
295
294 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
296 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
295 {
297 {
296 if (visitor) {
298 if (visitor) {
297 visitor->visitEnter(this);
299 visitor->visitEnter(this);
298
300
299 // Apply visitor to graph children: widgets different from graphs are not visited (no
301 // Apply visitor to graph children: widgets different from graphs are not visited (no
300 // action)
302 // action)
301 processGraphs(
303 processGraphs(
302 *ui->dragDropContainer->layout(),
304 *ui->dragDropContainer->layout(),
303 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
305 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
304
306
305 visitor->visitLeave(this);
307 visitor->visitLeave(this);
306 }
308 }
307 else {
309 else {
308 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
310 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
309 }
311 }
310 }
312 }
311
313
312 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
314 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
313 {
315 {
314 // A tab can always accomodate a variable
316 // A tab can always accomodate a variable
315 Q_UNUSED(variable);
317 Q_UNUSED(variable);
316 return true;
318 return true;
317 }
319 }
318
320
319 bool VisualizationZoneWidget::contains(const Variable &variable) const
321 bool VisualizationZoneWidget::contains(const Variable &variable) const
320 {
322 {
321 Q_UNUSED(variable);
323 Q_UNUSED(variable);
322 return false;
324 return false;
323 }
325 }
324
326
325 QString VisualizationZoneWidget::name() const
327 QString VisualizationZoneWidget::name() const
326 {
328 {
327 return ui->zoneNameLabel->text();
329 return ui->zoneNameLabel->text();
328 }
330 }
329
331
330 QMimeData *VisualizationZoneWidget::mimeData() const
332 QMimeData *VisualizationZoneWidget::mimeData() const
331 {
333 {
332 auto mimeData = new QMimeData;
334 auto mimeData = new QMimeData;
333 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
335 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
334
336
337 if (auto firstGraph = impl->firstGraph(this)) {
338 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
339 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
340 }
341
335 return mimeData;
342 return mimeData;
336 }
343 }
337
344
338 bool VisualizationZoneWidget::isDragAllowed() const
345 bool VisualizationZoneWidget::isDragAllowed() const
339 {
346 {
340 return true;
347 return true;
341 }
348 }
342
349
343 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
350 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
344 {
351 {
345 // Closes graphs in the zone
352 // Closes graphs in the zone
346 processGraphs(*ui->dragDropContainer->layout(),
353 processGraphs(*ui->dragDropContainer->layout(),
347 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
354 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
348
355
349 // Delete synchronization group from variable controller
356 // Delete synchronization group from variable controller
350 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
357 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
351 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
358 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
352
359
353 QWidget::closeEvent(event);
360 QWidget::closeEvent(event);
354 }
361 }
355
362
356 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
363 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
357 {
364 {
358 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
365 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
359 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
366 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
360 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
367 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
361 }
368 }
362
369
363 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
370 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
364 {
371 {
365 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
372 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
366 Q_ARG(std::shared_ptr<Variable>, variable),
373 Q_ARG(std::shared_ptr<Variable>, variable),
367 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
374 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
368 }
375 }
369
376
370 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
377 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
371 {
378 {
372 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
379 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
373 impl->dropGraph(index, this);
380 impl->dropGraph(index, this);
374 }
381 }
375 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
382 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
376 auto variables = sqpApp->variableController().variablesForMimeData(
383 auto variables = sqpApp->variableController().variablesForMimeData(
377 mimeData->data(MIME_TYPE_VARIABLE_LIST));
384 mimeData->data(MIME_TYPE_VARIABLE_LIST));
378 impl->dropVariables(variables, index, this);
385 impl->dropVariables(variables, index, this);
379 }
386 }
380 else {
387 else {
381 qCWarning(LOG_VisualizationZoneWidget())
388 qCWarning(LOG_VisualizationZoneWidget())
382 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
389 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
383 }
390 }
384 }
391 }
385
392
386 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
393 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
387 const QMimeData *mimeData)
394 const QMimeData *mimeData)
388 {
395 {
389 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
396 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
390 if (!graphWidget) {
397 if (!graphWidget) {
391 qCWarning(LOG_VisualizationZoneWidget())
398 qCWarning(LOG_VisualizationZoneWidget())
392 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
399 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
393 "drop aborted");
400 "drop aborted");
394 Q_ASSERT(false);
401 Q_ASSERT(false);
395 return;
402 return;
396 }
403 }
397
404
398 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
405 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
399 auto variables = sqpApp->variableController().variablesForMimeData(
406 auto variables = sqpApp->variableController().variablesForMimeData(
400 mimeData->data(MIME_TYPE_VARIABLE_LIST));
407 mimeData->data(MIME_TYPE_VARIABLE_LIST));
401 for (const auto &var : variables) {
408 for (const auto &var : variables) {
402 graphWidget->addVariable(var, graphWidget->graphRange());
409 graphWidget->addVariable(var, graphWidget->graphRange());
403 }
410 }
404 }
411 }
405 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
412 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
406 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
413 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
407 graphWidget->setGraphRange(range);
414 graphWidget->setGraphRange(range);
408 }
415 }
409 else {
416 else {
410 qCWarning(LOG_VisualizationZoneWidget())
417 qCWarning(LOG_VisualizationZoneWidget())
411 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
418 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
412 }
419 }
413 }
420 }
414
421
415 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
422 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
416 int index, VisualizationZoneWidget *zoneWidget)
423 int index, VisualizationZoneWidget *zoneWidget)
417 {
424 {
418 auto &helper = sqpApp->dragDropHelper();
425 auto &helper = sqpApp->dragDropHelper();
419
426
420 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
427 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
421 if (!graphWidget) {
428 if (!graphWidget) {
422 qCWarning(LOG_VisualizationZoneWidget())
429 qCWarning(LOG_VisualizationZoneWidget())
423 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
430 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
424 "found or invalid.");
431 "found or invalid.");
425 Q_ASSERT(false);
432 Q_ASSERT(false);
426 return;
433 return;
427 }
434 }
428
435
429 auto parentDragDropContainer
436 auto parentDragDropContainer
430 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
437 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
431 if (!parentDragDropContainer) {
438 if (!parentDragDropContainer) {
432 qCWarning(LOG_VisualizationZoneWidget())
439 qCWarning(LOG_VisualizationZoneWidget())
433 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
440 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
434 "the dropped graph is not found.");
441 "the dropped graph is not found.");
435 Q_ASSERT(false);
442 Q_ASSERT(false);
436 return;
443 return;
437 }
444 }
438
445
439 const auto &variables = graphWidget->variables();
446 const auto &variables = graphWidget->variables();
440
447
441 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
448 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
442 // The drop didn't occur in the same zone
449 // The drop didn't occur in the same zone
443
450
444 // Abort the requests for the variables (if any)
451 // Abort the requests for the variables (if any)
445 // Commented, because it's not sure if it's needed or not
452 // Commented, because it's not sure if it's needed or not
446 // for (const auto& var : variables)
453 // for (const auto& var : variables)
447 //{
454 //{
448 // sqpApp->variableController().onAbortProgressRequested(var);
455 // sqpApp->variableController().onAbortProgressRequested(var);
449 //}
456 //}
450
457
451 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
458 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
452 auto nbGraph = parentDragDropContainer->countDragWidget();
459 auto nbGraph = parentDragDropContainer->countDragWidget();
453 if (nbGraph == 1) {
460 if (nbGraph == 1) {
454 // This is the only graph in the previous zone, close the zone
461 // This is the only graph in the previous zone, close the zone
455 helper.delayedCloseWidget(previousParentZoneWidget);
462 helper.delayedCloseWidget(previousParentZoneWidget);
456 }
463 }
457 else {
464 else {
458 // Close the graph
465 // Close the graph
459 helper.delayedCloseWidget(graphWidget);
466 helper.delayedCloseWidget(graphWidget);
460 }
467 }
461
468
462 // Creates the new graph in the zone
469 // Creates the new graph in the zone
463 zoneWidget->createGraph(variables, index);
470 zoneWidget->createGraph(variables, index);
464 }
471 }
465 else {
472 else {
466 // The drop occurred in the same zone or the graph is empty
473 // The drop occurred in the same zone or the graph is empty
467 // Simple move of the graph, no variable operation associated
474 // Simple move of the graph, no variable operation associated
468 parentDragDropContainer->layout()->removeWidget(graphWidget);
475 parentDragDropContainer->layout()->removeWidget(graphWidget);
469
476
470 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
477 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
471 // The graph is empty and dropped in a different zone.
478 // The graph is empty and dropped in a different zone.
472 // Take the range of the first graph in the zone (if existing).
479 // Take the range of the first graph in the zone (if existing).
473 auto layout = zoneWidget->ui->dragDropContainer->layout();
480 auto layout = zoneWidget->ui->dragDropContainer->layout();
474 if (layout->count() > 0) {
481 if (layout->count() > 0) {
475 if (auto visualizationGraphWidget
482 if (auto visualizationGraphWidget
476 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
483 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
477 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
484 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
478 }
485 }
479 }
486 }
480 }
487 }
481
488
482 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
489 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
483 }
490 }
484 }
491 }
485
492
486 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
493 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
487 const QList<std::shared_ptr<Variable> > &variables, int index,
494 const QList<std::shared_ptr<Variable> > &variables, int index,
488 VisualizationZoneWidget *zoneWidget)
495 VisualizationZoneWidget *zoneWidget)
489 {
496 {
490 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
497 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
491 // compatible variable here
498 // compatible variable here
492 if (variables.count() > 1) {
499 if (variables.count() > 1) {
493 qCWarning(LOG_VisualizationZoneWidget())
500 qCWarning(LOG_VisualizationZoneWidget())
494 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
501 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
495 "aborted.");
502 "aborted.");
496 return;
503 return;
497 }
504 }
498
505
499 zoneWidget->createGraph(variables, index);
506 zoneWidget->createGraph(variables, index);
500 }
507 }
General Comments 1
Under Review
author

Auto status change to "Under Review"

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