##// END OF EJS Templates
Implements cursor mode
trabillard -
r960:569b12637de1
parent child
Show More
@@ -0,0 +1,26
1 #ifndef VISUALIZATIONCURSORITEM_H
2 #define VISUALIZATIONCURSORITEM_H
3
4 #include <Common/spimpl.h>
5 #include <SqpApplication.h>
6
7 class QCustomPlot;
8
9 class VisualizationCursorItem {
10 public:
11 VisualizationCursorItem(QCustomPlot *plot);
12
13 void setVisible(bool value);
14 bool isVisible() const;
15
16 void setPosition(double value);
17 void setAbsolutePosition(double value);
18 void setOrientation(Qt::Orientation orientation);
19 void setLabelText(const QString &text);
20
21 private:
22 class VisualizationCursorItemPrivate;
23 spimpl::unique_impl_ptr<VisualizationCursorItemPrivate> impl;
24 };
25
26 #endif // VISUALIZATIONCURSORITEM_H
@@ -0,0 +1,163
1 #include <Common/DateUtils.h>
2 #include <Visualization/VisualizationCursorItem.h>
3 #include <Visualization/qcustomplot.h>
4
5 /// Width of the cursor in pixel
6 const auto CURSOR_WIDTH = 3;
7
8 /// Color of the cursor in the graph
9 const auto CURSOR_COLOR = QColor{68, 114, 196};
10
11 /// Line style of the cursor in the graph
12 auto CURSOR_PEN_STYLE = Qt::DotLine;
13
14 struct VisualizationCursorItem::VisualizationCursorItemPrivate {
15
16 QCustomPlot *m_Plot = nullptr;
17
18 QCPItemStraightLine *m_LineItem = nullptr;
19 QCPItemText *m_LabelItem = nullptr;
20
21 Qt::Orientation m_Orientation;
22 double m_Position = 0.0;
23 bool m_IsAbsolutePosition = false;
24 QString m_LabelText;
25
26 explicit VisualizationCursorItemPrivate(QCustomPlot *plot)
27 : m_Plot(plot), m_Orientation(Qt::Vertical)
28 {
29 }
30
31 void updateOrientation()
32 {
33 if (m_LineItem) {
34 switch (m_Orientation) {
35 case Qt::Vertical:
36 m_LineItem->point1->setTypeX(m_IsAbsolutePosition
37 ? QCPItemPosition::ptAbsolute
38 : QCPItemPosition::ptPlotCoords);
39 m_LineItem->point1->setTypeY(QCPItemPosition::ptAxisRectRatio);
40 m_LineItem->point2->setTypeX(m_IsAbsolutePosition
41 ? QCPItemPosition::ptAbsolute
42 : QCPItemPosition::ptPlotCoords);
43 m_LineItem->point2->setTypeY(QCPItemPosition::ptAxisRectRatio);
44 m_LabelItem->setPositionAlignment(Qt::AlignLeft | Qt::AlignTop);
45 break;
46 case Qt::Horizontal:
47 m_LineItem->point1->setTypeX(QCPItemPosition::ptAxisRectRatio);
48 m_LineItem->point1->setTypeY(m_IsAbsolutePosition
49 ? QCPItemPosition::ptAbsolute
50 : QCPItemPosition::ptPlotCoords);
51 m_LineItem->point2->setTypeX(QCPItemPosition::ptAxisRectRatio);
52 m_LineItem->point2->setTypeY(m_IsAbsolutePosition
53 ? QCPItemPosition::ptAbsolute
54 : QCPItemPosition::ptPlotCoords);
55 m_LabelItem->setPositionAlignment(Qt::AlignRight | Qt::AlignBottom);
56 }
57 }
58 }
59
60 void updateCursorPosition()
61 {
62 if (m_LineItem) {
63 switch (m_Orientation) {
64 case Qt::Vertical:
65 m_LineItem->point1->setCoords(m_Position, 0);
66 m_LineItem->point2->setCoords(m_Position, 1);
67 m_LabelItem->position->setCoords(5, 5);
68 break;
69 case Qt::Horizontal:
70 m_LineItem->point1->setCoords(1, m_Position);
71 m_LineItem->point2->setCoords(0, m_Position);
72 m_LabelItem->position->setCoords(-5, -5);
73 }
74 }
75 }
76
77 void updateLabelText()
78 {
79 if (m_LabelItem) {
80 m_LabelItem->setText(m_LabelText);
81 }
82 }
83 };
84
85 VisualizationCursorItem::VisualizationCursorItem(QCustomPlot *plot)
86 : impl{spimpl::make_unique_impl<VisualizationCursorItemPrivate>(plot)}
87 {
88 }
89
90 void VisualizationCursorItem::setVisible(bool value)
91 {
92 if (value != isVisible()) {
93
94 if (value) {
95 Q_ASSERT(!impl->m_LineItem && !impl->m_Plot);
96
97 impl->m_LineItem = new QCPItemStraightLine{impl->m_Plot};
98 auto pen = QPen{CURSOR_PEN_STYLE};
99 pen.setColor(CURSOR_COLOR);
100 pen.setWidth(CURSOR_WIDTH);
101 impl->m_LineItem->setPen(pen);
102 impl->m_LineItem->setSelectable(false);
103
104 impl->m_LabelItem = new QCPItemText{impl->m_Plot};
105 impl->m_LabelItem->setColor(CURSOR_COLOR);
106 impl->m_LabelItem->setSelectable(false);
107 impl->m_LabelItem->position->setParentAnchor(impl->m_LineItem->point1);
108 impl->m_LabelItem->position->setTypeX(QCPItemPosition::ptAbsolute);
109 impl->m_LabelItem->position->setTypeY(QCPItemPosition::ptAbsolute);
110
111 auto font = impl->m_LabelItem->font();
112 font.setPointSize(10);
113 font.setBold(true);
114 impl->m_LabelItem->setFont(font);
115
116 impl->updateOrientation();
117 impl->updateLabelText();
118 impl->updateCursorPosition();
119 }
120 else {
121 Q_ASSERT(impl->m_LineItem && impl->m_Plot);
122
123 // Note: the items are destroyed by QCustomPlot in removeItem
124 impl->m_Plot->removeItem(impl->m_LineItem);
125 impl->m_LineItem = nullptr;
126 impl->m_Plot->removeItem(impl->m_LabelItem);
127 impl->m_LabelItem = nullptr;
128 }
129 }
130 }
131
132 bool VisualizationCursorItem::isVisible() const
133 {
134 return impl->m_LineItem != nullptr;
135 }
136
137 void VisualizationCursorItem::setPosition(double value)
138 {
139 impl->m_Position = value;
140 impl->m_IsAbsolutePosition = false;
141 impl->updateLabelText();
142 impl->updateCursorPosition();
143 }
144
145 void VisualizationCursorItem::setAbsolutePosition(double value)
146 {
147 setPosition(value);
148 impl->m_IsAbsolutePosition = true;
149 }
150
151 void VisualizationCursorItem::setOrientation(Qt::Orientation orientation)
152 {
153 impl->m_Orientation = orientation;
154 impl->updateLabelText();
155 impl->updateOrientation();
156 impl->updateCursorPosition();
157 }
158
159 void VisualizationCursorItem::setLabelText(const QString &text)
160 {
161 impl->m_LabelText = text;
162 impl->updateLabelText();
163 }
@@ -1,7 +1,8
1 #ifndef SCIQLOP_VISUALIZATIONDEF_H
1 #ifndef SCIQLOP_VISUALIZATIONDEF_H
2 #define SCIQLOP_VISUALIZATIONDEF_H
2 #define SCIQLOP_VISUALIZATIONDEF_H
3
3
4 /// Minimum height for graph added in zones (in pixels)
4 /// Minimum height for graph added in zones (in pixels)
5 extern const int GRAPH_MINIMUM_HEIGHT;
5 extern const int GRAPH_MINIMUM_HEIGHT;
6
6
7
7 #endif // SCIQLOP_VISUALIZATIONDEF_H
8 #endif // SCIQLOP_VISUALIZATIONDEF_H
@@ -1,109 +1,121
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 // IVisualizationWidget interface
54 // IVisualizationWidget interface
55 void accept(IVisualizationWidgetVisitor *visitor) override;
55 void accept(IVisualizationWidgetVisitor *visitor) override;
56 bool canDrop(const Variable &variable) const override;
56 bool canDrop(const Variable &variable) const override;
57 bool contains(const Variable &variable) const override;
57 bool contains(const Variable &variable) const override;
58 QString name() const override;
58 QString name() const override;
59
59
60 // VisualisationDragWidget
60 // VisualisationDragWidget
61 QMimeData *mimeData() const override;
61 QMimeData *mimeData() const override;
62 bool isDragAllowed() const override;
62 bool isDragAllowed() const override;
63 void highlightForMerge(bool highlighted) override;
63 void highlightForMerge(bool highlighted) override;
64
64
65 // Cursors
66 /// Adds or moves the vertical cursor at the specified value on the x-axis
67 void addVerticalCursor(double time);
68 /// Adds or moves the vertical cursor at the specified value on the x-axis
69 void addVerticalCursorAtViewportPosition(double position);
70 void removeVerticalCursor();
71 /// Adds or moves the vertical cursor at the specified value on the y-axis
72 void addHorizontalCursor(double value);
73 /// Adds or moves the vertical cursor at the specified value on the y-axis
74 void addHorizontalCursorAtViewportPosition(double position);
75 void removeHorizontalCursor();
76
65 signals:
77 signals:
66 void synchronize(const SqpRange &range, const SqpRange &oldRange);
78 void synchronize(const SqpRange &range, const SqpRange &oldRange);
67 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
79 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
68 bool synchronise);
80 bool synchronise);
69
81
70 /// Signal emitted when the variable is about to be removed from the graph
82 /// Signal emitted when the variable is about to be removed from the graph
71 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
83 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
72 /// Signal emitted when the variable has been added to the graph
84 /// Signal emitted when the variable has been added to the graph
73 void variableAdded(std::shared_ptr<Variable> var);
85 void variableAdded(std::shared_ptr<Variable> var);
74
86
75 protected:
87 protected:
76 void closeEvent(QCloseEvent *event) override;
88 void closeEvent(QCloseEvent *event) override;
77 void enterEvent(QEvent *event) override;
89 void enterEvent(QEvent *event) override;
78 void leaveEvent(QEvent *event) override;
90 void leaveEvent(QEvent *event) override;
79
91
80 QCustomPlot &plot() noexcept;
92 QCustomPlot &plot() noexcept;
81
93
82 private:
94 private:
83 Ui::VisualizationGraphWidget *ui;
95 Ui::VisualizationGraphWidget *ui;
84
96
85 class VisualizationGraphWidgetPrivate;
97 class VisualizationGraphWidgetPrivate;
86 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
98 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
87
99
88 private slots:
100 private slots:
89 /// Slot called when right clicking on the graph (displays a menu)
101 /// Slot called when right clicking on the graph (displays a menu)
90 void onGraphMenuRequested(const QPoint &pos) noexcept;
102 void onGraphMenuRequested(const QPoint &pos) noexcept;
91
103
92 /// Rescale the X axe to range parameter
104 /// Rescale the X axe to range parameter
93 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
105 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
94
106
95 /// Slot called when a mouse move was made
107 /// Slot called when a mouse move was made
96 void onMouseMove(QMouseEvent *event) noexcept;
108 void onMouseMove(QMouseEvent *event) noexcept;
97 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
109 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
98 void onMouseWheel(QWheelEvent *event) noexcept;
110 void onMouseWheel(QWheelEvent *event) noexcept;
99 /// Slot called when a mouse press was made, to activate the calibration of a graph
111 /// Slot called when a mouse press was made, to activate the calibration of a graph
100 void onMousePress(QMouseEvent *event) noexcept;
112 void onMousePress(QMouseEvent *event) noexcept;
101 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
113 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
102 void onMouseRelease(QMouseEvent *event) noexcept;
114 void onMouseRelease(QMouseEvent *event) noexcept;
103
115
104 void onDataCacheVariableUpdated();
116 void onDataCacheVariableUpdated();
105
117
106 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
118 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
107 };
119 };
108
120
109 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
121 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,91 +1,95
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 // IVisualizationWidget interface
63 // IVisualizationWidget interface
64 void accept(IVisualizationWidgetVisitor *visitor) override;
64 void accept(IVisualizationWidgetVisitor *visitor) override;
65 bool canDrop(const Variable &variable) const override;
65 bool canDrop(const Variable &variable) const override;
66 bool contains(const Variable &variable) const override;
66 bool contains(const Variable &variable) const override;
67 QString name() const override;
67 QString name() const override;
68
68
69 // VisualisationDragWidget
69 // VisualisationDragWidget
70 QMimeData *mimeData() const override;
70 QMimeData *mimeData() const override;
71 bool isDragAllowed() const override;
71 bool isDragAllowed() const override;
72
72
73 void notifyMouseMoveInGraph(const QPointF &graphPosition, const QPointF &plotPosition,
74 VisualizationGraphWidget *graphWidget);
75 void notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget);
76
73 protected:
77 protected:
74 void closeEvent(QCloseEvent *event) override;
78 void closeEvent(QCloseEvent *event) override;
75
79
76 private:
80 private:
77 Ui::VisualizationZoneWidget *ui;
81 Ui::VisualizationZoneWidget *ui;
78
82
79 class VisualizationZoneWidgetPrivate;
83 class VisualizationZoneWidgetPrivate;
80 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
84 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
81
85
82 private slots:
86 private slots:
83 void onVariableAdded(std::shared_ptr<Variable> variable);
87 void onVariableAdded(std::shared_ptr<Variable> variable);
84 /// Slot called when a variable is about to be removed from a graph contained in the zone
88 /// Slot called when a variable is about to be removed from a graph contained in the zone
85 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
89 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
86
90
87 void dropMimeData(int index, const QMimeData *mimeData);
91 void dropMimeData(int index, const QMimeData *mimeData);
88 void dropMimeDataOnGraph(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
92 void dropMimeDataOnGraph(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
89 };
93 };
90
94
91 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
95 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -1,98 +1,99
1
1
2 gui_moc_headers = [
2 gui_moc_headers = [
3 'include/DataSource/DataSourceWidget.h',
3 'include/DataSource/DataSourceWidget.h',
4 'include/DataSource/DataSourceTreeWidget.h',
4 'include/DataSource/DataSourceTreeWidget.h',
5 'include/Settings/SqpSettingsDialog.h',
5 'include/Settings/SqpSettingsDialog.h',
6 'include/Settings/SqpSettingsGeneralWidget.h',
6 'include/Settings/SqpSettingsGeneralWidget.h',
7 'include/SidePane/SqpSidePane.h',
7 'include/SidePane/SqpSidePane.h',
8 'include/SqpApplication.h',
8 'include/SqpApplication.h',
9 'include/DragAndDrop/DragDropHelper.h',
9 'include/DragAndDrop/DragDropHelper.h',
10 'include/DragAndDrop/DragDropScroller.h',
10 'include/DragAndDrop/DragDropScroller.h',
11 'include/DragAndDrop/DragDropTabSwitcher.h',
11 'include/DragAndDrop/DragDropTabSwitcher.h',
12 'include/TimeWidget/TimeWidget.h',
12 'include/TimeWidget/TimeWidget.h',
13 'include/Variable/VariableInspectorWidget.h',
13 'include/Variable/VariableInspectorWidget.h',
14 'include/Variable/VariableInspectorTableView.h',
14 'include/Variable/VariableInspectorTableView.h',
15 'include/Variable/RenameVariableDialog.h',
15 'include/Variable/RenameVariableDialog.h',
16 'include/Visualization/qcustomplot.h',
16 'include/Visualization/qcustomplot.h',
17 'include/Visualization/VisualizationGraphWidget.h',
17 'include/Visualization/VisualizationGraphWidget.h',
18 'include/Visualization/VisualizationTabWidget.h',
18 'include/Visualization/VisualizationTabWidget.h',
19 'include/Visualization/VisualizationWidget.h',
19 'include/Visualization/VisualizationWidget.h',
20 'include/Visualization/VisualizationZoneWidget.h',
20 'include/Visualization/VisualizationZoneWidget.h',
21 'include/Visualization/VisualizationDragDropContainer.h',
21 'include/Visualization/VisualizationDragDropContainer.h',
22 'include/Visualization/VisualizationDragWidget.h'
22 'include/Visualization/VisualizationDragWidget.h'
23 ]
23 ]
24
24
25 gui_ui_files = [
25 gui_ui_files = [
26 'ui/DataSource/DataSourceWidget.ui',
26 'ui/DataSource/DataSourceWidget.ui',
27 'ui/Settings/SqpSettingsDialog.ui',
27 'ui/Settings/SqpSettingsDialog.ui',
28 'ui/Settings/SqpSettingsGeneralWidget.ui',
28 'ui/Settings/SqpSettingsGeneralWidget.ui',
29 'ui/SidePane/SqpSidePane.ui',
29 'ui/SidePane/SqpSidePane.ui',
30 'ui/TimeWidget/TimeWidget.ui',
30 'ui/TimeWidget/TimeWidget.ui',
31 'ui/Variable/VariableInspectorWidget.ui',
31 'ui/Variable/VariableInspectorWidget.ui',
32 'ui/Variable/RenameVariableDialog.ui',
32 'ui/Variable/RenameVariableDialog.ui',
33 'ui/Variable/VariableMenuHeaderWidget.ui',
33 'ui/Variable/VariableMenuHeaderWidget.ui',
34 'ui/Visualization/VisualizationGraphWidget.ui',
34 'ui/Visualization/VisualizationGraphWidget.ui',
35 'ui/Visualization/VisualizationTabWidget.ui',
35 'ui/Visualization/VisualizationTabWidget.ui',
36 'ui/Visualization/VisualizationWidget.ui',
36 'ui/Visualization/VisualizationWidget.ui',
37 'ui/Visualization/VisualizationZoneWidget.ui'
37 'ui/Visualization/VisualizationZoneWidget.ui'
38 ]
38 ]
39
39
40 gui_qresources = ['resources/sqpguiresources.qrc']
40 gui_qresources = ['resources/sqpguiresources.qrc']
41
41
42 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
42 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
43 ui_files : gui_ui_files,
43 ui_files : gui_ui_files,
44 qresources : gui_qresources)
44 qresources : gui_qresources)
45
45
46 gui_sources = [
46 gui_sources = [
47 'src/SqpApplication.cpp',
47 'src/SqpApplication.cpp',
48 'src/DragAndDrop/DragDropHelper.cpp',
48 'src/DragAndDrop/DragDropHelper.cpp',
49 'src/DragAndDrop/DragDropScroller.cpp',
49 'src/DragAndDrop/DragDropScroller.cpp',
50 'src/DragAndDrop/DragDropTabSwitcher.cpp',
50 'src/DragAndDrop/DragDropTabSwitcher.cpp',
51 'src/Common/ColorUtils.cpp',
51 'src/Common/ColorUtils.cpp',
52 'src/Common/VisualizationDef.cpp',
52 'src/Common/VisualizationDef.cpp',
53 'src/DataSource/DataSourceTreeWidgetItem.cpp',
53 'src/DataSource/DataSourceTreeWidgetItem.cpp',
54 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
54 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
55 'src/DataSource/DataSourceWidget.cpp',
55 'src/DataSource/DataSourceWidget.cpp',
56 'src/DataSource/DataSourceTreeWidget.cpp',
56 'src/DataSource/DataSourceTreeWidget.cpp',
57 'src/Settings/SqpSettingsDialog.cpp',
57 'src/Settings/SqpSettingsDialog.cpp',
58 'src/Settings/SqpSettingsGeneralWidget.cpp',
58 'src/Settings/SqpSettingsGeneralWidget.cpp',
59 'src/SidePane/SqpSidePane.cpp',
59 'src/SidePane/SqpSidePane.cpp',
60 'src/TimeWidget/TimeWidget.cpp',
60 'src/TimeWidget/TimeWidget.cpp',
61 'src/Variable/VariableInspectorWidget.cpp',
61 'src/Variable/VariableInspectorWidget.cpp',
62 'src/Variable/VariableInspectorTableView.cpp',
62 'src/Variable/VariableInspectorTableView.cpp',
63 'src/Variable/VariableMenuHeaderWidget.cpp',
63 'src/Variable/VariableMenuHeaderWidget.cpp',
64 'src/Variable/RenameVariableDialog.cpp',
64 'src/Variable/RenameVariableDialog.cpp',
65 'src/Visualization/VisualizationGraphHelper.cpp',
65 'src/Visualization/VisualizationGraphHelper.cpp',
66 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
66 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
67 'src/Visualization/VisualizationGraphWidget.cpp',
67 'src/Visualization/VisualizationGraphWidget.cpp',
68 'src/Visualization/VisualizationTabWidget.cpp',
68 'src/Visualization/VisualizationTabWidget.cpp',
69 'src/Visualization/VisualizationWidget.cpp',
69 'src/Visualization/VisualizationWidget.cpp',
70 'src/Visualization/VisualizationZoneWidget.cpp',
70 'src/Visualization/VisualizationZoneWidget.cpp',
71 'src/Visualization/qcustomplot.cpp',
71 'src/Visualization/qcustomplot.cpp',
72 'src/Visualization/QCustomPlotSynchronizer.cpp',
72 'src/Visualization/QCustomPlotSynchronizer.cpp',
73 'src/Visualization/operations/FindVariableOperation.cpp',
73 'src/Visualization/operations/FindVariableOperation.cpp',
74 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
74 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
75 'src/Visualization/operations/MenuBuilder.cpp',
75 'src/Visualization/operations/MenuBuilder.cpp',
76 'src/Visualization/operations/RemoveVariableOperation.cpp',
76 'src/Visualization/operations/RemoveVariableOperation.cpp',
77 'src/Visualization/operations/RescaleAxeOperation.cpp',
77 'src/Visualization/operations/RescaleAxeOperation.cpp',
78 'src/Visualization/VisualizationDragDropContainer.cpp',
78 'src/Visualization/VisualizationDragDropContainer.cpp',
79 'src/Visualization/VisualizationDragWidget.cpp',
79 'src/Visualization/VisualizationDragWidget.cpp',
80 'src/Visualization/AxisRenderingUtils.cpp',
80 'src/Visualization/AxisRenderingUtils.cpp',
81 'src/Visualization/PlottablesRenderingUtils.cpp',
81 'src/Visualization/PlottablesRenderingUtils.cpp',
82 'src/Visualization/MacScrollBarStyle.cpp'
82 'src/Visualization/MacScrollBarStyle.cpp',
83 'src/Visualization/VisualizationCursorItem.cpp'
83 ]
84 ]
84
85
85 gui_inc = include_directories(['include'])
86 gui_inc = include_directories(['include'])
86
87
87 sciqlop_gui_lib = library('sciqlopgui',
88 sciqlop_gui_lib = library('sciqlopgui',
88 gui_sources,
89 gui_sources,
89 gui_moc_files,
90 gui_moc_files,
90 include_directories : [gui_inc],
91 include_directories : [gui_inc],
91 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
92 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
92 install : true
93 install : true
93 )
94 )
94
95
95 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
96 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
96 include_directories : gui_inc,
97 include_directories : gui_inc,
97 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
98 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
98
99
@@ -1,472 +1,473
1 #include "Visualization/VisualizationDragDropContainer.h"
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragAndDrop/DragDropHelper.h"
2 #include "DragAndDrop/DragDropHelper.h"
3 #include "SqpApplication.h"
3 #include "SqpApplication.h"
4 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5
5
6 #include "Common/VisualizationDef.h"
6 #include "Common/VisualizationDef.h"
7
7
8 #include <QDrag>
8 #include <QDrag>
9 #include <QDragEnterEvent>
9 #include <QDragEnterEvent>
10 #include <QVBoxLayout>
10 #include <QVBoxLayout>
11
11
12 #include <cmath>
12 #include <cmath>
13 #include <memory>
13 #include <memory>
14
14
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
16
16
17 auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels
17 auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels
18
18
19 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
19 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
20
20
21 QVBoxLayout *m_Layout;
21 QVBoxLayout *m_Layout;
22 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
22 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
23 QString m_PlaceHolderText;
23 QString m_PlaceHolderText;
24 DragDropHelper::PlaceHolderType m_PlaceHolderType = DragDropHelper::PlaceHolderType::Graph;
24 DragDropHelper::PlaceHolderType m_PlaceHolderType;
25
25
26 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
26 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
27 = [](auto mimeData) { return true; };
27 = [](auto mimeData) { return true; };
28
28
29 int m_MinContainerHeight = 0;
29 int m_MinContainerHeight = 0;
30
30
31 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
31 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
32 : m_PlaceHolderType(DragDropHelper::PlaceHolderType::Graph)
32 {
33 {
33 m_Layout = new QVBoxLayout(widget);
34 m_Layout = new QVBoxLayout(widget);
34 m_Layout->setContentsMargins(0, 0, 0, 0);
35 m_Layout->setContentsMargins(0, 0, 0, 0);
35 }
36 }
36
37
37 bool acceptMimeData(const QMimeData *data) const
38 bool acceptMimeData(const QMimeData *data) const
38 {
39 {
39 auto accepted = false;
40 auto accepted = false;
40 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
41 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
41 ++it) {
42 ++it) {
42 const auto &type = it.key();
43 const auto &type = it.key();
43 const auto &behavior = it.value();
44 const auto &behavior = it.value();
44
45
45 if (data->hasFormat(type)) {
46 if (data->hasFormat(type)) {
46 if (behavior != DropBehavior::Forbidden) {
47 if (behavior != DropBehavior::Forbidden) {
47 accepted = true;
48 accepted = true;
48 }
49 }
49 else {
50 else {
50 accepted = false;
51 accepted = false;
51 break;
52 break;
52 }
53 }
53 }
54 }
54 }
55 }
55
56
56 if (accepted) {
57 if (accepted) {
57 accepted = m_AcceptMimeDataFun(data);
58 accepted = m_AcceptMimeDataFun(data);
58 }
59 }
59
60
60 return accepted;
61 return accepted;
61 }
62 }
62
63
63 bool allowMergeForMimeData(const QMimeData *data) const
64 bool allowMergeForMimeData(const QMimeData *data) const
64 {
65 {
65 auto result = false;
66 auto result = false;
66 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
67 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
67 ++it) {
68 ++it) {
68
69
69 if (data->hasFormat(it.key())
70 if (data->hasFormat(it.key())
70 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
71 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
71 || it.value()
72 || it.value()
72 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
73 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
73 result = true;
74 result = true;
74 }
75 }
75 else if (data->hasFormat(it.key())
76 else if (data->hasFormat(it.key())
76 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
77 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
77 // Merge is forbidden if the mime data contain an acceptable type which cannot be
78 // Merge is forbidden if the mime data contain an acceptable type which cannot be
78 // merged
79 // merged
79 result = false;
80 result = false;
80 break;
81 break;
81 }
82 }
82 }
83 }
83
84
84 return result;
85 return result;
85 }
86 }
86
87
87 bool allowInsertForMimeData(const QMimeData *data) const
88 bool allowInsertForMimeData(const QMimeData *data) const
88 {
89 {
89 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
90 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
90 ++it) {
91 ++it) {
91 if (data->hasFormat(it.key())
92 if (data->hasFormat(it.key())
92 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
93 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
93 || it.value()
94 || it.value()
94 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
95 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
95 return true;
96 return true;
96 }
97 }
97 }
98 }
98
99
99 return false;
100 return false;
100 }
101 }
101
102
102 bool hasPlaceHolder() const
103 bool hasPlaceHolder() const
103 {
104 {
104 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
105 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
105 }
106 }
106
107
107 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
108 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
108 {
109 {
109 VisualizationDragWidget *dragWidget = nullptr;
110 VisualizationDragWidget *dragWidget = nullptr;
110
111
111 for (auto child : parent->children()) {
112 for (auto child : parent->children()) {
112 auto widget = qobject_cast<VisualizationDragWidget *>(child);
113 auto widget = qobject_cast<VisualizationDragWidget *>(child);
113 if (widget && widget->isVisible()) {
114 if (widget && widget->isVisible()) {
114 if (widget->frameGeometry().contains(pos)) {
115 if (widget->frameGeometry().contains(pos)) {
115 dragWidget = widget;
116 dragWidget = widget;
116 break;
117 break;
117 }
118 }
118 }
119 }
119 }
120 }
120
121
121 return dragWidget;
122 return dragWidget;
122 }
123 }
123
124
124 bool cursorIsInContainer(QWidget *container) const
125 bool cursorIsInContainer(QWidget *container) const
125 {
126 {
126 auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos());
127 auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos());
127 return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container
128 return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container
128 && sqpApp->dragDropHelper().placeHolder().isAncestorOf(widgetUnderMouse);
129 && sqpApp->dragDropHelper().placeHolder().isAncestorOf(widgetUnderMouse);
129 }
130 }
130
131
131 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
132 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
132 {
133 {
133 auto nbGraph = 0;
134 auto nbGraph = 0;
134 for (auto child : parent->children()) {
135 for (auto child : parent->children()) {
135 if (qobject_cast<VisualizationDragWidget *>(child)) {
136 if (qobject_cast<VisualizationDragWidget *>(child)) {
136 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
137 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
137 nbGraph += 1;
138 nbGraph += 1;
138 }
139 }
139 }
140 }
140 }
141 }
141
142
142 return nbGraph;
143 return nbGraph;
143 }
144 }
144
145
145 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
146 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
146 const VisualizationDragDropContainer *container);
147 const VisualizationDragDropContainer *container);
147 };
148 };
148
149
149 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
150 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
150 : QFrame{parent},
151 : QFrame{parent},
151 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
152 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
152 {
153 {
153 setAcceptDrops(true);
154 setAcceptDrops(true);
154 }
155 }
155
156
156 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
157 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
157 {
158 {
158 impl->m_Layout->addWidget(dragWidget);
159 impl->m_Layout->addWidget(dragWidget);
159 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
160 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
160 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
161 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
161 &VisualizationDragDropContainer::startDrag);
162 &VisualizationDragDropContainer::startDrag);
162 }
163 }
163
164
164 void VisualizationDragDropContainer::insertDragWidget(int index,
165 void VisualizationDragDropContainer::insertDragWidget(int index,
165 VisualizationDragWidget *dragWidget)
166 VisualizationDragWidget *dragWidget)
166 {
167 {
167 impl->m_Layout->insertWidget(index, dragWidget);
168 impl->m_Layout->insertWidget(index, dragWidget);
168 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
169 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
169 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
170 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
170 &VisualizationDragDropContainer::startDrag);
171 &VisualizationDragDropContainer::startDrag);
171 }
172 }
172
173
173 void VisualizationDragDropContainer::setMimeType(
174 void VisualizationDragDropContainer::setMimeType(
174 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
175 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
175 {
176 {
176 impl->m_AcceptedMimeTypes[mimeType] = behavior;
177 impl->m_AcceptedMimeTypes[mimeType] = behavior;
177 }
178 }
178
179
179 int VisualizationDragDropContainer::countDragWidget() const
180 int VisualizationDragDropContainer::countDragWidget() const
180 {
181 {
181 return impl->countDragWidget(this);
182 return impl->countDragWidget(this);
182 }
183 }
183
184
184 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
185 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
185 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
186 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
186 {
187 {
187 impl->m_AcceptMimeDataFun = fun;
188 impl->m_AcceptMimeDataFun = fun;
188 }
189 }
189
190
190 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
191 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
191 const QString &placeHolderText)
192 const QString &placeHolderText)
192 {
193 {
193 impl->m_PlaceHolderType = type;
194 impl->m_PlaceHolderType = type;
194 impl->m_PlaceHolderText = placeHolderText;
195 impl->m_PlaceHolderText = placeHolderText;
195 }
196 }
196
197
197 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
198 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
198 const QPoint &dragPosition)
199 const QPoint &dragPosition)
199 {
200 {
200 auto &helper = sqpApp->dragDropHelper();
201 auto &helper = sqpApp->dragDropHelper();
201 helper.resetDragAndDrop();
202 helper.resetDragAndDrop();
202
203
203 // Note: The management of the drag object is done by Qt
204 // Note: The management of the drag object is done by Qt
204 auto drag = new QDrag{dragWidget};
205 auto drag = new QDrag{dragWidget};
205
206
206 auto mimeData = dragWidget->mimeData();
207 auto mimeData = dragWidget->mimeData();
207 drag->setMimeData(mimeData);
208 drag->setMimeData(mimeData);
208
209
209 auto pixmap = QPixmap(dragWidget->size());
210 auto pixmap = QPixmap(dragWidget->size());
210 dragWidget->render(&pixmap);
211 dragWidget->render(&pixmap);
211 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
212 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
212 Qt::KeepAspectRatio, Qt::SmoothTransformation));
213 Qt::KeepAspectRatio, Qt::SmoothTransformation));
213
214
214 auto image = pixmap.toImage();
215 auto image = pixmap.toImage();
215 mimeData->setImageData(image);
216 mimeData->setImageData(image);
216 mimeData->setUrls({helper.imageTemporaryUrl(image)});
217 mimeData->setUrls({helper.imageTemporaryUrl(image)});
217
218
218 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
219 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
219 helper.setCurrentDragWidget(dragWidget);
220 helper.setCurrentDragWidget(dragWidget);
220
221
221 if (impl->cursorIsInContainer(this)) {
222 if (impl->cursorIsInContainer(this)) {
222 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
223 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
223 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
224 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
224 impl->m_PlaceHolderText);
225 impl->m_PlaceHolderText);
225 dragWidget->setVisible(false);
226 dragWidget->setVisible(false);
226 }
227 }
227 else {
228 else {
228 // The drag starts directly outside the drop zone
229 // The drag starts directly outside the drop zone
229 // do not add the placeHolder
230 // do not add the placeHolder
230 }
231 }
231
232
232 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
233 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
233
234
234 helper.doCloseWidgets();
235 helper.doCloseWidgets();
235 }
236 }
236 else {
237 else {
237 qCWarning(LOG_VisualizationDragDropContainer())
238 qCWarning(LOG_VisualizationDragDropContainer())
238 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
239 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
239 "VisualizationDragWidget is not found in this container.");
240 "VisualizationDragWidget is not found in this container.");
240 }
241 }
241 }
242 }
242
243
243 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
244 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
244 {
245 {
245 if (impl->acceptMimeData(event->mimeData())) {
246 if (impl->acceptMimeData(event->mimeData())) {
246 event->acceptProposedAction();
247 event->acceptProposedAction();
247
248
248 auto &helper = sqpApp->dragDropHelper();
249 auto &helper = sqpApp->dragDropHelper();
249
250
250 if (!impl->hasPlaceHolder()) {
251 if (!impl->hasPlaceHolder()) {
251 auto dragWidget = helper.getCurrentDragWidget();
252 auto dragWidget = helper.getCurrentDragWidget();
252
253
253 if (dragWidget) {
254 if (dragWidget) {
254 // If the drag&drop is internal to the visualization, entering the container hide
255 // If the drag&drop is internal to the visualization, entering the container hide
255 // the dragWidget which was made visible by the dragLeaveEvent
256 // the dragWidget which was made visible by the dragLeaveEvent
256 auto parentWidget
257 auto parentWidget
257 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
258 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
258 if (parentWidget) {
259 if (parentWidget) {
259 dragWidget->setVisible(false);
260 dragWidget->setVisible(false);
260 }
261 }
261 }
262 }
262
263
263 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
264 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
264 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
265 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
265 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
266 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
266 }
267 }
267 else {
268 else {
268 // do nothing
269 // do nothing
269 }
270 }
270 }
271 }
271 else {
272 else {
272 event->ignore();
273 event->ignore();
273 }
274 }
274
275
275 QWidget::dragEnterEvent(event);
276 QWidget::dragEnterEvent(event);
276 }
277 }
277
278
278 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
279 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
279 {
280 {
280 Q_UNUSED(event);
281 Q_UNUSED(event);
281
282
282 auto &helper = sqpApp->dragDropHelper();
283 auto &helper = sqpApp->dragDropHelper();
283
284
284 if (!impl->cursorIsInContainer(this)) {
285 if (!impl->cursorIsInContainer(this)) {
285 helper.removePlaceHolder();
286 helper.removePlaceHolder();
286 helper.setHightlightedDragWidget(nullptr);
287 helper.setHightlightedDragWidget(nullptr);
287 impl->m_MinContainerHeight = 0;
288 impl->m_MinContainerHeight = 0;
288
289
289 auto dragWidget = helper.getCurrentDragWidget();
290 auto dragWidget = helper.getCurrentDragWidget();
290 if (dragWidget) {
291 if (dragWidget) {
291 // dragWidget has a value only if the drag is started from the visualization
292 // dragWidget has a value only if the drag is started from the visualization
292 // In that case, shows the drag widget at its original place
293 // In that case, shows the drag widget at its original place
293 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
294 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
294 // drop zone (It is not possible to catch a drop event outside of the application)
295 // drop zone (It is not possible to catch a drop event outside of the application)
295
296
296 if (dragWidget) {
297 if (dragWidget) {
297 dragWidget->setVisible(true);
298 dragWidget->setVisible(true);
298 }
299 }
299 }
300 }
300 }
301 }
301 else {
302 else {
302 // Leave event probably received for a child widget.
303 // Leave event probably received for a child widget.
303 // Do nothing.
304 // Do nothing.
304 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
305 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
305 }
306 }
306
307
307 QWidget::dragLeaveEvent(event);
308 QWidget::dragLeaveEvent(event);
308 }
309 }
309
310
310 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
311 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
311 {
312 {
312 if (impl->acceptMimeData(event->mimeData())) {
313 if (impl->acceptMimeData(event->mimeData())) {
313 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
314 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
314 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
315 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
315 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
316 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
316 }
317 }
317 else {
318 else {
318 event->ignore();
319 event->ignore();
319 }
320 }
320
321
321 QWidget::dragMoveEvent(event);
322 QWidget::dragMoveEvent(event);
322 }
323 }
323
324
324 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
325 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
325 {
326 {
326 auto &helper = sqpApp->dragDropHelper();
327 auto &helper = sqpApp->dragDropHelper();
327
328
328 if (impl->acceptMimeData(event->mimeData())) {
329 if (impl->acceptMimeData(event->mimeData())) {
329 auto dragWidget = helper.getCurrentDragWidget();
330 auto dragWidget = helper.getCurrentDragWidget();
330 if (impl->hasPlaceHolder()) {
331 if (impl->hasPlaceHolder()) {
331 // drop where the placeHolder is located
332 // drop where the placeHolder is located
332
333
333 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
334 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
334 if (canInsert) {
335 if (canInsert) {
335 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
336 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
336
337
337 if (dragWidget) {
338 if (dragWidget) {
338 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
339 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
339 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
340 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
340 // Correction of the index if the drop occurs in the same container
341 // Correction of the index if the drop occurs in the same container
341 // and if the drag is started from the visualization (in that case, the
342 // and if the drag is started from the visualization (in that case, the
342 // dragWidget is hidden)
343 // dragWidget is hidden)
343 droppedIndex -= 1;
344 droppedIndex -= 1;
344 }
345 }
345
346
346 dragWidget->setVisible(true);
347 dragWidget->setVisible(true);
347 }
348 }
348
349
349 event->acceptProposedAction();
350 event->acceptProposedAction();
350
351
351 helper.removePlaceHolder();
352 helper.removePlaceHolder();
352
353
353 emit dropOccuredInContainer(droppedIndex, event->mimeData());
354 emit dropOccuredInContainer(droppedIndex, event->mimeData());
354 }
355 }
355 else {
356 else {
356 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
357 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
357 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
358 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
358 "the insertion is forbidden.");
359 "the insertion is forbidden.");
359 Q_ASSERT(false);
360 Q_ASSERT(false);
360 }
361 }
361 }
362 }
362 else if (helper.getHightlightedDragWidget()) {
363 else if (helper.getHightlightedDragWidget()) {
363 // drop on the highlighted widget
364 // drop on the highlighted widget
364
365
365 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
366 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
366 if (canMerge) {
367 if (canMerge) {
367 event->acceptProposedAction();
368 event->acceptProposedAction();
368 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
369 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
369 }
370 }
370 else {
371 else {
371 qCWarning(LOG_VisualizationDragDropContainer())
372 qCWarning(LOG_VisualizationDragDropContainer())
372 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
373 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
373 "the merge is forbidden.");
374 "the merge is forbidden.");
374 Q_ASSERT(false);
375 Q_ASSERT(false);
375 }
376 }
376 }
377 }
377 }
378 }
378 else {
379 else {
379 event->ignore();
380 event->ignore();
380 }
381 }
381
382
382 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
383 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
383 impl->m_MinContainerHeight = 0;
384 impl->m_MinContainerHeight = 0;
384
385
385 QWidget::dropEvent(event);
386 QWidget::dropEvent(event);
386 }
387 }
387
388
388
389
389 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
390 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
390 const QPoint &pos, bool canInsert, bool canMerge,
391 const QPoint &pos, bool canInsert, bool canMerge,
391 const VisualizationDragDropContainer *container)
392 const VisualizationDragDropContainer *container)
392 {
393 {
393 auto &helper = sqpApp->dragDropHelper();
394 auto &helper = sqpApp->dragDropHelper();
394
395
395 auto absPos = container->mapToGlobal(pos);
396 auto absPos = container->mapToGlobal(pos);
396 auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos));
397 auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos));
397
398
398 if (countDragWidget(container, true) == 0) {
399 if (countDragWidget(container, true) == 0) {
399 // Drop on an empty container, just add the placeHolder at the top
400 // Drop on an empty container, just add the placeHolder at the top
400 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
401 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
401 }
402 }
402 else if (!isOnPlaceHolder) {
403 else if (!isOnPlaceHolder) {
403 auto nbDragWidget = countDragWidget(container);
404 auto nbDragWidget = countDragWidget(container);
404 if (nbDragWidget > 0) {
405 if (nbDragWidget > 0) {
405
406
406 if (m_MinContainerHeight == 0) {
407 if (m_MinContainerHeight == 0) {
407 m_MinContainerHeight = container->size().height();
408 m_MinContainerHeight = container->size().height();
408 }
409 }
409
410
410 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
411 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
411 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
412 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
412
413
413 auto posY = pos.y();
414 auto posY = pos.y();
414 auto dropIndex = floor(posY / graphHeight);
415 auto dropIndex = floor(posY / graphHeight);
415 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
416 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
416
417
417
418
418 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
419 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
419 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
420 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
420
421
421 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
422 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
422
423
423 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
424 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
424
425
425 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
426 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
426 if (isOnBottom) {
427 if (isOnBottom) {
427 dropIndex += 1;
428 dropIndex += 1;
428 }
429 }
429
430
430 if (helper.getCurrentDragWidget()) {
431 if (helper.getCurrentDragWidget()) {
431 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
432 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
432 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
433 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
433 // Correction of the index if the drop occurs in the same container
434 // Correction of the index if the drop occurs in the same container
434 // and if the drag is started from the visualization (in that case, the
435 // and if the drag is started from the visualization (in that case, the
435 // dragWidget is hidden)
436 // dragWidget is hidden)
436 dropIndex += 1;
437 dropIndex += 1;
437 }
438 }
438 }
439 }
439
440
440 if (dropIndex != placeHolderIndex) {
441 if (dropIndex != placeHolderIndex) {
441 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
442 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
442 m_PlaceHolderText);
443 m_PlaceHolderText);
443 }
444 }
444
445
445 helper.setHightlightedDragWidget(nullptr);
446 helper.setHightlightedDragWidget(nullptr);
446 }
447 }
447 else if (canMerge && dragWidgetHovered) {
448 else if (canMerge && dragWidgetHovered) {
448 // drop on the middle -> merge
449 // drop on the middle -> merge
449 if (hasPlaceHolder()) {
450 if (hasPlaceHolder()) {
450 helper.removePlaceHolder();
451 helper.removePlaceHolder();
451 }
452 }
452
453
453 helper.setHightlightedDragWidget(dragWidgetHovered);
454 helper.setHightlightedDragWidget(dragWidgetHovered);
454 }
455 }
455 else {
456 else {
456 qCWarning(LOG_VisualizationDragDropContainer())
457 qCWarning(LOG_VisualizationDragDropContainer())
457 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
458 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
458 "action.");
459 "action.");
459 }
460 }
460 }
461 }
461 else {
462 else {
462 qCWarning(LOG_VisualizationDragDropContainer())
463 qCWarning(LOG_VisualizationDragDropContainer())
463 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
464 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
464 "found in the "
465 "found in the "
465 "container");
466 "container");
466 }
467 }
467 }
468 }
468 else {
469 else {
469 // the mouse is hover the placeHolder
470 // the mouse is hover the placeHolder
470 // Do nothing
471 // Do nothing
471 }
472 }
472 }
473 }
@@ -1,490 +1,593
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/VisualizationDefs.h"
4 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7 #include "Visualization/VisualizationZoneWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
8 #include "ui_VisualizationGraphWidget.h"
8
9
9 #include <Common/MimeTypesDef.h>
10 #include <Common/MimeTypesDef.h>
10 #include <Data/ArrayData.h>
11 #include <Data/ArrayData.h>
11 #include <Data/IDataSeries.h>
12 #include <Data/IDataSeries.h>
12 #include <DragAndDrop/DragDropHelper.h>
13 #include <DragAndDrop/DragDropHelper.h>
13 #include <Settings/SqpSettingsDefs.h>
14 #include <Settings/SqpSettingsDefs.h>
14 #include <SqpApplication.h>
15 #include <SqpApplication.h>
15 #include <Time/TimeController.h>
16 #include <Time/TimeController.h>
16 #include <Variable/Variable.h>
17 #include <Variable/Variable.h>
17 #include <Variable/VariableController.h>
18 #include <Variable/VariableController.h>
18
19
19 #include <unordered_map>
20 #include <unordered_map>
20
21
21 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
22 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
22
23
23 namespace {
24 namespace {
24
25
25 /// Key pressed to enable zoom on horizontal axis
26 /// Key pressed to enable zoom on horizontal axis
26 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
27 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
27
28
28 /// Key pressed to enable zoom on vertical axis
29 /// Key pressed to enable zoom on vertical axis
29 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
30 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
30
31
31 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
32 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
32 const auto PAN_SPEED = 5;
33 const auto PAN_SPEED = 5;
33
34
34 /// Key pressed to enable a calibration pan
35 /// Key pressed to enable a calibration pan
35 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
36 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
36
37
37 /// Minimum size for the zoom box, in percentage of the axis range
38 /// Minimum size for the zoom box, in percentage of the axis range
38 const auto ZOOM_BOX_MIN_SIZE = 0.8;
39 const auto ZOOM_BOX_MIN_SIZE = 0.8;
39
40
41 /// Format of the dates appearing in the label of a cursor
42 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
43
40 } // namespace
44 } // namespace
41
45
42 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
46 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
43
47
44 explicit VisualizationGraphWidgetPrivate(const QString &name)
48 explicit VisualizationGraphWidgetPrivate(const QString &name)
45 : m_Name{name},
49 : m_Name{name},
46 m_DoAcquisition{true},
50 m_DoAcquisition{true},
47 m_IsCalibration{false},
51 m_IsCalibration{false},
48 m_RenderingDelegate{nullptr}
52 m_RenderingDelegate{nullptr}
49 {
53 {
50 }
54 }
51
55
52 QString m_Name;
56 QString m_Name;
53 // 1 variable -> n qcpplot
57 // 1 variable -> n qcpplot
54 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
58 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
55 bool m_DoAcquisition;
59 bool m_DoAcquisition;
56 bool m_IsCalibration;
60 bool m_IsCalibration;
57 /// Delegate used to attach rendering features to the plot
61 /// Delegate used to attach rendering features to the plot
58 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
62 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
59
63
60 QCPItemRect *m_DrawingRect = nullptr;
64 QCPItemRect *m_DrawingRect = nullptr;
65 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
66 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
61
67
62 void configureDrawingRect()
68 void configureDrawingRect()
63 {
69 {
64 if (m_DrawingRect) {
70 if (m_DrawingRect) {
65 QPen p;
71 QPen p;
66 p.setWidth(2);
72 p.setWidth(2);
67 m_DrawingRect->setPen(p);
73 m_DrawingRect->setPen(p);
68 }
74 }
69 }
75 }
70
76
71 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
77 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
72 {
78 {
73 removeDrawingRect(plot);
79 removeDrawingRect(plot);
74
80
75 auto axisPos = posToAxisPos(pos, plot);
81 auto axisPos = posToAxisPos(pos, plot);
76
82
77 m_DrawingRect = new QCPItemRect{&plot};
83 m_DrawingRect = new QCPItemRect{&plot};
78 configureDrawingRect();
84 configureDrawingRect();
79
85
80 m_DrawingRect->topLeft->setCoords(axisPos);
86 m_DrawingRect->topLeft->setCoords(axisPos);
81 m_DrawingRect->bottomRight->setCoords(axisPos);
87 m_DrawingRect->bottomRight->setCoords(axisPos);
82 }
88 }
83
89
84 void removeDrawingRect(QCustomPlot &plot)
90 void removeDrawingRect(QCustomPlot &plot)
85 {
91 {
86 if (m_DrawingRect) {
92 if (m_DrawingRect) {
87 plot.removeItem(m_DrawingRect); // the item is deleted by QCustomPlot
93 plot.removeItem(m_DrawingRect); // the item is deleted by QCustomPlot
88 m_DrawingRect = nullptr;
94 m_DrawingRect = nullptr;
89 plot.replot(QCustomPlot::rpQueuedReplot);
95 plot.replot(QCustomPlot::rpQueuedReplot);
90 }
96 }
91 }
97 }
92
98
93 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
99 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
94 {
100 {
95 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
101 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
96 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
102 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
97 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
103 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
98 }
104 }
105
106 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
107 {
108 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
109 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
110
111 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
112 }
99 };
113 };
100
114
101 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
115 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
102 : VisualizationDragWidget{parent},
116 : VisualizationDragWidget{parent},
103 ui{new Ui::VisualizationGraphWidget},
117 ui{new Ui::VisualizationGraphWidget},
104 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
118 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
105 {
119 {
106 ui->setupUi(this);
120 ui->setupUi(this);
107
121
108 // 'Close' options : widget is deleted when closed
122 // 'Close' options : widget is deleted when closed
109 setAttribute(Qt::WA_DeleteOnClose);
123 setAttribute(Qt::WA_DeleteOnClose);
110
124
111 // Set qcpplot properties :
125 // Set qcpplot properties :
112 // - Drag (on x-axis) and zoom are enabled
126 // - Drag (on x-axis) and zoom are enabled
113 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
127 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
114 ui->widget->setInteractions(QCP::iRangeZoom | QCP::iSelectItems);
128 ui->widget->setInteractions(QCP::iRangeZoom | QCP::iSelectItems);
115
129
116 // The delegate must be initialized after the ui as it uses the plot
130 // The delegate must be initialized after the ui as it uses the plot
117 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
131 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
118
132
133 // Init the cursors
134 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
135 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
136 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
137 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
138
119 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
139 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
120 connect(ui->widget, &QCustomPlot::mouseRelease, this,
140 connect(ui->widget, &QCustomPlot::mouseRelease, this,
121 &VisualizationGraphWidget::onMouseRelease);
141 &VisualizationGraphWidget::onMouseRelease);
122 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
142 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
123 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
143 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
124 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
144 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
125 &QCPAxis::rangeChanged),
145 &QCPAxis::rangeChanged),
126 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
146 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
127
147
128 // Activates menu when right clicking on the graph
148 // Activates menu when right clicking on the graph
129 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
149 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
130 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
150 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
131 &VisualizationGraphWidget::onGraphMenuRequested);
151 &VisualizationGraphWidget::onGraphMenuRequested);
132
152
133 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
153 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
134 &VariableController::onRequestDataLoading);
154 &VariableController::onRequestDataLoading);
135
155
136 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
156 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
137 &VisualizationGraphWidget::onUpdateVarDisplaying);
157 &VisualizationGraphWidget::onUpdateVarDisplaying);
138 }
158 }
139
159
140
160
141 VisualizationGraphWidget::~VisualizationGraphWidget()
161 VisualizationGraphWidget::~VisualizationGraphWidget()
142 {
162 {
143 delete ui;
163 delete ui;
144 }
164 }
145
165
146 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
166 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
147 {
167 {
148 auto parent = parentWidget();
168 auto parent = parentWidget();
149 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
169 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
150 parent = parent->parentWidget();
170 parent = parent->parentWidget();
151 }
171 }
152
172
153 return qobject_cast<VisualizationZoneWidget *>(parent);
173 return qobject_cast<VisualizationZoneWidget *>(parent);
154 }
174 }
155
175
156 void VisualizationGraphWidget::enableAcquisition(bool enable)
176 void VisualizationGraphWidget::enableAcquisition(bool enable)
157 {
177 {
158 impl->m_DoAcquisition = enable;
178 impl->m_DoAcquisition = enable;
159 }
179 }
160
180
161 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
181 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
162 {
182 {
163 // Uses delegate to create the qcpplot components according to the variable
183 // Uses delegate to create the qcpplot components according to the variable
164 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
184 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
165
185
166 if (auto dataSeries = variable->dataSeries()) {
186 if (auto dataSeries = variable->dataSeries()) {
167 // Set axes properties according to the units of the data series
187 // Set axes properties according to the units of the data series
168 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
188 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
169
189
170 // Sets rendering properties for the new plottables
190 // Sets rendering properties for the new plottables
171 // Warning: this method must be called after setAxesProperties(), as it can access to some
191 // Warning: this method must be called after setAxesProperties(), as it can access to some
172 // axes properties that have to be initialized
192 // axes properties that have to be initialized
173 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
193 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
174 }
194 }
175
195
176 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
196 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
177
197
178 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
198 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
179
199
180 this->enableAcquisition(false);
200 this->enableAcquisition(false);
181 this->setGraphRange(range);
201 this->setGraphRange(range);
182 this->enableAcquisition(true);
202 this->enableAcquisition(true);
183
203
184 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
204 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
185
205
186 emit variableAdded(variable);
206 emit variableAdded(variable);
187 }
207 }
188
208
189 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
209 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
190 {
210 {
191 // Each component associated to the variable :
211 // Each component associated to the variable :
192 // - is removed from qcpplot (which deletes it)
212 // - is removed from qcpplot (which deletes it)
193 // - is no longer referenced in the map
213 // - is no longer referenced in the map
194 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
214 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
195 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
215 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
196 emit variableAboutToBeRemoved(variable);
216 emit variableAboutToBeRemoved(variable);
197
217
198 auto &plottablesMap = variableIt->second;
218 auto &plottablesMap = variableIt->second;
199
219
200 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
220 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
201 plottableIt != plottableEnd;) {
221 plottableIt != plottableEnd;) {
202 ui->widget->removePlottable(plottableIt->second);
222 ui->widget->removePlottable(plottableIt->second);
203 plottableIt = plottablesMap.erase(plottableIt);
223 plottableIt = plottablesMap.erase(plottableIt);
204 }
224 }
205
225
206 impl->m_VariableToPlotMultiMap.erase(variableIt);
226 impl->m_VariableToPlotMultiMap.erase(variableIt);
207 }
227 }
208
228
209 // Updates graph
229 // Updates graph
210 ui->widget->replot();
230 ui->widget->replot();
211 }
231 }
212
232
213 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
233 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
214 {
234 {
215 auto variables = QList<std::shared_ptr<Variable> >{};
235 auto variables = QList<std::shared_ptr<Variable> >{};
216 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
236 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
217 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
237 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
218 variables << it->first;
238 variables << it->first;
219 }
239 }
220
240
221 return variables;
241 return variables;
222 }
242 }
223
243
224 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
244 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
225 {
245 {
226 if (!variable) {
246 if (!variable) {
227 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
247 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
228 return;
248 return;
229 }
249 }
230
250
231 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
251 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
232 }
252 }
233
253
234 SqpRange VisualizationGraphWidget::graphRange() const noexcept
254 SqpRange VisualizationGraphWidget::graphRange() const noexcept
235 {
255 {
236 auto graphRange = ui->widget->xAxis->range();
256 auto graphRange = ui->widget->xAxis->range();
237 return SqpRange{graphRange.lower, graphRange.upper};
257 return SqpRange{graphRange.lower, graphRange.upper};
238 }
258 }
239
259
240 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
260 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
241 {
261 {
242 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
262 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
243 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
263 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
244 ui->widget->replot();
264 ui->widget->replot();
245 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
265 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
246 }
266 }
247
267
248 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
268 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
249 {
269 {
250 if (visitor) {
270 if (visitor) {
251 visitor->visit(this);
271 visitor->visit(this);
252 }
272 }
253 else {
273 else {
254 qCCritical(LOG_VisualizationGraphWidget())
274 qCCritical(LOG_VisualizationGraphWidget())
255 << tr("Can't visit widget : the visitor is null");
275 << tr("Can't visit widget : the visitor is null");
256 }
276 }
257 }
277 }
258
278
259 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
279 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
260 {
280 {
261 /// @todo : for the moment, a graph can always accomodate a variable
281 /// @todo : for the moment, a graph can always accomodate a variable
262 Q_UNUSED(variable);
282 Q_UNUSED(variable);
263 return true;
283 return true;
264 }
284 }
265
285
266 bool VisualizationGraphWidget::contains(const Variable &variable) const
286 bool VisualizationGraphWidget::contains(const Variable &variable) const
267 {
287 {
268 // Finds the variable among the keys of the map
288 // Finds the variable among the keys of the map
269 auto variablePtr = &variable;
289 auto variablePtr = &variable;
270 auto findVariable
290 auto findVariable
271 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
291 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
272
292
273 auto end = impl->m_VariableToPlotMultiMap.cend();
293 auto end = impl->m_VariableToPlotMultiMap.cend();
274 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
294 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
275 return it != end;
295 return it != end;
276 }
296 }
277
297
278 QString VisualizationGraphWidget::name() const
298 QString VisualizationGraphWidget::name() const
279 {
299 {
280 return impl->m_Name;
300 return impl->m_Name;
281 }
301 }
282
302
283 QMimeData *VisualizationGraphWidget::mimeData() const
303 QMimeData *VisualizationGraphWidget::mimeData() const
284 {
304 {
285 auto mimeData = new QMimeData;
305 auto mimeData = new QMimeData;
286 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
306 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
287
307
288 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
308 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
289 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
309 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
290
310
291 return mimeData;
311 return mimeData;
292 }
312 }
293
313
294 bool VisualizationGraphWidget::isDragAllowed() const
314 bool VisualizationGraphWidget::isDragAllowed() const
295 {
315 {
296 return true;
316 return true;
297 }
317 }
298
318
299 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
319 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
300 {
320 {
301 if (highlighted) {
321 if (highlighted) {
302 plot().setBackground(QBrush(QColor("#BBD5EE")));
322 plot().setBackground(QBrush(QColor("#BBD5EE")));
303 }
323 }
304 else {
324 else {
305 plot().setBackground(QBrush(Qt::white));
325 plot().setBackground(QBrush(Qt::white));
306 }
326 }
307
327
308 plot().update();
328 plot().update();
309 }
329 }
310
330
331 void VisualizationGraphWidget::addVerticalCursor(double time)
332 {
333 impl->m_VerticalCursor->setPosition(time);
334 impl->m_VerticalCursor->setVisible(true);
335
336 auto text
337 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
338 impl->m_VerticalCursor->setLabelText(text);
339 }
340
341 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
342 {
343 impl->m_VerticalCursor->setAbsolutePosition(position);
344 impl->m_VerticalCursor->setVisible(true);
345
346 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
347 auto text
348 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
349 impl->m_VerticalCursor->setLabelText(text);
350 }
351
352 void VisualizationGraphWidget::removeVerticalCursor()
353 {
354 impl->m_VerticalCursor->setVisible(false);
355 plot().replot(QCustomPlot::rpQueuedReplot);
356 }
357
358 void VisualizationGraphWidget::addHorizontalCursor(double value)
359 {
360 impl->m_HorizontalCursor->setPosition(value);
361 impl->m_HorizontalCursor->setVisible(true);
362 impl->m_HorizontalCursor->setLabelText(QString::number(value));
363 }
364
365 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
366 {
367 impl->m_HorizontalCursor->setAbsolutePosition(position);
368 impl->m_HorizontalCursor->setVisible(true);
369
370 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
371 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
372 }
373
374 void VisualizationGraphWidget::removeHorizontalCursor()
375 {
376 impl->m_HorizontalCursor->setVisible(false);
377 plot().replot(QCustomPlot::rpQueuedReplot);
378 }
379
311 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
380 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
312 {
381 {
313 Q_UNUSED(event);
382 Q_UNUSED(event);
314
383
315 // Prevents that all variables will be removed from graph when it will be closed
384 // Prevents that all variables will be removed from graph when it will be closed
316 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
385 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
317 emit variableAboutToBeRemoved(variableEntry.first);
386 emit variableAboutToBeRemoved(variableEntry.first);
318 }
387 }
319 }
388 }
320
389
321 void VisualizationGraphWidget::enterEvent(QEvent *event)
390 void VisualizationGraphWidget::enterEvent(QEvent *event)
322 {
391 {
323 Q_UNUSED(event);
392 Q_UNUSED(event);
324 impl->m_RenderingDelegate->showGraphOverlay(true);
393 impl->m_RenderingDelegate->showGraphOverlay(true);
325 }
394 }
326
395
327 void VisualizationGraphWidget::leaveEvent(QEvent *event)
396 void VisualizationGraphWidget::leaveEvent(QEvent *event)
328 {
397 {
329 Q_UNUSED(event);
398 Q_UNUSED(event);
330 impl->m_RenderingDelegate->showGraphOverlay(false);
399 impl->m_RenderingDelegate->showGraphOverlay(false);
400
401 if (auto parentZone = parentZoneWidget()) {
402 parentZone->notifyMouseLeaveGraph(this);
403 }
404 else {
405 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
406 }
331 }
407 }
332
408
333 QCustomPlot &VisualizationGraphWidget::plot() noexcept
409 QCustomPlot &VisualizationGraphWidget::plot() noexcept
334 {
410 {
335 return *ui->widget;
411 return *ui->widget;
336 }
412 }
337
413
338 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
414 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
339 {
415 {
340 QMenu graphMenu{};
416 QMenu graphMenu{};
341
417
342 // Iterates on variables (unique keys)
418 // Iterates on variables (unique keys)
343 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
419 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
344 end = impl->m_VariableToPlotMultiMap.cend();
420 end = impl->m_VariableToPlotMultiMap.cend();
345 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
421 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
346 // 'Remove variable' action
422 // 'Remove variable' action
347 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
423 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
348 [ this, var = it->first ]() { removeVariable(var); });
424 [ this, var = it->first ]() { removeVariable(var); });
349 }
425 }
350
426
351 if (!graphMenu.isEmpty()) {
427 if (!graphMenu.isEmpty()) {
352 graphMenu.exec(QCursor::pos());
428 graphMenu.exec(QCursor::pos());
353 }
429 }
354 }
430 }
355
431
356 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
432 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
357 {
433 {
358 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
434 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
359 << QThread::currentThread()->objectName() << "DoAcqui"
435 << QThread::currentThread()->objectName() << "DoAcqui"
360 << impl->m_DoAcquisition;
436 << impl->m_DoAcquisition;
361
437
362 auto graphRange = SqpRange{t1.lower, t1.upper};
438 auto graphRange = SqpRange{t1.lower, t1.upper};
363 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
439 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
364
440
365 if (impl->m_DoAcquisition) {
441 if (impl->m_DoAcquisition) {
366 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
442 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
367
443
368 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
444 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
369 end = impl->m_VariableToPlotMultiMap.end();
445 end = impl->m_VariableToPlotMultiMap.end();
370 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
446 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
371 variableUnderGraphVector.push_back(it->first);
447 variableUnderGraphVector.push_back(it->first);
372 }
448 }
373 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
449 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
374 !impl->m_IsCalibration);
450 !impl->m_IsCalibration);
375
451
376 if (!impl->m_IsCalibration) {
452 if (!impl->m_IsCalibration) {
377 qCDebug(LOG_VisualizationGraphWidget())
453 qCDebug(LOG_VisualizationGraphWidget())
378 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
454 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
379 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
455 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
380 emit synchronize(graphRange, oldGraphRange);
456 emit synchronize(graphRange, oldGraphRange);
381 }
457 }
382 }
458 }
459
460 auto pos = mapFromGlobal(QCursor::pos());
461 auto axisPos = impl->posToAxisPos(pos, plot());
462 if (auto parentZone = parentZoneWidget()) {
463 if (impl->pointIsInAxisRect(axisPos, plot())) {
464 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
465 }
466 else {
467 parentZone->notifyMouseLeaveGraph(this);
468 }
469 }
470 else {
471 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
472 }
383 }
473 }
384
474
385 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
475 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
386 {
476 {
387 // Handles plot rendering when mouse is moving
477 // Handles plot rendering when mouse is moving
388 impl->m_RenderingDelegate->onMouseMove(event);
478 impl->m_RenderingDelegate->onMouseMove(event);
389
479
480 auto axisPos = impl->posToAxisPos(event->pos(), plot());
481
390 if (impl->m_DrawingRect) {
482 if (impl->m_DrawingRect) {
391 auto axisPos = impl->posToAxisPos(event->pos(), plot());
392 impl->m_DrawingRect->bottomRight->setCoords(axisPos);
483 impl->m_DrawingRect->bottomRight->setCoords(axisPos);
393 }
484 }
394
485
486 if (auto parentZone = parentZoneWidget()) {
487 if (impl->pointIsInAxisRect(axisPos, plot())) {
488 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
489 }
490 else {
491 parentZone->notifyMouseLeaveGraph(this);
492 }
493 }
494 else {
495 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
496 }
497
395 VisualizationDragWidget::mouseMoveEvent(event);
498 VisualizationDragWidget::mouseMoveEvent(event);
396 }
499 }
397
500
398 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
501 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
399 {
502 {
400 auto value = event->angleDelta().x() + event->angleDelta().y();
503 auto value = event->angleDelta().x() + event->angleDelta().y();
401 if (value != 0) {
504 if (value != 0) {
402
505
403 auto direction = value > 0 ? 1.0 : -1.0;
506 auto direction = value > 0 ? 1.0 : -1.0;
404 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
507 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
405 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
508 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
406 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
509 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
407
510
408 auto zoomOrientations = QFlags<Qt::Orientation>{};
511 auto zoomOrientations = QFlags<Qt::Orientation>{};
409 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
512 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
410 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
513 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
411
514
412 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
515 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
413
516
414 if (!isZoomX && !isZoomY) {
517 if (!isZoomX && !isZoomY) {
415 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
518 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
416 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
519 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
417
520
418 axis->setRange(axis->range() + diff);
521 axis->setRange(axis->range() + diff);
419
522
420 if (plot().noAntialiasingOnDrag()) {
523 if (plot().noAntialiasingOnDrag()) {
421 plot().setNotAntialiasedElements(QCP::aeAll);
524 plot().setNotAntialiasedElements(QCP::aeAll);
422 }
525 }
423
526
424 plot().replot(QCustomPlot::rpQueuedReplot);
527 plot().replot(QCustomPlot::rpQueuedReplot);
425 }
528 }
426 }
529 }
427 }
530 }
428
531
429 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
532 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
430 {
533 {
431 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
534 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
432 impl->startDrawingRect(event->pos(), plot());
535 impl->startDrawingRect(event->pos(), plot());
433 }
536 }
434
537
435 VisualizationDragWidget::mousePressEvent(event);
538 VisualizationDragWidget::mousePressEvent(event);
436 }
539 }
437
540
438 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
541 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
439 {
542 {
440 if (impl->m_DrawingRect) {
543 if (impl->m_DrawingRect) {
441
544
442 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
545 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
443 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
546 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
444
547
445 auto newAxisXRange = QCPRange{impl->m_DrawingRect->topLeft->coords().x(),
548 auto newAxisXRange = QCPRange{impl->m_DrawingRect->topLeft->coords().x(),
446 impl->m_DrawingRect->bottomRight->coords().x()};
549 impl->m_DrawingRect->bottomRight->coords().x()};
447
550
448 auto newAxisYRange = QCPRange{impl->m_DrawingRect->topLeft->coords().y(),
551 auto newAxisYRange = QCPRange{impl->m_DrawingRect->topLeft->coords().y(),
449 impl->m_DrawingRect->bottomRight->coords().y()};
552 impl->m_DrawingRect->bottomRight->coords().y()};
450
553
451 impl->removeDrawingRect(plot());
554 impl->removeDrawingRect(plot());
452
555
453 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
556 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
454 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
557 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
455 axisX->setRange(newAxisXRange);
558 axisX->setRange(newAxisXRange);
456 axisY->setRange(newAxisYRange);
559 axisY->setRange(newAxisYRange);
457
560
458 plot().replot(QCustomPlot::rpQueuedReplot);
561 plot().replot(QCustomPlot::rpQueuedReplot);
459 }
562 }
460 }
563 }
461
564
462 impl->m_IsCalibration = false;
565 impl->m_IsCalibration = false;
463 }
566 }
464
567
465 void VisualizationGraphWidget::onDataCacheVariableUpdated()
568 void VisualizationGraphWidget::onDataCacheVariableUpdated()
466 {
569 {
467 auto graphRange = ui->widget->xAxis->range();
570 auto graphRange = ui->widget->xAxis->range();
468 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
571 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
469
572
470 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
573 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
471 auto variable = variableEntry.first;
574 auto variable = variableEntry.first;
472 qCDebug(LOG_VisualizationGraphWidget())
575 qCDebug(LOG_VisualizationGraphWidget())
473 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
576 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
474 qCDebug(LOG_VisualizationGraphWidget())
577 qCDebug(LOG_VisualizationGraphWidget())
475 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
578 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
476 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
579 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
477 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
580 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
478 variable->range());
581 variable->range());
479 }
582 }
480 }
583 }
481 }
584 }
482
585
483 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
586 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
484 const SqpRange &range)
587 const SqpRange &range)
485 {
588 {
486 auto it = impl->m_VariableToPlotMultiMap.find(variable);
589 auto it = impl->m_VariableToPlotMultiMap.find(variable);
487 if (it != impl->m_VariableToPlotMultiMap.end()) {
590 if (it != impl->m_VariableToPlotMultiMap.end()) {
488 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
591 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
489 }
592 }
490 }
593 }
@@ -1,507 +1,560
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/VisualizationWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
8
8
9 #include "Common/MimeTypesDef.h"
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
10 #include "Common/VisualizationDef.h"
11
11
12 #include <Data/SqpRange.h>
12 #include <Data/SqpRange.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14 #include <Variable/Variable.h>
14 #include <Variable/Variable.h>
15 #include <Variable/VariableController.h>
15 #include <Variable/VariableController.h>
16
16
17 #include <Visualization/operations/FindVariableOperation.h>
17 #include <Visualization/operations/FindVariableOperation.h>
18
18
19 #include <DragAndDrop/DragDropHelper.h>
19 #include <DragAndDrop/DragDropHelper.h>
20 #include <QUuid>
20 #include <QUuid>
21 #include <SqpApplication.h>
21 #include <SqpApplication.h>
22 #include <cmath>
22 #include <cmath>
23
23
24 #include <QLayout>
24 #include <QLayout>
25
25
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27
27
28 namespace {
28 namespace {
29
29
30
30
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
32 /// the zone
32 /// the zone
33 QString defaultGraphName(const QLayout &layout)
33 QString defaultGraphName(const QLayout &layout)
34 {
34 {
35 auto count = 0;
35 auto count = 0;
36 for (auto i = 0; i < layout.count(); ++i) {
36 for (auto i = 0; i < layout.count(); ++i) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
38 count++;
38 count++;
39 }
39 }
40 }
40 }
41
41
42 return QObject::tr("Graph %1").arg(count + 1);
42 return QObject::tr("Graph %1").arg(count + 1);
43 }
43 }
44
44
45 /**
45 /**
46 * Applies a function to all graphs of the zone represented by its layout
46 * Applies a function to all graphs of the zone represented by its layout
47 * @param layout the layout that contains graphs
47 * @param layout the layout that contains graphs
48 * @param fun the function to apply to each graph
48 * @param fun the function to apply to each graph
49 */
49 */
50 template <typename Fun>
50 template <typename Fun>
51 void processGraphs(QLayout &layout, Fun fun)
51 void processGraphs(QLayout &layout, Fun fun)
52 {
52 {
53 for (auto i = 0; i < layout.count(); ++i) {
53 for (auto i = 0; i < layout.count(); ++i) {
54 if (auto item = layout.itemAt(i)) {
54 if (auto item = layout.itemAt(i)) {
55 if (auto visualizationGraphWidget
55 if (auto visualizationGraphWidget
56 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
56 = 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
75 // Returns the first graph in the zone or nullptr if there is no graph inside
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
77 {
77 {
78 VisualizationGraphWidget *firstGraph = nullptr;
78 VisualizationGraphWidget *firstGraph = nullptr;
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
80 if (layout->count() > 0) {
80 if (layout->count() > 0) {
81 if (auto visualizationGraphWidget
81 if (auto visualizationGraphWidget
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
83 firstGraph = visualizationGraphWidget;
83 firstGraph = visualizationGraphWidget;
84 }
84 }
85 }
85 }
86
86
87 return firstGraph;
87 return firstGraph;
88 }
88 }
89
89
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
92 VisualizationZoneWidget *zoneWidget);
92 VisualizationZoneWidget *zoneWidget);
93 };
93 };
94
94
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
96 : VisualizationDragWidget{parent},
96 : VisualizationDragWidget{parent},
97 ui{new Ui::VisualizationZoneWidget},
97 ui{new Ui::VisualizationZoneWidget},
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
99 {
99 {
100 ui->setupUi(this);
100 ui->setupUi(this);
101
101
102 ui->zoneNameLabel->setText(name);
102 ui->zoneNameLabel->setText(name);
103
103
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
105 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
105 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
106 VisualizationDragDropContainer::DropBehavior::Inserted);
106 VisualizationDragDropContainer::DropBehavior::Inserted);
107 ui->dragDropContainer->setMimeType(
107 ui->dragDropContainer->setMimeType(
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
109 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
109 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
110 VisualizationDragDropContainer::DropBehavior::Merged);
110 VisualizationDragDropContainer::DropBehavior::Merged);
111 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
111 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
112 VisualizationDragDropContainer::DropBehavior::Forbidden);
112 VisualizationDragDropContainer::DropBehavior::Forbidden);
113 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
113 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
114 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
114 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
115 ui->dragDropContainer);
115 ui->dragDropContainer);
116 });
116 });
117
117
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
119 &VisualizationZoneWidget::dropMimeData);
119 &VisualizationZoneWidget::dropMimeData);
120 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
120 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
121 &VisualizationZoneWidget::dropMimeDataOnGraph);
121 &VisualizationZoneWidget::dropMimeDataOnGraph);
122
122
123 // 'Close' options : widget is deleted when closed
123 // 'Close' options : widget is deleted when closed
124 setAttribute(Qt::WA_DeleteOnClose);
124 setAttribute(Qt::WA_DeleteOnClose);
125 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
125 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
126 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
126 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
127
127
128 // Synchronisation id
128 // Synchronisation id
129 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
129 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
130 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
130 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
131 }
131 }
132
132
133 VisualizationZoneWidget::~VisualizationZoneWidget()
133 VisualizationZoneWidget::~VisualizationZoneWidget()
134 {
134 {
135 delete ui;
135 delete ui;
136 }
136 }
137
137
138 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
138 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
139 {
139 {
140 // Synchronize new graph with others in the zone
140 // Synchronize new graph with others in the zone
141 impl->m_Synchronizer->addGraph(*graphWidget);
141 impl->m_Synchronizer->addGraph(*graphWidget);
142
142
143 ui->dragDropContainer->addDragWidget(graphWidget);
143 ui->dragDropContainer->addDragWidget(graphWidget);
144 }
144 }
145
145
146 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
146 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
147 {
147 {
148 // Synchronize new graph with others in the zone
148 // Synchronize new graph with others in the zone
149 impl->m_Synchronizer->addGraph(*graphWidget);
149 impl->m_Synchronizer->addGraph(*graphWidget);
150
150
151 ui->dragDropContainer->insertDragWidget(index, graphWidget);
151 ui->dragDropContainer->insertDragWidget(index, graphWidget);
152 }
152 }
153
153
154 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
154 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
155 {
155 {
156 return createGraph(variable, -1);
156 return createGraph(variable, -1);
157 }
157 }
158
158
159 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
159 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
160 int index)
160 int index)
161 {
161 {
162 auto graphWidget
162 auto graphWidget
163 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
163 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
164
164
165
165
166 // Set graph properties
166 // Set graph properties
167 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
167 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
168 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
168 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
169
169
170
170
171 // Lambda to synchronize zone widget
171 // Lambda to synchronize zone widget
172 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
172 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
173 const SqpRange &oldGraphRange) {
173 const SqpRange &oldGraphRange) {
174
174
175 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
175 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
176 auto frameLayout = ui->dragDropContainer->layout();
176 auto frameLayout = ui->dragDropContainer->layout();
177 for (auto i = 0; i < frameLayout->count(); ++i) {
177 for (auto i = 0; i < frameLayout->count(); ++i) {
178 auto graphChild
178 auto graphChild
179 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
179 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
180 if (graphChild && (graphChild != graphWidget)) {
180 if (graphChild && (graphChild != graphWidget)) {
181
181
182 auto graphChildRange = graphChild->graphRange();
182 auto graphChildRange = graphChild->graphRange();
183 switch (zoomType) {
183 switch (zoomType) {
184 case AcquisitionZoomType::ZoomIn: {
184 case AcquisitionZoomType::ZoomIn: {
185 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
185 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
186 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
186 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
187 graphChildRange.m_TStart += deltaLeft;
187 graphChildRange.m_TStart += deltaLeft;
188 graphChildRange.m_TEnd -= deltaRight;
188 graphChildRange.m_TEnd -= deltaRight;
189 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
189 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
191 << deltaLeft;
191 << deltaLeft;
192 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
192 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
193 << deltaRight;
193 << deltaRight;
194 qCDebug(LOG_VisualizationZoneWidget())
194 qCDebug(LOG_VisualizationZoneWidget())
195 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
195 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
196
196
197 break;
197 break;
198 }
198 }
199
199
200 case AcquisitionZoomType::ZoomOut: {
200 case AcquisitionZoomType::ZoomOut: {
201 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
201 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
202 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
202 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
203 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
203 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
205 << deltaLeft;
205 << deltaLeft;
206 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
206 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
207 << deltaRight;
207 << deltaRight;
208 qCDebug(LOG_VisualizationZoneWidget())
208 qCDebug(LOG_VisualizationZoneWidget())
209 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
209 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
210 graphChildRange.m_TStart -= deltaLeft;
210 graphChildRange.m_TStart -= deltaLeft;
211 graphChildRange.m_TEnd += deltaRight;
211 graphChildRange.m_TEnd += deltaRight;
212 break;
212 break;
213 }
213 }
214 case AcquisitionZoomType::PanRight: {
214 case AcquisitionZoomType::PanRight: {
215 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
215 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
216 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
216 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
217 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
217 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
218 graphChildRange.m_TStart += deltaLeft;
218 graphChildRange.m_TStart += deltaLeft;
219 graphChildRange.m_TEnd += deltaRight;
219 graphChildRange.m_TEnd += deltaRight;
220 qCDebug(LOG_VisualizationZoneWidget())
220 qCDebug(LOG_VisualizationZoneWidget())
221 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
221 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
222 break;
222 break;
223 }
223 }
224 case AcquisitionZoomType::PanLeft: {
224 case AcquisitionZoomType::PanLeft: {
225 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
225 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
226 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
226 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
227 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
227 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
228 graphChildRange.m_TStart -= deltaLeft;
228 graphChildRange.m_TStart -= deltaLeft;
229 graphChildRange.m_TEnd -= deltaRight;
229 graphChildRange.m_TEnd -= deltaRight;
230 break;
230 break;
231 }
231 }
232 case AcquisitionZoomType::Unknown: {
232 case AcquisitionZoomType::Unknown: {
233 qCDebug(LOG_VisualizationZoneWidget())
233 qCDebug(LOG_VisualizationZoneWidget())
234 << tr("Impossible to synchronize: zoom type unknown");
234 << tr("Impossible to synchronize: zoom type unknown");
235 break;
235 break;
236 }
236 }
237 default:
237 default:
238 qCCritical(LOG_VisualizationZoneWidget())
238 qCCritical(LOG_VisualizationZoneWidget())
239 << tr("Impossible to synchronize: zoom type not take into account");
239 << tr("Impossible to synchronize: zoom type not take into account");
240 // No action
240 // No action
241 break;
241 break;
242 }
242 }
243 graphChild->enableAcquisition(false);
243 graphChild->enableAcquisition(false);
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
245 << graphChild->graphRange();
245 << graphChild->graphRange();
246 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
246 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
247 << graphChildRange;
247 << graphChildRange;
248 qCDebug(LOG_VisualizationZoneWidget())
248 qCDebug(LOG_VisualizationZoneWidget())
249 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
249 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
250 graphChild->setGraphRange(graphChildRange);
250 graphChild->setGraphRange(graphChildRange);
251 graphChild->enableAcquisition(true);
251 graphChild->enableAcquisition(true);
252 }
252 }
253 }
253 }
254 };
254 };
255
255
256 // connection for synchronization
256 // connection for synchronization
257 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
257 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
258 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
258 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
259 &VisualizationZoneWidget::onVariableAdded);
259 &VisualizationZoneWidget::onVariableAdded);
260 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
260 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
261 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
261 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
262
262
263 auto range = SqpRange{};
263 auto range = SqpRange{};
264 if (auto firstGraph = impl->firstGraph(this)) {
264 if (auto firstGraph = impl->firstGraph(this)) {
265 // Case of a new graph in a existant zone
265 // Case of a new graph in a existant zone
266 range = firstGraph->graphRange();
266 range = firstGraph->graphRange();
267 }
267 }
268 else {
268 else {
269 // Case of a new graph as the first of the zone
269 // Case of a new graph as the first of the zone
270 range = variable->range();
270 range = variable->range();
271 }
271 }
272
272
273 this->insertGraph(index, graphWidget);
273 this->insertGraph(index, graphWidget);
274
274
275 graphWidget->addVariable(variable, range);
275 graphWidget->addVariable(variable, range);
276 graphWidget->setYRange(variable);
276 graphWidget->setYRange(variable);
277
277
278 return graphWidget;
278 return graphWidget;
279 }
279 }
280
280
281 VisualizationGraphWidget *
281 VisualizationGraphWidget *
282 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
282 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
283 {
283 {
284 if (variables.isEmpty()) {
284 if (variables.isEmpty()) {
285 return nullptr;
285 return nullptr;
286 }
286 }
287
287
288 auto graphWidget = createGraph(variables.first(), index);
288 auto graphWidget = createGraph(variables.first(), index);
289 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
289 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
290 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
290 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
291 }
291 }
292
292
293 return graphWidget;
293 return graphWidget;
294 }
294 }
295
295
296 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
296 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
297 {
297 {
298 if (visitor) {
298 if (visitor) {
299 visitor->visitEnter(this);
299 visitor->visitEnter(this);
300
300
301 // Apply visitor to graph children: widgets different from graphs are not visited (no
301 // Apply visitor to graph children: widgets different from graphs are not visited (no
302 // action)
302 // action)
303 processGraphs(
303 processGraphs(
304 *ui->dragDropContainer->layout(),
304 *ui->dragDropContainer->layout(),
305 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
305 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
306
306
307 visitor->visitLeave(this);
307 visitor->visitLeave(this);
308 }
308 }
309 else {
309 else {
310 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
310 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
311 }
311 }
312 }
312 }
313
313
314 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
314 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
315 {
315 {
316 // A tab can always accomodate a variable
316 // A tab can always accomodate a variable
317 Q_UNUSED(variable);
317 Q_UNUSED(variable);
318 return true;
318 return true;
319 }
319 }
320
320
321 bool VisualizationZoneWidget::contains(const Variable &variable) const
321 bool VisualizationZoneWidget::contains(const Variable &variable) const
322 {
322 {
323 Q_UNUSED(variable);
323 Q_UNUSED(variable);
324 return false;
324 return false;
325 }
325 }
326
326
327 QString VisualizationZoneWidget::name() const
327 QString VisualizationZoneWidget::name() const
328 {
328 {
329 return ui->zoneNameLabel->text();
329 return ui->zoneNameLabel->text();
330 }
330 }
331
331
332 QMimeData *VisualizationZoneWidget::mimeData() const
332 QMimeData *VisualizationZoneWidget::mimeData() const
333 {
333 {
334 auto mimeData = new QMimeData;
334 auto mimeData = new QMimeData;
335 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
335 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
336
336
337 if (auto firstGraph = impl->firstGraph(this)) {
337 if (auto firstGraph = impl->firstGraph(this)) {
338 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
338 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
339 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
339 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
340 }
340 }
341
341
342 return mimeData;
342 return mimeData;
343 }
343 }
344
344
345 bool VisualizationZoneWidget::isDragAllowed() const
345 bool VisualizationZoneWidget::isDragAllowed() const
346 {
346 {
347 return true;
347 return true;
348 }
348 }
349
349
350 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
351 const QPointF &plotPosition,
352 VisualizationGraphWidget *graphWidget)
353 {
354 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
355 VisualizationGraphWidget &processedGraph) {
356
357 switch (sqpApp->plotsCursorMode()) {
358 case SqpApplication::PlotsCursorMode::Vertical:
359 processedGraph.removeHorizontalCursor();
360 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
361 break;
362 case SqpApplication::PlotsCursorMode::Temporal:
363 processedGraph.addVerticalCursor(plotPosition.x());
364 processedGraph.removeHorizontalCursor();
365 break;
366 case SqpApplication::PlotsCursorMode::Horizontal:
367 processedGraph.removeVerticalCursor();
368 if (&processedGraph == graphWidget) {
369 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
370 }
371 else {
372 processedGraph.removeHorizontalCursor();
373 }
374 break;
375 case SqpApplication::PlotsCursorMode::Cross:
376 if (&processedGraph == graphWidget) {
377 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
378 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
379 }
380 else {
381 processedGraph.removeHorizontalCursor();
382 processedGraph.removeVerticalCursor();
383 }
384 break;
385 case SqpApplication::PlotsCursorMode::NoCursor:
386 processedGraph.removeHorizontalCursor();
387 processedGraph.removeVerticalCursor();
388 break;
389 }
390
391
392 });
393 }
394
395 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
396 {
397 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
398 processedGraph.removeHorizontalCursor();
399 processedGraph.removeVerticalCursor();
400 });
401 }
402
350 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
403 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
351 {
404 {
352 // Closes graphs in the zone
405 // Closes graphs in the zone
353 processGraphs(*ui->dragDropContainer->layout(),
406 processGraphs(*ui->dragDropContainer->layout(),
354 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
407 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
355
408
356 // Delete synchronization group from variable controller
409 // Delete synchronization group from variable controller
357 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
410 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
358 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
411 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
359
412
360 QWidget::closeEvent(event);
413 QWidget::closeEvent(event);
361 }
414 }
362
415
363 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
416 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
364 {
417 {
365 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
418 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
366 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
419 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
367 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
420 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
368 }
421 }
369
422
370 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
423 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
371 {
424 {
372 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
425 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
373 Q_ARG(std::shared_ptr<Variable>, variable),
426 Q_ARG(std::shared_ptr<Variable>, variable),
374 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
427 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
375 }
428 }
376
429
377 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
430 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
378 {
431 {
379 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
432 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
380 impl->dropGraph(index, this);
433 impl->dropGraph(index, this);
381 }
434 }
382 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
435 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
383 auto variables = sqpApp->variableController().variablesForMimeData(
436 auto variables = sqpApp->variableController().variablesForMimeData(
384 mimeData->data(MIME_TYPE_VARIABLE_LIST));
437 mimeData->data(MIME_TYPE_VARIABLE_LIST));
385 impl->dropVariables(variables, index, this);
438 impl->dropVariables(variables, index, this);
386 }
439 }
387 else {
440 else {
388 qCWarning(LOG_VisualizationZoneWidget())
441 qCWarning(LOG_VisualizationZoneWidget())
389 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
442 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
390 }
443 }
391 }
444 }
392
445
393 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
446 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
394 const QMimeData *mimeData)
447 const QMimeData *mimeData)
395 {
448 {
396 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
449 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
397 if (!graphWidget) {
450 if (!graphWidget) {
398 qCWarning(LOG_VisualizationZoneWidget())
451 qCWarning(LOG_VisualizationZoneWidget())
399 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
452 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
400 "drop aborted");
453 "drop aborted");
401 Q_ASSERT(false);
454 Q_ASSERT(false);
402 return;
455 return;
403 }
456 }
404
457
405 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
458 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
406 auto variables = sqpApp->variableController().variablesForMimeData(
459 auto variables = sqpApp->variableController().variablesForMimeData(
407 mimeData->data(MIME_TYPE_VARIABLE_LIST));
460 mimeData->data(MIME_TYPE_VARIABLE_LIST));
408 for (const auto &var : variables) {
461 for (const auto &var : variables) {
409 graphWidget->addVariable(var, graphWidget->graphRange());
462 graphWidget->addVariable(var, graphWidget->graphRange());
410 }
463 }
411 }
464 }
412 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
465 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
413 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
466 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
414 graphWidget->setGraphRange(range);
467 graphWidget->setGraphRange(range);
415 }
468 }
416 else {
469 else {
417 qCWarning(LOG_VisualizationZoneWidget())
470 qCWarning(LOG_VisualizationZoneWidget())
418 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
471 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
419 }
472 }
420 }
473 }
421
474
422 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
475 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
423 int index, VisualizationZoneWidget *zoneWidget)
476 int index, VisualizationZoneWidget *zoneWidget)
424 {
477 {
425 auto &helper = sqpApp->dragDropHelper();
478 auto &helper = sqpApp->dragDropHelper();
426
479
427 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
480 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
428 if (!graphWidget) {
481 if (!graphWidget) {
429 qCWarning(LOG_VisualizationZoneWidget())
482 qCWarning(LOG_VisualizationZoneWidget())
430 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
483 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
431 "found or invalid.");
484 "found or invalid.");
432 Q_ASSERT(false);
485 Q_ASSERT(false);
433 return;
486 return;
434 }
487 }
435
488
436 auto parentDragDropContainer
489 auto parentDragDropContainer
437 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
490 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
438 if (!parentDragDropContainer) {
491 if (!parentDragDropContainer) {
439 qCWarning(LOG_VisualizationZoneWidget())
492 qCWarning(LOG_VisualizationZoneWidget())
440 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
493 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
441 "the dropped graph is not found.");
494 "the dropped graph is not found.");
442 Q_ASSERT(false);
495 Q_ASSERT(false);
443 return;
496 return;
444 }
497 }
445
498
446 const auto &variables = graphWidget->variables();
499 const auto &variables = graphWidget->variables();
447
500
448 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
501 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
449 // The drop didn't occur in the same zone
502 // The drop didn't occur in the same zone
450
503
451 // Abort the requests for the variables (if any)
504 // Abort the requests for the variables (if any)
452 // Commented, because it's not sure if it's needed or not
505 // Commented, because it's not sure if it's needed or not
453 // for (const auto& var : variables)
506 // for (const auto& var : variables)
454 //{
507 //{
455 // sqpApp->variableController().onAbortProgressRequested(var);
508 // sqpApp->variableController().onAbortProgressRequested(var);
456 //}
509 //}
457
510
458 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
511 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
459 auto nbGraph = parentDragDropContainer->countDragWidget();
512 auto nbGraph = parentDragDropContainer->countDragWidget();
460 if (nbGraph == 1) {
513 if (nbGraph == 1) {
461 // This is the only graph in the previous zone, close the zone
514 // This is the only graph in the previous zone, close the zone
462 helper.delayedCloseWidget(previousParentZoneWidget);
515 helper.delayedCloseWidget(previousParentZoneWidget);
463 }
516 }
464 else {
517 else {
465 // Close the graph
518 // Close the graph
466 helper.delayedCloseWidget(graphWidget);
519 helper.delayedCloseWidget(graphWidget);
467 }
520 }
468
521
469 // Creates the new graph in the zone
522 // Creates the new graph in the zone
470 zoneWidget->createGraph(variables, index);
523 zoneWidget->createGraph(variables, index);
471 }
524 }
472 else {
525 else {
473 // The drop occurred in the same zone or the graph is empty
526 // The drop occurred in the same zone or the graph is empty
474 // Simple move of the graph, no variable operation associated
527 // Simple move of the graph, no variable operation associated
475 parentDragDropContainer->layout()->removeWidget(graphWidget);
528 parentDragDropContainer->layout()->removeWidget(graphWidget);
476
529
477 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
530 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
478 // The graph is empty and dropped in a different zone.
531 // The graph is empty and dropped in a different zone.
479 // Take the range of the first graph in the zone (if existing).
532 // Take the range of the first graph in the zone (if existing).
480 auto layout = zoneWidget->ui->dragDropContainer->layout();
533 auto layout = zoneWidget->ui->dragDropContainer->layout();
481 if (layout->count() > 0) {
534 if (layout->count() > 0) {
482 if (auto visualizationGraphWidget
535 if (auto visualizationGraphWidget
483 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
536 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
484 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
537 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
485 }
538 }
486 }
539 }
487 }
540 }
488
541
489 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
542 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
490 }
543 }
491 }
544 }
492
545
493 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
546 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
494 const QList<std::shared_ptr<Variable> > &variables, int index,
547 const QList<std::shared_ptr<Variable> > &variables, int index,
495 VisualizationZoneWidget *zoneWidget)
548 VisualizationZoneWidget *zoneWidget)
496 {
549 {
497 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
550 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
498 // compatible variable here
551 // compatible variable here
499 if (variables.count() > 1) {
552 if (variables.count() > 1) {
500 qCWarning(LOG_VisualizationZoneWidget())
553 qCWarning(LOG_VisualizationZoneWidget())
501 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
554 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
502 "aborted.");
555 "aborted.");
503 return;
556 return;
504 }
557 }
505
558
506 zoneWidget->createGraph(variables, index);
559 zoneWidget->createGraph(variables, index);
507 }
560 }
General Comments 0
You need to be logged in to leave comments. Login now