##// END OF EJS Templates
Keep the selection zones when a graph is dropped in another synchro zone
trabillard -
r1048:1eed201e150e
parent child
Show More
@@ -1,127 +1,133
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 /// Sets the y-axis range based on the data of a variable
49 /// Sets the y-axis range based on the data of a variable
50 void setYRange(std::shared_ptr<Variable> variable);
50 void setYRange(std::shared_ptr<Variable> variable);
51 SqpRange graphRange() const noexcept;
51 SqpRange graphRange() const noexcept;
52 void setGraphRange(const SqpRange &range);
52 void setGraphRange(const SqpRange &range);
53
53
54 /// Returns the ranges of all the selection zones on the graph
55 QVector<SqpRange> selectionZoneRanges() const;
56
57 /// Adds new selection zones in the graph
58 void addSelectionZones(const QVector<SqpRange> &ranges);
59
54 /// Undo the last zoom done with a zoom box
60 /// Undo the last zoom done with a zoom box
55 void undoZoom();
61 void undoZoom();
56
62
57 // IVisualizationWidget interface
63 // IVisualizationWidget interface
58 void accept(IVisualizationWidgetVisitor *visitor) override;
64 void accept(IVisualizationWidgetVisitor *visitor) override;
59 bool canDrop(const Variable &variable) const override;
65 bool canDrop(const Variable &variable) const override;
60 bool contains(const Variable &variable) const override;
66 bool contains(const Variable &variable) const override;
61 QString name() const override;
67 QString name() const override;
62
68
63 // VisualisationDragWidget
69 // VisualisationDragWidget
64 QMimeData *mimeData(const QPoint &position) const override;
70 QMimeData *mimeData(const QPoint &position) const override;
65 QPixmap customDragPixmap(const QPoint &dragPosition) override;
71 QPixmap customDragPixmap(const QPoint &dragPosition) override;
66 bool isDragAllowed() const override;
72 bool isDragAllowed() const override;
67 void highlightForMerge(bool highlighted) override;
73 void highlightForMerge(bool highlighted) override;
68
74
69 // Cursors
75 // Cursors
70 /// Adds or moves the vertical cursor at the specified value on the x-axis
76 /// Adds or moves the vertical cursor at the specified value on the x-axis
71 void addVerticalCursor(double time);
77 void addVerticalCursor(double time);
72 /// Adds or moves the vertical cursor at the specified value on the x-axis
78 /// Adds or moves the vertical cursor at the specified value on the x-axis
73 void addVerticalCursorAtViewportPosition(double position);
79 void addVerticalCursorAtViewportPosition(double position);
74 void removeVerticalCursor();
80 void removeVerticalCursor();
75 /// Adds or moves the vertical cursor at the specified value on the y-axis
81 /// Adds or moves the vertical cursor at the specified value on the y-axis
76 void addHorizontalCursor(double value);
82 void addHorizontalCursor(double value);
77 /// Adds or moves the vertical cursor at the specified value on the y-axis
83 /// Adds or moves the vertical cursor at the specified value on the y-axis
78 void addHorizontalCursorAtViewportPosition(double position);
84 void addHorizontalCursorAtViewportPosition(double position);
79 void removeHorizontalCursor();
85 void removeHorizontalCursor();
80
86
81 signals:
87 signals:
82 void synchronize(const SqpRange &range, const SqpRange &oldRange);
88 void synchronize(const SqpRange &range, const SqpRange &oldRange);
83 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
89 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
84 bool synchronise);
90 bool synchronise);
85
91
86 /// Signal emitted when the variable is about to be removed from the graph
92 /// Signal emitted when the variable is about to be removed from the graph
87 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
93 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
88 /// Signal emitted when the variable has been added to the graph
94 /// Signal emitted when the variable has been added to the graph
89 void variableAdded(std::shared_ptr<Variable> var);
95 void variableAdded(std::shared_ptr<Variable> var);
90
96
91 protected:
97 protected:
92 void closeEvent(QCloseEvent *event) override;
98 void closeEvent(QCloseEvent *event) override;
93 void enterEvent(QEvent *event) override;
99 void enterEvent(QEvent *event) override;
94 void leaveEvent(QEvent *event) override;
100 void leaveEvent(QEvent *event) override;
95
101
96 QCustomPlot &plot() const noexcept;
102 QCustomPlot &plot() const noexcept;
97
103
98 private:
104 private:
99 Ui::VisualizationGraphWidget *ui;
105 Ui::VisualizationGraphWidget *ui;
100
106
101 class VisualizationGraphWidgetPrivate;
107 class VisualizationGraphWidgetPrivate;
102 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
108 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
103
109
104 private slots:
110 private slots:
105 /// Slot called when right clicking on the graph (displays a menu)
111 /// Slot called when right clicking on the graph (displays a menu)
106 void onGraphMenuRequested(const QPoint &pos) noexcept;
112 void onGraphMenuRequested(const QPoint &pos) noexcept;
107
113
108 /// Rescale the X axe to range parameter
114 /// Rescale the X axe to range parameter
109 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
115 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
110
116
111 /// Slot called when a mouse double click was made
117 /// Slot called when a mouse double click was made
112 void onMouseDoubleClick(QMouseEvent *event) noexcept;
118 void onMouseDoubleClick(QMouseEvent *event) noexcept;
113 /// Slot called when a mouse move was made
119 /// Slot called when a mouse move was made
114 void onMouseMove(QMouseEvent *event) noexcept;
120 void onMouseMove(QMouseEvent *event) noexcept;
115 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
121 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
116 void onMouseWheel(QWheelEvent *event) noexcept;
122 void onMouseWheel(QWheelEvent *event) noexcept;
117 /// Slot called when a mouse press was made, to activate the calibration of a graph
123 /// Slot called when a mouse press was made, to activate the calibration of a graph
118 void onMousePress(QMouseEvent *event) noexcept;
124 void onMousePress(QMouseEvent *event) noexcept;
119 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
125 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
120 void onMouseRelease(QMouseEvent *event) noexcept;
126 void onMouseRelease(QMouseEvent *event) noexcept;
121
127
122 void onDataCacheVariableUpdated();
128 void onDataCacheVariableUpdated();
123
129
124 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
130 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
125 };
131 };
126
132
127 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
133 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,95 +1,98
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
5 #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_VisualizationZoneWidget)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
15
15
16 namespace Ui {
16 namespace Ui {
17 class VisualizationZoneWidget;
17 class VisualizationZoneWidget;
18 } // namespace Ui
18 } // namespace Ui
19
19
20 class Variable;
20 class Variable;
21 class VisualizationGraphWidget;
21 class VisualizationGraphWidget;
22
22
23 class VisualizationZoneWidget : public VisualizationDragWidget, public IVisualizationWidget {
23 class VisualizationZoneWidget : public VisualizationDragWidget, public IVisualizationWidget {
24 Q_OBJECT
24 Q_OBJECT
25
25
26 public:
26 public:
27 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
27 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
28 virtual ~VisualizationZoneWidget();
28 virtual ~VisualizationZoneWidget();
29
29
30 /// Adds a graph widget
30 /// Adds a graph widget
31 void addGraph(VisualizationGraphWidget *graphWidget);
31 void addGraph(VisualizationGraphWidget *graphWidget);
32
32
33 /// Inserts a graph widget
33 /// Inserts a graph widget
34 void insertGraph(int index, VisualizationGraphWidget *graphWidget);
34 void insertGraph(int index, VisualizationGraphWidget *graphWidget);
35
35
36 /**
36 /**
37 * Creates a graph using a variable. The variable will be displayed in the new graph.
37 * Creates a graph using a variable. The variable will be displayed in the new graph.
38 * The graph is added at the end.
38 * The graph is added at the end.
39 * @param variable the variable for which to create the graph
39 * @param variable the variable for which to create the graph
40 * @return the pointer to the created graph
40 * @return the pointer to the created graph
41 */
41 */
42 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
42 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
43
43
44 /**
44 /**
45 * Creates a graph using a variable. The variable will be displayed in the new graph.
45 * Creates a graph using a variable. The variable will be displayed in the new graph.
46 * The graph is inserted at the specified index.
46 * The graph is inserted at the specified index.
47 * @param variable the variable for which to create the graph
47 * @param variable the variable for which to create the graph
48 * @param index The index where the graph should be inserted in the layout
48 * @param index The index where the graph should be inserted in the layout
49 * @return the pointer to the created graph
49 * @return the pointer to the created graph
50 */
50 */
51 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable, int index);
51 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable, int index);
52
52
53 /**
53 /**
54 * Creates a graph using a list of variables. The variables will be displayed in the new graph.
54 * Creates a graph using a list of variables. The variables will be displayed in the new graph.
55 * The graph is inserted at the specified index.
55 * The graph is inserted at the specified index.
56 * @param variables List of variables to be added to the graph
56 * @param variables List of variables to be added to the graph
57 * @param index The index where the graph should be inserted in the layout
57 * @param index The index where the graph should be inserted in the layout
58 * @return the pointer to the created graph
58 * @return the pointer to the created graph
59 */
59 */
60 VisualizationGraphWidget *createGraph(const QList<std::shared_ptr<Variable> > variables,
60 VisualizationGraphWidget *createGraph(const QList<std::shared_ptr<Variable> > variables,
61 int index);
61 int index);
62
62
63 /// Returns the first graph in the zone or nullptr if there is no graph inside
64 VisualizationGraphWidget *firstGraph() const;
65
63 // IVisualizationWidget interface
66 // IVisualizationWidget interface
64 void accept(IVisualizationWidgetVisitor *visitor) override;
67 void accept(IVisualizationWidgetVisitor *visitor) override;
65 bool canDrop(const Variable &variable) const override;
68 bool canDrop(const Variable &variable) const override;
66 bool contains(const Variable &variable) const override;
69 bool contains(const Variable &variable) const override;
67 QString name() const override;
70 QString name() const override;
68
71
69 // VisualisationDragWidget
72 // VisualisationDragWidget
70 QMimeData *mimeData(const QPoint &position) const override;
73 QMimeData *mimeData(const QPoint &position) const override;
71 bool isDragAllowed() const override;
74 bool isDragAllowed() const override;
72
75
73 void notifyMouseMoveInGraph(const QPointF &graphPosition, const QPointF &plotPosition,
76 void notifyMouseMoveInGraph(const QPointF &graphPosition, const QPointF &plotPosition,
74 VisualizationGraphWidget *graphWidget);
77 VisualizationGraphWidget *graphWidget);
75 void notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget);
78 void notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget);
76
79
77 protected:
80 protected:
78 void closeEvent(QCloseEvent *event) override;
81 void closeEvent(QCloseEvent *event) override;
79
82
80 private:
83 private:
81 Ui::VisualizationZoneWidget *ui;
84 Ui::VisualizationZoneWidget *ui;
82
85
83 class VisualizationZoneWidgetPrivate;
86 class VisualizationZoneWidgetPrivate;
84 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
87 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
85
88
86 private slots:
89 private slots:
87 void onVariableAdded(std::shared_ptr<Variable> variable);
90 void onVariableAdded(std::shared_ptr<Variable> variable);
88 /// Slot called when a variable is about to be removed from a graph contained in the zone
91 /// Slot called when a variable is about to be removed from a graph contained in the zone
89 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
92 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
90
93
91 void dropMimeData(int index, const QMimeData *mimeData);
94 void dropMimeData(int index, const QMimeData *mimeData);
92 void dropMimeDataOnGraph(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
95 void dropMimeDataOnGraph(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
93 };
96 };
94
97
95 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
98 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -1,61 +1,61
1 #include "Visualization/VisualizationDragWidget.h"
1 #include "Visualization/VisualizationDragWidget.h"
2 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "Visualization/VisualizationDragDropContainer.h"
3
3
4 #include <QApplication>
4 #include <QApplication>
5 #include <QMouseEvent>
5 #include <QMouseEvent>
6
6
7 #include <SqpApplication.h>
7 #include <SqpApplication.h>
8
8
9 struct VisualizationDragWidget::VisualizationDragWidgetPrivate {
9 struct VisualizationDragWidget::VisualizationDragWidgetPrivate {
10
10
11 QPoint m_DragStartPosition;
11 QPoint m_DragStartPosition;
12 bool m_DragStartPositionValid = false;
12 bool m_DragStartPositionValid = false;
13
13
14 explicit VisualizationDragWidgetPrivate() {}
14 explicit VisualizationDragWidgetPrivate() {}
15 };
15 };
16
16
17 VisualizationDragWidget::VisualizationDragWidget(QWidget *parent)
17 VisualizationDragWidget::VisualizationDragWidget(QWidget *parent)
18 : QWidget{parent}, impl{spimpl::make_unique_impl<VisualizationDragWidgetPrivate>()}
18 : QWidget{parent}, impl{spimpl::make_unique_impl<VisualizationDragWidgetPrivate>()}
19 {
19 {
20 }
20 }
21
21
22 virtual QPixmap VisualizationDragWidget::customDragPixmap(const QPoint &dragPosition)
22 QPixmap VisualizationDragWidget::customDragPixmap(const QPoint &dragPosition)
23 {
23 {
24 Q_UNUSED(dragPosition);
24 Q_UNUSED(dragPosition);
25 return QPixmap();
25 return QPixmap();
26 }
26 }
27
27
28 void VisualizationDragWidget::mousePressEvent(QMouseEvent *event)
28 void VisualizationDragWidget::mousePressEvent(QMouseEvent *event)
29 {
29 {
30 if (event->button() == Qt::LeftButton) {
30 if (event->button() == Qt::LeftButton) {
31 impl->m_DragStartPosition = event->pos();
31 impl->m_DragStartPosition = event->pos();
32 }
32 }
33
33
34 impl->m_DragStartPositionValid = isDragAllowed();
34 impl->m_DragStartPositionValid = isDragAllowed();
35
35
36 QWidget::mousePressEvent(event);
36 QWidget::mousePressEvent(event);
37 }
37 }
38
38
39 void VisualizationDragWidget::mouseMoveEvent(QMouseEvent *event)
39 void VisualizationDragWidget::mouseMoveEvent(QMouseEvent *event)
40 {
40 {
41 if (!impl->m_DragStartPositionValid || !isDragAllowed()) {
41 if (!impl->m_DragStartPositionValid || !isDragAllowed()) {
42 return;
42 return;
43 }
43 }
44
44
45 if (!(event->buttons() & Qt::LeftButton)) {
45 if (!(event->buttons() & Qt::LeftButton)) {
46 return;
46 return;
47 }
47 }
48
48
49 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::DragAndDrop
49 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::DragAndDrop
50 || event->modifiers().testFlag(Qt::AltModifier)) {
50 || event->modifiers().testFlag(Qt::AltModifier)) {
51
51
52 if ((event->pos() - impl->m_DragStartPosition).manhattanLength()
52 if ((event->pos() - impl->m_DragStartPosition).manhattanLength()
53 < QApplication::startDragDistance()) {
53 < QApplication::startDragDistance()) {
54 return;
54 return;
55 }
55 }
56
56
57 emit dragDetected(this, impl->m_DragStartPosition);
57 emit dragDetected(this, impl->m_DragStartPosition);
58 }
58 }
59
59
60 QWidget::mouseMoveEvent(event);
60 QWidget::mouseMoveEvent(event);
61 }
61 }
@@ -1,797 +1,818
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationCursorItem.h"
3 #include "Visualization/VisualizationCursorItem.h"
4 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationDefs.h"
5 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphHelper.h"
6 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationGraphRenderingDelegate.h"
7 #include "Visualization/VisualizationSelectionZoneItem.h"
7 #include "Visualization/VisualizationSelectionZoneItem.h"
8 #include "Visualization/VisualizationZoneWidget.h"
8 #include "Visualization/VisualizationZoneWidget.h"
9 #include "ui_VisualizationGraphWidget.h"
9 #include "ui_VisualizationGraphWidget.h"
10
10
11 #include <Common/MimeTypesDef.h>
11 #include <Common/MimeTypesDef.h>
12 #include <Data/ArrayData.h>
12 #include <Data/ArrayData.h>
13 #include <Data/IDataSeries.h>
13 #include <Data/IDataSeries.h>
14 #include <Data/SpectrogramSeries.h>
14 #include <Data/SpectrogramSeries.h>
15 #include <DragAndDrop/DragDropHelper.h>
15 #include <DragAndDrop/DragDropHelper.h>
16 #include <Settings/SqpSettingsDefs.h>
16 #include <Settings/SqpSettingsDefs.h>
17 #include <SqpApplication.h>
17 #include <SqpApplication.h>
18 #include <Time/TimeController.h>
18 #include <Time/TimeController.h>
19 #include <Variable/Variable.h>
19 #include <Variable/Variable.h>
20 #include <Variable/VariableController.h>
20 #include <Variable/VariableController.h>
21
21
22 #include <unordered_map>
22 #include <unordered_map>
23
23
24 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
24 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
25
25
26 namespace {
26 namespace {
27
27
28 /// Key pressed to enable drag&drop in all modes
28 /// Key pressed to enable drag&drop in all modes
29 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
29 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
30
30
31 /// Key pressed to enable zoom on horizontal axis
31 /// Key pressed to enable zoom on horizontal axis
32 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
32 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
33
33
34 /// Key pressed to enable zoom on vertical axis
34 /// Key pressed to enable zoom on vertical axis
35 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
35 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
36
36
37 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
37 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
38 const auto PAN_SPEED = 5;
38 const auto PAN_SPEED = 5;
39
39
40 /// Key pressed to enable a calibration pan
40 /// Key pressed to enable a calibration pan
41 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
41 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
42
42
43 /// Minimum size for the zoom box, in percentage of the axis range
43 /// Minimum size for the zoom box, in percentage of the axis range
44 const auto ZOOM_BOX_MIN_SIZE = 0.8;
44 const auto ZOOM_BOX_MIN_SIZE = 0.8;
45
45
46 /// Format of the dates appearing in the label of a cursor
46 /// Format of the dates appearing in the label of a cursor
47 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
47 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
48
48
49 } // namespace
49 } // namespace
50
50
51 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
51 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
52
52
53 explicit VisualizationGraphWidgetPrivate(const QString &name)
53 explicit VisualizationGraphWidgetPrivate(const QString &name)
54 : m_Name{name},
54 : m_Name{name},
55 m_DoAcquisition{true},
55 m_DoAcquisition{true},
56 m_IsCalibration{false},
56 m_IsCalibration{false},
57 m_RenderingDelegate{nullptr}
57 m_RenderingDelegate{nullptr}
58 {
58 {
59 }
59 }
60
60
61 void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
61 void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
62 const SqpRange &range)
62 const SqpRange &range)
63 {
63 {
64 VisualizationGraphHelper::updateData(plottables, dataSeries, range);
64 VisualizationGraphHelper::updateData(plottables, dataSeries, range);
65
65
66 // Prevents that data has changed to update rendering
66 // Prevents that data has changed to update rendering
67 m_RenderingDelegate->onPlotUpdated();
67 m_RenderingDelegate->onPlotUpdated();
68 }
68 }
69
69
70 QString m_Name;
70 QString m_Name;
71 // 1 variable -> n qcpplot
71 // 1 variable -> n qcpplot
72 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
72 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
73 bool m_DoAcquisition;
73 bool m_DoAcquisition;
74 bool m_IsCalibration;
74 bool m_IsCalibration;
75 /// Delegate used to attach rendering features to the plot
75 /// Delegate used to attach rendering features to the plot
76 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
76 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
77
77
78 QCPItemRect *m_DrawingZoomRect = nullptr;
78 QCPItemRect *m_DrawingZoomRect = nullptr;
79 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
79 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
80
80
81 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
81 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
82 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
82 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
83
83
84 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
84 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
85 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
85 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
86 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
86 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
87
87
88 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
88 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
89 {
89 {
90 removeDrawingRect(plot);
90 removeDrawingRect(plot);
91
91
92 auto axisPos = posToAxisPos(pos, plot);
92 auto axisPos = posToAxisPos(pos, plot);
93
93
94 m_DrawingZoomRect = new QCPItemRect{&plot};
94 m_DrawingZoomRect = new QCPItemRect{&plot};
95 QPen p;
95 QPen p;
96 p.setWidth(2);
96 p.setWidth(2);
97 m_DrawingZoomRect->setPen(p);
97 m_DrawingZoomRect->setPen(p);
98
98
99 m_DrawingZoomRect->topLeft->setCoords(axisPos);
99 m_DrawingZoomRect->topLeft->setCoords(axisPos);
100 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
100 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
101 }
101 }
102
102
103 void removeDrawingRect(QCustomPlot &plot)
103 void removeDrawingRect(QCustomPlot &plot)
104 {
104 {
105 if (m_DrawingZoomRect) {
105 if (m_DrawingZoomRect) {
106 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
106 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
107 m_DrawingZoomRect = nullptr;
107 m_DrawingZoomRect = nullptr;
108 plot.replot(QCustomPlot::rpQueuedReplot);
108 plot.replot(QCustomPlot::rpQueuedReplot);
109 }
109 }
110 }
110 }
111
111
112 void startDrawingZone(const QPoint &pos, QCustomPlot &plot)
112 void startDrawingZone(const QPoint &pos, QCustomPlot &plot)
113 {
113 {
114 endDrawingZone(plot);
114 endDrawingZone(plot);
115
115
116 auto axisPos = posToAxisPos(pos, plot);
116 auto axisPos = posToAxisPos(pos, plot);
117
117
118 m_DrawingZone = new VisualizationSelectionZoneItem{&plot};
118 m_DrawingZone = new VisualizationSelectionZoneItem{&plot};
119 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
119 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
120 m_DrawingZone->setEditionEnabled(false);
120 m_DrawingZone->setEditionEnabled(false);
121 }
121 }
122
122
123 void endDrawingZone(QCustomPlot &plot)
123 void endDrawingZone(QCustomPlot &plot)
124 {
124 {
125 if (m_DrawingZone) {
125 if (m_DrawingZone) {
126 auto drawingZoneRange = m_DrawingZone->range();
126 auto drawingZoneRange = m_DrawingZone->range();
127 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
127 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
128 m_DrawingZone->setEditionEnabled(true);
128 m_DrawingZone->setEditionEnabled(true);
129 m_SelectionZones.append(m_DrawingZone);
129 m_SelectionZones.append(m_DrawingZone);
130 }
130 }
131 else {
131 else {
132 plot.removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
132 plot.removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
133 }
133 }
134
134
135 plot.replot(QCustomPlot::rpQueuedReplot);
135 plot.replot(QCustomPlot::rpQueuedReplot);
136 m_DrawingZone = nullptr;
136 m_DrawingZone = nullptr;
137 }
137 }
138 }
138 }
139
139
140 void setSelectionZonesEditionEnabled(bool value)
140 void setSelectionZonesEditionEnabled(bool value)
141 {
141 {
142 for (auto s : m_SelectionZones) {
142 for (auto s : m_SelectionZones) {
143 s->setEditionEnabled(value);
143 s->setEditionEnabled(value);
144 }
144 }
145 }
145 }
146
146
147 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
147 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
148 const QCustomPlot &plot) const
148 const QCustomPlot &plot) const
149 {
149 {
150 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
150 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
151 auto minDistanceToZone = -1;
151 auto minDistanceToZone = -1;
152 for (auto zone : m_SelectionZones) {
152 for (auto zone : m_SelectionZones) {
153 auto distanceToZone = zone->selectTest(pos, false);
153 auto distanceToZone = zone->selectTest(pos, false);
154 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
154 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
155 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
155 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
156 selectionZoneItemUnderCursor = zone;
156 selectionZoneItemUnderCursor = zone;
157 }
157 }
158 }
158 }
159
159
160 return selectionZoneItemUnderCursor;
160 return selectionZoneItemUnderCursor;
161 }
161 }
162
162
163 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
163 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
164 {
164 {
165 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
165 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
166 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
166 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
167 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
167 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
168 }
168 }
169
169
170 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
170 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
171 {
171 {
172 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
172 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
173 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
173 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
174 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
174 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
175 }
175 }
176 };
176 };
177
177
178 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
178 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
179 : VisualizationDragWidget{parent},
179 : VisualizationDragWidget{parent},
180 ui{new Ui::VisualizationGraphWidget},
180 ui{new Ui::VisualizationGraphWidget},
181 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
181 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
182 {
182 {
183 ui->setupUi(this);
183 ui->setupUi(this);
184
184
185 // 'Close' options : widget is deleted when closed
185 // 'Close' options : widget is deleted when closed
186 setAttribute(Qt::WA_DeleteOnClose);
186 setAttribute(Qt::WA_DeleteOnClose);
187
187
188 // Set qcpplot properties :
188 // Set qcpplot properties :
189 // - zoom is enabled
189 // - zoom is enabled
190 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
190 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
191 ui->widget->setInteractions(QCP::iRangeZoom | QCP::iSelectItems);
191 ui->widget->setInteractions(QCP::iRangeZoom | QCP::iSelectItems);
192 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
192 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
193
193
194 // The delegate must be initialized after the ui as it uses the plot
194 // The delegate must be initialized after the ui as it uses the plot
195 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
195 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
196
196
197 // Init the cursors
197 // Init the cursors
198 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
198 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
199 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
199 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
200 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
200 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
201 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
201 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
202
202
203 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
203 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
204 connect(ui->widget, &QCustomPlot::mouseRelease, this,
204 connect(ui->widget, &QCustomPlot::mouseRelease, this,
205 &VisualizationGraphWidget::onMouseRelease);
205 &VisualizationGraphWidget::onMouseRelease);
206 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
206 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
207 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
207 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
208 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
208 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
209 &VisualizationGraphWidget::onMouseDoubleClick);
209 &VisualizationGraphWidget::onMouseDoubleClick);
210 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
210 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
211 &QCPAxis::rangeChanged),
211 &QCPAxis::rangeChanged),
212 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
212 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
213
213
214 // Activates menu when right clicking on the graph
214 // Activates menu when right clicking on the graph
215 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
215 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
216 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
216 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
217 &VisualizationGraphWidget::onGraphMenuRequested);
217 &VisualizationGraphWidget::onGraphMenuRequested);
218
218
219 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
219 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
220 &VariableController::onRequestDataLoading);
220 &VariableController::onRequestDataLoading);
221
221
222 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
222 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
223 &VisualizationGraphWidget::onUpdateVarDisplaying);
223 &VisualizationGraphWidget::onUpdateVarDisplaying);
224
224
225 #ifdef Q_OS_MAC
225 #ifdef Q_OS_MAC
226 plot().setPlottingHint(QCP::phFastPolylines, true);
226 plot().setPlottingHint(QCP::phFastPolylines, true);
227 #endif
227 #endif
228 }
228 }
229
229
230
230
231 VisualizationGraphWidget::~VisualizationGraphWidget()
231 VisualizationGraphWidget::~VisualizationGraphWidget()
232 {
232 {
233 delete ui;
233 delete ui;
234 }
234 }
235
235
236 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
236 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
237 {
237 {
238 auto parent = parentWidget();
238 auto parent = parentWidget();
239 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
239 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
240 parent = parent->parentWidget();
240 parent = parent->parentWidget();
241 }
241 }
242
242
243 return qobject_cast<VisualizationZoneWidget *>(parent);
243 return qobject_cast<VisualizationZoneWidget *>(parent);
244 }
244 }
245
245
246 void VisualizationGraphWidget::enableAcquisition(bool enable)
246 void VisualizationGraphWidget::enableAcquisition(bool enable)
247 {
247 {
248 impl->m_DoAcquisition = enable;
248 impl->m_DoAcquisition = enable;
249 }
249 }
250
250
251 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
251 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
252 {
252 {
253 // Uses delegate to create the qcpplot components according to the variable
253 // Uses delegate to create the qcpplot components according to the variable
254 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
254 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
255
255
256 if (auto dataSeries = variable->dataSeries()) {
256 if (auto dataSeries = variable->dataSeries()) {
257 // Set axes properties according to the units of the data series
257 // Set axes properties according to the units of the data series
258 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
258 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
259
259
260 // Sets rendering properties for the new plottables
260 // Sets rendering properties for the new plottables
261 // Warning: this method must be called after setAxesProperties(), as it can access to some
261 // Warning: this method must be called after setAxesProperties(), as it can access to some
262 // axes properties that have to be initialized
262 // axes properties that have to be initialized
263 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
263 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
264 }
264 }
265
265
266 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
266 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
267
267
268 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
268 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
269
269
270 this->enableAcquisition(false);
270 this->enableAcquisition(false);
271 this->setGraphRange(range);
271 this->setGraphRange(range);
272 this->enableAcquisition(true);
272 this->enableAcquisition(true);
273
273
274 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
274 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
275
275
276 emit variableAdded(variable);
276 emit variableAdded(variable);
277 }
277 }
278
278
279 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
279 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
280 {
280 {
281 // Each component associated to the variable :
281 // Each component associated to the variable :
282 // - is removed from qcpplot (which deletes it)
282 // - is removed from qcpplot (which deletes it)
283 // - is no longer referenced in the map
283 // - is no longer referenced in the map
284 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
284 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
285 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
285 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
286 emit variableAboutToBeRemoved(variable);
286 emit variableAboutToBeRemoved(variable);
287
287
288 auto &plottablesMap = variableIt->second;
288 auto &plottablesMap = variableIt->second;
289
289
290 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
290 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
291 plottableIt != plottableEnd;) {
291 plottableIt != plottableEnd;) {
292 ui->widget->removePlottable(plottableIt->second);
292 ui->widget->removePlottable(plottableIt->second);
293 plottableIt = plottablesMap.erase(plottableIt);
293 plottableIt = plottablesMap.erase(plottableIt);
294 }
294 }
295
295
296 impl->m_VariableToPlotMultiMap.erase(variableIt);
296 impl->m_VariableToPlotMultiMap.erase(variableIt);
297 }
297 }
298
298
299 // Updates graph
299 // Updates graph
300 ui->widget->replot();
300 ui->widget->replot();
301 }
301 }
302
302
303 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
303 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
304 {
304 {
305 auto variables = QList<std::shared_ptr<Variable> >{};
305 auto variables = QList<std::shared_ptr<Variable> >{};
306 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
306 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
307 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
307 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
308 variables << it->first;
308 variables << it->first;
309 }
309 }
310
310
311 return variables;
311 return variables;
312 }
312 }
313
313
314 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
314 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
315 {
315 {
316 if (!variable) {
316 if (!variable) {
317 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
317 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
318 return;
318 return;
319 }
319 }
320
320
321 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
321 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
322 }
322 }
323
323
324 SqpRange VisualizationGraphWidget::graphRange() const noexcept
324 SqpRange VisualizationGraphWidget::graphRange() const noexcept
325 {
325 {
326 auto graphRange = ui->widget->xAxis->range();
326 auto graphRange = ui->widget->xAxis->range();
327 return SqpRange{graphRange.lower, graphRange.upper};
327 return SqpRange{graphRange.lower, graphRange.upper};
328 }
328 }
329
329
330 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
330 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
331 {
331 {
332 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
332 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
333 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
333 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
334 ui->widget->replot();
334 ui->widget->replot();
335 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
335 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
336 }
336 }
337
337
338 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
339 {
340 QVector<SqpRange> ranges;
341 for (auto zone : impl->m_SelectionZones) {
342 ranges << zone->range();
343 }
344
345 return ranges;
346 }
347
348 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges)
349 {
350 for (const auto &range : ranges) {
351 auto zone = new VisualizationSelectionZoneItem(&plot());
352 zone->setRange(range.m_TStart, range.m_TEnd);
353 impl->m_SelectionZones << zone;
354 }
355
356 plot().replot(QCustomPlot::rpQueuedReplot);
357 }
358
338 void VisualizationGraphWidget::undoZoom()
359 void VisualizationGraphWidget::undoZoom()
339 {
360 {
340 auto zoom = impl->m_ZoomStack.pop();
361 auto zoom = impl->m_ZoomStack.pop();
341 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
362 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
342 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
363 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
343
364
344 axisX->setRange(zoom.first);
365 axisX->setRange(zoom.first);
345 axisY->setRange(zoom.second);
366 axisY->setRange(zoom.second);
346
367
347 plot().replot(QCustomPlot::rpQueuedReplot);
368 plot().replot(QCustomPlot::rpQueuedReplot);
348 }
369 }
349
370
350 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
371 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
351 {
372 {
352 if (visitor) {
373 if (visitor) {
353 visitor->visit(this);
374 visitor->visit(this);
354 }
375 }
355 else {
376 else {
356 qCCritical(LOG_VisualizationGraphWidget())
377 qCCritical(LOG_VisualizationGraphWidget())
357 << tr("Can't visit widget : the visitor is null");
378 << tr("Can't visit widget : the visitor is null");
358 }
379 }
359 }
380 }
360
381
361 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
382 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
362 {
383 {
363 auto isSpectrogram = [](const auto &variable) {
384 auto isSpectrogram = [](const auto &variable) {
364 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
385 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
365 };
386 };
366
387
367 // - A spectrogram series can't be dropped on graph with existing plottables
388 // - A spectrogram series can't be dropped on graph with existing plottables
368 // - No data series can be dropped on graph with existing spectrogram series
389 // - No data series can be dropped on graph with existing spectrogram series
369 return isSpectrogram(variable)
390 return isSpectrogram(variable)
370 ? impl->m_VariableToPlotMultiMap.empty()
391 ? impl->m_VariableToPlotMultiMap.empty()
371 : std::none_of(
392 : std::none_of(
372 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
393 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
373 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
394 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
374 }
395 }
375
396
376 bool VisualizationGraphWidget::contains(const Variable &variable) const
397 bool VisualizationGraphWidget::contains(const Variable &variable) const
377 {
398 {
378 // Finds the variable among the keys of the map
399 // Finds the variable among the keys of the map
379 auto variablePtr = &variable;
400 auto variablePtr = &variable;
380 auto findVariable
401 auto findVariable
381 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
402 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
382
403
383 auto end = impl->m_VariableToPlotMultiMap.cend();
404 auto end = impl->m_VariableToPlotMultiMap.cend();
384 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
405 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
385 return it != end;
406 return it != end;
386 }
407 }
387
408
388 QString VisualizationGraphWidget::name() const
409 QString VisualizationGraphWidget::name() const
389 {
410 {
390 return impl->m_Name;
411 return impl->m_Name;
391 }
412 }
392
413
393 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
414 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
394 {
415 {
395 auto mimeData = new QMimeData;
416 auto mimeData = new QMimeData;
396
417
397 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
418 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
398 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
419 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
399 && selectionZoneItemUnderCursor) {
420 && selectionZoneItemUnderCursor) {
400 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
421 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
401 selectionZoneItemUnderCursor->range()));
422 selectionZoneItemUnderCursor->range()));
402 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
423 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
403 selectionZoneItemUnderCursor->range()));
424 selectionZoneItemUnderCursor->range()));
404 }
425 }
405 else {
426 else {
406 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
427 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
407
428
408 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
429 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
409 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
430 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
410 }
431 }
411
432
412 return mimeData;
433 return mimeData;
413 }
434 }
414
435
415 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
436 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
416 {
437 {
417 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
438 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
418 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
439 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
419 && selectionZoneItemUnderCursor) {
440 && selectionZoneItemUnderCursor) {
420
441
421 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
442 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
422 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
443 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
423
444
424 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
445 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
425 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
446 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
426 .toSize();
447 .toSize();
427
448
428 auto pixmap = QPixmap(zoneSize);
449 auto pixmap = QPixmap(zoneSize);
429 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
450 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
430
451
431 return pixmap;
452 return pixmap;
432 }
453 }
433
454
434 return QPixmap();
455 return QPixmap();
435 }
456 }
436
457
437 bool VisualizationGraphWidget::isDragAllowed() const
458 bool VisualizationGraphWidget::isDragAllowed() const
438 {
459 {
439 return true;
460 return true;
440 }
461 }
441
462
442 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
463 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
443 {
464 {
444 if (highlighted) {
465 if (highlighted) {
445 plot().setBackground(QBrush(QColor("#BBD5EE")));
466 plot().setBackground(QBrush(QColor("#BBD5EE")));
446 }
467 }
447 else {
468 else {
448 plot().setBackground(QBrush(Qt::white));
469 plot().setBackground(QBrush(Qt::white));
449 }
470 }
450
471
451 plot().update();
472 plot().update();
452 }
473 }
453
474
454 void VisualizationGraphWidget::addVerticalCursor(double time)
475 void VisualizationGraphWidget::addVerticalCursor(double time)
455 {
476 {
456 impl->m_VerticalCursor->setPosition(time);
477 impl->m_VerticalCursor->setPosition(time);
457 impl->m_VerticalCursor->setVisible(true);
478 impl->m_VerticalCursor->setVisible(true);
458
479
459 auto text
480 auto text
460 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
481 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
461 impl->m_VerticalCursor->setLabelText(text);
482 impl->m_VerticalCursor->setLabelText(text);
462 }
483 }
463
484
464 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
485 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
465 {
486 {
466 impl->m_VerticalCursor->setAbsolutePosition(position);
487 impl->m_VerticalCursor->setAbsolutePosition(position);
467 impl->m_VerticalCursor->setVisible(true);
488 impl->m_VerticalCursor->setVisible(true);
468
489
469 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
490 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
470 auto text
491 auto text
471 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
492 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
472 impl->m_VerticalCursor->setLabelText(text);
493 impl->m_VerticalCursor->setLabelText(text);
473 }
494 }
474
495
475 void VisualizationGraphWidget::removeVerticalCursor()
496 void VisualizationGraphWidget::removeVerticalCursor()
476 {
497 {
477 impl->m_VerticalCursor->setVisible(false);
498 impl->m_VerticalCursor->setVisible(false);
478 plot().replot(QCustomPlot::rpQueuedReplot);
499 plot().replot(QCustomPlot::rpQueuedReplot);
479 }
500 }
480
501
481 void VisualizationGraphWidget::addHorizontalCursor(double value)
502 void VisualizationGraphWidget::addHorizontalCursor(double value)
482 {
503 {
483 impl->m_HorizontalCursor->setPosition(value);
504 impl->m_HorizontalCursor->setPosition(value);
484 impl->m_HorizontalCursor->setVisible(true);
505 impl->m_HorizontalCursor->setVisible(true);
485 impl->m_HorizontalCursor->setLabelText(QString::number(value));
506 impl->m_HorizontalCursor->setLabelText(QString::number(value));
486 }
507 }
487
508
488 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
509 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
489 {
510 {
490 impl->m_HorizontalCursor->setAbsolutePosition(position);
511 impl->m_HorizontalCursor->setAbsolutePosition(position);
491 impl->m_HorizontalCursor->setVisible(true);
512 impl->m_HorizontalCursor->setVisible(true);
492
513
493 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
514 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
494 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
515 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
495 }
516 }
496
517
497 void VisualizationGraphWidget::removeHorizontalCursor()
518 void VisualizationGraphWidget::removeHorizontalCursor()
498 {
519 {
499 impl->m_HorizontalCursor->setVisible(false);
520 impl->m_HorizontalCursor->setVisible(false);
500 plot().replot(QCustomPlot::rpQueuedReplot);
521 plot().replot(QCustomPlot::rpQueuedReplot);
501 }
522 }
502
523
503 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
524 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
504 {
525 {
505 Q_UNUSED(event);
526 Q_UNUSED(event);
506
527
507 // Prevents that all variables will be removed from graph when it will be closed
528 // Prevents that all variables will be removed from graph when it will be closed
508 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
529 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
509 emit variableAboutToBeRemoved(variableEntry.first);
530 emit variableAboutToBeRemoved(variableEntry.first);
510 }
531 }
511 }
532 }
512
533
513 void VisualizationGraphWidget::enterEvent(QEvent *event)
534 void VisualizationGraphWidget::enterEvent(QEvent *event)
514 {
535 {
515 Q_UNUSED(event);
536 Q_UNUSED(event);
516 impl->m_RenderingDelegate->showGraphOverlay(true);
537 impl->m_RenderingDelegate->showGraphOverlay(true);
517 }
538 }
518
539
519 void VisualizationGraphWidget::leaveEvent(QEvent *event)
540 void VisualizationGraphWidget::leaveEvent(QEvent *event)
520 {
541 {
521 Q_UNUSED(event);
542 Q_UNUSED(event);
522 impl->m_RenderingDelegate->showGraphOverlay(false);
543 impl->m_RenderingDelegate->showGraphOverlay(false);
523
544
524 if (auto parentZone = parentZoneWidget()) {
545 if (auto parentZone = parentZoneWidget()) {
525 parentZone->notifyMouseLeaveGraph(this);
546 parentZone->notifyMouseLeaveGraph(this);
526 }
547 }
527 else {
548 else {
528 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
549 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
529 }
550 }
530
551
531 if (impl->m_HoveredZone) {
552 if (impl->m_HoveredZone) {
532 impl->m_HoveredZone->setHovered(false);
553 impl->m_HoveredZone->setHovered(false);
533 impl->m_HoveredZone = nullptr;
554 impl->m_HoveredZone = nullptr;
534 }
555 }
535 }
556 }
536
557
537 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
558 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
538 {
559 {
539 return *ui->widget;
560 return *ui->widget;
540 }
561 }
541
562
542 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
563 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
543 {
564 {
544 QMenu graphMenu{};
565 QMenu graphMenu{};
545
566
546 // Iterates on variables (unique keys)
567 // Iterates on variables (unique keys)
547 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
568 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
548 end = impl->m_VariableToPlotMultiMap.cend();
569 end = impl->m_VariableToPlotMultiMap.cend();
549 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
570 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
550 // 'Remove variable' action
571 // 'Remove variable' action
551 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
572 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
552 [ this, var = it->first ]() { removeVariable(var); });
573 [ this, var = it->first ]() { removeVariable(var); });
553 }
574 }
554
575
555 if (!impl->m_ZoomStack.isEmpty()) {
576 if (!impl->m_ZoomStack.isEmpty()) {
556 if (!graphMenu.isEmpty()) {
577 if (!graphMenu.isEmpty()) {
557 graphMenu.addSeparator();
578 graphMenu.addSeparator();
558 }
579 }
559
580
560 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
581 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
561 }
582 }
562
583
563 if (!graphMenu.isEmpty()) {
584 if (!graphMenu.isEmpty()) {
564 graphMenu.exec(QCursor::pos());
585 graphMenu.exec(QCursor::pos());
565 }
586 }
566 }
587 }
567
588
568 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
589 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
569 {
590 {
570 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
591 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
571 << QThread::currentThread()->objectName() << "DoAcqui"
592 << QThread::currentThread()->objectName() << "DoAcqui"
572 << impl->m_DoAcquisition;
593 << impl->m_DoAcquisition;
573
594
574 auto graphRange = SqpRange{t1.lower, t1.upper};
595 auto graphRange = SqpRange{t1.lower, t1.upper};
575 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
596 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
576
597
577 if (impl->m_DoAcquisition) {
598 if (impl->m_DoAcquisition) {
578 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
599 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
579
600
580 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
601 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
581 end = impl->m_VariableToPlotMultiMap.end();
602 end = impl->m_VariableToPlotMultiMap.end();
582 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
603 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
583 variableUnderGraphVector.push_back(it->first);
604 variableUnderGraphVector.push_back(it->first);
584 }
605 }
585 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
606 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
586 !impl->m_IsCalibration);
607 !impl->m_IsCalibration);
587
608
588 if (!impl->m_IsCalibration) {
609 if (!impl->m_IsCalibration) {
589 qCDebug(LOG_VisualizationGraphWidget())
610 qCDebug(LOG_VisualizationGraphWidget())
590 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
611 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
591 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
612 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
592 emit synchronize(graphRange, oldGraphRange);
613 emit synchronize(graphRange, oldGraphRange);
593 }
614 }
594 }
615 }
595
616
596 auto pos = mapFromGlobal(QCursor::pos());
617 auto pos = mapFromGlobal(QCursor::pos());
597 auto axisPos = impl->posToAxisPos(pos, plot());
618 auto axisPos = impl->posToAxisPos(pos, plot());
598 if (auto parentZone = parentZoneWidget()) {
619 if (auto parentZone = parentZoneWidget()) {
599 if (impl->pointIsInAxisRect(axisPos, plot())) {
620 if (impl->pointIsInAxisRect(axisPos, plot())) {
600 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
621 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
601 }
622 }
602 else {
623 else {
603 parentZone->notifyMouseLeaveGraph(this);
624 parentZone->notifyMouseLeaveGraph(this);
604 }
625 }
605 }
626 }
606 else {
627 else {
607 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
628 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
608 }
629 }
609 }
630 }
610
631
611 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
632 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
612 {
633 {
613 impl->m_RenderingDelegate->onMouseDoubleClick(event);
634 impl->m_RenderingDelegate->onMouseDoubleClick(event);
614 }
635 }
615
636
616 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
637 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
617 {
638 {
618 // Handles plot rendering when mouse is moving
639 // Handles plot rendering when mouse is moving
619 impl->m_RenderingDelegate->onMouseMove(event);
640 impl->m_RenderingDelegate->onMouseMove(event);
620
641
621 auto axisPos = impl->posToAxisPos(event->pos(), plot());
642 auto axisPos = impl->posToAxisPos(event->pos(), plot());
622
643
623 // Zoom box and zone drawing
644 // Zoom box and zone drawing
624 if (impl->m_DrawingZoomRect) {
645 if (impl->m_DrawingZoomRect) {
625 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
646 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
626 }
647 }
627 else if (impl->m_DrawingZone) {
648 else if (impl->m_DrawingZone) {
628 impl->m_DrawingZone->setEnd(axisPos.x());
649 impl->m_DrawingZone->setEnd(axisPos.x());
629 }
650 }
630
651
631 // Cursor
652 // Cursor
632 if (auto parentZone = parentZoneWidget()) {
653 if (auto parentZone = parentZoneWidget()) {
633 if (impl->pointIsInAxisRect(axisPos, plot())) {
654 if (impl->pointIsInAxisRect(axisPos, plot())) {
634 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
655 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
635 }
656 }
636 else {
657 else {
637 parentZone->notifyMouseLeaveGraph(this);
658 parentZone->notifyMouseLeaveGraph(this);
638 }
659 }
639 }
660 }
640 else {
661 else {
641 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
662 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
642 }
663 }
643
664
644 // Search for the selection zone under the mouse
665 // Search for the selection zone under the mouse
645 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
666 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
646 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
667 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
647 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
668 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
648
669
649 // Sets the appropriate cursor shape
670 // Sets the appropriate cursor shape
650 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
671 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
651 setCursor(cursorShape);
672 setCursor(cursorShape);
652
673
653 // Manages the hovered zone
674 // Manages the hovered zone
654 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
675 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
655 if (impl->m_HoveredZone) {
676 if (impl->m_HoveredZone) {
656 impl->m_HoveredZone->setHovered(false);
677 impl->m_HoveredZone->setHovered(false);
657 }
678 }
658 selectionZoneItemUnderCursor->setHovered(true);
679 selectionZoneItemUnderCursor->setHovered(true);
659 impl->m_HoveredZone = selectionZoneItemUnderCursor;
680 impl->m_HoveredZone = selectionZoneItemUnderCursor;
660 plot().replot(QCustomPlot::rpQueuedReplot);
681 plot().replot(QCustomPlot::rpQueuedReplot);
661 }
682 }
662 }
683 }
663 else {
684 else {
664 // There is no zone under the mouse or the interaction mode is not "selection zones"
685 // There is no zone under the mouse or the interaction mode is not "selection zones"
665 if (impl->m_HoveredZone) {
686 if (impl->m_HoveredZone) {
666 impl->m_HoveredZone->setHovered(false);
687 impl->m_HoveredZone->setHovered(false);
667 impl->m_HoveredZone = nullptr;
688 impl->m_HoveredZone = nullptr;
668 }
689 }
669
690
670 setCursor(Qt::ArrowCursor);
691 setCursor(Qt::ArrowCursor);
671 }
692 }
672
693
673 VisualizationDragWidget::mouseMoveEvent(event);
694 VisualizationDragWidget::mouseMoveEvent(event);
674 }
695 }
675
696
676 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
697 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
677 {
698 {
678 auto value = event->angleDelta().x() + event->angleDelta().y();
699 auto value = event->angleDelta().x() + event->angleDelta().y();
679 if (value != 0) {
700 if (value != 0) {
680
701
681 auto direction = value > 0 ? 1.0 : -1.0;
702 auto direction = value > 0 ? 1.0 : -1.0;
682 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
703 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
683 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
704 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
684 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
705 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
685
706
686 auto zoomOrientations = QFlags<Qt::Orientation>{};
707 auto zoomOrientations = QFlags<Qt::Orientation>{};
687 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
708 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
688 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
709 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
689
710
690 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
711 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
691
712
692 if (!isZoomX && !isZoomY) {
713 if (!isZoomX && !isZoomY) {
693 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
714 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
694 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
715 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
695
716
696 axis->setRange(axis->range() + diff);
717 axis->setRange(axis->range() + diff);
697
718
698 if (plot().noAntialiasingOnDrag()) {
719 if (plot().noAntialiasingOnDrag()) {
699 plot().setNotAntialiasedElements(QCP::aeAll);
720 plot().setNotAntialiasedElements(QCP::aeAll);
700 }
721 }
701
722
702 plot().replot(QCustomPlot::rpQueuedReplot);
723 plot().replot(QCustomPlot::rpQueuedReplot);
703 }
724 }
704 }
725 }
705 }
726 }
706
727
707 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
728 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
708 {
729 {
709 bool isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
730 bool isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
710
731
711 if (!isDragDropClick) {
732 if (!isDragDropClick) {
712 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
733 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
713 // Starts a zoom box
734 // Starts a zoom box
714 impl->startDrawingRect(event->pos(), plot());
735 impl->startDrawingRect(event->pos(), plot());
715 }
736 }
716 else if (sqpApp->plotsInteractionMode()
737 else if (sqpApp->plotsInteractionMode()
717 == SqpApplication::PlotsInteractionMode::SelectionZones
738 == SqpApplication::PlotsInteractionMode::SelectionZones
718 && impl->m_DrawingZone == nullptr) {
739 && impl->m_DrawingZone == nullptr) {
719 // Starts a new selection zone
740 // Starts a new selection zone
720 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
741 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
721 if (!zoneAtPos) {
742 if (!zoneAtPos) {
722 impl->startDrawingZone(event->pos(), plot());
743 impl->startDrawingZone(event->pos(), plot());
723 }
744 }
724 }
745 }
725 }
746 }
726 else if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::None) {
747 else if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::None) {
727 plot().setInteraction(QCP::iRangeDrag, true);
748 plot().setInteraction(QCP::iRangeDrag, true);
728 }
749 }
729
750
730 // Allows mouse panning only in default mode
751 // Allows mouse panning only in default mode
731 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
752 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
732 == SqpApplication::PlotsInteractionMode::None
753 == SqpApplication::PlotsInteractionMode::None
733 && !isDragDropClick);
754 && !isDragDropClick);
734
755
735 // Allows zone edition only in selection zone mode without ALT pressed (ALT is for drag&drop)
756 // Allows zone edition only in selection zone mode without ALT pressed (ALT is for drag&drop)
736 impl->setSelectionZonesEditionEnabled(
757 impl->setSelectionZonesEditionEnabled(
737 sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
758 sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
738 && !isDragDropClick);
759 && !isDragDropClick);
739
760
740 VisualizationDragWidget::mousePressEvent(event);
761 VisualizationDragWidget::mousePressEvent(event);
741 }
762 }
742
763
743 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
764 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
744 {
765 {
745 if (impl->m_DrawingZoomRect) {
766 if (impl->m_DrawingZoomRect) {
746
767
747 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
768 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
748 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
769 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
749
770
750 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
771 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
751 impl->m_DrawingZoomRect->bottomRight->coords().x()};
772 impl->m_DrawingZoomRect->bottomRight->coords().x()};
752
773
753 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
774 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
754 impl->m_DrawingZoomRect->bottomRight->coords().y()};
775 impl->m_DrawingZoomRect->bottomRight->coords().y()};
755
776
756 impl->removeDrawingRect(plot());
777 impl->removeDrawingRect(plot());
757
778
758 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
779 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
759 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
780 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
760 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
781 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
761 axisX->setRange(newAxisXRange);
782 axisX->setRange(newAxisXRange);
762 axisY->setRange(newAxisYRange);
783 axisY->setRange(newAxisYRange);
763
784
764 plot().replot(QCustomPlot::rpQueuedReplot);
785 plot().replot(QCustomPlot::rpQueuedReplot);
765 }
786 }
766 }
787 }
767
788
768 impl->endDrawingZone(plot());
789 impl->endDrawingZone(plot());
769
790
770 impl->m_IsCalibration = false;
791 impl->m_IsCalibration = false;
771 }
792 }
772
793
773 void VisualizationGraphWidget::onDataCacheVariableUpdated()
794 void VisualizationGraphWidget::onDataCacheVariableUpdated()
774 {
795 {
775 auto graphRange = ui->widget->xAxis->range();
796 auto graphRange = ui->widget->xAxis->range();
776 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
797 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
777
798
778 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
799 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
779 auto variable = variableEntry.first;
800 auto variable = variableEntry.first;
780 qCDebug(LOG_VisualizationGraphWidget())
801 qCDebug(LOG_VisualizationGraphWidget())
781 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
802 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
782 qCDebug(LOG_VisualizationGraphWidget())
803 qCDebug(LOG_VisualizationGraphWidget())
783 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
804 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
784 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
805 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
785 impl->updateData(variableEntry.second, variable->dataSeries(), variable->range());
806 impl->updateData(variableEntry.second, variable->dataSeries(), variable->range());
786 }
807 }
787 }
808 }
788 }
809 }
789
810
790 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
811 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
791 const SqpRange &range)
812 const SqpRange &range)
792 {
813 {
793 auto it = impl->m_VariableToPlotMultiMap.find(variable);
814 auto it = impl->m_VariableToPlotMultiMap.find(variable);
794 if (it != impl->m_VariableToPlotMultiMap.end()) {
815 if (it != impl->m_VariableToPlotMultiMap.end()) {
795 impl->updateData(it->second, variable->dataSeries(), range);
816 impl->updateData(it->second, variable->dataSeries(), range);
796 }
817 }
797 }
818 }
@@ -1,320 +1,329
1 #include "Visualization/VisualizationTabWidget.h"
1 #include "Visualization/VisualizationTabWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "ui_VisualizationTabWidget.h"
3 #include "ui_VisualizationTabWidget.h"
4
4
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7
7
8 #include "Visualization/MacScrollBarStyle.h"
8 #include "Visualization/MacScrollBarStyle.h"
9
9
10 #include "Variable/VariableController.h"
10 #include "Variable/VariableController.h"
11
11
12 #include "Common/MimeTypesDef.h"
12 #include "Common/MimeTypesDef.h"
13
13
14 #include "DragAndDrop/DragDropHelper.h"
14 #include "DragAndDrop/DragDropHelper.h"
15 #include "SqpApplication.h"
15 #include "SqpApplication.h"
16
16
17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
18
18
19 namespace {
19 namespace {
20
20
21 /// Generates a default name for a new zone, according to the number of zones already displayed in
21 /// Generates a default name for a new zone, according to the number of zones already displayed in
22 /// the tab
22 /// the tab
23 QString defaultZoneName(const QLayout &layout)
23 QString defaultZoneName(const QLayout &layout)
24 {
24 {
25 auto count = 0;
25 auto count = 0;
26 for (auto i = 0; i < layout.count(); ++i) {
26 for (auto i = 0; i < layout.count(); ++i) {
27 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
27 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
28 count++;
28 count++;
29 }
29 }
30 }
30 }
31
31
32 return QObject::tr("Zone %1").arg(count + 1);
32 return QObject::tr("Zone %1").arg(count + 1);
33 }
33 }
34
34
35 /**
35 /**
36 * Applies a function to all zones of the tab represented by its layout
36 * Applies a function to all zones of the tab represented by its layout
37 * @param layout the layout that contains zones
37 * @param layout the layout that contains zones
38 * @param fun the function to apply to each zone
38 * @param fun the function to apply to each zone
39 */
39 */
40 template <typename Fun>
40 template <typename Fun>
41 void processZones(QLayout &layout, Fun fun)
41 void processZones(QLayout &layout, Fun fun)
42 {
42 {
43 for (auto i = 0; i < layout.count(); ++i) {
43 for (auto i = 0; i < layout.count(); ++i) {
44 if (auto item = layout.itemAt(i)) {
44 if (auto item = layout.itemAt(i)) {
45 if (auto visualizationZoneWidget
45 if (auto visualizationZoneWidget
46 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
46 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
47 fun(*visualizationZoneWidget);
47 fun(*visualizationZoneWidget);
48 }
48 }
49 }
49 }
50 }
50 }
51 }
51 }
52
52
53 } // namespace
53 } // namespace
54
54
55 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
55 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
56 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
56 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
57
57
58 QString m_Name;
58 QString m_Name;
59
59
60 #ifdef Q_OS_MAC
60 #ifdef Q_OS_MAC
61 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
61 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
62 #endif
62 #endif
63
63
64 void dropGraph(int index, VisualizationTabWidget *tabWidget);
64 void dropGraph(int index, VisualizationTabWidget *tabWidget);
65 void dropZone(int index, VisualizationTabWidget *tabWidget);
65 void dropZone(int index, VisualizationTabWidget *tabWidget);
66 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
66 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
67 VisualizationTabWidget *tabWidget);
67 VisualizationTabWidget *tabWidget);
68 };
68 };
69
69
70 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
70 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
71 : QWidget{parent},
71 : QWidget{parent},
72 ui{new Ui::VisualizationTabWidget},
72 ui{new Ui::VisualizationTabWidget},
73 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
73 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
74 {
74 {
75 ui->setupUi(this);
75 ui->setupUi(this);
76
76
77 #ifdef Q_OS_MAC
77 #ifdef Q_OS_MAC
78 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
78 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
79 #endif
79 #endif
80
80
81 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Zone, "Zone");
81 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Zone, "Zone");
82 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
82 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
83 ui->dragDropContainer->layout()->setSpacing(0);
83 ui->dragDropContainer->layout()->setSpacing(0);
84 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
84 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
85 VisualizationDragDropContainer::DropBehavior::Inserted);
85 VisualizationDragDropContainer::DropBehavior::Inserted);
86 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
86 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
87 VisualizationDragDropContainer::DropBehavior::Inserted);
87 VisualizationDragDropContainer::DropBehavior::Inserted);
88 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
88 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
89 VisualizationDragDropContainer::DropBehavior::Inserted);
89 VisualizationDragDropContainer::DropBehavior::Inserted);
90
90
91 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
91 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
92 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
92 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
93 ui->dragDropContainer);
93 ui->dragDropContainer);
94 });
94 });
95
95
96 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
96 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
97 &VisualizationTabWidget::dropMimeData);
97 &VisualizationTabWidget::dropMimeData);
98
98
99 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
99 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
100
100
101 // Widget is deleted when closed
101 // Widget is deleted when closed
102 setAttribute(Qt::WA_DeleteOnClose);
102 setAttribute(Qt::WA_DeleteOnClose);
103 }
103 }
104
104
105 VisualizationTabWidget::~VisualizationTabWidget()
105 VisualizationTabWidget::~VisualizationTabWidget()
106 {
106 {
107 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
107 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
108 delete ui;
108 delete ui;
109 }
109 }
110
110
111 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
111 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
112 {
112 {
113 ui->dragDropContainer->addDragWidget(zoneWidget);
113 ui->dragDropContainer->addDragWidget(zoneWidget);
114 }
114 }
115
115
116 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
116 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
117 {
117 {
118 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
118 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
119 }
119 }
120
120
121 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
121 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
122 {
122 {
123 return createZone({variable}, -1);
123 return createZone({variable}, -1);
124 }
124 }
125
125
126 VisualizationZoneWidget *
126 VisualizationZoneWidget *
127 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
127 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
128 {
128 {
129 auto zoneWidget = createEmptyZone(index);
129 auto zoneWidget = createEmptyZone(index);
130
130
131 // Creates a new graph into the zone
131 // Creates a new graph into the zone
132 zoneWidget->createGraph(variables, index);
132 zoneWidget->createGraph(variables, index);
133
133
134 return zoneWidget;
134 return zoneWidget;
135 }
135 }
136
136
137 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
137 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
138 {
138 {
139 auto zoneWidget
139 auto zoneWidget
140 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
140 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
141 this->insertZone(index, zoneWidget);
141 this->insertZone(index, zoneWidget);
142
142
143 return zoneWidget;
143 return zoneWidget;
144 }
144 }
145
145
146 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
146 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
147 {
147 {
148 if (visitor) {
148 if (visitor) {
149 visitor->visitEnter(this);
149 visitor->visitEnter(this);
150
150
151 // Apply visitor to zone children: widgets different from zones are not visited (no action)
151 // Apply visitor to zone children: widgets different from zones are not visited (no action)
152 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
152 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
153 zoneWidget.accept(visitor);
153 zoneWidget.accept(visitor);
154 });
154 });
155
155
156 visitor->visitLeave(this);
156 visitor->visitLeave(this);
157 }
157 }
158 else {
158 else {
159 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
159 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
160 }
160 }
161 }
161 }
162
162
163 bool VisualizationTabWidget::canDrop(const Variable &variable) const
163 bool VisualizationTabWidget::canDrop(const Variable &variable) const
164 {
164 {
165 // A tab can always accomodate a variable
165 // A tab can always accomodate a variable
166 Q_UNUSED(variable);
166 Q_UNUSED(variable);
167 return true;
167 return true;
168 }
168 }
169
169
170 bool VisualizationTabWidget::contains(const Variable &variable) const
170 bool VisualizationTabWidget::contains(const Variable &variable) const
171 {
171 {
172 Q_UNUSED(variable);
172 Q_UNUSED(variable);
173 return false;
173 return false;
174 }
174 }
175
175
176 QString VisualizationTabWidget::name() const
176 QString VisualizationTabWidget::name() const
177 {
177 {
178 return impl->m_Name;
178 return impl->m_Name;
179 }
179 }
180
180
181 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
181 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
182 {
182 {
183 // Closes zones in the tab
183 // Closes zones in the tab
184 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
184 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
185
185
186 QWidget::closeEvent(event);
186 QWidget::closeEvent(event);
187 }
187 }
188
188
189 QLayout &VisualizationTabWidget::tabLayout() const noexcept
189 QLayout &VisualizationTabWidget::tabLayout() const noexcept
190 {
190 {
191 return *ui->dragDropContainer->layout();
191 return *ui->dragDropContainer->layout();
192 }
192 }
193
193
194 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
194 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
195 {
195 {
196 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
196 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
197 impl->dropGraph(index, this);
197 impl->dropGraph(index, this);
198 }
198 }
199 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
199 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
200 impl->dropZone(index, this);
200 impl->dropZone(index, this);
201 }
201 }
202 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
202 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
203 auto variables = sqpApp->variableController().variablesForMimeData(
203 auto variables = sqpApp->variableController().variablesForMimeData(
204 mimeData->data(MIME_TYPE_VARIABLE_LIST));
204 mimeData->data(MIME_TYPE_VARIABLE_LIST));
205 impl->dropVariables(variables, index, this);
205 impl->dropVariables(variables, index, this);
206 }
206 }
207 else {
207 else {
208 qCWarning(LOG_VisualizationZoneWidget())
208 qCWarning(LOG_VisualizationZoneWidget())
209 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
209 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
210 }
210 }
211 }
211 }
212
212
213 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
213 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
214 int index, VisualizationTabWidget *tabWidget)
214 int index, VisualizationTabWidget *tabWidget)
215 {
215 {
216 auto &helper = sqpApp->dragDropHelper();
216 auto &helper = sqpApp->dragDropHelper();
217
217
218 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
218 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
219 if (!graphWidget) {
219 if (!graphWidget) {
220 qCWarning(LOG_VisualizationZoneWidget())
220 qCWarning(LOG_VisualizationZoneWidget())
221 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
221 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
222 "found or invalid.");
222 "found or invalid.");
223 Q_ASSERT(false);
223 Q_ASSERT(false);
224 return;
224 return;
225 }
225 }
226
226
227 auto parentDragDropContainer
227 auto parentDragDropContainer
228 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
228 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
229 if (!parentDragDropContainer) {
229 if (!parentDragDropContainer) {
230 qCWarning(LOG_VisualizationZoneWidget())
230 qCWarning(LOG_VisualizationZoneWidget())
231 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
231 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
232 "the dropped graph is not found.");
232 "the dropped graph is not found.");
233 Q_ASSERT(false);
233 Q_ASSERT(false);
234 return;
234 return;
235 }
235 }
236
236
237 auto nbGraph = parentDragDropContainer->countDragWidget();
237 auto nbGraph = parentDragDropContainer->countDragWidget();
238
238
239 const auto &variables = graphWidget->variables();
239 const auto &variables = graphWidget->variables();
240
240
241 if (!variables.isEmpty()) {
241 if (!variables.isEmpty()) {
242 // Abort the requests for the variables (if any)
242 // Abort the requests for the variables (if any)
243 // Commented, because it's not sure if it's needed or not
243 // Commented, because it's not sure if it's needed or not
244 // for (const auto& var : variables)
244 // for (const auto& var : variables)
245 //{
245 //{
246 // sqpApp->variableController().onAbortProgressRequested(var);
246 // sqpApp->variableController().onAbortProgressRequested(var);
247 //}
247 //}
248
248
249 if (nbGraph == 1) {
249 if (nbGraph == 1) {
250 // This is the only graph in the previous zone, close the zone
250 // This is the only graph in the previous zone, close the zone
251 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
251 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
252 }
252 }
253 else {
253 else {
254 // Close the graph
254 // Close the graph
255 helper.delayedCloseWidget(graphWidget);
255 helper.delayedCloseWidget(graphWidget);
256 }
256 }
257
257
258 tabWidget->createZone(variables, index);
258 auto zoneWidget = tabWidget->createZone(variables, index);
259 auto firstGraph = zoneWidget->firstGraph();
260 if (firstGraph) {
261 firstGraph->addSelectionZones(graphWidget->selectionZoneRanges());
262 }
263 else {
264 qCWarning(LOG_VisualizationZoneWidget())
265 << tr("VisualizationTabWidget::dropGraph, no graph added in the widget.");
266 Q_ASSERT(false);
267 }
259 }
268 }
260 else {
269 else {
261 // The graph is empty, create an empty zone and move the graph inside
270 // The graph is empty, create an empty zone and move the graph inside
262
271
263 auto parentZoneWidget = graphWidget->parentZoneWidget();
272 auto parentZoneWidget = graphWidget->parentZoneWidget();
264
273
265 parentDragDropContainer->layout()->removeWidget(graphWidget);
274 parentDragDropContainer->layout()->removeWidget(graphWidget);
266
275
267 auto zoneWidget = tabWidget->createEmptyZone(index);
276 auto zoneWidget = tabWidget->createEmptyZone(index);
268 zoneWidget->addGraph(graphWidget);
277 zoneWidget->addGraph(graphWidget);
269
278
270 // Close the old zone if it was the only graph inside
279 // Close the old zone if it was the only graph inside
271 if (nbGraph == 1) {
280 if (nbGraph == 1) {
272 helper.delayedCloseWidget(parentZoneWidget);
281 helper.delayedCloseWidget(parentZoneWidget);
273 }
282 }
274 }
283 }
275 }
284 }
276
285
277 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
286 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
278 int index, VisualizationTabWidget *tabWidget)
287 int index, VisualizationTabWidget *tabWidget)
279 {
288 {
280 auto &helper = sqpApp->dragDropHelper();
289 auto &helper = sqpApp->dragDropHelper();
281
290
282 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
291 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
283 if (!zoneWidget) {
292 if (!zoneWidget) {
284 qCWarning(LOG_VisualizationZoneWidget())
293 qCWarning(LOG_VisualizationZoneWidget())
285 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
294 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
286 "found or invalid.");
295 "found or invalid.");
287 Q_ASSERT(false);
296 Q_ASSERT(false);
288 return;
297 return;
289 }
298 }
290
299
291 auto parentDragDropContainer
300 auto parentDragDropContainer
292 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
301 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
293 if (!parentDragDropContainer) {
302 if (!parentDragDropContainer) {
294 qCWarning(LOG_VisualizationZoneWidget())
303 qCWarning(LOG_VisualizationZoneWidget())
295 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
304 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
296 "the dropped zone is not found.");
305 "the dropped zone is not found.");
297 Q_ASSERT(false);
306 Q_ASSERT(false);
298 return;
307 return;
299 }
308 }
300
309
301 // Simple move of the zone, no variable operation associated
310 // Simple move of the zone, no variable operation associated
302 parentDragDropContainer->layout()->removeWidget(zoneWidget);
311 parentDragDropContainer->layout()->removeWidget(zoneWidget);
303 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
312 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
304 }
313 }
305
314
306 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
315 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
307 const QList<std::shared_ptr<Variable> > &variables, int index,
316 const QList<std::shared_ptr<Variable> > &variables, int index,
308 VisualizationTabWidget *tabWidget)
317 VisualizationTabWidget *tabWidget)
309 {
318 {
310 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
319 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
311 // compatible variable here
320 // compatible variable here
312 if (variables.count() > 1) {
321 if (variables.count() > 1) {
313 qCWarning(LOG_VisualizationZoneWidget())
322 qCWarning(LOG_VisualizationZoneWidget())
314 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
323 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
315 "aborted.");
324 "aborted.");
316 return;
325 return;
317 }
326 }
318
327
319 tabWidget->createZone(variables, index);
328 tabWidget->createZone(variables, index);
320 }
329 }
@@ -1,587 +1,587
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/VisualizationWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
8
8
9 #include "Common/MimeTypesDef.h"
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
10 #include "Common/VisualizationDef.h"
11
11
12 #include <Data/SqpRange.h>
12 #include <Data/SqpRange.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14 #include <Variable/Variable.h>
14 #include <Variable/Variable.h>
15 #include <Variable/VariableController.h>
15 #include <Variable/VariableController.h>
16
16
17 #include <Visualization/operations/FindVariableOperation.h>
17 #include <Visualization/operations/FindVariableOperation.h>
18
18
19 #include <DragAndDrop/DragDropHelper.h>
19 #include <DragAndDrop/DragDropHelper.h>
20 #include <QUuid>
20 #include <QUuid>
21 #include <SqpApplication.h>
21 #include <SqpApplication.h>
22 #include <cmath>
22 #include <cmath>
23
23
24 #include <QLayout>
24 #include <QLayout>
25
25
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27
27
28 namespace {
28 namespace {
29
29
30
30
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
32 /// the zone
32 /// the zone
33 QString defaultGraphName(const QLayout &layout)
33 QString defaultGraphName(const QLayout &layout)
34 {
34 {
35 auto count = 0;
35 auto count = 0;
36 for (auto i = 0; i < layout.count(); ++i) {
36 for (auto i = 0; i < layout.count(); ++i) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
38 count++;
38 count++;
39 }
39 }
40 }
40 }
41
41
42 return QObject::tr("Graph %1").arg(count + 1);
42 return QObject::tr("Graph %1").arg(count + 1);
43 }
43 }
44
44
45 /**
45 /**
46 * Applies a function to all graphs of the zone represented by its layout
46 * Applies a function to all graphs of the zone represented by its layout
47 * @param layout the layout that contains graphs
47 * @param layout the layout that contains graphs
48 * @param fun the function to apply to each graph
48 * @param fun the function to apply to each graph
49 */
49 */
50 template <typename Fun>
50 template <typename Fun>
51 void processGraphs(QLayout &layout, Fun fun)
51 void processGraphs(QLayout &layout, Fun fun)
52 {
52 {
53 for (auto i = 0; i < layout.count(); ++i) {
53 for (auto i = 0; i < layout.count(); ++i) {
54 if (auto item = layout.itemAt(i)) {
54 if (auto item = layout.itemAt(i)) {
55 if (auto visualizationGraphWidget
55 if (auto visualizationGraphWidget
56 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
56 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
57 fun(*visualizationGraphWidget);
57 fun(*visualizationGraphWidget);
58 }
58 }
59 }
59 }
60 }
60 }
61 }
61 }
62
62
63 } // namespace
63 } // namespace
64
64
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
66
66
67 explicit VisualizationZoneWidgetPrivate()
67 explicit VisualizationZoneWidgetPrivate()
68 : m_SynchronisationGroupId{QUuid::createUuid()},
68 : m_SynchronisationGroupId{QUuid::createUuid()},
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
70 {
70 {
71 }
71 }
72 QUuid m_SynchronisationGroupId;
72 QUuid m_SynchronisationGroupId;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
74
74
75 // Returns the first graph in the zone or nullptr if there is no graph inside
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
77 {
78 VisualizationGraphWidget *firstGraph = nullptr;
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
80 if (layout->count() > 0) {
81 if (auto visualizationGraphWidget
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
83 firstGraph = visualizationGraphWidget;
84 }
85 }
86
87 return firstGraph;
88 }
89
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
75 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
76 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
92 VisualizationZoneWidget *zoneWidget);
77 VisualizationZoneWidget *zoneWidget);
93 };
78 };
94
79
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
80 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
96 : VisualizationDragWidget{parent},
81 : VisualizationDragWidget{parent},
97 ui{new Ui::VisualizationZoneWidget},
82 ui{new Ui::VisualizationZoneWidget},
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
83 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
99 {
84 {
100 ui->setupUi(this);
85 ui->setupUi(this);
101
86
102 ui->zoneNameLabel->setText(name);
87 ui->zoneNameLabel->setText(name);
103
88
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
89 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
105 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
90 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
106 VisualizationDragDropContainer::DropBehavior::Inserted);
91 VisualizationDragDropContainer::DropBehavior::Inserted);
107 ui->dragDropContainer->setMimeType(
92 ui->dragDropContainer->setMimeType(
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
93 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
109 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
94 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
110 VisualizationDragDropContainer::DropBehavior::Merged);
95 VisualizationDragDropContainer::DropBehavior::Merged);
111 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
96 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
112 VisualizationDragDropContainer::DropBehavior::Forbidden);
97 VisualizationDragDropContainer::DropBehavior::Forbidden);
113 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
98 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
114 VisualizationDragDropContainer::DropBehavior::Forbidden);
99 VisualizationDragDropContainer::DropBehavior::Forbidden);
115 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
100 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
116 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
101 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
117 ui->dragDropContainer);
102 ui->dragDropContainer);
118 });
103 });
119
104
120 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
105 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
121 if (!mimeData) {
106 if (!mimeData) {
122 return false;
107 return false;
123 }
108 }
124
109
125 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
110 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
126 auto variables = sqpApp->variableController().variablesForMimeData(
111 auto variables = sqpApp->variableController().variablesForMimeData(
127 mimeData->data(MIME_TYPE_VARIABLE_LIST));
112 mimeData->data(MIME_TYPE_VARIABLE_LIST));
128
113
129 if (variables.count() != 1) {
114 if (variables.count() != 1) {
130 return false;
115 return false;
131 }
116 }
132 auto variable = variables.first();
117 auto variable = variables.first();
133
118
134 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
119 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
135 return graphWidget->canDrop(*variable);
120 return graphWidget->canDrop(*variable);
136 }
121 }
137 }
122 }
138
123
139 return true;
124 return true;
140 };
125 };
141 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
126 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
142
127
143 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
128 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
144 &VisualizationZoneWidget::dropMimeData);
129 &VisualizationZoneWidget::dropMimeData);
145 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
130 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
146 &VisualizationZoneWidget::dropMimeDataOnGraph);
131 &VisualizationZoneWidget::dropMimeDataOnGraph);
147
132
148 // 'Close' options : widget is deleted when closed
133 // 'Close' options : widget is deleted when closed
149 setAttribute(Qt::WA_DeleteOnClose);
134 setAttribute(Qt::WA_DeleteOnClose);
150 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
135 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
151 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
136 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
152
137
153 // Synchronisation id
138 // Synchronisation id
154 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
139 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
155 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
140 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
156 }
141 }
157
142
158 VisualizationZoneWidget::~VisualizationZoneWidget()
143 VisualizationZoneWidget::~VisualizationZoneWidget()
159 {
144 {
160 delete ui;
145 delete ui;
161 }
146 }
162
147
163 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
148 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
164 {
149 {
165 // Synchronize new graph with others in the zone
150 // Synchronize new graph with others in the zone
166 impl->m_Synchronizer->addGraph(*graphWidget);
151 impl->m_Synchronizer->addGraph(*graphWidget);
167
152
168 ui->dragDropContainer->addDragWidget(graphWidget);
153 ui->dragDropContainer->addDragWidget(graphWidget);
169 }
154 }
170
155
171 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
156 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
172 {
157 {
173 // Synchronize new graph with others in the zone
158 // Synchronize new graph with others in the zone
174 impl->m_Synchronizer->addGraph(*graphWidget);
159 impl->m_Synchronizer->addGraph(*graphWidget);
175
160
176 ui->dragDropContainer->insertDragWidget(index, graphWidget);
161 ui->dragDropContainer->insertDragWidget(index, graphWidget);
177 }
162 }
178
163
179 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
164 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
180 {
165 {
181 return createGraph(variable, -1);
166 return createGraph(variable, -1);
182 }
167 }
183
168
184 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
169 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
185 int index)
170 int index)
186 {
171 {
187 auto graphWidget
172 auto graphWidget
188 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
173 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
189
174
190
175
191 // Set graph properties
176 // Set graph properties
192 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
177 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
193 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
178 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
194
179
195
180
196 // Lambda to synchronize zone widget
181 // Lambda to synchronize zone widget
197 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
182 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
198 const SqpRange &oldGraphRange) {
183 const SqpRange &oldGraphRange) {
199
184
200 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
185 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
201 auto frameLayout = ui->dragDropContainer->layout();
186 auto frameLayout = ui->dragDropContainer->layout();
202 for (auto i = 0; i < frameLayout->count(); ++i) {
187 for (auto i = 0; i < frameLayout->count(); ++i) {
203 auto graphChild
188 auto graphChild
204 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
189 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
205 if (graphChild && (graphChild != graphWidget)) {
190 if (graphChild && (graphChild != graphWidget)) {
206
191
207 auto graphChildRange = graphChild->graphRange();
192 auto graphChildRange = graphChild->graphRange();
208 switch (zoomType) {
193 switch (zoomType) {
209 case AcquisitionZoomType::ZoomIn: {
194 case AcquisitionZoomType::ZoomIn: {
210 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
195 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
211 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
196 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
212 graphChildRange.m_TStart += deltaLeft;
197 graphChildRange.m_TStart += deltaLeft;
213 graphChildRange.m_TEnd -= deltaRight;
198 graphChildRange.m_TEnd -= deltaRight;
214 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
215 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
200 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
216 << deltaLeft;
201 << deltaLeft;
217 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
218 << deltaRight;
203 << deltaRight;
219 qCDebug(LOG_VisualizationZoneWidget())
204 qCDebug(LOG_VisualizationZoneWidget())
220 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
205 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
221
206
222 break;
207 break;
223 }
208 }
224
209
225 case AcquisitionZoomType::ZoomOut: {
210 case AcquisitionZoomType::ZoomOut: {
226 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
211 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
227 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
212 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
228 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
213 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
229 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
214 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
230 << deltaLeft;
215 << deltaLeft;
231 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
216 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
232 << deltaRight;
217 << deltaRight;
233 qCDebug(LOG_VisualizationZoneWidget())
218 qCDebug(LOG_VisualizationZoneWidget())
234 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
219 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
235 graphChildRange.m_TStart -= deltaLeft;
220 graphChildRange.m_TStart -= deltaLeft;
236 graphChildRange.m_TEnd += deltaRight;
221 graphChildRange.m_TEnd += deltaRight;
237 break;
222 break;
238 }
223 }
239 case AcquisitionZoomType::PanRight: {
224 case AcquisitionZoomType::PanRight: {
240 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
225 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
241 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
226 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
242 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
227 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
243 graphChildRange.m_TStart += deltaLeft;
228 graphChildRange.m_TStart += deltaLeft;
244 graphChildRange.m_TEnd += deltaRight;
229 graphChildRange.m_TEnd += deltaRight;
245 qCDebug(LOG_VisualizationZoneWidget())
230 qCDebug(LOG_VisualizationZoneWidget())
246 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
231 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
247 break;
232 break;
248 }
233 }
249 case AcquisitionZoomType::PanLeft: {
234 case AcquisitionZoomType::PanLeft: {
250 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
235 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
251 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
236 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
252 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
237 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
253 graphChildRange.m_TStart -= deltaLeft;
238 graphChildRange.m_TStart -= deltaLeft;
254 graphChildRange.m_TEnd -= deltaRight;
239 graphChildRange.m_TEnd -= deltaRight;
255 break;
240 break;
256 }
241 }
257 case AcquisitionZoomType::Unknown: {
242 case AcquisitionZoomType::Unknown: {
258 qCDebug(LOG_VisualizationZoneWidget())
243 qCDebug(LOG_VisualizationZoneWidget())
259 << tr("Impossible to synchronize: zoom type unknown");
244 << tr("Impossible to synchronize: zoom type unknown");
260 break;
245 break;
261 }
246 }
262 default:
247 default:
263 qCCritical(LOG_VisualizationZoneWidget())
248 qCCritical(LOG_VisualizationZoneWidget())
264 << tr("Impossible to synchronize: zoom type not take into account");
249 << tr("Impossible to synchronize: zoom type not take into account");
265 // No action
250 // No action
266 break;
251 break;
267 }
252 }
268 graphChild->enableAcquisition(false);
253 graphChild->enableAcquisition(false);
269 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
254 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
270 << graphChild->graphRange();
255 << graphChild->graphRange();
271 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
256 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
272 << graphChildRange;
257 << graphChildRange;
273 qCDebug(LOG_VisualizationZoneWidget())
258 qCDebug(LOG_VisualizationZoneWidget())
274 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
259 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
275 graphChild->setGraphRange(graphChildRange);
260 graphChild->setGraphRange(graphChildRange);
276 graphChild->enableAcquisition(true);
261 graphChild->enableAcquisition(true);
277 }
262 }
278 }
263 }
279 };
264 };
280
265
281 // connection for synchronization
266 // connection for synchronization
282 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
267 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
283 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
268 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
284 &VisualizationZoneWidget::onVariableAdded);
269 &VisualizationZoneWidget::onVariableAdded);
285 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
270 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
286 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
271 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
287
272
288 auto range = SqpRange{};
273 auto range = SqpRange{};
289 if (auto firstGraph = impl->firstGraph(this)) {
274 if (auto firstGraph = this->firstGraph()) {
290 // Case of a new graph in a existant zone
275 // Case of a new graph in a existant zone
291 range = firstGraph->graphRange();
276 range = firstGraph->graphRange();
292 }
277 }
293 else {
278 else {
294 // Case of a new graph as the first of the zone
279 // Case of a new graph as the first of the zone
295 range = variable->range();
280 range = variable->range();
296 }
281 }
297
282
298 this->insertGraph(index, graphWidget);
283 this->insertGraph(index, graphWidget);
299
284
300 graphWidget->addVariable(variable, range);
285 graphWidget->addVariable(variable, range);
301 graphWidget->setYRange(variable);
286 graphWidget->setYRange(variable);
302
287
303 return graphWidget;
288 return graphWidget;
304 }
289 }
305
290
306 VisualizationGraphWidget *
291 VisualizationGraphWidget *
307 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
292 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
308 {
293 {
309 if (variables.isEmpty()) {
294 if (variables.isEmpty()) {
310 return nullptr;
295 return nullptr;
311 }
296 }
312
297
313 auto graphWidget = createGraph(variables.first(), index);
298 auto graphWidget = createGraph(variables.first(), index);
314 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
299 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
315 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
300 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
316 }
301 }
317
302
318 return graphWidget;
303 return graphWidget;
319 }
304 }
320
305
306 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
307 {
308 VisualizationGraphWidget *firstGraph = nullptr;
309 auto layout = ui->dragDropContainer->layout();
310 if (layout->count() > 0) {
311 if (auto visualizationGraphWidget
312 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
313 firstGraph = visualizationGraphWidget;
314 }
315 }
316
317 return firstGraph;
318 }
319
321 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
320 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
322 {
321 {
323 if (visitor) {
322 if (visitor) {
324 visitor->visitEnter(this);
323 visitor->visitEnter(this);
325
324
326 // Apply visitor to graph children: widgets different from graphs are not visited (no
325 // Apply visitor to graph children: widgets different from graphs are not visited (no
327 // action)
326 // action)
328 processGraphs(
327 processGraphs(
329 *ui->dragDropContainer->layout(),
328 *ui->dragDropContainer->layout(),
330 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
329 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
331
330
332 visitor->visitLeave(this);
331 visitor->visitLeave(this);
333 }
332 }
334 else {
333 else {
335 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
334 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
336 }
335 }
337 }
336 }
338
337
339 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
338 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
340 {
339 {
341 // A tab can always accomodate a variable
340 // A tab can always accomodate a variable
342 Q_UNUSED(variable);
341 Q_UNUSED(variable);
343 return true;
342 return true;
344 }
343 }
345
344
346 bool VisualizationZoneWidget::contains(const Variable &variable) const
345 bool VisualizationZoneWidget::contains(const Variable &variable) const
347 {
346 {
348 Q_UNUSED(variable);
347 Q_UNUSED(variable);
349 return false;
348 return false;
350 }
349 }
351
350
352 QString VisualizationZoneWidget::name() const
351 QString VisualizationZoneWidget::name() const
353 {
352 {
354 return ui->zoneNameLabel->text();
353 return ui->zoneNameLabel->text();
355 }
354 }
356
355
357 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
356 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
358 {
357 {
359 Q_UNUSED(position);
358 Q_UNUSED(position);
360
359
361 auto mimeData = new QMimeData;
360 auto mimeData = new QMimeData;
362 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
361 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
363
362
364 if (auto firstGraph = impl->firstGraph(this)) {
363 if (auto firstGraph = this->firstGraph()) {
365 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
364 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
366 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
365 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
367 }
366 }
368
367
369 return mimeData;
368 return mimeData;
370 }
369 }
371
370
372 bool VisualizationZoneWidget::isDragAllowed() const
371 bool VisualizationZoneWidget::isDragAllowed() const
373 {
372 {
374 return true;
373 return true;
375 }
374 }
376
375
377 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
376 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
378 const QPointF &plotPosition,
377 const QPointF &plotPosition,
379 VisualizationGraphWidget *graphWidget)
378 VisualizationGraphWidget *graphWidget)
380 {
379 {
381 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
380 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
382 VisualizationGraphWidget &processedGraph) {
381 VisualizationGraphWidget &processedGraph) {
383
382
384 switch (sqpApp->plotsCursorMode()) {
383 switch (sqpApp->plotsCursorMode()) {
385 case SqpApplication::PlotsCursorMode::Vertical:
384 case SqpApplication::PlotsCursorMode::Vertical:
386 processedGraph.removeHorizontalCursor();
385 processedGraph.removeHorizontalCursor();
387 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
386 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
388 break;
387 break;
389 case SqpApplication::PlotsCursorMode::Temporal:
388 case SqpApplication::PlotsCursorMode::Temporal:
390 processedGraph.addVerticalCursor(plotPosition.x());
389 processedGraph.addVerticalCursor(plotPosition.x());
391 processedGraph.removeHorizontalCursor();
390 processedGraph.removeHorizontalCursor();
392 break;
391 break;
393 case SqpApplication::PlotsCursorMode::Horizontal:
392 case SqpApplication::PlotsCursorMode::Horizontal:
394 processedGraph.removeVerticalCursor();
393 processedGraph.removeVerticalCursor();
395 if (&processedGraph == graphWidget) {
394 if (&processedGraph == graphWidget) {
396 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
395 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
397 }
396 }
398 else {
397 else {
399 processedGraph.removeHorizontalCursor();
398 processedGraph.removeHorizontalCursor();
400 }
399 }
401 break;
400 break;
402 case SqpApplication::PlotsCursorMode::Cross:
401 case SqpApplication::PlotsCursorMode::Cross:
403 if (&processedGraph == graphWidget) {
402 if (&processedGraph == graphWidget) {
404 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
403 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
405 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
404 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
406 }
405 }
407 else {
406 else {
408 processedGraph.removeHorizontalCursor();
407 processedGraph.removeHorizontalCursor();
409 processedGraph.removeVerticalCursor();
408 processedGraph.removeVerticalCursor();
410 }
409 }
411 break;
410 break;
412 case SqpApplication::PlotsCursorMode::NoCursor:
411 case SqpApplication::PlotsCursorMode::NoCursor:
413 processedGraph.removeHorizontalCursor();
412 processedGraph.removeHorizontalCursor();
414 processedGraph.removeVerticalCursor();
413 processedGraph.removeVerticalCursor();
415 break;
414 break;
416 }
415 }
417
416
418
417
419 });
418 });
420 }
419 }
421
420
422 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
421 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
423 {
422 {
424 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
423 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
425 processedGraph.removeHorizontalCursor();
424 processedGraph.removeHorizontalCursor();
426 processedGraph.removeVerticalCursor();
425 processedGraph.removeVerticalCursor();
427 });
426 });
428 }
427 }
429
428
430 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
429 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
431 {
430 {
432 // Closes graphs in the zone
431 // Closes graphs in the zone
433 processGraphs(*ui->dragDropContainer->layout(),
432 processGraphs(*ui->dragDropContainer->layout(),
434 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
433 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
435
434
436 // Delete synchronization group from variable controller
435 // Delete synchronization group from variable controller
437 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
436 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
438 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
437 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
439
438
440 QWidget::closeEvent(event);
439 QWidget::closeEvent(event);
441 }
440 }
442
441
443 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
442 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
444 {
443 {
445 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
444 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
446 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
445 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
447 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
446 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
448 }
447 }
449
448
450 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
449 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
451 {
450 {
452 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
451 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
453 Q_ARG(std::shared_ptr<Variable>, variable),
452 Q_ARG(std::shared_ptr<Variable>, variable),
454 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
453 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
455 }
454 }
456
455
457 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
456 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
458 {
457 {
459 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
458 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
460 impl->dropGraph(index, this);
459 impl->dropGraph(index, this);
461 }
460 }
462 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
461 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
463 auto variables = sqpApp->variableController().variablesForMimeData(
462 auto variables = sqpApp->variableController().variablesForMimeData(
464 mimeData->data(MIME_TYPE_VARIABLE_LIST));
463 mimeData->data(MIME_TYPE_VARIABLE_LIST));
465 impl->dropVariables(variables, index, this);
464 impl->dropVariables(variables, index, this);
466 }
465 }
467 else {
466 else {
468 qCWarning(LOG_VisualizationZoneWidget())
467 qCWarning(LOG_VisualizationZoneWidget())
469 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
468 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
470 }
469 }
471 }
470 }
472
471
473 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
472 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
474 const QMimeData *mimeData)
473 const QMimeData *mimeData)
475 {
474 {
476 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
475 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
477 if (!graphWidget) {
476 if (!graphWidget) {
478 qCWarning(LOG_VisualizationZoneWidget())
477 qCWarning(LOG_VisualizationZoneWidget())
479 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
478 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
480 "drop aborted");
479 "drop aborted");
481 Q_ASSERT(false);
480 Q_ASSERT(false);
482 return;
481 return;
483 }
482 }
484
483
485 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
484 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
486 auto variables = sqpApp->variableController().variablesForMimeData(
485 auto variables = sqpApp->variableController().variablesForMimeData(
487 mimeData->data(MIME_TYPE_VARIABLE_LIST));
486 mimeData->data(MIME_TYPE_VARIABLE_LIST));
488 for (const auto &var : variables) {
487 for (const auto &var : variables) {
489 graphWidget->addVariable(var, graphWidget->graphRange());
488 graphWidget->addVariable(var, graphWidget->graphRange());
490 }
489 }
491 }
490 }
492 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
491 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
493 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
492 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
494 graphWidget->setGraphRange(range);
493 graphWidget->setGraphRange(range);
495 }
494 }
496 else {
495 else {
497 qCWarning(LOG_VisualizationZoneWidget())
496 qCWarning(LOG_VisualizationZoneWidget())
498 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
497 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
499 }
498 }
500 }
499 }
501
500
502 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
501 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
503 int index, VisualizationZoneWidget *zoneWidget)
502 int index, VisualizationZoneWidget *zoneWidget)
504 {
503 {
505 auto &helper = sqpApp->dragDropHelper();
504 auto &helper = sqpApp->dragDropHelper();
506
505
507 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
506 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
508 if (!graphWidget) {
507 if (!graphWidget) {
509 qCWarning(LOG_VisualizationZoneWidget())
508 qCWarning(LOG_VisualizationZoneWidget())
510 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
509 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
511 "found or invalid.");
510 "found or invalid.");
512 Q_ASSERT(false);
511 Q_ASSERT(false);
513 return;
512 return;
514 }
513 }
515
514
516 auto parentDragDropContainer
515 auto parentDragDropContainer
517 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
516 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
518 if (!parentDragDropContainer) {
517 if (!parentDragDropContainer) {
519 qCWarning(LOG_VisualizationZoneWidget())
518 qCWarning(LOG_VisualizationZoneWidget())
520 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
519 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
521 "the dropped graph is not found.");
520 "the dropped graph is not found.");
522 Q_ASSERT(false);
521 Q_ASSERT(false);
523 return;
522 return;
524 }
523 }
525
524
526 const auto &variables = graphWidget->variables();
525 const auto &variables = graphWidget->variables();
527
526
528 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
527 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
529 // The drop didn't occur in the same zone
528 // The drop didn't occur in the same zone
530
529
531 // Abort the requests for the variables (if any)
530 // Abort the requests for the variables (if any)
532 // Commented, because it's not sure if it's needed or not
531 // Commented, because it's not sure if it's needed or not
533 // for (const auto& var : variables)
532 // for (const auto& var : variables)
534 //{
533 //{
535 // sqpApp->variableController().onAbortProgressRequested(var);
534 // sqpApp->variableController().onAbortProgressRequested(var);
536 //}
535 //}
537
536
538 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
537 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
539 auto nbGraph = parentDragDropContainer->countDragWidget();
538 auto nbGraph = parentDragDropContainer->countDragWidget();
540 if (nbGraph == 1) {
539 if (nbGraph == 1) {
541 // This is the only graph in the previous zone, close the zone
540 // This is the only graph in the previous zone, close the zone
542 helper.delayedCloseWidget(previousParentZoneWidget);
541 helper.delayedCloseWidget(previousParentZoneWidget);
543 }
542 }
544 else {
543 else {
545 // Close the graph
544 // Close the graph
546 helper.delayedCloseWidget(graphWidget);
545 helper.delayedCloseWidget(graphWidget);
547 }
546 }
548
547
549 // Creates the new graph in the zone
548 // Creates the new graph in the zone
550 zoneWidget->createGraph(variables, index);
549 auto newGraphWidget = zoneWidget->createGraph(variables, index);
550 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
551 }
551 }
552 else {
552 else {
553 // The drop occurred in the same zone or the graph is empty
553 // The drop occurred in the same zone or the graph is empty
554 // Simple move of the graph, no variable operation associated
554 // Simple move of the graph, no variable operation associated
555 parentDragDropContainer->layout()->removeWidget(graphWidget);
555 parentDragDropContainer->layout()->removeWidget(graphWidget);
556
556
557 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
557 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
558 // The graph is empty and dropped in a different zone.
558 // The graph is empty and dropped in a different zone.
559 // Take the range of the first graph in the zone (if existing).
559 // Take the range of the first graph in the zone (if existing).
560 auto layout = zoneWidget->ui->dragDropContainer->layout();
560 auto layout = zoneWidget->ui->dragDropContainer->layout();
561 if (layout->count() > 0) {
561 if (layout->count() > 0) {
562 if (auto visualizationGraphWidget
562 if (auto visualizationGraphWidget
563 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
563 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
564 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
564 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
565 }
565 }
566 }
566 }
567 }
567 }
568
568
569 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
569 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
570 }
570 }
571 }
571 }
572
572
573 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
573 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
574 const QList<std::shared_ptr<Variable> > &variables, int index,
574 const QList<std::shared_ptr<Variable> > &variables, int index,
575 VisualizationZoneWidget *zoneWidget)
575 VisualizationZoneWidget *zoneWidget)
576 {
576 {
577 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
577 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
578 // compatible variable here
578 // compatible variable here
579 if (variables.count() > 1) {
579 if (variables.count() > 1) {
580 qCWarning(LOG_VisualizationZoneWidget())
580 qCWarning(LOG_VisualizationZoneWidget())
581 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
581 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
582 "aborted.");
582 "aborted.");
583 return;
583 return;
584 }
584 }
585
585
586 zoneWidget->createGraph(variables, index);
586 zoneWidget->createGraph(variables, index);
587 }
587 }
General Comments 0
You need to be logged in to leave comments. Login now