##// END OF EJS Templates
Improves visual effect of dropping a variable in a graph
trabillard -
r879:5662e2f354c4
parent child
Show More
@@ -1,85 +1,87
1 #ifndef SCIQLOP_DRAGDROPHELPER_H
1 #ifndef SCIQLOP_DRAGDROPHELPER_H
2 #define SCIQLOP_DRAGDROPHELPER_H
2 #define SCIQLOP_DRAGDROPHELPER_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 #include <QLoggingCategory>
6 #include <QWidget>
6 #include <QWidget>
7
7
8 class QVBoxLayout;
8 class QVBoxLayout;
9 class QScrollArea;
9 class QScrollArea;
10 class VisualizationDragWidget;
10 class VisualizationDragWidget;
11 class VisualizationDragDropContainer;
11 class VisualizationDragDropContainer;
12 class QMimeData;
12 class QMimeData;
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_DragDropHelper)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_DragDropHelper)
15
15
16 /**
16 /**
17 * @brief Helper class for drag&drop operations.
17 * @brief Helper class for drag&drop operations.
18 * @note The helper is accessible from the sqpApp singleton and has the same life as the whole
18 * @note The helper is accessible from the sqpApp singleton and has the same life as the whole
19 * application (like a controller). But contrary to a controller, it doesn't live in a thread and
19 * application (like a controller). But contrary to a controller, it doesn't live in a thread and
20 * can interect with the gui.
20 * can interect with the gui.
21 * @see SqpApplication
21 * @see SqpApplication
22 */
22 */
23 class DragDropHelper {
23 class DragDropHelper {
24 public:
24 public:
25 static const QString MIME_TYPE_GRAPH;
25 static const QString MIME_TYPE_GRAPH;
26 static const QString MIME_TYPE_ZONE;
26 static const QString MIME_TYPE_ZONE;
27
27
28 DragDropHelper();
28 DragDropHelper();
29 virtual ~DragDropHelper();
29 virtual ~DragDropHelper();
30
30
31 /// Resets some internal variables. Must be called before any new drag&drop operation.
31 /// Resets some internal variables. Must be called before any new drag&drop operation.
32 void resetDragAndDrop();
32 void resetDragAndDrop();
33
33
34 /// Sets the visualization widget currently being drag on the visualization.
34 /// Sets the visualization widget currently being drag on the visualization.
35 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
35 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
36
36
37 /// Returns the visualization widget currently being drag on the visualization.
37 /// Returns the visualization widget currently being drag on the visualization.
38 /// Can be null if a new visualization widget is intended to be created by the drag&drop
38 /// Can be null if a new visualization widget is intended to be created by the drag&drop
39 /// operation.
39 /// operation.
40 VisualizationDragWidget *getCurrentDragWidget() const;
40 VisualizationDragWidget *getCurrentDragWidget() const;
41
41
42 QWidget &placeHolder() const;
42 QWidget &placeHolder() const;
43 void insertPlaceHolder(QVBoxLayout *layout, int index);
43 void insertPlaceHolder(QVBoxLayout *layout, int index);
44 void removePlaceHolder();
44 void removePlaceHolder();
45 bool isPlaceHolderSet() const;
45 bool isPlaceHolderSet() const;
46
46
47 /// Checks if the specified mime data is valid for a drop in the visualization
47 /// Checks if the specified mime data is valid for a drop in the visualization
48 bool checkMimeDataForVisualization(const QMimeData *mimeData,
48 bool checkMimeDataForVisualization(const QMimeData *mimeData,
49 VisualizationDragDropContainer *dropContainer);
49 VisualizationDragDropContainer *dropContainer);
50
50
51 void addDragDropScrollArea(QScrollArea *scrollArea);
51 void addDragDropScrollArea(QScrollArea *scrollArea);
52 void removeDragDropScrollArea(QScrollArea *scrollArea);
52 void removeDragDropScrollArea(QScrollArea *scrollArea);
53
53
54 QUrl imageTemporaryUrl(const QImage &image) const;
54 QUrl imageTemporaryUrl(const QImage &image) const;
55
55
56 void setHightlightedDragWidget(VisualizationDragWidget *dragWidget);
57
56 private:
58 private:
57 class DragDropHelperPrivate;
59 class DragDropHelperPrivate;
58 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
60 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
59 };
61 };
60
62
61 /**
63 /**
62 * @brief Event filter class which manage the scroll of QScrollArea during a drag&drop operation.
64 * @brief Event filter class which manage the scroll of QScrollArea during a drag&drop operation.
63 * @note A QScrollArea inside an other QScrollArea is not fully supported.
65 * @note A QScrollArea inside an other QScrollArea is not fully supported.
64 */
66 */
65 class DragDropScroller : public QObject {
67 class DragDropScroller : public QObject {
66 Q_OBJECT
68 Q_OBJECT
67
69
68 public:
70 public:
69 DragDropScroller(QObject *parent = nullptr);
71 DragDropScroller(QObject *parent = nullptr);
70
72
71 void addScrollArea(QScrollArea *scrollArea);
73 void addScrollArea(QScrollArea *scrollArea);
72 void removeScrollArea(QScrollArea *scrollArea);
74 void removeScrollArea(QScrollArea *scrollArea);
73
75
74 protected:
76 protected:
75 bool eventFilter(QObject *obj, QEvent *event);
77 bool eventFilter(QObject *obj, QEvent *event);
76
78
77 private:
79 private:
78 class DragDropScrollerPrivate;
80 class DragDropScrollerPrivate;
79 spimpl::unique_impl_ptr<DragDropScrollerPrivate> impl;
81 spimpl::unique_impl_ptr<DragDropScrollerPrivate> impl;
80
82
81 private slots:
83 private slots:
82 void onTimer();
84 void onTimer();
83 };
85 };
84
86
85 #endif // SCIQLOP_DRAGDROPHELPER_H
87 #endif // SCIQLOP_DRAGDROPHELPER_H
@@ -1,29 +1,30
1 #ifndef SCIQLOP_VISUALIZATIONDRAGWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONDRAGWIDGET_H
2 #define SCIQLOP_VISUALIZATIONDRAGWIDGET_H
2 #define SCIQLOP_VISUALIZATIONDRAGWIDGET_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QMimeData>
5 #include <QMimeData>
6 #include <QWidget>
6 #include <QWidget>
7
7
8 class VisualizationDragWidget : public QWidget {
8 class VisualizationDragWidget : public QWidget {
9 Q_OBJECT
9 Q_OBJECT
10
10
11 public:
11 public:
12 VisualizationDragWidget(QWidget *parent = nullptr);
12 VisualizationDragWidget(QWidget *parent = nullptr);
13
13
14 virtual QMimeData *mimeData() const = 0;
14 virtual QMimeData *mimeData() const = 0;
15 virtual bool isDragAllowed() const = 0;
15 virtual bool isDragAllowed() const = 0;
16 virtual void highlightForMerge(bool highlighted) { Q_UNUSED(highlighted); };
16
17
17 protected:
18 protected:
18 virtual void mousePressEvent(QMouseEvent *event) override;
19 virtual void mousePressEvent(QMouseEvent *event) override;
19 virtual void mouseMoveEvent(QMouseEvent *event) override;
20 virtual void mouseMoveEvent(QMouseEvent *event) override;
20
21
21 private:
22 private:
22 class VisualizationDragWidgetPrivate;
23 class VisualizationDragWidgetPrivate;
23 spimpl::unique_impl_ptr<VisualizationDragWidgetPrivate> impl;
24 spimpl::unique_impl_ptr<VisualizationDragWidgetPrivate> impl;
24
25
25 signals:
26 signals:
26 void dragDetected(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
27 void dragDetected(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
27 };
28 };
28
29
29 #endif // SCIQLOP_VISUALIZATIONDRAGWIDGET_H
30 #endif // SCIQLOP_VISUALIZATIONDRAGWIDGET_H
@@ -1,107 +1,108
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 #include "Visualization/VisualizationDragWidget.h"
6
6
7 #include <QLoggingCategory>
7 #include <QLoggingCategory>
8 #include <QWidget>
8 #include <QWidget>
9
9
10 #include <memory>
10 #include <memory>
11
11
12 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
15
15
16 class QCPRange;
16 class QCPRange;
17 class QCustomPlot;
17 class QCustomPlot;
18 class SqpRange;
18 class SqpRange;
19 class Variable;
19 class Variable;
20 class VisualizationZoneWidget;
20 class VisualizationZoneWidget;
21
21
22 namespace Ui {
22 namespace Ui {
23 class VisualizationGraphWidget;
23 class VisualizationGraphWidget;
24 } // namespace Ui
24 } // namespace Ui
25
25
26 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
26 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
27 Q_OBJECT
27 Q_OBJECT
28
28
29 friend class QCustomPlotSynchronizer;
29 friend class QCustomPlotSynchronizer;
30 friend class VisualizationGraphRenderingDelegate;
30 friend class VisualizationGraphRenderingDelegate;
31
31
32 public:
32 public:
33 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
33 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
34 virtual ~VisualizationGraphWidget();
34 virtual ~VisualizationGraphWidget();
35
35
36 VisualizationZoneWidget *parentZoneWidget() const noexcept;
36 VisualizationZoneWidget *parentZoneWidget() const noexcept;
37
37
38 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
38 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
39 void enableAcquisition(bool enable);
39 void enableAcquisition(bool enable);
40
40
41 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
41 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
42
42
43 /// Removes a variable from the graph
43 /// Removes a variable from the graph
44 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
44 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
45
45
46 /// Returns the list of all variables used in the graph
46 /// Returns the list of all variables used in the graph
47 QList<std::shared_ptr<Variable> > variables() const;
47 QList<std::shared_ptr<Variable> > variables() const;
48
48
49 void setYRange(const SqpRange &range);
49 void setYRange(const SqpRange &range);
50 SqpRange graphRange() const noexcept;
50 SqpRange graphRange() const noexcept;
51 void setGraphRange(const SqpRange &range);
51 void setGraphRange(const SqpRange &range);
52
52
53 // IVisualizationWidget interface
53 // IVisualizationWidget interface
54 void accept(IVisualizationWidgetVisitor *visitor) override;
54 void accept(IVisualizationWidgetVisitor *visitor) override;
55 bool canDrop(const Variable &variable) const override;
55 bool canDrop(const Variable &variable) const override;
56 bool contains(const Variable &variable) const override;
56 bool contains(const Variable &variable) const override;
57 QString name() const override;
57 QString name() const override;
58
58
59 // VisualisationDragWidget
59 // VisualisationDragWidget
60 QMimeData *mimeData() const override;
60 QMimeData *mimeData() const override;
61 bool isDragAllowed() const override;
61 bool isDragAllowed() const override;
62 void highlightForMerge(bool highlighted) override;
62
63
63 signals:
64 signals:
64 void synchronize(const SqpRange &range, const SqpRange &oldRange);
65 void synchronize(const SqpRange &range, const SqpRange &oldRange);
65 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
66 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
66 bool synchronise);
67 bool synchronise);
67
68
68 /// Signal emitted when the variable is about to be removed from the graph
69 /// Signal emitted when the variable is about to be removed from the graph
69 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
70 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
70 /// Signal emitted when the variable has been added to the graph
71 /// Signal emitted when the variable has been added to the graph
71 void variableAdded(std::shared_ptr<Variable> var);
72 void variableAdded(std::shared_ptr<Variable> var);
72
73
73 protected:
74 protected:
74 void closeEvent(QCloseEvent *event) override;
75 void closeEvent(QCloseEvent *event) override;
75 void enterEvent(QEvent *event) override;
76 void enterEvent(QEvent *event) override;
76 void leaveEvent(QEvent *event) override;
77 void leaveEvent(QEvent *event) override;
77
78
78 QCustomPlot &plot() noexcept;
79 QCustomPlot &plot() noexcept;
79
80
80 private:
81 private:
81 Ui::VisualizationGraphWidget *ui;
82 Ui::VisualizationGraphWidget *ui;
82
83
83 class VisualizationGraphWidgetPrivate;
84 class VisualizationGraphWidgetPrivate;
84 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
85 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
85
86
86 private slots:
87 private slots:
87 /// Slot called when right clicking on the graph (displays a menu)
88 /// Slot called when right clicking on the graph (displays a menu)
88 void onGraphMenuRequested(const QPoint &pos) noexcept;
89 void onGraphMenuRequested(const QPoint &pos) noexcept;
89
90
90 /// Rescale the X axe to range parameter
91 /// Rescale the X axe to range parameter
91 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
92 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
92
93
93 /// Slot called when a mouse move was made
94 /// Slot called when a mouse move was made
94 void onMouseMove(QMouseEvent *event) noexcept;
95 void onMouseMove(QMouseEvent *event) noexcept;
95 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
96 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
96 void onMouseWheel(QWheelEvent *event) noexcept;
97 void onMouseWheel(QWheelEvent *event) noexcept;
97 /// Slot called when a mouse press was made, to activate the calibration of a graph
98 /// Slot called when a mouse press was made, to activate the calibration of a graph
98 void onMousePress(QMouseEvent *event) noexcept;
99 void onMousePress(QMouseEvent *event) noexcept;
99 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
100 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
100 void onMouseRelease(QMouseEvent *event) noexcept;
101 void onMouseRelease(QMouseEvent *event) noexcept;
101
102
102 void onDataCacheVariableUpdated();
103 void onDataCacheVariableUpdated();
103
104
104 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
105 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
105 };
106 };
106
107
107 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
108 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,295 +1,309
1 #include "DragDropHelper.h"
1 #include "DragDropHelper.h"
2 #include "SqpApplication.h"
2 #include "SqpApplication.h"
3 #include "Visualization/VisualizationDragDropContainer.h"
3 #include "Visualization/VisualizationDragDropContainer.h"
4 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5 #include "Visualization/VisualizationWidget.h"
5 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/operations/FindVariableOperation.h"
6 #include "Visualization/operations/FindVariableOperation.h"
7
7
8 #include "Variable/VariableController.h"
8 #include "Variable/VariableController.h"
9
9
10 #include "Common/MimeTypesDef.h"
10 #include "Common/MimeTypesDef.h"
11 #include "Common/VisualizationDef.h"
11 #include "Common/VisualizationDef.h"
12
12
13 #include <QDir>
13 #include <QDir>
14 #include <QDragEnterEvent>
14 #include <QDragEnterEvent>
15 #include <QDragMoveEvent>
15 #include <QDragMoveEvent>
16 #include <QScrollArea>
16 #include <QScrollArea>
17 #include <QScrollBar>
17 #include <QScrollBar>
18 #include <QTimer>
18 #include <QTimer>
19 #include <QVBoxLayout>
19 #include <QVBoxLayout>
20
20
21 const int SCROLL_SPEED = 5;
21 const int SCROLL_SPEED = 5;
22 const int SCROLL_ZONE_SIZE = 50;
22 const int SCROLL_ZONE_SIZE = 50;
23
23
24 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDrophelper")
24 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDrophelper")
25
25
26 struct DragDropScroller::DragDropScrollerPrivate {
26 struct DragDropScroller::DragDropScrollerPrivate {
27
27
28 QList<QScrollArea *> m_ScrollAreas;
28 QList<QScrollArea *> m_ScrollAreas;
29 QScrollArea *m_CurrentScrollArea = nullptr;
29 QScrollArea *m_CurrentScrollArea = nullptr;
30 std::unique_ptr<QTimer> m_Timer = nullptr;
30 std::unique_ptr<QTimer> m_Timer = nullptr;
31
31
32
33 enum class ScrollDirection { up, down, unknown };
32 enum class ScrollDirection { up, down, unknown };
34 ScrollDirection m_Direction = ScrollDirection::unknown;
33 ScrollDirection m_Direction = ScrollDirection::unknown;
35
34
36 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
35 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
37 {
36 {
38 m_Timer->setInterval(0);
37 m_Timer->setInterval(0);
39 }
38 }
40 };
39 };
41
40
42 DragDropScroller::DragDropScroller(QObject *parent)
41 DragDropScroller::DragDropScroller(QObject *parent)
43 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
42 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
44 {
43 {
45 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
44 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
46 }
45 }
47
46
48 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
47 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
49 {
48 {
50 impl->m_ScrollAreas << scrollArea;
49 impl->m_ScrollAreas << scrollArea;
51 scrollArea->viewport()->setAcceptDrops(true);
50 scrollArea->viewport()->setAcceptDrops(true);
52 }
51 }
53
52
54 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
53 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
55 {
54 {
56 impl->m_ScrollAreas.removeAll(scrollArea);
55 impl->m_ScrollAreas.removeAll(scrollArea);
57 scrollArea->viewport()->setAcceptDrops(false);
56 scrollArea->viewport()->setAcceptDrops(false);
58 }
57 }
59
58
60 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
59 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
61 {
60 {
62 if (event->type() == QEvent::DragMove) {
61 if (event->type() == QEvent::DragMove) {
63 auto w = static_cast<QWidget *>(obj);
62 auto w = static_cast<QWidget *>(obj);
64
63
65 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
64 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
66 auto moveEvent = static_cast<QDragMoveEvent *>(event);
65 auto moveEvent = static_cast<QDragMoveEvent *>(event);
67
66
68 auto pos = moveEvent->pos();
67 auto pos = moveEvent->pos();
69 if (impl->m_CurrentScrollArea->viewport() != w) {
68 if (impl->m_CurrentScrollArea->viewport() != w) {
70 auto globalPos = w->mapToGlobal(moveEvent->pos());
69 auto globalPos = w->mapToGlobal(moveEvent->pos());
71 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
70 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
72 }
71 }
73
72
74 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
73 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
75 - SCROLL_ZONE_SIZE;
74 - SCROLL_ZONE_SIZE;
76 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
75 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
77
76
78 if (!isInTopZone && !isInBottomZone) {
77 if (!isInTopZone && !isInBottomZone) {
79 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
78 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
80 impl->m_Timer->stop();
79 impl->m_Timer->stop();
81 }
80 }
82 else if (!impl->m_Timer->isActive()) {
81 else if (!impl->m_Timer->isActive()) {
83 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
82 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
84 : DragDropScrollerPrivate::ScrollDirection::down;
83 : DragDropScrollerPrivate::ScrollDirection::down;
85 impl->m_Timer->start();
84 impl->m_Timer->start();
86 }
85 }
87 }
86 }
88 }
87 }
89 else if (event->type() == QEvent::DragEnter) {
88 else if (event->type() == QEvent::DragEnter) {
90 auto w = static_cast<QWidget *>(obj);
89 auto w = static_cast<QWidget *>(obj);
91
90
92 for (auto scrollArea : impl->m_ScrollAreas) {
91 for (auto scrollArea : impl->m_ScrollAreas) {
93 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
92 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
94 auto enterEvent = static_cast<QDragEnterEvent *>(event);
93 auto enterEvent = static_cast<QDragEnterEvent *>(event);
95 enterEvent->acceptProposedAction();
94 enterEvent->acceptProposedAction();
96 enterEvent->setDropAction(Qt::IgnoreAction);
95 enterEvent->setDropAction(Qt::IgnoreAction);
97 impl->m_CurrentScrollArea = scrollArea;
96 impl->m_CurrentScrollArea = scrollArea;
98 break;
97 break;
99 }
98 }
100 }
99 }
101 }
100 }
102 else if (event->type() == QEvent::DragLeave) {
101 else if (event->type() == QEvent::DragLeave) {
103 if (impl->m_CurrentScrollArea) {
102 if (impl->m_CurrentScrollArea) {
104 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
103 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
105 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
104 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
106 impl->m_CurrentScrollArea = nullptr;
105 impl->m_CurrentScrollArea = nullptr;
107 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
106 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
108 impl->m_Timer->stop();
107 impl->m_Timer->stop();
109 }
108 }
110 }
109 }
111 }
110 }
112 else if (event->type() == QEvent::Drop) {
111 else if (event->type() == QEvent::Drop) {
113 if (impl->m_CurrentScrollArea) {
112 if (impl->m_CurrentScrollArea) {
114 impl->m_CurrentScrollArea = nullptr;
113 impl->m_CurrentScrollArea = nullptr;
115 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
114 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
116 impl->m_Timer->stop();
115 impl->m_Timer->stop();
117 }
116 }
118 }
117 }
119
118
120 return false;
119 return false;
121 }
120 }
122
121
123 void DragDropScroller::onTimer()
122 void DragDropScroller::onTimer()
124 {
123 {
125 if (impl->m_CurrentScrollArea) {
124 if (impl->m_CurrentScrollArea) {
126 auto mvt = 0;
125 auto mvt = 0;
127 switch (impl->m_Direction) {
126 switch (impl->m_Direction) {
128 case DragDropScrollerPrivate::ScrollDirection::up:
127 case DragDropScrollerPrivate::ScrollDirection::up:
129 mvt = SCROLL_SPEED;
128 mvt = SCROLL_SPEED;
130 break;
129 break;
131 case DragDropScrollerPrivate::ScrollDirection::down:
130 case DragDropScrollerPrivate::ScrollDirection::down:
132 mvt = -SCROLL_SPEED;
131 mvt = -SCROLL_SPEED;
133 break;
132 break;
134 default:
133 default:
135 break;
134 break;
136 }
135 }
137
136
138 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
137 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
139 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
138 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
140 }
139 }
141 }
140 }
142
141
143 struct DragDropHelper::DragDropHelperPrivate {
142 struct DragDropHelper::DragDropHelperPrivate {
144
143
145 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
144 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
146 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
145 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
147 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
146 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
148 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
147 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
149 // QTemporaryFile to have a name which is not generated.
148 // QTemporaryFile to have a name which is not generated.
150
149
150 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
151
151 explicit DragDropHelperPrivate()
152 explicit DragDropHelperPrivate()
152 : m_PlaceHolder{std::make_unique<QWidget>()},
153 : m_PlaceHolder{std::make_unique<QWidget>()},
153 m_DragDropScroller{std::make_unique<DragDropScroller>()}
154 m_DragDropScroller{std::make_unique<DragDropScroller>()}
154 {
155 {
155 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
156 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
156 sqpApp->installEventFilter(m_DragDropScroller.get());
157 sqpApp->installEventFilter(m_DragDropScroller.get());
157
158
158
159
159 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
160 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
160 }
161 }
161
162
162 void preparePlaceHolder() const
163 void preparePlaceHolder() const
163 {
164 {
164 if (m_CurrentDragWidget) {
165 if (m_CurrentDragWidget) {
165 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
166 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
166 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
167 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
167 }
168 }
168 else {
169 else {
169 // Configuration of the placeHolder when there is no dragWidget
170 // Configuration of the placeHolder when there is no dragWidget
170 // (for instance with a drag from a variable)
171 // (for instance with a drag from a variable)
171
172
172 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
173 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
173 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
174 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
174 }
175 }
175 }
176 }
176 };
177 };
177
178
178
179
179 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
180 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
180 {
181 {
181 }
182 }
182
183
183 DragDropHelper::~DragDropHelper()
184 DragDropHelper::~DragDropHelper()
184 {
185 {
185 QFile::remove(impl->m_ImageTempUrl);
186 QFile::remove(impl->m_ImageTempUrl);
186 }
187 }
187
188
188 void DragDropHelper::resetDragAndDrop()
189 void DragDropHelper::resetDragAndDrop()
189 {
190 {
190 setCurrentDragWidget(nullptr);
191 setCurrentDragWidget(nullptr);
192 impl->m_HighlightedDragWidget = nullptr;
191 }
193 }
192
194
193 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
195 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
194 {
196 {
195 impl->m_CurrentDragWidget = dragWidget;
197 impl->m_CurrentDragWidget = dragWidget;
196 }
198 }
197
199
198 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
200 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
199 {
201 {
200 return impl->m_CurrentDragWidget;
202 return impl->m_CurrentDragWidget;
201 }
203 }
202
204
203
205
204 QWidget &DragDropHelper::placeHolder() const
206 QWidget &DragDropHelper::placeHolder() const
205 {
207 {
206 return *impl->m_PlaceHolder;
208 return *impl->m_PlaceHolder;
207 }
209 }
208
210
209 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
211 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
210 {
212 {
211 removePlaceHolder();
213 removePlaceHolder();
212 impl->preparePlaceHolder();
214 impl->preparePlaceHolder();
213 layout->insertWidget(index, impl->m_PlaceHolder.get());
215 layout->insertWidget(index, impl->m_PlaceHolder.get());
214 impl->m_PlaceHolder->show();
216 impl->m_PlaceHolder->show();
215 }
217 }
216
218
217 void DragDropHelper::removePlaceHolder()
219 void DragDropHelper::removePlaceHolder()
218 {
220 {
219 auto parentWidget = impl->m_PlaceHolder->parentWidget();
221 auto parentWidget = impl->m_PlaceHolder->parentWidget();
220 if (parentWidget) {
222 if (parentWidget) {
221 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
223 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
222 impl->m_PlaceHolder->setParent(nullptr);
224 impl->m_PlaceHolder->setParent(nullptr);
223 impl->m_PlaceHolder->hide();
225 impl->m_PlaceHolder->hide();
224 }
226 }
225 }
227 }
226
228
227 bool DragDropHelper::isPlaceHolderSet() const
229 bool DragDropHelper::isPlaceHolderSet() const
228 {
230 {
229 return impl->m_PlaceHolder->parentWidget();
231 return impl->m_PlaceHolder->parentWidget();
230 }
232 }
231
233
232 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
234 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
233 {
235 {
234 impl->m_DragDropScroller->addScrollArea(scrollArea);
236 impl->m_DragDropScroller->addScrollArea(scrollArea);
235 }
237 }
236
238
237 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
239 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
238 {
240 {
239 impl->m_DragDropScroller->removeScrollArea(scrollArea);
241 impl->m_DragDropScroller->removeScrollArea(scrollArea);
240 }
242 }
241
243
242 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
244 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
243 {
245 {
244 image.save(impl->m_ImageTempUrl);
246 image.save(impl->m_ImageTempUrl);
245 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
247 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
246 }
248 }
247
249
250 void DragDropHelper::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
251 {
252 if (impl->m_HighlightedDragWidget) {
253 impl->m_HighlightedDragWidget->highlightForMerge(false);
254 }
255
256 if (dragWidget) {
257 impl->m_HighlightedDragWidget = dragWidget;
258 impl->m_HighlightedDragWidget->highlightForMerge(true);
259 }
260 }
261
248 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
262 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
249 VisualizationDragDropContainer *dropContainer)
263 VisualizationDragDropContainer *dropContainer)
250 {
264 {
251 if (!mimeData || !dropContainer) {
265 if (!mimeData || !dropContainer) {
252 qCWarning(LOG_DragDropHelper()) << QObject::tr(
266 qCWarning(LOG_DragDropHelper()) << QObject::tr(
253 "DragDropHelper::checkMimeDataForVisualization, invalid input parameters.");
267 "DragDropHelper::checkMimeDataForVisualization, invalid input parameters.");
254 Q_ASSERT(false);
268 Q_ASSERT(false);
255 }
269 }
256
270
257 auto result = true;
271 auto result = true;
258
272
259 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
273 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
260 auto variables = sqpApp->variableController().variablesForMimeData(
274 auto variables = sqpApp->variableController().variablesForMimeData(
261 mimeData->data(MIME_TYPE_VARIABLE_LIST));
275 mimeData->data(MIME_TYPE_VARIABLE_LIST));
262
276
263 if (variables.count() == 1) {
277 if (variables.count() == 1) {
264 // Check that the viariable is not already in a graph
278 // Check that the viariable is not already in a graph
265
279
266 // Search for the top level VisualizationWidget
280 // Search for the top level VisualizationWidget
267 auto parent = dropContainer->parentWidget();
281 auto parent = dropContainer->parentWidget();
268 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
282 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
269 parent = parent->parentWidget();
283 parent = parent->parentWidget();
270 }
284 }
271
285
272 if (parent) {
286 if (parent) {
273 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
287 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
274
288
275 FindVariableOperation findVariableOperation{variables.first()};
289 FindVariableOperation findVariableOperation{variables.first()};
276 visualizationWidget->accept(&findVariableOperation);
290 visualizationWidget->accept(&findVariableOperation);
277 auto variableContainers = findVariableOperation.result();
291 auto variableContainers = findVariableOperation.result();
278 if (!variableContainers.empty()) {
292 if (!variableContainers.empty()) {
279 result = false;
293 result = false;
280 }
294 }
281 }
295 }
282 else {
296 else {
283 qCWarning(LOG_DragDropHelper()) << QObject::tr(
297 qCWarning(LOG_DragDropHelper()) << QObject::tr(
284 "DragDropHelper::checkMimeDataForVisualization, the parent "
298 "DragDropHelper::checkMimeDataForVisualization, the parent "
285 "VisualizationWidget cannot be found.");
299 "VisualizationWidget cannot be found.");
286 result = false;
300 result = false;
287 }
301 }
288 }
302 }
289 else {
303 else {
290 result = false;
304 result = false;
291 }
305 }
292 }
306 }
293
307
294 return result;
308 return result;
295 }
309 }
@@ -1,362 +1,380
1 #include "Visualization/VisualizationDragDropContainer.h"
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragDropHelper.h"
2 #include "DragDropHelper.h"
3 #include "SqpApplication.h"
3 #include "SqpApplication.h"
4 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5
5
6 #include "Common/VisualizationDef.h"
6 #include "Common/VisualizationDef.h"
7
7
8 #include <QDrag>
8 #include <QDrag>
9 #include <QDragEnterEvent>
9 #include <QDragEnterEvent>
10 #include <QVBoxLayout>
10 #include <QVBoxLayout>
11
11
12 #include <cmath>
12 #include <cmath>
13 #include <memory>
13 #include <memory>
14
14
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
16
16
17 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
17 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
18
18
19 QVBoxLayout *m_Layout;
19 QVBoxLayout *m_Layout;
20 QStringList m_AcceptedMimeTypes;
20 QStringList m_AcceptedMimeTypes;
21 QStringList m_MergeAllowedMimeTypes;
21 QStringList m_MergeAllowedMimeTypes;
22 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
22 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
23 = [](auto mimeData) { return true; };
23 = [](auto mimeData) { return true; };
24 int m_MinContainerHeight = 0;
24
25
25 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
26 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
26 {
27 {
27 m_Layout = new QVBoxLayout(widget);
28 m_Layout = new QVBoxLayout(widget);
28 m_Layout->setContentsMargins(0, 0, 0, 0);
29 m_Layout->setContentsMargins(0, 0, 0, 0);
29 }
30 }
30
31
31 bool acceptMimeData(const QMimeData *data) const
32 bool acceptMimeData(const QMimeData *data) const
32 {
33 {
33 for (const auto &type : m_AcceptedMimeTypes) {
34 for (const auto &type : m_AcceptedMimeTypes) {
34 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
35 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
35 return true;
36 return true;
36 }
37 }
37 }
38 }
38
39
39 return false;
40 return false;
40 }
41 }
41
42
42 bool allowMergeMimeData(const QMimeData *data) const
43 bool allowMergeMimeData(const QMimeData *data) const
43 {
44 {
44 for (const auto &type : m_MergeAllowedMimeTypes) {
45 for (const auto &type : m_MergeAllowedMimeTypes) {
45 if (data->hasFormat(type)) {
46 if (data->hasFormat(type)) {
46 return true;
47 return true;
47 }
48 }
48 }
49 }
49
50
50 return false;
51 return false;
51 }
52 }
52
53
53 bool hasPlaceHolder() const
54 bool hasPlaceHolder() const
54 {
55 {
55 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
56 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
56 }
57 }
57
58
58 VisualizationDragWidget *getChildDragWidgetAt(QWidget *parent, const QPoint &pos) const
59 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
59 {
60 {
60 VisualizationDragWidget *dragWidget = nullptr;
61 VisualizationDragWidget *dragWidget = nullptr;
61
62
62 for (auto child : parent->children()) {
63 for (auto child : parent->children()) {
63 auto widget = qobject_cast<VisualizationDragWidget *>(child);
64 auto widget = qobject_cast<VisualizationDragWidget *>(child);
64 if (widget && widget->isVisible()) {
65 if (widget && widget->isVisible()) {
65 if (widget->frameGeometry().contains(pos)) {
66 if (widget->frameGeometry().contains(pos)) {
66 dragWidget = widget;
67 dragWidget = widget;
67 break;
68 break;
68 }
69 }
69 }
70 }
70 }
71 }
71
72
72 return dragWidget;
73 return dragWidget;
73 }
74 }
74
75
75 bool cursorIsInContainer(QWidget *container) const
76 bool cursorIsInContainer(QWidget *container) const
76 {
77 {
77 auto adustNum = 18; // to be safe, in case of scrollbar on the side
78 auto adustNum = 18; // to be safe, in case of scrollbar on the side
78 auto containerRect = QRect(QPoint(), container->contentsRect().size())
79 auto containerRect = QRect(QPoint(), container->contentsRect().size())
79 .adjusted(adustNum, adustNum, -adustNum, -adustNum);
80 .adjusted(adustNum, adustNum, -adustNum, -adustNum);
80 return containerRect.contains(container->mapFromGlobal(QCursor::pos()));
81 return containerRect.contains(container->mapFromGlobal(QCursor::pos()));
81 }
82 }
83
84 int countDragWidget(const QWidget *parent) const
85 {
86 auto nbGraph = 0;
87 for (auto child : parent->children()) {
88 if (qobject_cast<VisualizationDragWidget *>(child)) {
89 nbGraph += 1;
90 }
91 }
92
93 return nbGraph;
94 }
95
96 void findPlaceHolderPosition(const QPoint &pos, bool canMerge,
97 const VisualizationDragDropContainer *container);
82 };
98 };
83
99
84 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
100 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
85 : QWidget{parent},
101 : QWidget{parent},
86 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
102 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
87 {
103 {
88 setAcceptDrops(true);
104 setAcceptDrops(true);
89 }
105 }
90
106
91 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
107 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
92 {
108 {
93 impl->m_Layout->addWidget(dragWidget);
109 impl->m_Layout->addWidget(dragWidget);
94 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
110 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
95 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
111 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
96 &VisualizationDragDropContainer::startDrag);
112 &VisualizationDragDropContainer::startDrag);
97 }
113 }
98
114
99 void VisualizationDragDropContainer::insertDragWidget(int index,
115 void VisualizationDragDropContainer::insertDragWidget(int index,
100 VisualizationDragWidget *dragWidget)
116 VisualizationDragWidget *dragWidget)
101 {
117 {
102 impl->m_Layout->insertWidget(index, dragWidget);
118 impl->m_Layout->insertWidget(index, dragWidget);
103 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
119 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
104 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
120 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
105 &VisualizationDragDropContainer::startDrag);
121 &VisualizationDragDropContainer::startDrag);
106 }
122 }
107
123
108 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
124 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
109 {
125 {
110 impl->m_AcceptedMimeTypes = mimeTypes;
126 impl->m_AcceptedMimeTypes = mimeTypes;
111 }
127 }
112
128
113 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
129 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
114 {
130 {
115 impl->m_MergeAllowedMimeTypes = mimeTypes;
131 impl->m_MergeAllowedMimeTypes = mimeTypes;
116 }
132 }
117
133
118 int VisualizationDragDropContainer::countDragWidget() const
134 int VisualizationDragDropContainer::countDragWidget() const
119 {
135 {
120 auto nbGraph = 0;
136 return impl->countDragWidget(this);
121 for (auto child : children()) {
122 if (qobject_cast<VisualizationDragWidget *>(child)) {
123 nbGraph += 1;
124 }
125 }
126
127 return nbGraph;
128 }
137 }
129
138
130 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
139 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
131 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
140 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
132 {
141 {
133 impl->m_AcceptMimeDataFun = fun;
142 impl->m_AcceptMimeDataFun = fun;
134 }
143 }
135
144
136 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
145 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
137 const QPoint &dragPosition)
146 const QPoint &dragPosition)
138 {
147 {
139 auto &helper = sqpApp->dragDropHelper();
148 auto &helper = sqpApp->dragDropHelper();
140 helper.resetDragAndDrop();
149 helper.resetDragAndDrop();
141
150
142 // Note: The management of the drag object is done by Qt
151 // Note: The management of the drag object is done by Qt
143 auto drag = new QDrag{dragWidget};
152 auto drag = new QDrag{dragWidget};
144 drag->setHotSpot(dragPosition);
153 drag->setHotSpot(dragPosition);
145
154
146 auto mimeData = dragWidget->mimeData();
155 auto mimeData = dragWidget->mimeData();
147 drag->setMimeData(mimeData);
156 drag->setMimeData(mimeData);
148
157
149 auto pixmap = QPixmap(dragWidget->size());
158 auto pixmap = QPixmap(dragWidget->size());
150 dragWidget->render(&pixmap);
159 dragWidget->render(&pixmap);
151 drag->setPixmap(pixmap);
160 drag->setPixmap(pixmap);
152
161
153 auto image = pixmap.toImage();
162 auto image = pixmap.toImage();
154 mimeData->setImageData(image);
163 mimeData->setImageData(image);
155 mimeData->setUrls({helper.imageTemporaryUrl(image)});
164 mimeData->setUrls({helper.imageTemporaryUrl(image)});
156
165
157 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
166 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
158 helper.setCurrentDragWidget(dragWidget);
167 helper.setCurrentDragWidget(dragWidget);
159
168
160 if (impl->cursorIsInContainer(this)) {
169 if (impl->cursorIsInContainer(this)) {
161 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
170 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
162 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
171 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
163 dragWidget->setVisible(false);
172 dragWidget->setVisible(false);
164 }
173 }
165
174
166 // Note: The exec() is blocking on windows but not on linux and macOS
175 // Note: The exec() is blocking on windows but not on linux and macOS
167 drag->exec(Qt::MoveAction | Qt::CopyAction);
176 drag->exec(Qt::MoveAction | Qt::CopyAction);
168 }
177 }
169 else {
178 else {
170 qCWarning(LOG_VisualizationDragDropContainer())
179 qCWarning(LOG_VisualizationDragDropContainer())
171 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
180 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
172 "VisualizationDragWidget is not found in this container.");
181 "VisualizationDragWidget is not found in this container.");
173 }
182 }
174 }
183 }
175
184
176 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
185 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
177 {
186 {
178 if (impl->acceptMimeData(event->mimeData())) {
187 if (impl->acceptMimeData(event->mimeData())) {
179 event->acceptProposedAction();
188 event->acceptProposedAction();
180
189
181 auto &helper = sqpApp->dragDropHelper();
190 auto &helper = sqpApp->dragDropHelper();
182
191
183 if (!impl->hasPlaceHolder()) {
192 if (!impl->hasPlaceHolder()) {
184 auto dragWidget = helper.getCurrentDragWidget();
193 auto dragWidget = helper.getCurrentDragWidget();
185
194
186 if (dragWidget) {
195 if (dragWidget) {
187 // If the drag&drop is internal to the visualization, entering the container hide
196 // If the drag&drop is internal to the visualization, entering the container hide
188 // the dragWidget which was hidden by the dragLeaveEvent
197 // the dragWidget which was made visible by the dragLeaveEvent
189 auto parentWidget
198 auto parentWidget
190 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
199 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
191 if (parentWidget) {
200 if (parentWidget) {
192 dragWidget->setVisible(false);
201 dragWidget->setVisible(false);
193 }
202 }
194 }
203 }
195
204
196 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
205 auto canMerge = impl->allowMergeMimeData(event->mimeData());
197
206 impl->findPlaceHolderPosition(event->pos(), canMerge, this);
198 if (dragWidgetHovered) {
199 auto hoveredWidgetIndex = impl->m_Layout->indexOf(dragWidgetHovered);
200
201 if (dragWidget) {
202 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
203 if (dragWidgetIndex >= 0 && dragWidgetIndex <= hoveredWidgetIndex) {
204 // Correction of the index if the drop occurs in the same container
205 // and if the drag is started from the visualization (in that case, the
206 // dragWidget is hidden)
207 hoveredWidgetIndex += 1;
208 }
209 }
210
211 helper.insertPlaceHolder(impl->m_Layout, hoveredWidgetIndex);
212 }
213 else {
214 helper.insertPlaceHolder(impl->m_Layout, 0);
215 }
216 }
207 }
217 else {
208 else {
218 // do nothing
209 // do nothing
219 }
210 }
220 }
211 }
221 else {
212 else {
222 event->ignore();
213 event->ignore();
223 }
214 }
224
215
225 QWidget::dragEnterEvent(event);
216 QWidget::dragEnterEvent(event);
226 }
217 }
227
218
228 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
219 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
229 {
220 {
230 Q_UNUSED(event);
221 Q_UNUSED(event);
231
222
232 auto &helper = sqpApp->dragDropHelper();
223 auto &helper = sqpApp->dragDropHelper();
233
224
234 if (!impl->cursorIsInContainer(this)) {
225 if (!impl->cursorIsInContainer(this)) {
235 helper.removePlaceHolder();
226 helper.removePlaceHolder();
227 helper.setHightlightedDragWidget(nullptr);
228 impl->m_MinContainerHeight = 0;
236
229
237 auto dragWidget = helper.getCurrentDragWidget();
230 auto dragWidget = helper.getCurrentDragWidget();
238 if (dragWidget) {
231 if (dragWidget) {
239 // dragWidget has a value only if the drag is started from the visualization
232 // dragWidget has a value only if the drag is started from the visualization
240 // In that case, shows the drag widget at its original place
233 // In that case, shows the drag widget at its original place
241 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
234 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
242 // drop zone (It is not possible to catch a drop event outside of the application)
235 // drop zone (It is not possible to catch a drop event outside of the application)
243
236
244 if (dragWidget) {
237 if (dragWidget) {
245 dragWidget->setVisible(true);
238 dragWidget->setVisible(true);
246 }
239 }
247 }
240 }
248 }
241 }
249 else {
242 else {
250 // Leave event probably received for a child widget.
243 // Leave event probably received for a child widget.
251 // Do nothing.
244 // Do nothing.
252 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
245 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
253 }
246 }
254
247
255 QWidget::dragLeaveEvent(event);
248 QWidget::dragLeaveEvent(event);
256 }
249 }
257
250
258 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
251 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
259 {
252 {
260 if (impl->acceptMimeData(event->mimeData())) {
253 if (impl->acceptMimeData(event->mimeData())) {
261 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
254 auto canMerge = impl->allowMergeMimeData(event->mimeData());
262 if (dragWidgetHovered) {
255 impl->findPlaceHolderPosition(event->pos(), canMerge, this);
263 auto canMerge = impl->allowMergeMimeData(event->mimeData());
264
265 auto nbDragWidget = countDragWidget();
266 if (nbDragWidget > 0) {
267 auto graphHeight = qMax(size().height() / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
268
269 auto dropIndex = floor(event->pos().y() / graphHeight);
270 auto zoneSize = qMin(graphHeight / 3.0, 150.0);
271
272 auto isOnTop = event->pos().y() < dropIndex * graphHeight + zoneSize;
273 auto isOnBottom = event->pos().y() > (dropIndex + 1) * graphHeight - zoneSize;
274
275 auto &helper = sqpApp->dragDropHelper();
276 auto placeHolderIndex = impl->m_Layout->indexOf(&(helper.placeHolder()));
277
278 if (isOnTop || isOnBottom) {
279 if (isOnBottom) {
280 dropIndex += 1;
281 }
282
283 if (helper.getCurrentDragWidget()) {
284 auto dragWidgetIndex
285 = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
286 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
287 // Correction of the index if the drop occurs in the same container
288 // and if the drag is started from the visualization (in that case, the
289 // dragWidget is hidden)
290 dropIndex += 1;
291 }
292 }
293
294 if (dropIndex != placeHolderIndex) {
295 helper.insertPlaceHolder(impl->m_Layout, dropIndex);
296 }
297 }
298 else if (canMerge) {
299 // drop on the middle -> merge
300 if (impl->hasPlaceHolder()) {
301 helper.removePlaceHolder();
302 }
303 }
304 }
305 else {
306 qCWarning(LOG_VisualizationDragDropContainer())
307 << tr("VisualizationDragDropContainer::dragMoveEvent, no widget found in the "
308 "container");
309 }
310 }
311 else {
312 // No hovered drag widget, the mouse is probably hover the placeHolder
313 // Do nothing
314 }
315 }
256 }
316 else {
257 else {
317 event->ignore();
258 event->ignore();
318 }
259 }
319
260
320 QWidget::dragMoveEvent(event);
261 QWidget::dragMoveEvent(event);
321 }
262 }
322
263
323 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
264 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
324 {
265 {
325 if (impl->acceptMimeData(event->mimeData())) {
266 if (impl->acceptMimeData(event->mimeData())) {
326 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
267 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
327 if (impl->hasPlaceHolder()) {
268 if (impl->hasPlaceHolder()) {
328 auto &helper = sqpApp->dragDropHelper();
269 auto &helper = sqpApp->dragDropHelper();
329
270
330 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
271 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
331
272
332 if (dragWidget) {
273 if (dragWidget) {
333 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
274 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
334 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
275 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
335 // Correction of the index if the drop occurs in the same container
276 // Correction of the index if the drop occurs in the same container
336 // and if the drag is started from the visualization (in that case, the
277 // and if the drag is started from the visualization (in that case, the
337 // dragWidget is hidden)
278 // dragWidget is hidden)
338 droppedIndex -= 1;
279 droppedIndex -= 1;
339 }
280 }
340
281
341 dragWidget->setVisible(true);
282 dragWidget->setVisible(true);
342 }
283 }
343
284
344 event->acceptProposedAction();
285 event->acceptProposedAction();
345
286
346 helper.removePlaceHolder();
287 helper.removePlaceHolder();
347
288
348 emit dropOccured(droppedIndex, event->mimeData());
289 emit dropOccured(droppedIndex, event->mimeData());
349 }
290 }
350 else {
291 else {
351 qCWarning(LOG_VisualizationDragDropContainer())
292 qCWarning(LOG_VisualizationDragDropContainer())
352 << tr("VisualizationDragDropContainer::dropEvent, couldn't drop because the "
293 << tr("VisualizationDragDropContainer::dropEvent, couldn't drop because the "
353 "placeHolder is not found.");
294 "placeHolder is not found.");
354 Q_ASSERT(false);
295 // Q_ASSERT(false);
355 }
296 }
356 }
297 }
357 else {
298 else {
358 event->ignore();
299 event->ignore();
359 }
300 }
360
301
302 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
303 impl->m_MinContainerHeight = 0;
304
361 QWidget::dropEvent(event);
305 QWidget::dropEvent(event);
362 }
306 }
307
308
309 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
310 const QPoint &pos, bool canMerge, const VisualizationDragDropContainer *container)
311 {
312 auto &helper = sqpApp->dragDropHelper();
313
314 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
315 if (dragWidgetHovered) {
316 auto nbDragWidget = countDragWidget(container);
317 if (nbDragWidget > 0) {
318
319 if (m_MinContainerHeight == 0) {
320 m_MinContainerHeight = container->size().height();
321 }
322
323 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
324 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
325
326 auto posY = pos.y();
327 auto dropIndex = floor(posY / graphHeight);
328 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
329
330
331 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
332 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
333
334 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
335
336 if (isOnTop || isOnBottom || !canMerge) {
337 if (isOnBottom) {
338 dropIndex += 1;
339 }
340
341 if (helper.getCurrentDragWidget()) {
342 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
343 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
344 // Correction of the index if the drop occurs in the same container
345 // and if the drag is started from the visualization (in that case, the
346 // dragWidget is hidden)
347 dropIndex += 1;
348 }
349 }
350
351 if (dropIndex != placeHolderIndex) {
352 helper.insertPlaceHolder(m_Layout, dropIndex);
353 }
354
355 helper.setHightlightedDragWidget(nullptr);
356 }
357 else if (canMerge) {
358 // drop on the middle -> merge
359 if (hasPlaceHolder()) {
360 helper.removePlaceHolder();
361 }
362
363 helper.setHightlightedDragWidget(dragWidgetHovered);
364 }
365 }
366 else {
367 qCWarning(LOG_VisualizationDragDropContainer())
368 << tr("VisualizationDragDropContainer::dragMoveEvent, no widget found in the "
369 "container");
370 }
371 }
372 else if (!hasPlaceHolder()) {
373 // Drop on an empty container, just add the placeHolder at the top
374 helper.insertPlaceHolder(m_Layout, 0);
375 }
376 else {
377 // No hovered drag widget, the mouse is probably hover the placeHolder
378 // Do nothing
379 }
380 }
@@ -1,385 +1,397
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 "Visualization/VisualizationZoneWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
8
8
9 #include <Common/MimeTypesDef.h>
9 #include <Common/MimeTypesDef.h>
10 #include <Data/ArrayData.h>
10 #include <Data/ArrayData.h>
11 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
12 #include <DragDropHelper.h>
12 #include <DragDropHelper.h>
13 #include <Settings/SqpSettingsDefs.h>
13 #include <Settings/SqpSettingsDefs.h>
14 #include <SqpApplication.h>
14 #include <SqpApplication.h>
15 #include <Variable/Variable.h>
15 #include <Variable/Variable.h>
16 #include <Variable/VariableController.h>
16 #include <Variable/VariableController.h>
17
17
18 #include <unordered_map>
18 #include <unordered_map>
19
19
20 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
20 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
21
21
22 namespace {
22 namespace {
23
23
24 /// Key pressed to enable zoom on horizontal axis
24 /// Key pressed to enable zoom on horizontal axis
25 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
25 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
26
26
27 /// Key pressed to enable zoom on vertical axis
27 /// Key pressed to enable zoom on vertical axis
28 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
28 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
29
29
30 } // namespace
30 } // namespace
31
31
32 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
32 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
33
33
34 explicit VisualizationGraphWidgetPrivate(const QString &name)
34 explicit VisualizationGraphWidgetPrivate(const QString &name)
35 : m_Name{name},
35 : m_Name{name},
36 m_DoAcquisition{true},
36 m_DoAcquisition{true},
37 m_IsCalibration{false},
37 m_IsCalibration{false},
38 m_RenderingDelegate{nullptr}
38 m_RenderingDelegate{nullptr}
39 {
39 {
40 }
40 }
41
41
42 QString m_Name;
42 QString m_Name;
43 // 1 variable -> n qcpplot
43 // 1 variable -> n qcpplot
44 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
44 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
45 bool m_DoAcquisition;
45 bool m_DoAcquisition;
46 bool m_IsCalibration;
46 bool m_IsCalibration;
47 QCPItemTracer *m_TextTracer;
47 QCPItemTracer *m_TextTracer;
48 /// Delegate used to attach rendering features to the plot
48 /// Delegate used to attach rendering features to the plot
49 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
49 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
50 };
50 };
51
51
52 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
52 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
53 : VisualizationDragWidget{parent},
53 : VisualizationDragWidget{parent},
54 ui{new Ui::VisualizationGraphWidget},
54 ui{new Ui::VisualizationGraphWidget},
55 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
55 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
56 {
56 {
57 ui->setupUi(this);
57 ui->setupUi(this);
58
58
59 // 'Close' options : widget is deleted when closed
59 // 'Close' options : widget is deleted when closed
60 setAttribute(Qt::WA_DeleteOnClose);
60 setAttribute(Qt::WA_DeleteOnClose);
61
61
62 // Set qcpplot properties :
62 // Set qcpplot properties :
63 // - Drag (on x-axis) and zoom are enabled
63 // - Drag (on x-axis) and zoom are enabled
64 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
64 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
65 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
65 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
66 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
66 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
67
67
68 // The delegate must be initialized after the ui as it uses the plot
68 // The delegate must be initialized after the ui as it uses the plot
69 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
69 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
70
70
71 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
71 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
72 connect(ui->widget, &QCustomPlot::mouseRelease, this,
72 connect(ui->widget, &QCustomPlot::mouseRelease, this,
73 &VisualizationGraphWidget::onMouseRelease);
73 &VisualizationGraphWidget::onMouseRelease);
74 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
74 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
75 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
75 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
76 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
76 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
77 &QCPAxis::rangeChanged),
77 &QCPAxis::rangeChanged),
78 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
78 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
79
79
80 // Activates menu when right clicking on the graph
80 // Activates menu when right clicking on the graph
81 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
81 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
82 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
82 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
83 &VisualizationGraphWidget::onGraphMenuRequested);
83 &VisualizationGraphWidget::onGraphMenuRequested);
84
84
85 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
85 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
86 &VariableController::onRequestDataLoading);
86 &VariableController::onRequestDataLoading);
87
87
88 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
88 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
89 &VisualizationGraphWidget::onUpdateVarDisplaying);
89 &VisualizationGraphWidget::onUpdateVarDisplaying);
90 }
90 }
91
91
92
92
93 VisualizationGraphWidget::~VisualizationGraphWidget()
93 VisualizationGraphWidget::~VisualizationGraphWidget()
94 {
94 {
95 delete ui;
95 delete ui;
96 }
96 }
97
97
98 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
98 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
99 {
99 {
100 auto parent = parentWidget();
100 auto parent = parentWidget();
101 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
101 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
102 parent = parent->parentWidget();
102 parent = parent->parentWidget();
103 }
103 }
104
104
105 return qobject_cast<VisualizationZoneWidget *>(parent);
105 return qobject_cast<VisualizationZoneWidget *>(parent);
106 }
106 }
107
107
108 void VisualizationGraphWidget::enableAcquisition(bool enable)
108 void VisualizationGraphWidget::enableAcquisition(bool enable)
109 {
109 {
110 impl->m_DoAcquisition = enable;
110 impl->m_DoAcquisition = enable;
111 }
111 }
112
112
113 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
113 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
114 {
114 {
115 // Uses delegate to create the qcpplot components according to the variable
115 // Uses delegate to create the qcpplot components according to the variable
116 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
116 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
117 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
117 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
118
118
119 // Set axes properties according to the units of the data series
119 // Set axes properties according to the units of the data series
120 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
120 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
121 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
121 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
122 auto xAxisUnit = Unit{};
122 auto xAxisUnit = Unit{};
123 auto valuesUnit = Unit{};
123 auto valuesUnit = Unit{};
124
124
125 if (auto dataSeries = variable->dataSeries()) {
125 if (auto dataSeries = variable->dataSeries()) {
126 dataSeries->lockRead();
126 dataSeries->lockRead();
127 xAxisUnit = dataSeries->xAxisUnit();
127 xAxisUnit = dataSeries->xAxisUnit();
128 valuesUnit = dataSeries->valuesUnit();
128 valuesUnit = dataSeries->valuesUnit();
129 dataSeries->unlock();
129 dataSeries->unlock();
130 }
130 }
131 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
131 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
132
132
133 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
133 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
134
134
135 this->enableAcquisition(false);
135 this->enableAcquisition(false);
136 this->setGraphRange(range);
136 this->setGraphRange(range);
137 this->enableAcquisition(true);
137 this->enableAcquisition(true);
138
138
139 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
139 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
140
140
141 emit variableAdded(variable);
141 emit variableAdded(variable);
142 }
142 }
143
143
144 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
144 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
145 {
145 {
146 // Each component associated to the variable :
146 // Each component associated to the variable :
147 // - is removed from qcpplot (which deletes it)
147 // - is removed from qcpplot (which deletes it)
148 // - is no longer referenced in the map
148 // - is no longer referenced in the map
149 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
149 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
150 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
150 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
151 emit variableAboutToBeRemoved(variable);
151 emit variableAboutToBeRemoved(variable);
152
152
153 auto &plottablesMap = variableIt->second;
153 auto &plottablesMap = variableIt->second;
154
154
155 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
155 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
156 plottableIt != plottableEnd;) {
156 plottableIt != plottableEnd;) {
157 ui->widget->removePlottable(plottableIt->second);
157 ui->widget->removePlottable(plottableIt->second);
158 plottableIt = plottablesMap.erase(plottableIt);
158 plottableIt = plottablesMap.erase(plottableIt);
159 }
159 }
160
160
161 impl->m_VariableToPlotMultiMap.erase(variableIt);
161 impl->m_VariableToPlotMultiMap.erase(variableIt);
162 }
162 }
163
163
164 // Updates graph
164 // Updates graph
165 ui->widget->replot();
165 ui->widget->replot();
166 }
166 }
167
167
168 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
168 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
169 {
169 {
170 auto variables = QList<std::shared_ptr<Variable> >{};
170 auto variables = QList<std::shared_ptr<Variable> >{};
171 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
171 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
172 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
172 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
173 variables << it->first;
173 variables << it->first;
174 }
174 }
175
175
176 return variables;
176 return variables;
177 }
177 }
178
178
179 void VisualizationGraphWidget::setYRange(const SqpRange &range)
179 void VisualizationGraphWidget::setYRange(const SqpRange &range)
180 {
180 {
181 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
181 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
182 }
182 }
183
183
184 SqpRange VisualizationGraphWidget::graphRange() const noexcept
184 SqpRange VisualizationGraphWidget::graphRange() const noexcept
185 {
185 {
186 auto graphRange = ui->widget->xAxis->range();
186 auto graphRange = ui->widget->xAxis->range();
187 return SqpRange{graphRange.lower, graphRange.upper};
187 return SqpRange{graphRange.lower, graphRange.upper};
188 }
188 }
189
189
190 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
190 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
191 {
191 {
192 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
192 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
193 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
193 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
194 ui->widget->replot();
194 ui->widget->replot();
195 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
195 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
196 }
196 }
197
197
198 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
198 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
199 {
199 {
200 if (visitor) {
200 if (visitor) {
201 visitor->visit(this);
201 visitor->visit(this);
202 }
202 }
203 else {
203 else {
204 qCCritical(LOG_VisualizationGraphWidget())
204 qCCritical(LOG_VisualizationGraphWidget())
205 << tr("Can't visit widget : the visitor is null");
205 << tr("Can't visit widget : the visitor is null");
206 }
206 }
207 }
207 }
208
208
209 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
209 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
210 {
210 {
211 /// @todo : for the moment, a graph can always accomodate a variable
211 /// @todo : for the moment, a graph can always accomodate a variable
212 Q_UNUSED(variable);
212 Q_UNUSED(variable);
213 return true;
213 return true;
214 }
214 }
215
215
216 bool VisualizationGraphWidget::contains(const Variable &variable) const
216 bool VisualizationGraphWidget::contains(const Variable &variable) const
217 {
217 {
218 // Finds the variable among the keys of the map
218 // Finds the variable among the keys of the map
219 auto variablePtr = &variable;
219 auto variablePtr = &variable;
220 auto findVariable
220 auto findVariable
221 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
221 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
222
222
223 auto end = impl->m_VariableToPlotMultiMap.cend();
223 auto end = impl->m_VariableToPlotMultiMap.cend();
224 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
224 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
225 return it != end;
225 return it != end;
226 }
226 }
227
227
228 QString VisualizationGraphWidget::name() const
228 QString VisualizationGraphWidget::name() const
229 {
229 {
230 return impl->m_Name;
230 return impl->m_Name;
231 }
231 }
232
232
233 QMimeData *VisualizationGraphWidget::mimeData() const
233 QMimeData *VisualizationGraphWidget::mimeData() const
234 {
234 {
235 auto mimeData = new QMimeData;
235 auto mimeData = new QMimeData;
236 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
236 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
237
237
238 return mimeData;
238 return mimeData;
239 }
239 }
240
240
241 bool VisualizationGraphWidget::isDragAllowed() const
241 bool VisualizationGraphWidget::isDragAllowed() const
242 {
242 {
243 return true;
243 return true;
244 }
244 }
245
245
246 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
247 {
248 if (highlighted) {
249 plot().setBackground(QBrush(QColor("#BBD5EE")));
250 }
251 else {
252 plot().setBackground(QBrush(Qt::white));
253 }
254
255 plot().update();
256 }
257
246 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
258 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
247 {
259 {
248 Q_UNUSED(event);
260 Q_UNUSED(event);
249
261
250 // Prevents that all variables will be removed from graph when it will be closed
262 // Prevents that all variables will be removed from graph when it will be closed
251 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
263 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
252 emit variableAboutToBeRemoved(variableEntry.first);
264 emit variableAboutToBeRemoved(variableEntry.first);
253 }
265 }
254 }
266 }
255
267
256 void VisualizationGraphWidget::enterEvent(QEvent *event)
268 void VisualizationGraphWidget::enterEvent(QEvent *event)
257 {
269 {
258 Q_UNUSED(event);
270 Q_UNUSED(event);
259 impl->m_RenderingDelegate->showGraphOverlay(true);
271 impl->m_RenderingDelegate->showGraphOverlay(true);
260 }
272 }
261
273
262 void VisualizationGraphWidget::leaveEvent(QEvent *event)
274 void VisualizationGraphWidget::leaveEvent(QEvent *event)
263 {
275 {
264 Q_UNUSED(event);
276 Q_UNUSED(event);
265 impl->m_RenderingDelegate->showGraphOverlay(false);
277 impl->m_RenderingDelegate->showGraphOverlay(false);
266 }
278 }
267
279
268 QCustomPlot &VisualizationGraphWidget::plot() noexcept
280 QCustomPlot &VisualizationGraphWidget::plot() noexcept
269 {
281 {
270 return *ui->widget;
282 return *ui->widget;
271 }
283 }
272
284
273 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
285 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
274 {
286 {
275 QMenu graphMenu{};
287 QMenu graphMenu{};
276
288
277 // Iterates on variables (unique keys)
289 // Iterates on variables (unique keys)
278 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
290 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
279 end = impl->m_VariableToPlotMultiMap.cend();
291 end = impl->m_VariableToPlotMultiMap.cend();
280 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
292 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
281 // 'Remove variable' action
293 // 'Remove variable' action
282 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
294 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
283 [ this, var = it->first ]() { removeVariable(var); });
295 [ this, var = it->first ]() { removeVariable(var); });
284 }
296 }
285
297
286 if (!graphMenu.isEmpty()) {
298 if (!graphMenu.isEmpty()) {
287 graphMenu.exec(QCursor::pos());
299 graphMenu.exec(QCursor::pos());
288 }
300 }
289 }
301 }
290
302
291 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
303 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
292 {
304 {
293 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
305 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
294 << QThread::currentThread()->objectName() << "DoAcqui"
306 << QThread::currentThread()->objectName() << "DoAcqui"
295 << impl->m_DoAcquisition;
307 << impl->m_DoAcquisition;
296
308
297 auto graphRange = SqpRange{t1.lower, t1.upper};
309 auto graphRange = SqpRange{t1.lower, t1.upper};
298 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
310 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
299
311
300 if (impl->m_DoAcquisition) {
312 if (impl->m_DoAcquisition) {
301 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
313 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
302
314
303 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
315 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
304 end = impl->m_VariableToPlotMultiMap.end();
316 end = impl->m_VariableToPlotMultiMap.end();
305 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
317 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
306 variableUnderGraphVector.push_back(it->first);
318 variableUnderGraphVector.push_back(it->first);
307 }
319 }
308 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
320 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
309 !impl->m_IsCalibration);
321 !impl->m_IsCalibration);
310
322
311 if (!impl->m_IsCalibration) {
323 if (!impl->m_IsCalibration) {
312 qCDebug(LOG_VisualizationGraphWidget())
324 qCDebug(LOG_VisualizationGraphWidget())
313 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
325 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
314 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
326 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
315 emit synchronize(graphRange, oldGraphRange);
327 emit synchronize(graphRange, oldGraphRange);
316 }
328 }
317 }
329 }
318 }
330 }
319
331
320 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
332 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
321 {
333 {
322 // Handles plot rendering when mouse is moving
334 // Handles plot rendering when mouse is moving
323 impl->m_RenderingDelegate->onMouseMove(event);
335 impl->m_RenderingDelegate->onMouseMove(event);
324
336
325 VisualizationDragWidget::mouseMoveEvent(event);
337 VisualizationDragWidget::mouseMoveEvent(event);
326 }
338 }
327
339
328 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
340 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
329 {
341 {
330 auto zoomOrientations = QFlags<Qt::Orientation>{};
342 auto zoomOrientations = QFlags<Qt::Orientation>{};
331
343
332 // Lambda that enables a zoom orientation if the key modifier related to this orientation
344 // Lambda that enables a zoom orientation if the key modifier related to this orientation
333 // has
345 // has
334 // been pressed
346 // been pressed
335 auto enableOrientation
347 auto enableOrientation
336 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
348 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
337 auto orientationEnabled = event->modifiers().testFlag(modifier);
349 auto orientationEnabled = event->modifiers().testFlag(modifier);
338 zoomOrientations.setFlag(orientation, orientationEnabled);
350 zoomOrientations.setFlag(orientation, orientationEnabled);
339 };
351 };
340 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
352 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
341 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
353 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
342
354
343 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
355 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
344 }
356 }
345
357
346 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
358 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
347 {
359 {
348 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
360 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
349
361
350 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
362 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
351
363
352 VisualizationDragWidget::mousePressEvent(event);
364 VisualizationDragWidget::mousePressEvent(event);
353 }
365 }
354
366
355 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
367 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
356 {
368 {
357 impl->m_IsCalibration = false;
369 impl->m_IsCalibration = false;
358 }
370 }
359
371
360 void VisualizationGraphWidget::onDataCacheVariableUpdated()
372 void VisualizationGraphWidget::onDataCacheVariableUpdated()
361 {
373 {
362 auto graphRange = ui->widget->xAxis->range();
374 auto graphRange = ui->widget->xAxis->range();
363 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
375 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
364
376
365 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
377 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
366 auto variable = variableEntry.first;
378 auto variable = variableEntry.first;
367 qCDebug(LOG_VisualizationGraphWidget())
379 qCDebug(LOG_VisualizationGraphWidget())
368 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
380 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
369 qCDebug(LOG_VisualizationGraphWidget())
381 qCDebug(LOG_VisualizationGraphWidget())
370 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
382 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
371 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
383 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
372 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
384 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
373 variable->range());
385 variable->range());
374 }
386 }
375 }
387 }
376 }
388 }
377
389
378 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
390 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
379 const SqpRange &range)
391 const SqpRange &range)
380 {
392 {
381 auto it = impl->m_VariableToPlotMultiMap.find(variable);
393 auto it = impl->m_VariableToPlotMultiMap.find(variable);
382 if (it != impl->m_VariableToPlotMultiMap.end()) {
394 if (it != impl->m_VariableToPlotMultiMap.end()) {
383 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
395 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
384 }
396 }
385 }
397 }
@@ -1,468 +1,469
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/VisualizationWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
8
8
9 #include "Common/MimeTypesDef.h"
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
10 #include "Common/VisualizationDef.h"
11
11
12 #include <Data/SqpRange.h>
12 #include <Data/SqpRange.h>
13 #include <Variable/Variable.h>
13 #include <Variable/Variable.h>
14 #include <Variable/VariableController.h>
14 #include <Variable/VariableController.h>
15
15
16 #include <Visualization/operations/FindVariableOperation.h>
16 #include <Visualization/operations/FindVariableOperation.h>
17
17
18 #include <DragDropHelper.h>
18 #include <DragDropHelper.h>
19 #include <QUuid>
19 #include <QUuid>
20 #include <SqpApplication.h>
20 #include <SqpApplication.h>
21 #include <cmath>
21 #include <cmath>
22
22
23 #include <QLayout>
23 #include <QLayout>
24
24
25 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
25 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26
26
27 namespace {
27 namespace {
28
28
29
29
30 /// Generates a default name for a new graph, according to the number of graphs already displayed in
30 /// Generates a default name for a new graph, according to the number of graphs already displayed in
31 /// the zone
31 /// the zone
32 QString defaultGraphName(const QLayout &layout)
32 QString defaultGraphName(const QLayout &layout)
33 {
33 {
34 auto count = 0;
34 auto count = 0;
35 for (auto i = 0; i < layout.count(); ++i) {
35 for (auto i = 0; i < layout.count(); ++i) {
36 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
36 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 count++;
37 count++;
38 }
38 }
39 }
39 }
40
40
41 return QObject::tr("Graph %1").arg(count + 1);
41 return QObject::tr("Graph %1").arg(count + 1);
42 }
42 }
43
43
44 /**
44 /**
45 * Applies a function to all graphs of the zone represented by its layout
45 * Applies a function to all graphs of the zone represented by its layout
46 * @param layout the layout that contains graphs
46 * @param layout the layout that contains graphs
47 * @param fun the function to apply to each graph
47 * @param fun the function to apply to each graph
48 */
48 */
49 template <typename Fun>
49 template <typename Fun>
50 void processGraphs(QLayout &layout, Fun fun)
50 void processGraphs(QLayout &layout, Fun fun)
51 {
51 {
52 for (auto i = 0; i < layout.count(); ++i) {
52 for (auto i = 0; i < layout.count(); ++i) {
53 if (auto item = layout.itemAt(i)) {
53 if (auto item = layout.itemAt(i)) {
54 if (auto visualizationGraphWidget
54 if (auto visualizationGraphWidget
55 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
55 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
56 fun(*visualizationGraphWidget);
56 fun(*visualizationGraphWidget);
57 }
57 }
58 }
58 }
59 }
59 }
60 }
60 }
61
61
62 } // namespace
62 } // namespace
63
63
64 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
64 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65
65
66 explicit VisualizationZoneWidgetPrivate()
66 explicit VisualizationZoneWidgetPrivate()
67 : m_SynchronisationGroupId{QUuid::createUuid()},
67 : m_SynchronisationGroupId{QUuid::createUuid()},
68 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
68 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 {
69 {
70 }
70 }
71 QUuid m_SynchronisationGroupId;
71 QUuid m_SynchronisationGroupId;
72 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
72 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73
73
74 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
74 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
75 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
75 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
76 VisualizationZoneWidget *zoneWidget);
76 VisualizationZoneWidget *zoneWidget);
77 };
77 };
78
78
79 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
79 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
80 : VisualizationDragWidget{parent},
80 : VisualizationDragWidget{parent},
81 ui{new Ui::VisualizationZoneWidget},
81 ui{new Ui::VisualizationZoneWidget},
82 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
82 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
83 {
83 {
84 ui->setupUi(this);
84 ui->setupUi(this);
85
85
86 ui->zoneNameLabel->setText(name);
86 ui->zoneNameLabel->setText(name);
87
87
88 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST});
88 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST});
89 ui->dragDropContainer->setMergeAllowedMimeTypes({MIME_TYPE_VARIABLE_LIST});
89 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
90 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
90 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
91 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
91 ui->dragDropContainer);
92 ui->dragDropContainer);
92 });
93 });
93 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
94 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
94 &VisualizationZoneWidget::dropMimeData);
95 &VisualizationZoneWidget::dropMimeData);
95
96
96 // 'Close' options : widget is deleted when closed
97 // 'Close' options : widget is deleted when closed
97 setAttribute(Qt::WA_DeleteOnClose);
98 setAttribute(Qt::WA_DeleteOnClose);
98 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
99 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
99 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
100 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
100
101
101 // Synchronisation id
102 // Synchronisation id
102 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
103 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
103 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
104 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
104 }
105 }
105
106
106 VisualizationZoneWidget::~VisualizationZoneWidget()
107 VisualizationZoneWidget::~VisualizationZoneWidget()
107 {
108 {
108 delete ui;
109 delete ui;
109 }
110 }
110
111
111 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
112 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
112 {
113 {
113 // Synchronize new graph with others in the zone
114 // Synchronize new graph with others in the zone
114 impl->m_Synchronizer->addGraph(*graphWidget);
115 impl->m_Synchronizer->addGraph(*graphWidget);
115
116
116 ui->dragDropContainer->addDragWidget(graphWidget);
117 ui->dragDropContainer->addDragWidget(graphWidget);
117 }
118 }
118
119
119 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
120 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
120 {
121 {
121 // Synchronize new graph with others in the zone
122 // Synchronize new graph with others in the zone
122 impl->m_Synchronizer->addGraph(*graphWidget);
123 impl->m_Synchronizer->addGraph(*graphWidget);
123
124
124 ui->dragDropContainer->insertDragWidget(index, graphWidget);
125 ui->dragDropContainer->insertDragWidget(index, graphWidget);
125 }
126 }
126
127
127 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
128 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
128 {
129 {
129 return createGraph(variable, -1);
130 return createGraph(variable, -1);
130 }
131 }
131
132
132 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
133 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
133 int index)
134 int index)
134 {
135 {
135 auto graphWidget
136 auto graphWidget
136 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
137 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
137
138
138
139
139 // Set graph properties
140 // Set graph properties
140 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
141 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
141 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
142 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
142
143
143
144
144 // Lambda to synchronize zone widget
145 // Lambda to synchronize zone widget
145 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
146 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
146 const SqpRange &oldGraphRange) {
147 const SqpRange &oldGraphRange) {
147
148
148 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
149 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
149 auto frameLayout = ui->dragDropContainer->layout();
150 auto frameLayout = ui->dragDropContainer->layout();
150 for (auto i = 0; i < frameLayout->count(); ++i) {
151 for (auto i = 0; i < frameLayout->count(); ++i) {
151 auto graphChild
152 auto graphChild
152 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
153 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
153 if (graphChild && (graphChild != graphWidget)) {
154 if (graphChild && (graphChild != graphWidget)) {
154
155
155 auto graphChildRange = graphChild->graphRange();
156 auto graphChildRange = graphChild->graphRange();
156 switch (zoomType) {
157 switch (zoomType) {
157 case AcquisitionZoomType::ZoomIn: {
158 case AcquisitionZoomType::ZoomIn: {
158 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
159 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
159 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
160 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
160 graphChildRange.m_TStart += deltaLeft;
161 graphChildRange.m_TStart += deltaLeft;
161 graphChildRange.m_TEnd -= deltaRight;
162 graphChildRange.m_TEnd -= deltaRight;
162 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
163 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
163 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
164 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
164 << deltaLeft;
165 << deltaLeft;
165 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
166 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
166 << deltaRight;
167 << deltaRight;
167 qCDebug(LOG_VisualizationZoneWidget())
168 qCDebug(LOG_VisualizationZoneWidget())
168 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
169 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
169
170
170 break;
171 break;
171 }
172 }
172
173
173 case AcquisitionZoomType::ZoomOut: {
174 case AcquisitionZoomType::ZoomOut: {
174 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
175 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
175 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
176 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
176 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
177 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
177 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
178 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
178 << deltaLeft;
179 << deltaLeft;
179 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
180 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
180 << deltaRight;
181 << deltaRight;
181 qCDebug(LOG_VisualizationZoneWidget())
182 qCDebug(LOG_VisualizationZoneWidget())
182 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
183 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
183 graphChildRange.m_TStart -= deltaLeft;
184 graphChildRange.m_TStart -= deltaLeft;
184 graphChildRange.m_TEnd += deltaRight;
185 graphChildRange.m_TEnd += deltaRight;
185 break;
186 break;
186 }
187 }
187 case AcquisitionZoomType::PanRight: {
188 case AcquisitionZoomType::PanRight: {
188 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
189 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
189 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
190 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
190 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
191 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
191 graphChildRange.m_TStart += deltaLeft;
192 graphChildRange.m_TStart += deltaLeft;
192 graphChildRange.m_TEnd += deltaRight;
193 graphChildRange.m_TEnd += deltaRight;
193 qCDebug(LOG_VisualizationZoneWidget())
194 qCDebug(LOG_VisualizationZoneWidget())
194 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
195 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
195 break;
196 break;
196 }
197 }
197 case AcquisitionZoomType::PanLeft: {
198 case AcquisitionZoomType::PanLeft: {
198 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
199 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
200 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
200 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
201 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
201 graphChildRange.m_TStart -= deltaLeft;
202 graphChildRange.m_TStart -= deltaLeft;
202 graphChildRange.m_TEnd -= deltaRight;
203 graphChildRange.m_TEnd -= deltaRight;
203 break;
204 break;
204 }
205 }
205 case AcquisitionZoomType::Unknown: {
206 case AcquisitionZoomType::Unknown: {
206 qCDebug(LOG_VisualizationZoneWidget())
207 qCDebug(LOG_VisualizationZoneWidget())
207 << tr("Impossible to synchronize: zoom type unknown");
208 << tr("Impossible to synchronize: zoom type unknown");
208 break;
209 break;
209 }
210 }
210 default:
211 default:
211 qCCritical(LOG_VisualizationZoneWidget())
212 qCCritical(LOG_VisualizationZoneWidget())
212 << tr("Impossible to synchronize: zoom type not take into account");
213 << tr("Impossible to synchronize: zoom type not take into account");
213 // No action
214 // No action
214 break;
215 break;
215 }
216 }
216 graphChild->enableAcquisition(false);
217 graphChild->enableAcquisition(false);
217 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
218 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
218 << graphChild->graphRange();
219 << graphChild->graphRange();
219 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
220 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
220 << graphChildRange;
221 << graphChildRange;
221 qCDebug(LOG_VisualizationZoneWidget())
222 qCDebug(LOG_VisualizationZoneWidget())
222 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
223 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
223 graphChild->setGraphRange(graphChildRange);
224 graphChild->setGraphRange(graphChildRange);
224 graphChild->enableAcquisition(true);
225 graphChild->enableAcquisition(true);
225 }
226 }
226 }
227 }
227 };
228 };
228
229
229 // connection for synchronization
230 // connection for synchronization
230 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
231 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
231 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
232 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
232 &VisualizationZoneWidget::onVariableAdded);
233 &VisualizationZoneWidget::onVariableAdded);
233 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
234 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
234 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
235 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
235
236
236 auto range = SqpRange{};
237 auto range = SqpRange{};
237
238
238 // Apply visitor to graph children
239 // Apply visitor to graph children
239 auto layout = ui->dragDropContainer->layout();
240 auto layout = ui->dragDropContainer->layout();
240 if (layout->count() > 0) {
241 if (layout->count() > 0) {
241 // Case of a new graph in a existant zone
242 // Case of a new graph in a existant zone
242 if (auto visualizationGraphWidget
243 if (auto visualizationGraphWidget
243 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
244 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
244 range = visualizationGraphWidget->graphRange();
245 range = visualizationGraphWidget->graphRange();
245 }
246 }
246 }
247 }
247 else {
248 else {
248 // Case of a new graph as the first of the zone
249 // Case of a new graph as the first of the zone
249 range = variable->range();
250 range = variable->range();
250 }
251 }
251
252
252 this->insertGraph(index, graphWidget);
253 this->insertGraph(index, graphWidget);
253
254
254 graphWidget->addVariable(variable, range);
255 graphWidget->addVariable(variable, range);
255
256
256 // get y using variable range
257 // get y using variable range
257 if (auto dataSeries = variable->dataSeries()) {
258 if (auto dataSeries = variable->dataSeries()) {
258 dataSeries->lockRead();
259 dataSeries->lockRead();
259 auto valuesBounds
260 auto valuesBounds
260 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
261 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
261 auto end = dataSeries->cend();
262 auto end = dataSeries->cend();
262 if (valuesBounds.first != end && valuesBounds.second != end) {
263 if (valuesBounds.first != end && valuesBounds.second != end) {
263 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
264 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
264
265
265 auto minValue = rangeValue(valuesBounds.first->minValue());
266 auto minValue = rangeValue(valuesBounds.first->minValue());
266 auto maxValue = rangeValue(valuesBounds.second->maxValue());
267 auto maxValue = rangeValue(valuesBounds.second->maxValue());
267
268
268 graphWidget->setYRange(SqpRange{minValue, maxValue});
269 graphWidget->setYRange(SqpRange{minValue, maxValue});
269 }
270 }
270 dataSeries->unlock();
271 dataSeries->unlock();
271 }
272 }
272
273
273 return graphWidget;
274 return graphWidget;
274 }
275 }
275
276
276 VisualizationGraphWidget *
277 VisualizationGraphWidget *
277 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
278 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
278 {
279 {
279 if (variables.isEmpty()) {
280 if (variables.isEmpty()) {
280 return nullptr;
281 return nullptr;
281 }
282 }
282
283
283 auto graphWidget = createGraph(variables.first(), index);
284 auto graphWidget = createGraph(variables.first(), index);
284 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
285 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
285 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
286 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
286 }
287 }
287
288
288 return graphWidget;
289 return graphWidget;
289 }
290 }
290
291
291 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
292 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
292 {
293 {
293 if (visitor) {
294 if (visitor) {
294 visitor->visitEnter(this);
295 visitor->visitEnter(this);
295
296
296 // Apply visitor to graph children: widgets different from graphs are not visited (no
297 // Apply visitor to graph children: widgets different from graphs are not visited (no
297 // action)
298 // action)
298 processGraphs(
299 processGraphs(
299 *ui->dragDropContainer->layout(),
300 *ui->dragDropContainer->layout(),
300 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
301 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
301
302
302 visitor->visitLeave(this);
303 visitor->visitLeave(this);
303 }
304 }
304 else {
305 else {
305 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
306 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
306 }
307 }
307 }
308 }
308
309
309 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
310 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
310 {
311 {
311 // A tab can always accomodate a variable
312 // A tab can always accomodate a variable
312 Q_UNUSED(variable);
313 Q_UNUSED(variable);
313 return true;
314 return true;
314 }
315 }
315
316
316 bool VisualizationZoneWidget::contains(const Variable &variable) const
317 bool VisualizationZoneWidget::contains(const Variable &variable) const
317 {
318 {
318 Q_UNUSED(variable);
319 Q_UNUSED(variable);
319 return false;
320 return false;
320 }
321 }
321
322
322 QString VisualizationZoneWidget::name() const
323 QString VisualizationZoneWidget::name() const
323 {
324 {
324 return ui->zoneNameLabel->text();
325 return ui->zoneNameLabel->text();
325 }
326 }
326
327
327 QMimeData *VisualizationZoneWidget::mimeData() const
328 QMimeData *VisualizationZoneWidget::mimeData() const
328 {
329 {
329 auto mimeData = new QMimeData;
330 auto mimeData = new QMimeData;
330 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
331 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
331
332
332 return mimeData;
333 return mimeData;
333 }
334 }
334
335
335 bool VisualizationZoneWidget::isDragAllowed() const
336 bool VisualizationZoneWidget::isDragAllowed() const
336 {
337 {
337 return true;
338 return true;
338 }
339 }
339
340
340 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
341 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
341 {
342 {
342 // Closes graphs in the zone
343 // Closes graphs in the zone
343 processGraphs(*ui->dragDropContainer->layout(),
344 processGraphs(*ui->dragDropContainer->layout(),
344 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
345 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
345
346
346 // Delete synchronization group from variable controller
347 // Delete synchronization group from variable controller
347 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
348 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
348 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
349 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
349
350
350 QWidget::closeEvent(event);
351 QWidget::closeEvent(event);
351 }
352 }
352
353
353 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
354 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
354 {
355 {
355 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
356 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
356 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
357 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
357 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
358 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
358 }
359 }
359
360
360 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
361 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
361 {
362 {
362 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
363 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
363 Q_ARG(std::shared_ptr<Variable>, variable),
364 Q_ARG(std::shared_ptr<Variable>, variable),
364 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
365 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
365 }
366 }
366
367
367 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
368 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
368 {
369 {
369 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
370 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
370 impl->dropGraph(index, this);
371 impl->dropGraph(index, this);
371 }
372 }
372 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
373 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
373 auto variables = sqpApp->variableController().variablesForMimeData(
374 auto variables = sqpApp->variableController().variablesForMimeData(
374 mimeData->data(MIME_TYPE_VARIABLE_LIST));
375 mimeData->data(MIME_TYPE_VARIABLE_LIST));
375 impl->dropVariables(variables, index, this);
376 impl->dropVariables(variables, index, this);
376 }
377 }
377 else {
378 else {
378 qCWarning(LOG_VisualizationZoneWidget())
379 qCWarning(LOG_VisualizationZoneWidget())
379 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
380 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
380 }
381 }
381 }
382 }
382
383
383 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
384 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
384 int index, VisualizationZoneWidget *zoneWidget)
385 int index, VisualizationZoneWidget *zoneWidget)
385 {
386 {
386 auto &helper = sqpApp->dragDropHelper();
387 auto &helper = sqpApp->dragDropHelper();
387
388
388 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
389 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
389 if (!graphWidget) {
390 if (!graphWidget) {
390 qCWarning(LOG_VisualizationZoneWidget())
391 qCWarning(LOG_VisualizationZoneWidget())
391 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
392 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
392 "found or invalid.");
393 "found or invalid.");
393 Q_ASSERT(false);
394 Q_ASSERT(false);
394 return;
395 return;
395 }
396 }
396
397
397 auto parentDragDropContainer
398 auto parentDragDropContainer
398 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
399 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
399 if (!parentDragDropContainer) {
400 if (!parentDragDropContainer) {
400 qCWarning(LOG_VisualizationZoneWidget())
401 qCWarning(LOG_VisualizationZoneWidget())
401 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
402 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
402 "the dropped graph is not found.");
403 "the dropped graph is not found.");
403 Q_ASSERT(false);
404 Q_ASSERT(false);
404 return;
405 return;
405 }
406 }
406
407
407 const auto &variables = graphWidget->variables();
408 const auto &variables = graphWidget->variables();
408
409
409 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
410 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
410 // The drop didn't occur in the same zone
411 // The drop didn't occur in the same zone
411
412
412 // Abort the requests for the variables (if any)
413 // Abort the requests for the variables (if any)
413 // Commented, because it's not sure if it's needed or not
414 // Commented, because it's not sure if it's needed or not
414 // for (const auto& var : variables)
415 // for (const auto& var : variables)
415 //{
416 //{
416 // sqpApp->variableController().onAbortProgressRequested(var);
417 // sqpApp->variableController().onAbortProgressRequested(var);
417 //}
418 //}
418
419
419 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
420 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
420 auto nbGraph = parentDragDropContainer->countDragWidget();
421 auto nbGraph = parentDragDropContainer->countDragWidget();
421 if (nbGraph == 1) {
422 if (nbGraph == 1) {
422 // This is the only graph in the previous zone, close the zone
423 // This is the only graph in the previous zone, close the zone
423 previousParentZoneWidget->close();
424 previousParentZoneWidget->close();
424 }
425 }
425 else {
426 else {
426 // Close the graph
427 // Close the graph
427 graphWidget->close();
428 graphWidget->close();
428 }
429 }
429
430
430 // Creates the new graph in the zone
431 // Creates the new graph in the zone
431 zoneWidget->createGraph(variables, index);
432 zoneWidget->createGraph(variables, index);
432 }
433 }
433 else {
434 else {
434 // The drop occurred in the same zone or the graph is empty
435 // The drop occurred in the same zone or the graph is empty
435 // Simple move of the graph, no variable operation associated
436 // Simple move of the graph, no variable operation associated
436 parentDragDropContainer->layout()->removeWidget(graphWidget);
437 parentDragDropContainer->layout()->removeWidget(graphWidget);
437
438
438 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
439 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
439 // The graph is empty and dropped in a different zone.
440 // The graph is empty and dropped in a different zone.
440 // Take the range of the first graph in the zone (if existing).
441 // Take the range of the first graph in the zone (if existing).
441 auto layout = zoneWidget->ui->dragDropContainer->layout();
442 auto layout = zoneWidget->ui->dragDropContainer->layout();
442 if (layout->count() > 0) {
443 if (layout->count() > 0) {
443 if (auto visualizationGraphWidget
444 if (auto visualizationGraphWidget
444 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
445 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
445 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
446 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
446 }
447 }
447 }
448 }
448 }
449 }
449
450
450 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
451 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
451 }
452 }
452 }
453 }
453
454
454 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
455 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
455 const QList<std::shared_ptr<Variable> > &variables, int index,
456 const QList<std::shared_ptr<Variable> > &variables, int index,
456 VisualizationZoneWidget *zoneWidget)
457 VisualizationZoneWidget *zoneWidget)
457 {
458 {
458 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
459 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
459 // compatible variable here
460 // compatible variable here
460 if (variables.count() > 1) {
461 if (variables.count() > 1) {
461 qCWarning(LOG_VisualizationZoneWidget())
462 qCWarning(LOG_VisualizationZoneWidget())
462 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
463 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
463 "aborted.");
464 "aborted.");
464 return;
465 return;
465 }
466 }
466
467
467 zoneWidget->createGraph(variables, index);
468 zoneWidget->createGraph(variables, index);
468 }
469 }
General Comments 3
Under Review
author

Pull request updated. Auto status change to "Under Review"

Changed commits:
  * 1 added
  * 0 removed

Changed files:
  * A core/tests/meson.build
You need to be logged in to leave comments. Login now