##// END OF EJS Templates
Merge pull request 315 from SciQLop-fork develop...
leroux -
r847:6af9a63cc3d0 merge
parent child
Show More
@@ -0,0 +1,65
1 #ifndef SCIQLOP_DRAGDROPHELPER_H
2 #define SCIQLOP_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 Q_OBJECT
18
19 public:
20 DragDropScroller(QObject *parent = nullptr);
21
22 void addScrollArea(QScrollArea *scrollArea);
23 void removeScrollArea(QScrollArea *scrollArea);
24
25 protected:
26 bool eventFilter(QObject *obj, QEvent *event);
27
28 private:
29 class DragDropScrollerPrivate;
30 spimpl::unique_impl_ptr<DragDropScrollerPrivate> impl;
31
32 private slots:
33 void onTimer();
34 };
35
36 /**
37 * @brief Helper class for drag&drop operations.
38 */
39 class DragDropHelper {
40 public:
41 static const QString MIME_TYPE_GRAPH;
42 static const QString MIME_TYPE_ZONE;
43
44 DragDropHelper();
45 virtual ~DragDropHelper();
46
47 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
48 VisualizationDragWidget *getCurrentDragWidget() const;
49
50 QWidget &placeHolder() const;
51 void insertPlaceHolder(QVBoxLayout *layout, int index);
52 void removePlaceHolder();
53 bool isPlaceHolderSet() const;
54
55 void addDragDropScrollArea(QScrollArea *scrollArea);
56 void removeDragDropScrollArea(QScrollArea *scrollArea);
57
58 QUrl imageTemporaryUrl(const QImage &image) const;
59
60 private:
61 class DragDropHelperPrivate;
62 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
63 };
64
65 #endif // SCIQLOP_DRAGDROPHELPER_H
@@ -0,0 +1,42
1 #ifndef SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
3
4 #include <Common/spimpl.h>
5 #include <QMimeData>
6 #include <QVBoxLayout>
7 #include <QWidget>
8
9 class VisualizationDragWidget;
10
11 class VisualizationDragDropContainer : public QWidget {
12 Q_OBJECT
13
14 signals:
15 void dropOccured(int dropIndex, const QMimeData *mimeData);
16
17 public:
18 VisualizationDragDropContainer(QWidget *parent = nullptr);
19
20 void addDragWidget(VisualizationDragWidget *dragWidget);
21 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
22
23 void setAcceptedMimeTypes(const QStringList &mimeTypes);
24 void setMergeAllowedMimeTypes(const QStringList &mimeTypes);
25
26 int countDragWidget() const;
27
28 protected:
29 void dragEnterEvent(QDragEnterEvent *event);
30 void dragLeaveEvent(QDragLeaveEvent *event);
31 void dragMoveEvent(QDragMoveEvent *event);
32 void dropEvent(QDropEvent *event);
33
34 private:
35 class VisualizationDragDropContainerPrivate;
36 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
37
38 private slots:
39 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
40 };
41
42 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
@@ -0,0 +1,29
1 #ifndef SCIQLOP_VISUALIZATIONDRAGWIDGET_H
2 #define SCIQLOP_VISUALIZATIONDRAGWIDGET_H
3
4 #include <Common/spimpl.h>
5 #include <QMimeData>
6 #include <QWidget>
7
8 class VisualizationDragWidget : public QWidget {
9 Q_OBJECT
10
11 public:
12 VisualizationDragWidget(QWidget *parent = nullptr);
13
14 virtual QMimeData *mimeData() const = 0;
15 virtual bool isDragAllowed() const = 0;
16
17 protected:
18 virtual void mousePressEvent(QMouseEvent *event) override;
19 virtual void mouseMoveEvent(QMouseEvent *event) override;
20
21 private:
22 class VisualizationDragWidgetPrivate;
23 spimpl::unique_impl_ptr<VisualizationDragWidgetPrivate> impl;
24
25 signals:
26 void dragDetected(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
27 };
28
29 #endif // SCIQLOP_VISUALIZATIONDRAGWIDGET_H
@@ -0,0 +1,230
1 #include "DragDropHelper.h"
2 #include "SqpApplication.h"
3 #include "Visualization/VisualizationDragWidget.h"
4
5 #include <QDir>
6 #include <QDragEnterEvent>
7 #include <QDragMoveEvent>
8 #include <QScrollArea>
9 #include <QScrollBar>
10 #include <QTimer>
11 #include <QVBoxLayout>
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() : m_Timer{std::make_unique<QTimer>()}
30 {
31 m_Timer->setInterval(0);
32 }
33 };
34
35 DragDropScroller::DragDropScroller(QObject *parent)
36 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
37 {
38 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
39 }
40
41 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
42 {
43 impl->m_ScrollAreas << scrollArea;
44 scrollArea->viewport()->setAcceptDrops(true);
45 }
46
47 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
48 {
49 impl->m_ScrollAreas.removeAll(scrollArea);
50 scrollArea->viewport()->setAcceptDrops(false);
51 }
52
53 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
54 {
55 if (event->type() == QEvent::DragMove) {
56 auto w = static_cast<QWidget *>(obj);
57
58 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
59 auto moveEvent = static_cast<QDragMoveEvent *>(event);
60
61 auto pos = moveEvent->pos();
62 if (impl->m_CurrentScrollArea->viewport() != w) {
63 auto globalPos = w->mapToGlobal(moveEvent->pos());
64 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
65 }
66
67 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
68 - SCROLL_ZONE_SIZE;
69 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
70
71 if (!isInTopZone && !isInBottomZone) {
72 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
73 impl->m_Timer->stop();
74 }
75 else if (!impl->m_Timer->isActive()) {
76 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
77 : DragDropScrollerPrivate::ScrollDirection::down;
78 impl->m_Timer->start();
79 }
80 }
81 }
82 else if (event->type() == QEvent::DragEnter) {
83 auto w = static_cast<QWidget *>(obj);
84
85 for (auto scrollArea : impl->m_ScrollAreas) {
86 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
87 auto enterEvent = static_cast<QDragEnterEvent *>(event);
88 enterEvent->acceptProposedAction();
89 enterEvent->setDropAction(Qt::IgnoreAction);
90 impl->m_CurrentScrollArea = scrollArea;
91 break;
92 }
93 }
94 }
95 else if (event->type() == QEvent::DragLeave) {
96 if (impl->m_CurrentScrollArea) {
97 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
98 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
99 impl->m_CurrentScrollArea = nullptr;
100 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
101 impl->m_Timer->stop();
102 }
103 }
104 }
105 else if (event->type() == QEvent::Drop) {
106 if (impl->m_CurrentScrollArea) {
107 impl->m_CurrentScrollArea = nullptr;
108 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
109 impl->m_Timer->stop();
110 }
111 }
112
113 return false;
114 }
115
116 void DragDropScroller::onTimer()
117 {
118 if (impl->m_CurrentScrollArea) {
119 auto mvt = 0;
120 switch (impl->m_Direction) {
121 case DragDropScrollerPrivate::ScrollDirection::up:
122 mvt = SCROLL_SPEED;
123 break;
124 case DragDropScrollerPrivate::ScrollDirection::down:
125 mvt = -SCROLL_SPEED;
126 break;
127 default:
128 break;
129 }
130
131 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
132 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
133 }
134 }
135
136 struct DragDropHelper::DragDropHelperPrivate {
137
138 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
139 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
140 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
141 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
142 // QTemporaryFile to have a name which is not generated.
143
144 explicit DragDropHelperPrivate()
145 : m_PlaceHolder{std::make_unique<QWidget>()},
146 m_DragDropScroller{std::make_unique<DragDropScroller>()}
147 {
148 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
149 sqpApp->installEventFilter(m_DragDropScroller.get());
150
151
152 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
153 }
154
155 void preparePlaceHolder() const
156 {
157 if (m_CurrentDragWidget) {
158 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
159 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
160 }
161 else {
162 m_PlaceHolder->setMinimumSize(200, 200);
163 }
164 }
165 };
166
167
168 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
169 {
170 }
171
172 DragDropHelper::~DragDropHelper()
173 {
174 QFile::remove(impl->m_ImageTempUrl);
175 }
176
177 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
178 {
179 impl->m_CurrentDragWidget = dragWidget;
180 }
181
182 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
183 {
184 return impl->m_CurrentDragWidget;
185 }
186
187
188 QWidget &DragDropHelper::placeHolder() const
189 {
190 return *impl->m_PlaceHolder;
191 }
192
193 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
194 {
195 removePlaceHolder();
196 impl->preparePlaceHolder();
197 layout->insertWidget(index, impl->m_PlaceHolder.get());
198 impl->m_PlaceHolder->show();
199 }
200
201 void DragDropHelper::removePlaceHolder()
202 {
203 auto parentWidget = impl->m_PlaceHolder->parentWidget();
204 if (parentWidget) {
205 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
206 impl->m_PlaceHolder->setParent(nullptr);
207 impl->m_PlaceHolder->hide();
208 }
209 }
210
211 bool DragDropHelper::isPlaceHolderSet() const
212 {
213 return impl->m_PlaceHolder->parentWidget();
214 }
215
216 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
217 {
218 impl->m_DragDropScroller->addScrollArea(scrollArea);
219 }
220
221 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
222 {
223 impl->m_DragDropScroller->removeScrollArea(scrollArea);
224 }
225
226 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
227 {
228 image.save(impl->m_ImageTempUrl);
229 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
230 }
@@ -0,0 +1,302
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragDropHelper.h"
3 #include "SqpApplication.h"
4 #include "Visualization/VisualizationDragWidget.h"
5
6 #include <QDrag>
7 #include <QDragEnterEvent>
8 #include <QVBoxLayout>
9
10 #include <cmath>
11 #include <memory>
12
13 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
14
15 QVBoxLayout *m_Layout;
16 QStringList m_AcceptedMimeTypes;
17 QStringList m_MergeAllowedMimeTypes;
18
19 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
20 {
21 m_Layout = new QVBoxLayout(widget);
22 m_Layout->setContentsMargins(0, 0, 0, 0);
23 }
24
25 bool acceptMimeData(const QMimeData *data) const
26 {
27 for (const auto &type : m_AcceptedMimeTypes) {
28 if (data->hasFormat(type)) {
29 return true;
30 }
31 }
32
33 return false;
34 }
35
36 bool allowMergeMimeData(const QMimeData *data) const
37 {
38 for (const auto &type : m_MergeAllowedMimeTypes) {
39 if (data->hasFormat(type)) {
40 return true;
41 }
42 }
43
44 return false;
45 }
46
47 bool hasPlaceHolder() const
48 {
49 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
50 }
51
52 VisualizationDragWidget *getChildDragWidgetAt(QWidget *parent, const QPoint &pos) const
53 {
54 VisualizationDragWidget *dragWidget = nullptr;
55
56 for (auto child : parent->children()) {
57 auto widget = qobject_cast<VisualizationDragWidget *>(child);
58 if (widget && widget->isVisible()) {
59 if (widget->frameGeometry().contains(pos)) {
60 dragWidget = widget;
61 break;
62 }
63 }
64 }
65
66 return dragWidget;
67 }
68
69 bool cursorIsInContainer(QWidget *container) const
70 {
71 auto adustNum = 18; // to be safe, in case of scrollbar on the side
72 auto containerRect = QRect(QPoint(), container->contentsRect().size())
73 .adjusted(adustNum, adustNum, -adustNum, -adustNum);
74 return containerRect.contains(container->mapFromGlobal(QCursor::pos()));
75 }
76 };
77
78 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
79 : QWidget{parent},
80 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
81 {
82 setAcceptDrops(true);
83 }
84
85 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
86 {
87 impl->m_Layout->addWidget(dragWidget);
88 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
89 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
90 &VisualizationDragDropContainer::startDrag);
91 }
92
93 void VisualizationDragDropContainer::insertDragWidget(int index,
94 VisualizationDragWidget *dragWidget)
95 {
96 impl->m_Layout->insertWidget(index, dragWidget);
97 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
98 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
99 &VisualizationDragDropContainer::startDrag);
100 }
101
102 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
103 {
104 impl->m_AcceptedMimeTypes = mimeTypes;
105 }
106
107 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
108 {
109 impl->m_MergeAllowedMimeTypes = mimeTypes;
110 }
111
112 int VisualizationDragDropContainer::countDragWidget() const
113 {
114 auto nbGraph = 0;
115 for (auto child : children()) {
116 if (qobject_cast<VisualizationDragWidget *>(child)) {
117 nbGraph += 1;
118 }
119 }
120
121 return nbGraph;
122 }
123
124 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
125 const QPoint &dragPosition)
126 {
127 auto &helper = sqpApp->dragDropHelper();
128
129 // Note: The management of the drag object is done by Qt
130 auto drag = new QDrag{dragWidget};
131 drag->setHotSpot(dragPosition);
132
133 auto mimeData = dragWidget->mimeData();
134 drag->setMimeData(mimeData);
135
136 auto pixmap = QPixmap(dragWidget->size());
137 dragWidget->render(&pixmap);
138 drag->setPixmap(pixmap);
139
140 auto image = pixmap.toImage();
141 mimeData->setImageData(image);
142 mimeData->setUrls({helper.imageTemporaryUrl(image)});
143
144 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
145 helper.setCurrentDragWidget(dragWidget);
146
147 if (impl->cursorIsInContainer(this)) {
148 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
149 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
150 dragWidget->setVisible(false);
151 }
152 }
153
154 // Note: The exec() is blocking on windows but not on linux and macOS
155 drag->exec(Qt::MoveAction | Qt::CopyAction);
156 }
157
158 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
159 {
160 if (impl->acceptMimeData(event->mimeData())) {
161 event->acceptProposedAction();
162
163 auto &helper = sqpApp->dragDropHelper();
164
165 if (!impl->hasPlaceHolder()) {
166 auto dragWidget = helper.getCurrentDragWidget();
167 auto parentWidget
168 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
169 if (parentWidget) {
170 dragWidget->setVisible(false);
171 }
172
173 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
174
175 if (dragWidgetHovered) {
176 auto hoveredWidgetIndex = impl->m_Layout->indexOf(dragWidgetHovered);
177 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
178 if (dragWidgetIndex >= 0 && dragWidgetIndex <= hoveredWidgetIndex) {
179 hoveredWidgetIndex
180 += 1; // Correction of the index if the drop occurs in the same container
181 }
182
183 helper.insertPlaceHolder(impl->m_Layout, hoveredWidgetIndex);
184 }
185 else {
186 helper.insertPlaceHolder(impl->m_Layout, 0);
187 }
188 }
189 }
190 else {
191 event->ignore();
192 }
193
194 QWidget::dragEnterEvent(event);
195 }
196
197 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
198 {
199 Q_UNUSED(event);
200
201 auto &helper = sqpApp->dragDropHelper();
202
203 if (!impl->cursorIsInContainer(this)) {
204 helper.removePlaceHolder();
205
206 bool isInternal = true;
207 if (isInternal) {
208 // Only if the drag is started from the visualization
209 // Show the drag widget at its original place
210 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
211 // drop zone (It is not possible to catch a drop event outside of the application)
212
213 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
214 if (dragWidget) {
215 dragWidget->setVisible(true);
216 }
217 }
218 }
219
220 QWidget::dragLeaveEvent(event);
221 }
222
223 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
224 {
225 if (impl->acceptMimeData(event->mimeData())) {
226 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
227 if (dragWidgetHovered) {
228 auto canMerge = impl->allowMergeMimeData(event->mimeData());
229
230 auto nbDragWidget = countDragWidget();
231 if (nbDragWidget > 0) {
232 auto graphHeight = size().height() / nbDragWidget;
233 auto dropIndex = floor(event->pos().y() / graphHeight);
234 auto zoneSize = qMin(graphHeight / 3.0, 150.0);
235
236 auto isOnTop = event->pos().y() < dropIndex * graphHeight + zoneSize;
237 auto isOnBottom = event->pos().y() > (dropIndex + 1) * graphHeight - zoneSize;
238
239 auto &helper = sqpApp->dragDropHelper();
240 auto placeHolderIndex = impl->m_Layout->indexOf(&(helper.placeHolder()));
241
242 if (isOnTop || isOnBottom) {
243 if (isOnBottom) {
244 dropIndex += 1;
245 }
246
247 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
248 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
249 dropIndex += 1; // Correction of the index if the drop occurs in the same
250 // container
251 }
252
253 if (dropIndex != placeHolderIndex) {
254 helper.insertPlaceHolder(impl->m_Layout, dropIndex);
255 }
256 }
257 else if (canMerge) {
258 // drop on the middle -> merge
259 if (impl->hasPlaceHolder()) {
260 helper.removePlaceHolder();
261 }
262 }
263 }
264 }
265 }
266 else {
267 event->ignore();
268 }
269
270 QWidget::dragMoveEvent(event);
271 }
272
273 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
274 {
275 if (impl->acceptMimeData(event->mimeData())) {
276 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
277 if (impl->hasPlaceHolder() && dragWidget) {
278 auto &helper = sqpApp->dragDropHelper();
279
280 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
281
282 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
283 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
284 droppedIndex
285 -= 1; // Correction of the index if the drop occurs in the same container
286 }
287
288 dragWidget->setVisible(true);
289
290 event->acceptProposedAction();
291
292 helper.removePlaceHolder();
293
294 emit dropOccured(droppedIndex, event->mimeData());
295 }
296 }
297 else {
298 event->ignore();
299 }
300
301 QWidget::dropEvent(event);
302 }
@@ -0,0 +1,53
1 #include "Visualization/VisualizationDragWidget.h"
2 #include "Visualization/VisualizationDragDropContainer.h"
3
4 #include <QApplication>
5 #include <QMouseEvent>
6
7 struct VisualizationDragWidget::VisualizationDragWidgetPrivate {
8
9 QPoint m_DragStartPosition;
10 bool m_DragStartPositionValid = false;
11
12 explicit VisualizationDragWidgetPrivate() {}
13 };
14
15 VisualizationDragWidget::VisualizationDragWidget(QWidget *parent)
16 : QWidget{parent}, impl{spimpl::make_unique_impl<VisualizationDragWidgetPrivate>()}
17 {
18 }
19
20 void VisualizationDragWidget::mousePressEvent(QMouseEvent *event)
21 {
22 if (event->button() == Qt::LeftButton) {
23 impl->m_DragStartPosition = event->pos();
24 }
25
26 impl->m_DragStartPositionValid = isDragAllowed();
27
28 QWidget::mousePressEvent(event);
29 }
30
31 void VisualizationDragWidget::mouseMoveEvent(QMouseEvent *event)
32 {
33 if (!impl->m_DragStartPositionValid || !isDragAllowed()) {
34 return;
35 }
36
37 if (!(event->buttons() & Qt::LeftButton)) {
38 return;
39 }
40
41 if (!event->modifiers().testFlag(Qt::AltModifier)) {
42 return;
43 }
44
45 if ((event->pos() - impl->m_DragStartPosition).manhattanLength()
46 < QApplication::startDragDistance()) {
47 return;
48 }
49
50 emit dragDetected(this, impl->m_DragStartPosition);
51
52 QWidget::mouseMoveEvent(event);
53 }
@@ -1,52 +1,56
1 #ifndef SCIQLOP_SQPAPPLICATION_H
1 #ifndef SCIQLOP_SQPAPPLICATION_H
2 #define SCIQLOP_SQPAPPLICATION_H
2 #define SCIQLOP_SQPAPPLICATION_H
3
3
4 #include "SqpApplication.h"
4 #include "SqpApplication.h"
5
5
6 #include <QApplication>
6 #include <QApplication>
7 #include <QLoggingCategory>
7 #include <QLoggingCategory>
8
8
9 #include <Common/spimpl.h>
9 #include <Common/spimpl.h>
10
10
11 Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication)
11 Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication)
12
12
13 #if defined(sqpApp)
13 #if defined(sqpApp)
14 #undef sqpApp
14 #undef sqpApp
15 #endif
15 #endif
16 #define sqpApp (static_cast<SqpApplication *>(QCoreApplication::instance()))
16 #define sqpApp (static_cast<SqpApplication *>(QCoreApplication::instance()))
17
17
18 class DataSourceController;
18 class DataSourceController;
19 class NetworkController;
19 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
26 * and its plugins. This is the intermediate class that SciQlop has to use
27 * and its plugins. This is the intermediate class that SciQlop has to use
27 * in the way to connect a data source. Please first use load method to initialize
28 * in the way to connect a data source. Please first use load method to initialize
28 * a plugin specified by its metadata name (JSON plugin source) then others specifics
29 * a plugin specified by its metadata name (JSON plugin source) then others specifics
29 * method will be able to access it.
30 * method will be able to access it.
30 * You can load a data source driver plugin then create a data source.
31 * You can load a data source driver plugin then create a data source.
31 */
32 */
32
33
33 class SqpApplication : public QApplication {
34 class SqpApplication : public QApplication {
34 Q_OBJECT
35 Q_OBJECT
35 public:
36 public:
36 explicit SqpApplication(int &argc, char **argv);
37 explicit SqpApplication(int &argc, char **argv);
37 virtual ~SqpApplication();
38 virtual ~SqpApplication();
38 void initialize();
39 void initialize();
39
40
40 /// Accessors for the differents sciqlop controllers
41 /// Accessors for the differents sciqlop controllers
41 DataSourceController &dataSourceController() noexcept;
42 DataSourceController &dataSourceController() noexcept;
42 NetworkController &networkController() noexcept;
43 NetworkController &networkController() noexcept;
43 TimeController &timeController() noexcept;
44 TimeController &timeController() noexcept;
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;
50 };
54 };
51
55
52 #endif // SCIQLOP_SQPAPPLICATION_H
56 #endif // SCIQLOP_SQPAPPLICATION_H
@@ -1,97 +1,107
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
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>
8
9
9 #include <memory>
10 #include <memory>
10
11
11 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
12
13
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14
15
15 class QCPRange;
16 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;
28 friend class VisualizationGraphRenderingDelegate;
30 friend class VisualizationGraphRenderingDelegate;
29
31
30 public:
32 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
37 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
41 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
38
42
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);
45
52
46 // IVisualizationWidget interface
53 // IVisualizationWidget interface
47 void accept(IVisualizationWidgetVisitor *visitor) override;
54 void accept(IVisualizationWidgetVisitor *visitor) override;
48 bool canDrop(const Variable &variable) const override;
55 bool canDrop(const Variable &variable) const override;
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);
55 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
65 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
56 bool synchronise);
66 bool synchronise);
57
67
58 /// Signal emitted when the variable is about to be removed from the graph
68 /// Signal emitted when the variable is about to be removed from the graph
59 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
69 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
60 /// Signal emitted when the variable has been added to the graph
70 /// Signal emitted when the variable has been added to the graph
61 void variableAdded(std::shared_ptr<Variable> var);
71 void variableAdded(std::shared_ptr<Variable> var);
62
72
63 protected:
73 protected:
64 void closeEvent(QCloseEvent *event) override;
74 void closeEvent(QCloseEvent *event) override;
65 void enterEvent(QEvent *event) override;
75 void enterEvent(QEvent *event) override;
66 void leaveEvent(QEvent *event) override;
76 void leaveEvent(QEvent *event) override;
67
77
68 QCustomPlot &plot() noexcept;
78 QCustomPlot &plot() noexcept;
69
79
70 private:
80 private:
71 Ui::VisualizationGraphWidget *ui;
81 Ui::VisualizationGraphWidget *ui;
72
82
73 class VisualizationGraphWidgetPrivate;
83 class VisualizationGraphWidgetPrivate;
74 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
84 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
75
85
76 private slots:
86 private slots:
77 /// Slot called when right clicking on the graph (displays a menu)
87 /// Slot called when right clicking on the graph (displays a menu)
78 void onGraphMenuRequested(const QPoint &pos) noexcept;
88 void onGraphMenuRequested(const QPoint &pos) noexcept;
79
89
80 /// Rescale the X axe to range parameter
90 /// Rescale the X axe to range parameter
81 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
91 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
82
92
83 /// Slot called when a mouse move was made
93 /// Slot called when a mouse move was made
84 void onMouseMove(QMouseEvent *event) noexcept;
94 void onMouseMove(QMouseEvent *event) noexcept;
85 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
95 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
86 void onMouseWheel(QWheelEvent *event) noexcept;
96 void onMouseWheel(QWheelEvent *event) noexcept;
87 /// Slot called when a mouse press was made, to activate the calibration of a graph
97 /// Slot called when a mouse press was made, to activate the calibration of a graph
88 void onMousePress(QMouseEvent *event) noexcept;
98 void onMousePress(QMouseEvent *event) noexcept;
89 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
99 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
90 void onMouseRelease(QMouseEvent *event) noexcept;
100 void onMouseRelease(QMouseEvent *event) noexcept;
91
101
92 void onDataCacheVariableUpdated();
102 void onDataCacheVariableUpdated();
93
103
94 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
104 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
95 };
105 };
96
106
97 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
107 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,57 +1,80
1 #ifndef SCIQLOP_VISUALIZATIONTABWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONTABWIDGET_H
2 #define SCIQLOP_VISUALIZATIONTABWIDGET_H
2 #define SCIQLOP_VISUALIZATIONTABWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5
5
6 #include <Common/spimpl.h>
6 #include <Common/spimpl.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QMimeData>
9 #include <QWidget>
10 #include <QWidget>
10
11
11 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget)
12
13
13 class Variable;
14 class Variable;
14 class VisualizationZoneWidget;
15 class VisualizationZoneWidget;
15
16
16 namespace Ui {
17 namespace Ui {
17 class VisualizationTabWidget;
18 class VisualizationTabWidget;
18 } // namespace Ui
19 } // namespace Ui
19
20
20 class VisualizationTabWidget : public QWidget, public IVisualizationWidget {
21 class VisualizationTabWidget : public QWidget, public IVisualizationWidget {
21 Q_OBJECT
22 Q_OBJECT
22
23
23 public:
24 public:
24 explicit VisualizationTabWidget(const QString &name = {}, QWidget *parent = 0);
25 explicit VisualizationTabWidget(const QString &name = {}, QWidget *parent = 0);
25 virtual ~VisualizationTabWidget();
26 virtual ~VisualizationTabWidget();
26
27
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
43 * the new 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,
49 int index);
50
51 /**
52 * Creates a zone which is empty (no variables). The zone is inserted at the specified index.
53 * @param index The index where the zone should be inserted in the layout
54 * @return the pointer to the created zone
55 */
56 VisualizationZoneWidget *createEmptyZone(int index);
57
38 // IVisualizationWidget interface
58 // IVisualizationWidget interface
39 void accept(IVisualizationWidgetVisitor *visitor) override;
59 void accept(IVisualizationWidgetVisitor *visitor) override;
40 bool canDrop(const Variable &variable) const override;
60 bool canDrop(const Variable &variable) const override;
41 bool contains(const Variable &variable) const override;
61 bool contains(const Variable &variable) const override;
42 QString name() const override;
62 QString name() const override;
43
63
44 protected:
64 protected:
45 void closeEvent(QCloseEvent *event) override;
65 void closeEvent(QCloseEvent *event) override;
46
66
47 private:
67 private:
48 /// @return the layout of tab in which zones are added
68 /// @return the layout of tab in which zones are added
49 QLayout &tabLayout() const noexcept;
69 QLayout &tabLayout() const noexcept;
50
70
51 Ui::VisualizationTabWidget *ui;
71 Ui::VisualizationTabWidget *ui;
52
72
53 class VisualizationTabWidgetPrivate;
73 class VisualizationTabWidgetPrivate;
54 spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl;
74 spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl;
75
76 private slots:
77 void dropMimeData(int index, const QMimeData *mimeData);
55 };
78 };
56
79
57 #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H
80 #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H
@@ -1,60 +1,90
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
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>
8
9
9 #include <memory>
10 #include <memory>
10
11
11 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
12
13
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
14
15
15 namespace Ui {
16 namespace Ui {
16 class VisualizationZoneWidget;
17 class VisualizationZoneWidget;
17 } // Ui
18 } // namespace Ui
18
19
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,
61 int index);
62
39 // IVisualizationWidget interface
63 // IVisualizationWidget interface
40 void accept(IVisualizationWidgetVisitor *visitor) override;
64 void accept(IVisualizationWidgetVisitor *visitor) override;
41 bool canDrop(const Variable &variable) const override;
65 bool canDrop(const Variable &variable) const override;
42 bool contains(const Variable &variable) const override;
66 bool contains(const Variable &variable) const override;
43 QString name() const override;
67 QString name() const override;
44
68
69 // VisualisationDragWidget
70 QMimeData *mimeData() const override;
71 bool isDragAllowed() const override;
72
45 protected:
73 protected:
46 void closeEvent(QCloseEvent *event) override;
74 void closeEvent(QCloseEvent *event) override;
47
75
48 private:
76 private:
49 Ui::VisualizationZoneWidget *ui;
77 Ui::VisualizationZoneWidget *ui;
50
78
51 class VisualizationZoneWidgetPrivate;
79 class VisualizationZoneWidgetPrivate;
52 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
80 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
53
81
54 private slots:
82 private slots:
55 void onVariableAdded(std::shared_ptr<Variable> variable);
83 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
84 /// 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);
85 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
86
87 void dropMimeData(int index, const QMimeData *mimeData);
58 };
88 };
59
89
60 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
90 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -1,150 +1,159
1 #include "SqpApplication.h"
1 #include "SqpApplication.h"
2
2
3 #include <Data/IDataProvider.h>
3 #include <Data/IDataProvider.h>
4 #include <DataSource/DataSourceController.h>
4 #include <DataSource/DataSourceController.h>
5 #include <DragDropHelper.h>
5 #include <Network/NetworkController.h>
6 #include <Network/NetworkController.h>
6 #include <QThread>
7 #include <QThread>
7 #include <Time/TimeController.h>
8 #include <Time/TimeController.h>
8 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
9 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
10 #include <Visualization/VisualizationController.h>
11 #include <Visualization/VisualizationController.h>
11
12
12 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
13 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
13
14
14 class SqpApplication::SqpApplicationPrivate {
15 class SqpApplication::SqpApplicationPrivate {
15 public:
16 public:
16 SqpApplicationPrivate()
17 SqpApplicationPrivate()
17 : m_DataSourceController{std::make_unique<DataSourceController>()},
18 : m_DataSourceController{std::make_unique<DataSourceController>()},
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 //
25 // /////////////////////////////// //
27 // /////////////////////////////// //
26
28
27 // VariableController <-> DataSourceController
29 // VariableController <-> DataSourceController
28 connect(m_DataSourceController.get(),
30 connect(m_DataSourceController.get(),
29 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
31 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
30 std::shared_ptr<IDataProvider>)),
32 std::shared_ptr<IDataProvider>)),
31 m_VariableController.get(),
33 m_VariableController.get(),
32 SLOT(createVariable(const QString &, const QVariantHash &,
34 SLOT(createVariable(const QString &, const QVariantHash &,
33 std::shared_ptr<IDataProvider>)));
35 std::shared_ptr<IDataProvider>)));
34
36
35 // VariableController <-> VisualizationController
37 // VariableController <-> VisualizationController
36 connect(m_VariableController.get(),
38 connect(m_VariableController.get(),
37 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
39 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
38 m_VisualizationController.get(),
40 m_VisualizationController.get(),
39 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
41 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
40
42
41 connect(m_VariableController.get(),
43 connect(m_VariableController.get(),
42 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
44 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
43 m_VisualizationController.get(),
45 m_VisualizationController.get(),
44 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
46 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
45
47
46
48
47 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
49 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
48 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
50 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
49 m_NetworkController->moveToThread(&m_NetworkControllerThread);
51 m_NetworkController->moveToThread(&m_NetworkControllerThread);
50 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
52 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
51 m_VariableController->moveToThread(&m_VariableControllerThread);
53 m_VariableController->moveToThread(&m_VariableControllerThread);
52 m_VariableControllerThread.setObjectName("VariableControllerThread");
54 m_VariableControllerThread.setObjectName("VariableControllerThread");
53 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
55 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
54 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
56 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
55
57
56
58
57 // Additionnal init
59 // Additionnal init
58 m_VariableController->setTimeController(m_TimeController.get());
60 m_VariableController->setTimeController(m_TimeController.get());
59 }
61 }
60
62
61 virtual ~SqpApplicationPrivate()
63 virtual ~SqpApplicationPrivate()
62 {
64 {
63 m_DataSourceControllerThread.quit();
65 m_DataSourceControllerThread.quit();
64 m_DataSourceControllerThread.wait();
66 m_DataSourceControllerThread.wait();
65
67
66 m_NetworkControllerThread.quit();
68 m_NetworkControllerThread.quit();
67 m_NetworkControllerThread.wait();
69 m_NetworkControllerThread.wait();
68
70
69 m_VariableControllerThread.quit();
71 m_VariableControllerThread.quit();
70 m_VariableControllerThread.wait();
72 m_VariableControllerThread.wait();
71
73
72 m_VisualizationControllerThread.quit();
74 m_VisualizationControllerThread.quit();
73 m_VisualizationControllerThread.wait();
75 m_VisualizationControllerThread.wait();
74 }
76 }
75
77
76 std::unique_ptr<DataSourceController> m_DataSourceController;
78 std::unique_ptr<DataSourceController> m_DataSourceController;
77 std::unique_ptr<VariableController> m_VariableController;
79 std::unique_ptr<VariableController> m_VariableController;
78 std::unique_ptr<TimeController> m_TimeController;
80 std::unique_ptr<TimeController> m_TimeController;
79 std::unique_ptr<NetworkController> m_NetworkController;
81 std::unique_ptr<NetworkController> m_NetworkController;
80 std::unique_ptr<VisualizationController> m_VisualizationController;
82 std::unique_ptr<VisualizationController> m_VisualizationController;
81 QThread m_DataSourceControllerThread;
83 QThread m_DataSourceControllerThread;
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
88 SqpApplication::SqpApplication(int &argc, char **argv)
92 SqpApplication::SqpApplication(int &argc, char **argv)
89 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
93 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
90 {
94 {
91 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
95 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
92
96
93 connect(&impl->m_DataSourceControllerThread, &QThread::started,
97 connect(&impl->m_DataSourceControllerThread, &QThread::started,
94 impl->m_DataSourceController.get(), &DataSourceController::initialize);
98 impl->m_DataSourceController.get(), &DataSourceController::initialize);
95 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
99 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
96 impl->m_DataSourceController.get(), &DataSourceController::finalize);
100 impl->m_DataSourceController.get(), &DataSourceController::finalize);
97
101
98 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
102 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
99 &NetworkController::initialize);
103 &NetworkController::initialize);
100 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
104 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
101 &NetworkController::finalize);
105 &NetworkController::finalize);
102
106
103 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
107 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
104 &VariableController::initialize);
108 &VariableController::initialize);
105 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
109 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
106 &VariableController::finalize);
110 &VariableController::finalize);
107
111
108 connect(&impl->m_VisualizationControllerThread, &QThread::started,
112 connect(&impl->m_VisualizationControllerThread, &QThread::started,
109 impl->m_VisualizationController.get(), &VisualizationController::initialize);
113 impl->m_VisualizationController.get(), &VisualizationController::initialize);
110 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
114 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
111 impl->m_VisualizationController.get(), &VisualizationController::finalize);
115 impl->m_VisualizationController.get(), &VisualizationController::finalize);
112
116
113 impl->m_DataSourceControllerThread.start();
117 impl->m_DataSourceControllerThread.start();
114 impl->m_NetworkControllerThread.start();
118 impl->m_NetworkControllerThread.start();
115 impl->m_VariableControllerThread.start();
119 impl->m_VariableControllerThread.start();
116 impl->m_VisualizationControllerThread.start();
120 impl->m_VisualizationControllerThread.start();
117 }
121 }
118
122
119 SqpApplication::~SqpApplication()
123 SqpApplication::~SqpApplication()
120 {
124 {
121 }
125 }
122
126
123 void SqpApplication::initialize()
127 void SqpApplication::initialize()
124 {
128 {
125 }
129 }
126
130
127 DataSourceController &SqpApplication::dataSourceController() noexcept
131 DataSourceController &SqpApplication::dataSourceController() noexcept
128 {
132 {
129 return *impl->m_DataSourceController;
133 return *impl->m_DataSourceController;
130 }
134 }
131
135
132 NetworkController &SqpApplication::networkController() noexcept
136 NetworkController &SqpApplication::networkController() noexcept
133 {
137 {
134 return *impl->m_NetworkController;
138 return *impl->m_NetworkController;
135 }
139 }
136
140
137 TimeController &SqpApplication::timeController() noexcept
141 TimeController &SqpApplication::timeController() noexcept
138 {
142 {
139 return *impl->m_TimeController;
143 return *impl->m_TimeController;
140 }
144 }
141
145
142 VariableController &SqpApplication::variableController() noexcept
146 VariableController &SqpApplication::variableController() noexcept
143 {
147 {
144 return *impl->m_VariableController;
148 return *impl->m_VariableController;
145 }
149 }
146
150
147 VisualizationController &SqpApplication::visualizationController() noexcept
151 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 }
@@ -1,342 +1,384
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
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>
11 #include <DragDropHelper.h>
10 #include <Settings/SqpSettingsDefs.h>
12 #include <Settings/SqpSettingsDefs.h>
11 #include <SqpApplication.h>
13 #include <SqpApplication.h>
12 #include <Variable/Variable.h>
14 #include <Variable/Variable.h>
13 #include <Variable/VariableController.h>
15 #include <Variable/VariableController.h>
14
16
15 #include <unordered_map>
17 #include <unordered_map>
16
18
17 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
19 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
18
20
19 namespace {
21 namespace {
20
22
21 /// Key pressed to enable zoom on horizontal axis
23 /// Key pressed to enable zoom on horizontal axis
22 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
24 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
23
25
24 /// Key pressed to enable zoom on vertical axis
26 /// Key pressed to enable zoom on vertical axis
25 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
27 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
26
28
27 } // namespace
29 } // namespace
28
30
29 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
31 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
30
32
31 explicit VisualizationGraphWidgetPrivate(const QString &name)
33 explicit VisualizationGraphWidgetPrivate(const QString &name)
32 : m_Name{name},
34 : m_Name{name},
33 m_DoAcquisition{true},
35 m_DoAcquisition{true},
34 m_IsCalibration{false},
36 m_IsCalibration{false},
35 m_RenderingDelegate{nullptr}
37 m_RenderingDelegate{nullptr}
36 {
38 {
37 }
39 }
38
40
39 QString m_Name;
41 QString m_Name;
40 // 1 variable -> n qcpplot
42 // 1 variable -> n qcpplot
41 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
43 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
42 bool m_DoAcquisition;
44 bool m_DoAcquisition;
43 bool m_IsCalibration;
45 bool m_IsCalibration;
44 QCPItemTracer *m_TextTracer;
46 QCPItemTracer *m_TextTracer;
45 /// Delegate used to attach rendering features to the plot
47 /// Delegate used to attach rendering features to the plot
46 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
48 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
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 {
54 ui->setupUi(this);
56 ui->setupUi(this);
55
57
56 // 'Close' options : widget is deleted when closed
58 // 'Close' options : widget is deleted when closed
57 setAttribute(Qt::WA_DeleteOnClose);
59 setAttribute(Qt::WA_DeleteOnClose);
58
60
59 // Set qcpplot properties :
61 // Set qcpplot properties :
60 // - Drag (on x-axis) and zoom are enabled
62 // - Drag (on x-axis) and zoom are enabled
61 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
63 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
62 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
64 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
63 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
65 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
64
66
65 // The delegate must be initialized after the ui as it uses the plot
67 // The delegate must be initialized after the ui as it uses the plot
66 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
68 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
67
69
68 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
70 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
69 connect(ui->widget, &QCustomPlot::mouseRelease, this,
71 connect(ui->widget, &QCustomPlot::mouseRelease, this,
70 &VisualizationGraphWidget::onMouseRelease);
72 &VisualizationGraphWidget::onMouseRelease);
71 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
73 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
72 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
74 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
73 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
75 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
74 &QCPAxis::rangeChanged),
76 &QCPAxis::rangeChanged),
75 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
77 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
76
78
77 // Activates menu when right clicking on the graph
79 // Activates menu when right clicking on the graph
78 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
80 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
79 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
81 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
80 &VisualizationGraphWidget::onGraphMenuRequested);
82 &VisualizationGraphWidget::onGraphMenuRequested);
81
83
82 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
84 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
83 &VariableController::onRequestDataLoading);
85 &VariableController::onRequestDataLoading);
84
86
85 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
87 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
86 &VisualizationGraphWidget::onUpdateVarDisplaying);
88 &VisualizationGraphWidget::onUpdateVarDisplaying);
87 }
89 }
88
90
89
91
90 VisualizationGraphWidget::~VisualizationGraphWidget()
92 VisualizationGraphWidget::~VisualizationGraphWidget()
91 {
93 {
92 delete ui;
94 delete ui;
93 }
95 }
94
96
97 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
98 {
99 auto parent = parentWidget();
100 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
101 parent = parent->parentWidget();
102 }
103
104 return qobject_cast<VisualizationZoneWidget *>(parent);
105 }
106
95 void VisualizationGraphWidget::enableAcquisition(bool enable)
107 void VisualizationGraphWidget::enableAcquisition(bool enable)
96 {
108 {
97 impl->m_DoAcquisition = enable;
109 impl->m_DoAcquisition = enable;
98 }
110 }
99
111
100 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
112 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
101 {
113 {
102 // Uses delegate to create the qcpplot components according to the variable
114 // Uses delegate to create the qcpplot components according to the variable
103 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
115 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
104 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
116 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
105
117
106 // Set axes properties according to the units of the data series
118 // Set axes properties according to the units of the data series
107 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
119 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
108 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
120 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
109 auto xAxisUnit = Unit{};
121 auto xAxisUnit = Unit{};
110 auto valuesUnit = Unit{};
122 auto valuesUnit = Unit{};
111
123
112 if (auto dataSeries = variable->dataSeries()) {
124 if (auto dataSeries = variable->dataSeries()) {
113 dataSeries->lockRead();
125 dataSeries->lockRead();
114 xAxisUnit = dataSeries->xAxisUnit();
126 xAxisUnit = dataSeries->xAxisUnit();
115 valuesUnit = dataSeries->valuesUnit();
127 valuesUnit = dataSeries->valuesUnit();
116 dataSeries->unlock();
128 dataSeries->unlock();
117 }
129 }
118 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
130 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
119
131
120 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
132 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
121
133
122 this->enableAcquisition(false);
134 this->enableAcquisition(false);
123 this->setGraphRange(range);
135 this->setGraphRange(range);
124 this->enableAcquisition(true);
136 this->enableAcquisition(true);
125
137
126 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
138 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
127
139
128 emit variableAdded(variable);
140 emit variableAdded(variable);
129 }
141 }
130
142
131 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
143 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
132 {
144 {
133 // Each component associated to the variable :
145 // Each component associated to the variable :
134 // - is removed from qcpplot (which deletes it)
146 // - is removed from qcpplot (which deletes it)
135 // - is no longer referenced in the map
147 // - is no longer referenced in the map
136 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
148 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
137 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
149 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
138 emit variableAboutToBeRemoved(variable);
150 emit variableAboutToBeRemoved(variable);
139
151
140 auto &plottablesMap = variableIt->second;
152 auto &plottablesMap = variableIt->second;
141
153
142 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
154 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
143 plottableIt != plottableEnd;) {
155 plottableIt != plottableEnd;) {
144 ui->widget->removePlottable(plottableIt->second);
156 ui->widget->removePlottable(plottableIt->second);
145 plottableIt = plottablesMap.erase(plottableIt);
157 plottableIt = plottablesMap.erase(plottableIt);
146 }
158 }
147
159
148 impl->m_VariableToPlotMultiMap.erase(variableIt);
160 impl->m_VariableToPlotMultiMap.erase(variableIt);
149 }
161 }
150
162
151 // Updates graph
163 // Updates graph
152 ui->widget->replot();
164 ui->widget->replot();
153 }
165 }
154
166
167 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
168 {
169 auto variables = QList<std::shared_ptr<Variable> >{};
170 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
171 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
172 variables << it->first;
173 }
174
175 return variables;
176 }
177
155 void VisualizationGraphWidget::setYRange(const SqpRange &range)
178 void VisualizationGraphWidget::setYRange(const SqpRange &range)
156 {
179 {
157 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
180 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
158 }
181 }
159
182
160 SqpRange VisualizationGraphWidget::graphRange() const noexcept
183 SqpRange VisualizationGraphWidget::graphRange() const noexcept
161 {
184 {
162 auto graphRange = ui->widget->xAxis->range();
185 auto graphRange = ui->widget->xAxis->range();
163 return SqpRange{graphRange.lower, graphRange.upper};
186 return SqpRange{graphRange.lower, graphRange.upper};
164 }
187 }
165
188
166 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
189 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
167 {
190 {
168 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
191 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
169 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
192 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
170 ui->widget->replot();
193 ui->widget->replot();
171 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
194 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
172 }
195 }
173
196
174 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
197 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
175 {
198 {
176 if (visitor) {
199 if (visitor) {
177 visitor->visit(this);
200 visitor->visit(this);
178 }
201 }
179 else {
202 else {
180 qCCritical(LOG_VisualizationGraphWidget())
203 qCCritical(LOG_VisualizationGraphWidget())
181 << tr("Can't visit widget : the visitor is null");
204 << tr("Can't visit widget : the visitor is null");
182 }
205 }
183 }
206 }
184
207
185 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
208 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
186 {
209 {
187 /// @todo : for the moment, a graph can always accomodate a variable
210 /// @todo : for the moment, a graph can always accomodate a variable
188 Q_UNUSED(variable);
211 Q_UNUSED(variable);
189 return true;
212 return true;
190 }
213 }
191
214
192 bool VisualizationGraphWidget::contains(const Variable &variable) const
215 bool VisualizationGraphWidget::contains(const Variable &variable) const
193 {
216 {
194 // Finds the variable among the keys of the map
217 // Finds the variable among the keys of the map
195 auto variablePtr = &variable;
218 auto variablePtr = &variable;
196 auto findVariable
219 auto findVariable
197 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
220 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
198
221
199 auto end = impl->m_VariableToPlotMultiMap.cend();
222 auto end = impl->m_VariableToPlotMultiMap.cend();
200 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
223 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
201 return it != end;
224 return it != end;
202 }
225 }
203
226
204 QString VisualizationGraphWidget::name() const
227 QString VisualizationGraphWidget::name() const
205 {
228 {
206 return impl->m_Name;
229 return impl->m_Name;
207 }
230 }
208
231
232 QMimeData *VisualizationGraphWidget::mimeData() const
233 {
234 auto mimeData = new QMimeData;
235 mimeData->setData(DragDropHelper::MIME_TYPE_GRAPH, QByteArray());
236
237 return mimeData;
238 }
239
240 bool VisualizationGraphWidget::isDragAllowed() const
241 {
242 return true;
243 }
244
209 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
245 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
210 {
246 {
211 Q_UNUSED(event);
247 Q_UNUSED(event);
212
248
213 // Prevents that all variables will be removed from graph when it will be closed
249 // Prevents that all variables will be removed from graph when it will be closed
214 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
250 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
215 emit variableAboutToBeRemoved(variableEntry.first);
251 emit variableAboutToBeRemoved(variableEntry.first);
216 }
252 }
217 }
253 }
218
254
219 void VisualizationGraphWidget::enterEvent(QEvent *event)
255 void VisualizationGraphWidget::enterEvent(QEvent *event)
220 {
256 {
221 Q_UNUSED(event);
257 Q_UNUSED(event);
222 impl->m_RenderingDelegate->showGraphOverlay(true);
258 impl->m_RenderingDelegate->showGraphOverlay(true);
223 }
259 }
224
260
225 void VisualizationGraphWidget::leaveEvent(QEvent *event)
261 void VisualizationGraphWidget::leaveEvent(QEvent *event)
226 {
262 {
227 Q_UNUSED(event);
263 Q_UNUSED(event);
228 impl->m_RenderingDelegate->showGraphOverlay(false);
264 impl->m_RenderingDelegate->showGraphOverlay(false);
229 }
265 }
230
266
231 QCustomPlot &VisualizationGraphWidget::plot() noexcept
267 QCustomPlot &VisualizationGraphWidget::plot() noexcept
232 {
268 {
233 return *ui->widget;
269 return *ui->widget;
234 }
270 }
235
271
236 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
272 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
237 {
273 {
238 QMenu graphMenu{};
274 QMenu graphMenu{};
239
275
240 // Iterates on variables (unique keys)
276 // Iterates on variables (unique keys)
241 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
277 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
242 end = impl->m_VariableToPlotMultiMap.cend();
278 end = impl->m_VariableToPlotMultiMap.cend();
243 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
279 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
244 // 'Remove variable' action
280 // 'Remove variable' action
245 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
281 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
246 [ this, var = it->first ]() { removeVariable(var); });
282 [ this, var = it->first ]() { removeVariable(var); });
247 }
283 }
248
284
249 if (!graphMenu.isEmpty()) {
285 if (!graphMenu.isEmpty()) {
250 graphMenu.exec(QCursor::pos());
286 graphMenu.exec(QCursor::pos());
251 }
287 }
252 }
288 }
253
289
254 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
290 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
255 {
291 {
256 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
292 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
257 << QThread::currentThread()->objectName() << "DoAcqui"
293 << QThread::currentThread()->objectName() << "DoAcqui"
258 << impl->m_DoAcquisition;
294 << impl->m_DoAcquisition;
259
295
260 auto graphRange = SqpRange{t1.lower, t1.upper};
296 auto graphRange = SqpRange{t1.lower, t1.upper};
261 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
297 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
262
298
263 if (impl->m_DoAcquisition) {
299 if (impl->m_DoAcquisition) {
264 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
300 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
265
301
266 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
302 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
267 end = impl->m_VariableToPlotMultiMap.end();
303 end = impl->m_VariableToPlotMultiMap.end();
268 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
304 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
269 variableUnderGraphVector.push_back(it->first);
305 variableUnderGraphVector.push_back(it->first);
270 }
306 }
271 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
307 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
272 !impl->m_IsCalibration);
308 !impl->m_IsCalibration);
273
309
274 if (!impl->m_IsCalibration) {
310 if (!impl->m_IsCalibration) {
275 qCDebug(LOG_VisualizationGraphWidget())
311 qCDebug(LOG_VisualizationGraphWidget())
276 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
312 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
277 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
313 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
278 emit synchronize(graphRange, oldGraphRange);
314 emit synchronize(graphRange, oldGraphRange);
279 }
315 }
280 }
316 }
281 }
317 }
282
318
283 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
319 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
284 {
320 {
285 // Handles plot rendering when mouse is moving
321 // Handles plot rendering when mouse is moving
286 impl->m_RenderingDelegate->onMouseMove(event);
322 impl->m_RenderingDelegate->onMouseMove(event);
323
324 VisualizationDragWidget::mouseMoveEvent(event);
287 }
325 }
288
326
289 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
327 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
290 {
328 {
291 auto zoomOrientations = QFlags<Qt::Orientation>{};
329 auto zoomOrientations = QFlags<Qt::Orientation>{};
292
330
293 // Lambda that enables a zoom orientation if the key modifier related to this orientation
331 // Lambda that enables a zoom orientation if the key modifier related to this orientation
294 // has
332 // has
295 // been pressed
333 // been pressed
296 auto enableOrientation
334 auto enableOrientation
297 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
335 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
298 auto orientationEnabled = event->modifiers().testFlag(modifier);
336 auto orientationEnabled = event->modifiers().testFlag(modifier);
299 zoomOrientations.setFlag(orientation, orientationEnabled);
337 zoomOrientations.setFlag(orientation, orientationEnabled);
300 };
338 };
301 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
339 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
302 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
340 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
303
341
304 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
342 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
305 }
343 }
306
344
307 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
345 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
308 {
346 {
309 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
347 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
348
349 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
350
351 VisualizationDragWidget::mousePressEvent(event);
310 }
352 }
311
353
312 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
354 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
313 {
355 {
314 impl->m_IsCalibration = false;
356 impl->m_IsCalibration = false;
315 }
357 }
316
358
317 void VisualizationGraphWidget::onDataCacheVariableUpdated()
359 void VisualizationGraphWidget::onDataCacheVariableUpdated()
318 {
360 {
319 auto graphRange = ui->widget->xAxis->range();
361 auto graphRange = ui->widget->xAxis->range();
320 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
362 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
321
363
322 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
364 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
323 auto variable = variableEntry.first;
365 auto variable = variableEntry.first;
324 qCDebug(LOG_VisualizationGraphWidget())
366 qCDebug(LOG_VisualizationGraphWidget())
325 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
367 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
326 qCDebug(LOG_VisualizationGraphWidget())
368 qCDebug(LOG_VisualizationGraphWidget())
327 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
369 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
328 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
370 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
329 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
371 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
330 variable->range());
372 variable->range());
331 }
373 }
332 }
374 }
333 }
375 }
334
376
335 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
377 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
336 const SqpRange &range)
378 const SqpRange &range)
337 {
379 {
338 auto it = impl->m_VariableToPlotMultiMap.find(variable);
380 auto it = impl->m_VariableToPlotMultiMap.find(variable);
339 if (it != impl->m_VariableToPlotMultiMap.end()) {
381 if (it != impl->m_VariableToPlotMultiMap.end()) {
340 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
382 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
341 }
383 }
342 }
384 }
@@ -1,129 +1,219
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/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6
7
8 #include "Variable/VariableController.h"
9
10 #include "DragDropHelper.h"
11 #include "SqpApplication.h"
12
7 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
13 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
8
14
9 namespace {
15 namespace {
10
16
11 /// Generates a default name for a new zone, according to the number of zones already displayed in
17 /// Generates a default name for a new zone, according to the number of zones already displayed in
12 /// the tab
18 /// the tab
13 QString defaultZoneName(const QLayout &layout)
19 QString defaultZoneName(const QLayout &layout)
14 {
20 {
15 auto count = 0;
21 auto count = 0;
16 for (auto i = 0; i < layout.count(); ++i) {
22 for (auto i = 0; i < layout.count(); ++i) {
17 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
23 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
18 count++;
24 count++;
19 }
25 }
20 }
26 }
21
27
22 return QObject::tr("Zone %1").arg(count + 1);
28 return QObject::tr("Zone %1").arg(count + 1);
23 }
29 }
24
30
25 /**
31 /**
26 * Applies a function to all zones of the tab represented by its layout
32 * Applies a function to all zones of the tab represented by its layout
27 * @param layout the layout that contains zones
33 * @param layout the layout that contains zones
28 * @param fun the function to apply to each zone
34 * @param fun the function to apply to each zone
29 */
35 */
30 template <typename Fun>
36 template <typename Fun>
31 void processZones(QLayout &layout, Fun fun)
37 void processZones(QLayout &layout, Fun fun)
32 {
38 {
33 for (auto i = 0; i < layout.count(); ++i) {
39 for (auto i = 0; i < layout.count(); ++i) {
34 if (auto item = layout.itemAt(i)) {
40 if (auto item = layout.itemAt(i)) {
35 if (auto visualizationZoneWidget
41 if (auto visualizationZoneWidget
36 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
42 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
37 fun(*visualizationZoneWidget);
43 fun(*visualizationZoneWidget);
38 }
44 }
39 }
45 }
40 }
46 }
41 }
47 }
42
48
43 } // namespace
49 } // namespace
44
50
45 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
51 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
46 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
52 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
47
53
48 QString m_Name;
54 QString m_Name;
49 };
55 };
50
56
51 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
57 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
52 : QWidget{parent},
58 : QWidget{parent},
53 ui{new Ui::VisualizationTabWidget},
59 ui{new Ui::VisualizationTabWidget},
54 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
60 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
55 {
61 {
56 ui->setupUi(this);
62 ui->setupUi(this);
57
63
64 ui->dragDropContainer->setAcceptedMimeTypes(
65 {DragDropHelper::MIME_TYPE_GRAPH, DragDropHelper::MIME_TYPE_ZONE});
66 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
67 &VisualizationTabWidget::dropMimeData);
68 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
69
58 // Widget is deleted when closed
70 // Widget is deleted when closed
59 setAttribute(Qt::WA_DeleteOnClose);
71 setAttribute(Qt::WA_DeleteOnClose);
60 }
72 }
61
73
62 VisualizationTabWidget::~VisualizationTabWidget()
74 VisualizationTabWidget::~VisualizationTabWidget()
63 {
75 {
76 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
64 delete ui;
77 delete ui;
65 }
78 }
66
79
67 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
80 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
68 {
81 {
69 tabLayout().addWidget(zoneWidget);
82 ui->dragDropContainer->addDragWidget(zoneWidget);
83 }
84
85 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
86 {
87 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
70 }
88 }
71
89
72 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
90 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
73 {
91 {
74 auto zoneWidget = new VisualizationZoneWidget{defaultZoneName(tabLayout()), this};
92 return createZone({variable}, -1);
75 this->addZone(zoneWidget);
93 }
94
95 VisualizationZoneWidget *
96 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
97 {
98 auto zoneWidget = createEmptyZone(index);
76
99
77 // Creates a new graph into the zone
100 // Creates a new graph into the zone
78 zoneWidget->createGraph(variable);
101 zoneWidget->createGraph(variables, index);
102
103 return zoneWidget;
104 }
105
106 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
107 {
108 auto zoneWidget
109 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
110 this->insertZone(index, zoneWidget);
79
111
80 return zoneWidget;
112 return zoneWidget;
81 }
113 }
82
114
83 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
115 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
84 {
116 {
85 if (visitor) {
117 if (visitor) {
86 visitor->visitEnter(this);
118 visitor->visitEnter(this);
87
119
88 // Apply visitor to zone children: widgets different from zones are not visited (no action)
120 // Apply visitor to zone children: widgets different from zones are not visited (no action)
89 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
121 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
90 zoneWidget.accept(visitor);
122 zoneWidget.accept(visitor);
91 });
123 });
92
124
93 visitor->visitLeave(this);
125 visitor->visitLeave(this);
94 }
126 }
95 else {
127 else {
96 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
128 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
97 }
129 }
98 }
130 }
99
131
100 bool VisualizationTabWidget::canDrop(const Variable &variable) const
132 bool VisualizationTabWidget::canDrop(const Variable &variable) const
101 {
133 {
102 // A tab can always accomodate a variable
134 // A tab can always accomodate a variable
103 Q_UNUSED(variable);
135 Q_UNUSED(variable);
104 return true;
136 return true;
105 }
137 }
106
138
107 bool VisualizationTabWidget::contains(const Variable &variable) const
139 bool VisualizationTabWidget::contains(const Variable &variable) const
108 {
140 {
109 Q_UNUSED(variable);
141 Q_UNUSED(variable);
110 return false;
142 return false;
111 }
143 }
112
144
113 QString VisualizationTabWidget::name() const
145 QString VisualizationTabWidget::name() const
114 {
146 {
115 return impl->m_Name;
147 return impl->m_Name;
116 }
148 }
117
149
118 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
150 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
119 {
151 {
120 // Closes zones in the tab
152 // Closes zones in the tab
121 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
153 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
122
154
123 QWidget::closeEvent(event);
155 QWidget::closeEvent(event);
124 }
156 }
125
157
126 QLayout &VisualizationTabWidget::tabLayout() const noexcept
158 QLayout &VisualizationTabWidget::tabLayout() const noexcept
127 {
159 {
128 return *ui->scrollAreaWidgetContents->layout();
160 return *ui->dragDropContainer->layout();
161 }
162
163 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
164 {
165 auto &helper = sqpApp->dragDropHelper();
166 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH)) {
167 auto graphWidget = static_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
168 auto parentDragDropContainer
169 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
170 Q_ASSERT(parentDragDropContainer);
171
172 auto nbGraph = parentDragDropContainer->countDragWidget();
173
174 const auto &variables = graphWidget->variables();
175
176 if (!variables.isEmpty()) {
177 // Abort the requests for the variables (if any)
178 // Commented, because it's not sure if it's needed or not
179 // for (const auto& var : variables)
180 //{
181 // sqpApp->variableController().onAbortProgressRequested(var);
182 //}
183
184 if (nbGraph == 1) {
185 // This is the only graph in the previous zone, close the zone
186 graphWidget->parentZoneWidget()->close();
187 }
188 else {
189 // Close the graph
190 graphWidget->close();
191 }
192
193 createZone(variables, index);
194 }
195 else {
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 }
211 else if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_ZONE)) {
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 }
@@ -1,304 +1,410
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 "ui_VisualizationZoneWidget.h"
6 #include "ui_VisualizationZoneWidget.h"
7
7
8 #include <Data/SqpRange.h>
8 #include <Data/SqpRange.h>
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
11
11
12 #include <DragDropHelper.h>
12 #include <QUuid>
13 #include <QUuid>
13 #include <SqpApplication.h>
14 #include <SqpApplication.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 {
19
22
20 /// Minimum height for graph added in zones (in pixels)
23 /// Minimum height for graph added in zones (in pixels)
21 const auto GRAPH_MINIMUM_HEIGHT = 300;
24 const auto GRAPH_MINIMUM_HEIGHT = 300;
22
25
23 /// Generates a default name for a new graph, according to the number of graphs already displayed in
26 /// Generates a default name for a new graph, according to the number of graphs already displayed in
24 /// the zone
27 /// the zone
25 QString defaultGraphName(const QLayout &layout)
28 QString defaultGraphName(const QLayout &layout)
26 {
29 {
27 auto count = 0;
30 auto count = 0;
28 for (auto i = 0; i < layout.count(); ++i) {
31 for (auto i = 0; i < layout.count(); ++i) {
29 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
32 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
30 count++;
33 count++;
31 }
34 }
32 }
35 }
33
36
34 return QObject::tr("Graph %1").arg(count + 1);
37 return QObject::tr("Graph %1").arg(count + 1);
35 }
38 }
36
39
37 /**
40 /**
38 * Applies a function to all graphs of the zone represented by its layout
41 * Applies a function to all graphs of the zone represented by its layout
39 * @param layout the layout that contains graphs
42 * @param layout the layout that contains graphs
40 * @param fun the function to apply to each graph
43 * @param fun the function to apply to each graph
41 */
44 */
42 template <typename Fun>
45 template <typename Fun>
43 void processGraphs(QLayout &layout, Fun fun)
46 void processGraphs(QLayout &layout, Fun fun)
44 {
47 {
45 for (auto i = 0; i < layout.count(); ++i) {
48 for (auto i = 0; i < layout.count(); ++i) {
46 if (auto item = layout.itemAt(i)) {
49 if (auto item = layout.itemAt(i)) {
47 if (auto visualizationGraphWidget
50 if (auto visualizationGraphWidget
48 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
51 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
49 fun(*visualizationGraphWidget);
52 fun(*visualizationGraphWidget);
50 }
53 }
51 }
54 }
52 }
55 }
53 }
56 }
54
57
55 } // namespace
58 } // namespace
56
59
57 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
60 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
58
61
59 explicit VisualizationZoneWidgetPrivate()
62 explicit VisualizationZoneWidgetPrivate()
60 : m_SynchronisationGroupId{QUuid::createUuid()},
63 : m_SynchronisationGroupId{QUuid::createUuid()},
61 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
64 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
62 {
65 {
63 }
66 }
64 QUuid m_SynchronisationGroupId;
67 QUuid m_SynchronisationGroupId;
65 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
68 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
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 {
73 ui->setupUi(this);
76 ui->setupUi(this);
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,
82 &VisualizationZoneWidget::dropMimeData);
83
77 // 'Close' options : widget is deleted when closed
84 // 'Close' options : widget is deleted when closed
78 setAttribute(Qt::WA_DeleteOnClose);
85 setAttribute(Qt::WA_DeleteOnClose);
79 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
86 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
80 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
87 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
81
88
82 // Synchronisation id
89 // Synchronisation id
83 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
90 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
84 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
91 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
85 }
92 }
86
93
87 VisualizationZoneWidget::~VisualizationZoneWidget()
94 VisualizationZoneWidget::~VisualizationZoneWidget()
88 {
95 {
89 delete ui;
96 delete ui;
90 }
97 }
91
98
92 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
99 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
93 {
100 {
94 // Synchronize new graph with others in the zone
101 // Synchronize new graph with others in the zone
95 impl->m_Synchronizer->addGraph(*graphWidget);
102 impl->m_Synchronizer->addGraph(*graphWidget);
96
103
97 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
104 ui->dragDropContainer->addDragWidget(graphWidget);
105 }
106
107 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
108 {
109 // Synchronize new graph with others in the zone
110 impl->m_Synchronizer->addGraph(*graphWidget);
111
112 ui->dragDropContainer->insertDragWidget(index, graphWidget);
98 }
113 }
99
114
100 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
115 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
101 {
116 {
102 auto graphWidget = new VisualizationGraphWidget{
117 return createGraph(variable, -1);
103 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
118 }
119
120 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
121 int index)
122 {
123 auto graphWidget
124 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
104
125
105
126
106 // Set graph properties
127 // Set graph properties
107 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
128 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
108 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
129 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
109
130
110
131
111 // Lambda to synchronize zone widget
132 // Lambda to synchronize zone widget
112 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
133 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
113 const SqpRange &oldGraphRange) {
134 const SqpRange &oldGraphRange) {
114
135
115 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
136 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
116 auto frameLayout = ui->visualizationZoneFrame->layout();
137 auto frameLayout = ui->dragDropContainer->layout();
117 for (auto i = 0; i < frameLayout->count(); ++i) {
138 for (auto i = 0; i < frameLayout->count(); ++i) {
118 auto graphChild
139 auto graphChild
119 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
140 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
120 if (graphChild && (graphChild != graphWidget)) {
141 if (graphChild && (graphChild != graphWidget)) {
121
142
122 auto graphChildRange = graphChild->graphRange();
143 auto graphChildRange = graphChild->graphRange();
123 switch (zoomType) {
144 switch (zoomType) {
124 case AcquisitionZoomType::ZoomIn: {
145 case AcquisitionZoomType::ZoomIn: {
125 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
146 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
126 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
147 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
127 graphChildRange.m_TStart += deltaLeft;
148 graphChildRange.m_TStart += deltaLeft;
128 graphChildRange.m_TEnd -= deltaRight;
149 graphChildRange.m_TEnd -= deltaRight;
129 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
150 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
130 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
151 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
131 << deltaLeft;
152 << deltaLeft;
132 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
153 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
133 << deltaRight;
154 << deltaRight;
134 qCDebug(LOG_VisualizationZoneWidget())
155 qCDebug(LOG_VisualizationZoneWidget())
135 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
156 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
136
157
137 break;
158 break;
138 }
159 }
139
160
140 case AcquisitionZoomType::ZoomOut: {
161 case AcquisitionZoomType::ZoomOut: {
141 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
162 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
142 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
163 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
143 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
164 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
144 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
165 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
145 << deltaLeft;
166 << deltaLeft;
146 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
167 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
147 << deltaRight;
168 << deltaRight;
148 qCDebug(LOG_VisualizationZoneWidget())
169 qCDebug(LOG_VisualizationZoneWidget())
149 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
170 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
150 graphChildRange.m_TStart -= deltaLeft;
171 graphChildRange.m_TStart -= deltaLeft;
151 graphChildRange.m_TEnd += deltaRight;
172 graphChildRange.m_TEnd += deltaRight;
152 break;
173 break;
153 }
174 }
154 case AcquisitionZoomType::PanRight: {
175 case AcquisitionZoomType::PanRight: {
155 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
176 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
156 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
177 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
157 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
178 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
158 graphChildRange.m_TStart += deltaLeft;
179 graphChildRange.m_TStart += deltaLeft;
159 graphChildRange.m_TEnd += deltaRight;
180 graphChildRange.m_TEnd += deltaRight;
160 qCDebug(LOG_VisualizationZoneWidget())
181 qCDebug(LOG_VisualizationZoneWidget())
161 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
182 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
162 break;
183 break;
163 }
184 }
164 case AcquisitionZoomType::PanLeft: {
185 case AcquisitionZoomType::PanLeft: {
165 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
186 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
166 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
187 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
167 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
188 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
168 graphChildRange.m_TStart -= deltaLeft;
189 graphChildRange.m_TStart -= deltaLeft;
169 graphChildRange.m_TEnd -= deltaRight;
190 graphChildRange.m_TEnd -= deltaRight;
170 break;
191 break;
171 }
192 }
172 case AcquisitionZoomType::Unknown: {
193 case AcquisitionZoomType::Unknown: {
173 qCDebug(LOG_VisualizationZoneWidget())
194 qCDebug(LOG_VisualizationZoneWidget())
174 << tr("Impossible to synchronize: zoom type unknown");
195 << tr("Impossible to synchronize: zoom type unknown");
175 break;
196 break;
176 }
197 }
177 default:
198 default:
178 qCCritical(LOG_VisualizationZoneWidget())
199 qCCritical(LOG_VisualizationZoneWidget())
179 << tr("Impossible to synchronize: zoom type not take into account");
200 << tr("Impossible to synchronize: zoom type not take into account");
180 // No action
201 // No action
181 break;
202 break;
182 }
203 }
183 graphChild->enableAcquisition(false);
204 graphChild->enableAcquisition(false);
184 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
205 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
185 << graphChild->graphRange();
206 << graphChild->graphRange();
186 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
207 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
187 << graphChildRange;
208 << graphChildRange;
188 qCDebug(LOG_VisualizationZoneWidget())
209 qCDebug(LOG_VisualizationZoneWidget())
189 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
210 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
190 graphChild->setGraphRange(graphChildRange);
211 graphChild->setGraphRange(graphChildRange);
191 graphChild->enableAcquisition(true);
212 graphChild->enableAcquisition(true);
192 }
213 }
193 }
214 }
194 };
215 };
195
216
196 // connection for synchronization
217 // connection for synchronization
197 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
218 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
198 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
219 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
199 &VisualizationZoneWidget::onVariableAdded);
220 &VisualizationZoneWidget::onVariableAdded);
200 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
221 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
201 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
222 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
202
223
203 auto range = SqpRange{};
224 auto range = SqpRange{};
204
225
205 // Apply visitor to graph children
226 // Apply visitor to graph children
206 auto layout = ui->visualizationZoneFrame->layout();
227 auto layout = ui->dragDropContainer->layout();
207 if (layout->count() > 0) {
228 if (layout->count() > 0) {
208 // Case of a new graph in a existant zone
229 // Case of a new graph in a existant zone
209 if (auto visualizationGraphWidget
230 if (auto visualizationGraphWidget
210 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
231 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
211 range = visualizationGraphWidget->graphRange();
232 range = visualizationGraphWidget->graphRange();
212 }
233 }
213 }
234 }
214 else {
235 else {
215 // Case of a new graph as the first of the zone
236 // Case of a new graph as the first of the zone
216 range = variable->range();
237 range = variable->range();
217 }
238 }
218
239
219 this->addGraph(graphWidget);
240 this->insertGraph(index, graphWidget);
220
241
221 graphWidget->addVariable(variable, range);
242 graphWidget->addVariable(variable, range);
222
243
223 // get y using variable range
244 // get y using variable range
224 if (auto dataSeries = variable->dataSeries()) {
245 if (auto dataSeries = variable->dataSeries()) {
225 dataSeries->lockRead();
246 dataSeries->lockRead();
226 auto valuesBounds
247 auto valuesBounds
227 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
248 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
228 auto end = dataSeries->cend();
249 auto end = dataSeries->cend();
229 if (valuesBounds.first != end && valuesBounds.second != end) {
250 if (valuesBounds.first != end && valuesBounds.second != end) {
230 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
251 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
231
252
232 auto minValue = rangeValue(valuesBounds.first->minValue());
253 auto minValue = rangeValue(valuesBounds.first->minValue());
233 auto maxValue = rangeValue(valuesBounds.second->maxValue());
254 auto maxValue = rangeValue(valuesBounds.second->maxValue());
234
255
235 graphWidget->setYRange(SqpRange{minValue, maxValue});
256 graphWidget->setYRange(SqpRange{minValue, maxValue});
236 }
257 }
237 dataSeries->unlock();
258 dataSeries->unlock();
238 }
259 }
239
260
240 return graphWidget;
261 return graphWidget;
241 }
262 }
242
263
264 VisualizationGraphWidget *
265 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
266 {
267 if (variables.isEmpty()) {
268 return nullptr;
269 }
270
271 auto graphWidget = createGraph(variables.first(), index);
272 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
273 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
274 }
275
276 return graphWidget;
277 }
278
243 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
279 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
244 {
280 {
245 if (visitor) {
281 if (visitor) {
246 visitor->visitEnter(this);
282 visitor->visitEnter(this);
247
283
248 // Apply visitor to graph children: widgets different from graphs are not visited (no
284 // Apply visitor to graph children: widgets different from graphs are not visited (no
249 // action)
285 // action)
250 processGraphs(
286 processGraphs(
251 *ui->visualizationZoneFrame->layout(),
287 *ui->dragDropContainer->layout(),
252 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
288 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
253
289
254 visitor->visitLeave(this);
290 visitor->visitLeave(this);
255 }
291 }
256 else {
292 else {
257 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
293 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
258 }
294 }
259 }
295 }
260
296
261 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
297 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
262 {
298 {
263 // A tab can always accomodate a variable
299 // A tab can always accomodate a variable
264 Q_UNUSED(variable);
300 Q_UNUSED(variable);
265 return true;
301 return true;
266 }
302 }
267
303
268 bool VisualizationZoneWidget::contains(const Variable &variable) const
304 bool VisualizationZoneWidget::contains(const Variable &variable) const
269 {
305 {
270 Q_UNUSED(variable);
306 Q_UNUSED(variable);
271 return false;
307 return false;
272 }
308 }
273
309
274 QString VisualizationZoneWidget::name() const
310 QString VisualizationZoneWidget::name() const
275 {
311 {
276 return ui->zoneNameLabel->text();
312 return ui->zoneNameLabel->text();
277 }
313 }
278
314
315 QMimeData *VisualizationZoneWidget::mimeData() const
316 {
317 auto mimeData = new QMimeData;
318 mimeData->setData(DragDropHelper::MIME_TYPE_ZONE, QByteArray());
319
320 return mimeData;
321 }
322
323 bool VisualizationZoneWidget::isDragAllowed() const
324 {
325 return true;
326 }
327
279 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
328 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
280 {
329 {
281 // Closes graphs in the zone
330 // Closes graphs in the zone
282 processGraphs(*ui->visualizationZoneFrame->layout(),
331 processGraphs(*ui->dragDropContainer->layout(),
283 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
332 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
284
333
285 // Delete synchronization group from variable controller
334 // Delete synchronization group from variable controller
286 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
335 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
287 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
336 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
288
337
289 QWidget::closeEvent(event);
338 QWidget::closeEvent(event);
290 }
339 }
291
340
292 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
341 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
293 {
342 {
294 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
343 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
295 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
344 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
296 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
345 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
297 }
346 }
298
347
299 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
348 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
300 {
349 {
301 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
350 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
302 Q_ARG(std::shared_ptr<Variable>, variable),
351 Q_ARG(std::shared_ptr<Variable>, variable),
303 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
352 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
304 }
353 }
354
355 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
356 {
357 auto &helper = sqpApp->dragDropHelper();
358 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH)) {
359 auto graphWidget = static_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
360 auto parentDragDropContainer
361 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
362 Q_ASSERT(parentDragDropContainer);
363
364 const auto &variables = graphWidget->variables();
365
366 if (parentDragDropContainer != ui->dragDropContainer && !variables.isEmpty()) {
367 // The drop didn't occur in the same zone
368
369 // Abort the requests for the variables (if any)
370 // Commented, because it's not sure if it's needed or not
371 // for (const auto& var : variables)
372 //{
373 // sqpApp->variableController().onAbortProgressRequested(var);
374 //}
375
376 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
377 auto nbGraph = parentDragDropContainer->countDragWidget();
378 if (nbGraph == 1) {
379 // This is the only graph in the previous zone, close the zone
380 previousParentZoneWidget->close();
381 }
382 else {
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 // The drop occurred in the same zone or the graph is empty
392 // Simple move of the graph, no variable operation associated
393 parentDragDropContainer->layout()->removeWidget(graphWidget);
394
395 if (variables.isEmpty() && parentDragDropContainer != ui->dragDropContainer) {
396 // The graph is empty and dropped in a different zone.
397 // Take the range of the first graph in the zone (if existing).
398 auto layout = ui->dragDropContainer->layout();
399 if (layout->count() > 0) {
400 if (auto visualizationGraphWidget
401 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
402 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
403 }
404 }
405 }
406
407 ui->dragDropContainer->insertDragWidget(index, graphWidget);
408 }
409 }
410 }
@@ -1,73 +1,84
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>VisualizationTabWidget</class>
3 <class>VisualizationTabWidget</class>
4 <widget class="QWidget" name="VisualizationTabWidget">
4 <widget class="QWidget" name="VisualizationTabWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>400</width>
9 <width>400</width>
10 <height>300</height>
10 <height>300</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="windowTitle">
13 <property name="windowTitle">
14 <string>Form</string>
14 <string>Form</string>
15 </property>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout">
16 <layout class="QVBoxLayout" name="verticalLayout">
17 <property name="leftMargin">
17 <property name="leftMargin">
18 <number>0</number>
18 <number>0</number>
19 </property>
19 </property>
20 <property name="topMargin">
20 <property name="topMargin">
21 <number>0</number>
21 <number>0</number>
22 </property>
22 </property>
23 <property name="rightMargin">
23 <property name="rightMargin">
24 <number>0</number>
24 <number>0</number>
25 </property>
25 </property>
26 <property name="bottomMargin">
26 <property name="bottomMargin">
27 <number>0</number>
27 <number>0</number>
28 </property>
28 </property>
29 <item>
29 <item>
30 <widget class="QScrollArea" name="scrollArea">
30 <widget class="QScrollArea" name="scrollArea">
31 <property name="frameShape">
31 <property name="frameShape">
32 <enum>QFrame::NoFrame</enum>
32 <enum>QFrame::NoFrame</enum>
33 </property>
33 </property>
34 <property name="frameShadow">
34 <property name="frameShadow">
35 <enum>QFrame::Sunken</enum>
35 <enum>QFrame::Sunken</enum>
36 </property>
36 </property>
37 <property name="widgetResizable">
37 <property name="widgetResizable">
38 <bool>true</bool>
38 <bool>true</bool>
39 </property>
39 </property>
40 <widget class="QWidget" name="scrollAreaWidgetContents">
40 <widget class="QWidget" name="scrollAreaWidgetContents">
41 <property name="geometry">
41 <property name="geometry">
42 <rect>
42 <rect>
43 <x>0</x>
43 <x>0</x>
44 <y>0</y>
44 <y>0</y>
45 <width>400</width>
45 <width>400</width>
46 <height>300</height>
46 <height>300</height>
47 </rect>
47 </rect>
48 </property>
48 </property>
49 <layout class="QVBoxLayout" name="verticalLayout_3">
49 <layout class="QVBoxLayout" name="verticalLayout_3">
50 <property name="spacing">
50 <property name="spacing">
51 <number>3</number>
51 <number>3</number>
52 </property>
52 </property>
53 <property name="leftMargin">
53 <property name="leftMargin">
54 <number>0</number>
54 <number>0</number>
55 </property>
55 </property>
56 <property name="topMargin">
56 <property name="topMargin">
57 <number>0</number>
57 <number>0</number>
58 </property>
58 </property>
59 <property name="rightMargin">
59 <property name="rightMargin">
60 <number>0</number>
60 <number>0</number>
61 </property>
61 </property>
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>
@@ -1,117 +1,128
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>VisualizationZoneWidget</class>
3 <class>VisualizationZoneWidget</class>
4 <widget class="QWidget" name="VisualizationZoneWidget">
4 <widget class="QWidget" name="VisualizationZoneWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>400</width>
9 <width>400</width>
10 <height>300</height>
10 <height>300</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="windowTitle">
13 <property name="windowTitle">
14 <string>Form</string>
14 <string>Form</string>
15 </property>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout_2">
16 <layout class="QVBoxLayout" name="verticalLayout_2">
17 <property name="spacing">
17 <property name="spacing">
18 <number>0</number>
18 <number>0</number>
19 </property>
19 </property>
20 <property name="leftMargin">
20 <property name="leftMargin">
21 <number>0</number>
21 <number>0</number>
22 </property>
22 </property>
23 <property name="topMargin">
23 <property name="topMargin">
24 <number>0</number>
24 <number>0</number>
25 </property>
25 </property>
26 <property name="rightMargin">
26 <property name="rightMargin">
27 <number>0</number>
27 <number>0</number>
28 </property>
28 </property>
29 <property name="bottomMargin">
29 <property name="bottomMargin">
30 <number>0</number>
30 <number>0</number>
31 </property>
31 </property>
32 <item>
32 <item>
33 <widget class="QWidget" name="infobar" native="true">
33 <widget class="QWidget" name="infobar" native="true">
34 <property name="sizePolicy">
34 <property name="sizePolicy">
35 <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
35 <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
36 <horstretch>0</horstretch>
36 <horstretch>0</horstretch>
37 <verstretch>0</verstretch>
37 <verstretch>0</verstretch>
38 </sizepolicy>
38 </sizepolicy>
39 </property>
39 </property>
40 <layout class="QHBoxLayout" name="horizontalLayout">
40 <layout class="QHBoxLayout" name="horizontalLayout">
41 <property name="spacing">
41 <property name="spacing">
42 <number>0</number>
42 <number>0</number>
43 </property>
43 </property>
44 <property name="leftMargin">
44 <property name="leftMargin">
45 <number>0</number>
45 <number>0</number>
46 </property>
46 </property>
47 <property name="topMargin">
47 <property name="topMargin">
48 <number>0</number>
48 <number>0</number>
49 </property>
49 </property>
50 <property name="rightMargin">
50 <property name="rightMargin">
51 <number>0</number>
51 <number>0</number>
52 </property>
52 </property>
53 <property name="bottomMargin">
53 <property name="bottomMargin">
54 <number>0</number>
54 <number>0</number>
55 </property>
55 </property>
56 <item>
56 <item>
57 <widget class="QLabel" name="zoneNameLabel">
57 <widget class="QLabel" name="zoneNameLabel">
58 <property name="styleSheet">
58 <property name="styleSheet">
59 <string notr="true">color: rgb(127, 127, 127);
59 <string notr="true">color: rgb(127, 127, 127);
60 </string>
60 </string>
61 </property>
61 </property>
62 <property name="text">
62 <property name="text">
63 <string>TextLabel</string>
63 <string>TextLabel</string>
64 </property>
64 </property>
65 </widget>
65 </widget>
66 </item>
66 </item>
67 <item>
67 <item>
68 <widget class="QToolButton" name="closeButton">
68 <widget class="QToolButton" name="closeButton">
69 <property name="styleSheet">
69 <property name="styleSheet">
70 <string notr="true">background-color: transparent;</string>
70 <string notr="true">background-color: transparent;</string>
71 </property>
71 </property>
72 <property name="text">
72 <property name="text">
73 <string>Close</string>
73 <string>Close</string>
74 </property>
74 </property>
75 </widget>
75 </widget>
76 </item>
76 </item>
77 </layout>
77 </layout>
78 </widget>
78 </widget>
79 </item>
79 </item>
80 <item>
80 <item>
81 <widget class="QFrame" name="visualizationZoneFrame">
81 <widget class="QFrame" name="visualizationZoneFrame">
82 <property name="sizePolicy">
82 <property name="sizePolicy">
83 <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
83 <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
84 <horstretch>0</horstretch>
84 <horstretch>0</horstretch>
85 <verstretch>0</verstretch>
85 <verstretch>0</verstretch>
86 </sizepolicy>
86 </sizepolicy>
87 </property>
87 </property>
88 <property name="frameShape">
88 <property name="frameShape">
89 <enum>QFrame::Box</enum>
89 <enum>QFrame::Box</enum>
90 </property>
90 </property>
91 <property name="frameShadow">
91 <property name="frameShadow">
92 <enum>QFrame::Raised</enum>
92 <enum>QFrame::Raised</enum>
93 </property>
93 </property>
94 <property name="lineWidth">
94 <property name="lineWidth">
95 <number>1</number>
95 <number>1</number>
96 </property>
96 </property>
97 <layout class="QVBoxLayout" name="verticalLayout">
97 <layout class="QVBoxLayout" name="verticalLayout">
98 <property name="leftMargin">
98 <property name="leftMargin">
99 <number>0</number>
99 <number>0</number>
100 </property>
100 </property>
101 <property name="topMargin">
101 <property name="topMargin">
102 <number>0</number>
102 <number>0</number>
103 </property>
103 </property>
104 <property name="rightMargin">
104 <property name="rightMargin">
105 <number>0</number>
105 <number>0</number>
106 </property>
106 </property>
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 0
You need to be logged in to leave comments. Login now