##// END OF EJS Templates
multi selection of zones
trabillard -
r1049:ead367adcd3d
parent child
Show More
@@ -0,0 +1,26
1 #ifndef SCIQLOP_VISUALIZATIONSELECTIONZONEMANAGER_H
2 #define SCIQLOP_VISUALIZATIONSELECTIONZONEMANAGER_H
3
4 #include <Common/spimpl.h>
5
6 #include <QVector>
7
8 class VisualizationSelectionZoneItem;
9
10 class VisualizationSelectionZoneManager {
11 public:
12 VisualizationSelectionZoneManager();
13
14 void select(const QVector<VisualizationSelectionZoneItem *> &items);
15 void setSelected(VisualizationSelectionZoneItem *item, bool value);
16
17 void clearSelection();
18
19 QVector<VisualizationSelectionZoneItem *> selectedItems() const;
20
21 private:
22 class VisualizationSelectionZoneManagerPrivate;
23 spimpl::unique_impl_ptr<VisualizationSelectionZoneManagerPrivate> impl;
24 };
25
26 #endif // SCIQLOP_VISUALIZATIONSELECTIONZONEMANAGER_H
@@ -0,0 +1,51
1 #include "Visualization/VisualizationSelectionZoneManager.h"
2 #include "Visualization/VisualizationSelectionZoneItem.h"
3
4 struct VisualizationSelectionZoneManager::VisualizationSelectionZoneManagerPrivate {
5 QVector<VisualizationSelectionZoneItem *> m_SelectedItems;
6 };
7
8 VisualizationSelectionZoneManager::VisualizationSelectionZoneManager()
9 : impl{spimpl::make_unique_impl<VisualizationSelectionZoneManagerPrivate>()}
10 {
11 }
12
13 void VisualizationSelectionZoneManager::select(
14 const QVector<VisualizationSelectionZoneItem *> &items)
15 {
16 clearSelection();
17 for (auto item : items) {
18 setSelected(item, true);
19 }
20 }
21
22 void VisualizationSelectionZoneManager::setSelected(VisualizationSelectionZoneItem *item,
23 bool value)
24 {
25 if (value != item->selected()) {
26 item->setSelected(value);
27 item->parentPlot()->replot();
28 }
29
30 if (!value && impl->m_SelectedItems.contains(item)) {
31 impl->m_SelectedItems.removeAll(item);
32 }
33 else if (value) {
34 impl->m_SelectedItems << item;
35 }
36 }
37
38 void VisualizationSelectionZoneManager::clearSelection()
39 {
40 for (auto item : impl->m_SelectedItems) {
41 item->setSelected(false);
42 item->parentPlot()->replot();
43 }
44
45 impl->m_SelectedItems.clear();
46 }
47
48 QVector<VisualizationSelectionZoneItem *> VisualizationSelectionZoneManager::selectedItems() const
49 {
50 return impl->m_SelectedItems;
51 }
@@ -1,133 +1,138
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 VisualizationWidget;
20 class VisualizationZoneWidget;
21 class VisualizationZoneWidget;
21
22
22 namespace Ui {
23 namespace Ui {
23 class VisualizationGraphWidget;
24 class VisualizationGraphWidget;
24 } // namespace Ui
25 } // namespace Ui
25
26
26 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
27 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
27 Q_OBJECT
28 Q_OBJECT
28
29
29 friend class QCustomPlotSynchronizer;
30 friend class QCustomPlotSynchronizer;
30 friend class VisualizationGraphRenderingDelegate;
31 friend class VisualizationGraphRenderingDelegate;
31
32
32 public:
33 public:
33 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
34 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
34 virtual ~VisualizationGraphWidget();
35 virtual ~VisualizationGraphWidget();
35
36
37 /// Returns the VisualizationZoneWidget which contains the graph or nullptr
36 VisualizationZoneWidget *parentZoneWidget() const noexcept;
38 VisualizationZoneWidget *parentZoneWidget() const noexcept;
37
39
40 /// Returns the main VisualizationWidget which contains the graph or nullptr
41 VisualizationWidget *parentVisualizationWidget() const;
42
38 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
43 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
39 void enableAcquisition(bool enable);
44 void enableAcquisition(bool enable);
40
45
41 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
46 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
42
47
43 /// Removes a variable from the graph
48 /// Removes a variable from the graph
44 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
49 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
45
50
46 /// Returns the list of all variables used in the graph
51 /// Returns the list of all variables used in the graph
47 QList<std::shared_ptr<Variable> > variables() const;
52 QList<std::shared_ptr<Variable> > variables() const;
48
53
49 /// Sets the y-axis range based on the data of a variable
54 /// Sets the y-axis range based on the data of a variable
50 void setYRange(std::shared_ptr<Variable> variable);
55 void setYRange(std::shared_ptr<Variable> variable);
51 SqpRange graphRange() const noexcept;
56 SqpRange graphRange() const noexcept;
52 void setGraphRange(const SqpRange &range);
57 void setGraphRange(const SqpRange &range);
53
58
54 /// Returns the ranges of all the selection zones on the graph
59 /// Returns the ranges of all the selection zones on the graph
55 QVector<SqpRange> selectionZoneRanges() const;
60 QVector<SqpRange> selectionZoneRanges() const;
56
61
57 /// Adds new selection zones in the graph
62 /// Adds new selection zones in the graph
58 void addSelectionZones(const QVector<SqpRange> &ranges);
63 void addSelectionZones(const QVector<SqpRange> &ranges);
59
64
60 /// Undo the last zoom done with a zoom box
65 /// Undo the last zoom done with a zoom box
61 void undoZoom();
66 void undoZoom();
62
67
63 // IVisualizationWidget interface
68 // IVisualizationWidget interface
64 void accept(IVisualizationWidgetVisitor *visitor) override;
69 void accept(IVisualizationWidgetVisitor *visitor) override;
65 bool canDrop(const Variable &variable) const override;
70 bool canDrop(const Variable &variable) const override;
66 bool contains(const Variable &variable) const override;
71 bool contains(const Variable &variable) const override;
67 QString name() const override;
72 QString name() const override;
68
73
69 // VisualisationDragWidget
74 // VisualisationDragWidget
70 QMimeData *mimeData(const QPoint &position) const override;
75 QMimeData *mimeData(const QPoint &position) const override;
71 QPixmap customDragPixmap(const QPoint &dragPosition) override;
76 QPixmap customDragPixmap(const QPoint &dragPosition) override;
72 bool isDragAllowed() const override;
77 bool isDragAllowed() const override;
73 void highlightForMerge(bool highlighted) override;
78 void highlightForMerge(bool highlighted) override;
74
79
75 // Cursors
80 // Cursors
76 /// Adds or moves the vertical cursor at the specified value on the x-axis
81 /// Adds or moves the vertical cursor at the specified value on the x-axis
77 void addVerticalCursor(double time);
82 void addVerticalCursor(double time);
78 /// Adds or moves the vertical cursor at the specified value on the x-axis
83 /// Adds or moves the vertical cursor at the specified value on the x-axis
79 void addVerticalCursorAtViewportPosition(double position);
84 void addVerticalCursorAtViewportPosition(double position);
80 void removeVerticalCursor();
85 void removeVerticalCursor();
81 /// Adds or moves the vertical cursor at the specified value on the y-axis
86 /// Adds or moves the vertical cursor at the specified value on the y-axis
82 void addHorizontalCursor(double value);
87 void addHorizontalCursor(double value);
83 /// Adds or moves the vertical cursor at the specified value on the y-axis
88 /// Adds or moves the vertical cursor at the specified value on the y-axis
84 void addHorizontalCursorAtViewportPosition(double position);
89 void addHorizontalCursorAtViewportPosition(double position);
85 void removeHorizontalCursor();
90 void removeHorizontalCursor();
86
91
87 signals:
92 signals:
88 void synchronize(const SqpRange &range, const SqpRange &oldRange);
93 void synchronize(const SqpRange &range, const SqpRange &oldRange);
89 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
94 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
90 bool synchronise);
95 bool synchronise);
91
96
92 /// Signal emitted when the variable is about to be removed from the graph
97 /// Signal emitted when the variable is about to be removed from the graph
93 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
98 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
94 /// Signal emitted when the variable has been added to the graph
99 /// Signal emitted when the variable has been added to the graph
95 void variableAdded(std::shared_ptr<Variable> var);
100 void variableAdded(std::shared_ptr<Variable> var);
96
101
97 protected:
102 protected:
98 void closeEvent(QCloseEvent *event) override;
103 void closeEvent(QCloseEvent *event) override;
99 void enterEvent(QEvent *event) override;
104 void enterEvent(QEvent *event) override;
100 void leaveEvent(QEvent *event) override;
105 void leaveEvent(QEvent *event) override;
101
106
102 QCustomPlot &plot() const noexcept;
107 QCustomPlot &plot() const noexcept;
103
108
104 private:
109 private:
105 Ui::VisualizationGraphWidget *ui;
110 Ui::VisualizationGraphWidget *ui;
106
111
107 class VisualizationGraphWidgetPrivate;
112 class VisualizationGraphWidgetPrivate;
108 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
113 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
109
114
110 private slots:
115 private slots:
111 /// Slot called when right clicking on the graph (displays a menu)
116 /// Slot called when right clicking on the graph (displays a menu)
112 void onGraphMenuRequested(const QPoint &pos) noexcept;
117 void onGraphMenuRequested(const QPoint &pos) noexcept;
113
118
114 /// Rescale the X axe to range parameter
119 /// Rescale the X axe to range parameter
115 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
120 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
116
121
117 /// Slot called when a mouse double click was made
122 /// Slot called when a mouse double click was made
118 void onMouseDoubleClick(QMouseEvent *event) noexcept;
123 void onMouseDoubleClick(QMouseEvent *event) noexcept;
119 /// Slot called when a mouse move was made
124 /// Slot called when a mouse move was made
120 void onMouseMove(QMouseEvent *event) noexcept;
125 void onMouseMove(QMouseEvent *event) noexcept;
121 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
126 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
122 void onMouseWheel(QWheelEvent *event) noexcept;
127 void onMouseWheel(QWheelEvent *event) noexcept;
123 /// Slot called when a mouse press was made, to activate the calibration of a graph
128 /// Slot called when a mouse press was made, to activate the calibration of a graph
124 void onMousePress(QMouseEvent *event) noexcept;
129 void onMousePress(QMouseEvent *event) noexcept;
125 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
130 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
126 void onMouseRelease(QMouseEvent *event) noexcept;
131 void onMouseRelease(QMouseEvent *event) noexcept;
127
132
128 void onDataCacheVariableUpdated();
133 void onDataCacheVariableUpdated();
129
134
130 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
135 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
131 };
136 };
132
137
133 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
138 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,39 +1,40
1 #ifndef SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
1 #ifndef SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
2 #define SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
2 #define SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <Data/SqpRange.h>
5 #include <Data/SqpRange.h>
6 #include <Visualization/qcustomplot.h>
6 #include <Visualization/qcustomplot.h>
7
7
8 class VisualizationSelectionZoneItem : public QCPItemRect {
8 class VisualizationSelectionZoneItem : public QCPItemRect {
9
9 public:
10 public:
10 VisualizationSelectionZoneItem(QCustomPlot *plot);
11 VisualizationSelectionZoneItem(QCustomPlot *plot);
11 virtual ~VisualizationSelectionZoneItem();
12 virtual ~VisualizationSelectionZoneItem();
12
13
13 void setName(const QString &name);
14 void setName(const QString &name);
14 QString name() const;
15 QString name() const;
15
16
16 SqpRange range() const;
17 SqpRange range() const;
17 void setRange(double tstart, double tend);
18 void setRange(double tstart, double tend);
18 void setStart(double tstart);
19 void setStart(double tstart);
19 void setEnd(double tend);
20 void setEnd(double tend);
20
21
21 void setColor(const QColor &color);
22 void setColor(const QColor &color);
22
23
23 void setEditionEnabled(bool value);
24 void setEditionEnabled(bool value);
24 bool isEditionEnabled() const;
25 bool isEditionEnabled() const;
25
26
26 Qt::CursorShape curshorShapeForPosition(const QPoint &position) const;
27 Qt::CursorShape curshorShapeForPosition(const QPoint &position) const;
27 void setHovered(bool value);
28 void setHovered(bool value);
28
29
29 protected:
30 protected:
30 void mousePressEvent(QMouseEvent *event, const QVariant &details) override;
31 void mousePressEvent(QMouseEvent *event, const QVariant &details) override;
31 void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) override;
32 void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) override;
32 void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) override;
33 void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) override;
33
34
34 private:
35 private:
35 class VisualizationSelectionZoneItemPrivate;
36 class VisualizationSelectionZoneItemPrivate;
36 spimpl::unique_impl_ptr<VisualizationSelectionZoneItemPrivate> impl;
37 spimpl::unique_impl_ptr<VisualizationSelectionZoneItemPrivate> impl;
37 };
38 };
38
39
39 #endif // SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
40 #endif // SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
@@ -1,54 +1,63
1 #ifndef SCIQLOP_VISUALIZATIONWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONWIDGET_H
2 #define SCIQLOP_VISUALIZATIONWIDGET_H
2 #define SCIQLOP_VISUALIZATIONWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5 #include <Data/SqpRange.h>
5 #include <Data/SqpRange.h>
6
6
7 #include <QLoggingCategory>
7 #include <QLoggingCategory>
8 #include <QWidget>
8 #include <QWidget>
9
9
10 #include <Common/spimpl.h>
11
10 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationWidget)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationWidget)
11
13
12 class QMenu;
14 class QMenu;
13 class Variable;
15 class Variable;
14 class VisualizationTabWidget;
16 class VisualizationTabWidget;
17 class VisualizationSelectionZoneManager;
15
18
16 namespace Ui {
19 namespace Ui {
17 class VisualizationWidget;
20 class VisualizationWidget;
18 } // namespace Ui
21 } // namespace Ui
19
22
20 class VisualizationWidget : public QWidget, public IVisualizationWidget {
23 class VisualizationWidget : public QWidget, public IVisualizationWidget {
21 Q_OBJECT
24 Q_OBJECT
22
25
23 public:
26 public:
24 explicit VisualizationWidget(QWidget *parent = 0);
27 explicit VisualizationWidget(QWidget *parent = 0);
25 virtual ~VisualizationWidget();
28 virtual ~VisualizationWidget();
26
29
30 /// Returns the class which manage the selection of selection zone across the visualization
31 VisualizationSelectionZoneManager &selectionZoneManager() const;
32
27 // IVisualizationWidget interface
33 // IVisualizationWidget interface
28 void accept(IVisualizationWidgetVisitor *visitor) override;
34 void accept(IVisualizationWidgetVisitor *visitor) override;
29 bool canDrop(const Variable &variable) const override;
35 bool canDrop(const Variable &variable) const override;
30 bool contains(const Variable &variable) const override;
36 bool contains(const Variable &variable) const override;
31 QString name() const override;
37 QString name() const override;
32
38
33 public slots:
39 public slots:
34 /**
40 /**
35 * Attaches to a menu the menu relative to the visualization of variables
41 * Attaches to a menu the menu relative to the visualization of variables
36 * @param menu the parent menu of the generated menu
42 * @param menu the parent menu of the generated menu
37 * @param variables the variables for which to generate the menu
43 * @param variables the variables for which to generate the menu
38 */
44 */
39 void attachVariableMenu(QMenu *menu,
45 void attachVariableMenu(QMenu *menu,
40 const QVector<std::shared_ptr<Variable> > &variables) noexcept;
46 const QVector<std::shared_ptr<Variable> > &variables) noexcept;
41
47
42 /// Slot called when a variable is about to be deleted from SciQlop
48 /// Slot called when a variable is about to be deleted from SciQlop
43 void onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept;
49 void onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept;
44
50
45 void onRangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range) noexcept;
51 void onRangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range) noexcept;
46
52
47 protected:
53 protected:
48 void closeEvent(QCloseEvent *event) override;
54 void closeEvent(QCloseEvent *event) override;
49
55
50 private:
56 private:
51 Ui::VisualizationWidget *ui;
57 Ui::VisualizationWidget *ui;
58
59 class VisualizationWidgetPrivate;
60 spimpl::unique_impl_ptr<VisualizationWidgetPrivate> impl;
52 };
61 };
53
62
54 #endif // VISUALIZATIONWIDGET_H
63 #endif // VISUALIZATIONWIDGET_H
@@ -1,102 +1,103
1
1
2 gui_moc_headers = [
2 gui_moc_headers = [
3 'include/DataSource/DataSourceWidget.h',
3 'include/DataSource/DataSourceWidget.h',
4 'include/Settings/SqpSettingsDialog.h',
4 'include/Settings/SqpSettingsDialog.h',
5 'include/Settings/SqpSettingsGeneralWidget.h',
5 'include/Settings/SqpSettingsGeneralWidget.h',
6 'include/SidePane/SqpSidePane.h',
6 'include/SidePane/SqpSidePane.h',
7 'include/SqpApplication.h',
7 'include/SqpApplication.h',
8 'include/DragAndDrop/DragDropScroller.h',
8 'include/DragAndDrop/DragDropScroller.h',
9 'include/DragAndDrop/DragDropTabSwitcher.h',
9 'include/DragAndDrop/DragDropTabSwitcher.h',
10 'include/TimeWidget/TimeWidget.h',
10 'include/TimeWidget/TimeWidget.h',
11 'include/Variable/VariableInspectorWidget.h',
11 'include/Variable/VariableInspectorWidget.h',
12 'include/Variable/RenameVariableDialog.h',
12 'include/Variable/RenameVariableDialog.h',
13 'include/Visualization/qcustomplot.h',
13 'include/Visualization/qcustomplot.h',
14 'include/Visualization/VisualizationGraphWidget.h',
14 'include/Visualization/VisualizationGraphWidget.h',
15 'include/Visualization/VisualizationTabWidget.h',
15 'include/Visualization/VisualizationTabWidget.h',
16 'include/Visualization/VisualizationWidget.h',
16 'include/Visualization/VisualizationWidget.h',
17 'include/Visualization/VisualizationZoneWidget.h',
17 'include/Visualization/VisualizationZoneWidget.h',
18 'include/Visualization/VisualizationDragDropContainer.h',
18 'include/Visualization/VisualizationDragDropContainer.h',
19 'include/Visualization/VisualizationDragWidget.h',
19 'include/Visualization/VisualizationDragWidget.h',
20 'include/Visualization/ColorScaleEditor.h'
20 'include/Visualization/ColorScaleEditor.h'
21 ]
21 ]
22
22
23 gui_ui_files = [
23 gui_ui_files = [
24 'ui/DataSource/DataSourceWidget.ui',
24 'ui/DataSource/DataSourceWidget.ui',
25 'ui/Settings/SqpSettingsDialog.ui',
25 'ui/Settings/SqpSettingsDialog.ui',
26 'ui/Settings/SqpSettingsGeneralWidget.ui',
26 'ui/Settings/SqpSettingsGeneralWidget.ui',
27 'ui/SidePane/SqpSidePane.ui',
27 'ui/SidePane/SqpSidePane.ui',
28 'ui/TimeWidget/TimeWidget.ui',
28 'ui/TimeWidget/TimeWidget.ui',
29 'ui/Variable/VariableInspectorWidget.ui',
29 'ui/Variable/VariableInspectorWidget.ui',
30 'ui/Variable/RenameVariableDialog.ui',
30 'ui/Variable/RenameVariableDialog.ui',
31 'ui/Variable/VariableMenuHeaderWidget.ui',
31 'ui/Variable/VariableMenuHeaderWidget.ui',
32 'ui/Visualization/VisualizationGraphWidget.ui',
32 'ui/Visualization/VisualizationGraphWidget.ui',
33 'ui/Visualization/VisualizationTabWidget.ui',
33 'ui/Visualization/VisualizationTabWidget.ui',
34 'ui/Visualization/VisualizationWidget.ui',
34 'ui/Visualization/VisualizationWidget.ui',
35 'ui/Visualization/VisualizationZoneWidget.ui',
35 'ui/Visualization/VisualizationZoneWidget.ui',
36 'ui/Visualization/ColorScaleEditor.ui'
36 'ui/Visualization/ColorScaleEditor.ui'
37 ]
37 ]
38
38
39 gui_qresources = ['resources/sqpguiresources.qrc']
39 gui_qresources = ['resources/sqpguiresources.qrc']
40
40
41 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
41 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
42 ui_files : gui_ui_files,
42 ui_files : gui_ui_files,
43 qresources : gui_qresources)
43 qresources : gui_qresources)
44
44
45 gui_sources = [
45 gui_sources = [
46 'src/SqpApplication.cpp',
46 'src/SqpApplication.cpp',
47 'src/DragAndDrop/DragDropHelper.cpp',
47 'src/DragAndDrop/DragDropHelper.cpp',
48 'src/DragAndDrop/DragDropScroller.cpp',
48 'src/DragAndDrop/DragDropScroller.cpp',
49 'src/DragAndDrop/DragDropTabSwitcher.cpp',
49 'src/DragAndDrop/DragDropTabSwitcher.cpp',
50 'src/Common/ColorUtils.cpp',
50 'src/Common/ColorUtils.cpp',
51 'src/Common/VisualizationDef.cpp',
51 'src/Common/VisualizationDef.cpp',
52 'src/DataSource/DataSourceTreeWidgetItem.cpp',
52 'src/DataSource/DataSourceTreeWidgetItem.cpp',
53 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
53 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
54 'src/DataSource/DataSourceWidget.cpp',
54 'src/DataSource/DataSourceWidget.cpp',
55 'src/DataSource/DataSourceTreeWidget.cpp',
55 'src/DataSource/DataSourceTreeWidget.cpp',
56 'src/Settings/SqpSettingsDialog.cpp',
56 'src/Settings/SqpSettingsDialog.cpp',
57 'src/Settings/SqpSettingsGeneralWidget.cpp',
57 'src/Settings/SqpSettingsGeneralWidget.cpp',
58 'src/SidePane/SqpSidePane.cpp',
58 'src/SidePane/SqpSidePane.cpp',
59 'src/TimeWidget/TimeWidget.cpp',
59 'src/TimeWidget/TimeWidget.cpp',
60 'src/Variable/VariableInspectorWidget.cpp',
60 'src/Variable/VariableInspectorWidget.cpp',
61 'src/Variable/VariableInspectorTableView.cpp',
61 'src/Variable/VariableInspectorTableView.cpp',
62 'src/Variable/VariableMenuHeaderWidget.cpp',
62 'src/Variable/VariableMenuHeaderWidget.cpp',
63 'src/Variable/RenameVariableDialog.cpp',
63 'src/Variable/RenameVariableDialog.cpp',
64 'src/Visualization/VisualizationGraphHelper.cpp',
64 'src/Visualization/VisualizationGraphHelper.cpp',
65 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
65 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
66 'src/Visualization/VisualizationGraphWidget.cpp',
66 'src/Visualization/VisualizationGraphWidget.cpp',
67 'src/Visualization/VisualizationTabWidget.cpp',
67 'src/Visualization/VisualizationTabWidget.cpp',
68 'src/Visualization/VisualizationWidget.cpp',
68 'src/Visualization/VisualizationWidget.cpp',
69 'src/Visualization/VisualizationZoneWidget.cpp',
69 'src/Visualization/VisualizationZoneWidget.cpp',
70 'src/Visualization/qcustomplot.cpp',
70 'src/Visualization/qcustomplot.cpp',
71 'src/Visualization/QCustomPlotSynchronizer.cpp',
71 'src/Visualization/QCustomPlotSynchronizer.cpp',
72 'src/Visualization/operations/FindVariableOperation.cpp',
72 'src/Visualization/operations/FindVariableOperation.cpp',
73 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
73 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
74 'src/Visualization/operations/MenuBuilder.cpp',
74 'src/Visualization/operations/MenuBuilder.cpp',
75 'src/Visualization/operations/RemoveVariableOperation.cpp',
75 'src/Visualization/operations/RemoveVariableOperation.cpp',
76 'src/Visualization/operations/RescaleAxeOperation.cpp',
76 'src/Visualization/operations/RescaleAxeOperation.cpp',
77 'src/Visualization/VisualizationDragDropContainer.cpp',
77 'src/Visualization/VisualizationDragDropContainer.cpp',
78 'src/Visualization/VisualizationDragWidget.cpp',
78 'src/Visualization/VisualizationDragWidget.cpp',
79 'src/Visualization/AxisRenderingUtils.cpp',
79 'src/Visualization/AxisRenderingUtils.cpp',
80 'src/Visualization/PlottablesRenderingUtils.cpp',
80 'src/Visualization/PlottablesRenderingUtils.cpp',
81 'src/Visualization/MacScrollBarStyle.cpp',
81 'src/Visualization/MacScrollBarStyle.cpp',
82 'src/Visualization/VisualizationCursorItem.cpp',
82 'src/Visualization/VisualizationCursorItem.cpp',
83 'src/Visualization/ColorScaleEditor.cpp',
83 'src/Visualization/ColorScaleEditor.cpp',
84 'src/Visualization/SqpColorScale.cpp',
84 'src/Visualization/SqpColorScale.cpp',
85 'src/Visualization/QCPColorMapIterator.cpp',
85 'src/Visualization/QCPColorMapIterator.cpp',
86 'src/Visualization/VisualizationSelectionZoneItem.cpp'
86 'src/Visualization/VisualizationSelectionZoneItem.cpp',
87 'src/Visualization/VisualizationSelectionZoneManager.cpp'
87 ]
88 ]
88
89
89 gui_inc = include_directories(['include'])
90 gui_inc = include_directories(['include'])
90
91
91 sciqlop_gui_lib = library('sciqlopgui',
92 sciqlop_gui_lib = library('sciqlopgui',
92 gui_sources,
93 gui_sources,
93 gui_moc_files,
94 gui_moc_files,
94 include_directories : [gui_inc],
95 include_directories : [gui_inc],
95 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
96 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
96 install : true
97 install : true
97 )
98 )
98
99
99 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
100 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
100 include_directories : gui_inc,
101 include_directories : gui_inc,
101 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
102 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
102
103
@@ -1,818 +1,858
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationCursorItem.h"
3 #include "Visualization/VisualizationCursorItem.h"
4 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationDefs.h"
5 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphHelper.h"
6 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationGraphRenderingDelegate.h"
7 #include "Visualization/VisualizationSelectionZoneItem.h"
7 #include "Visualization/VisualizationSelectionZoneItem.h"
8 #include "Visualization/VisualizationSelectionZoneManager.h"
9 #include "Visualization/VisualizationWidget.h"
8 #include "Visualization/VisualizationZoneWidget.h"
10 #include "Visualization/VisualizationZoneWidget.h"
9 #include "ui_VisualizationGraphWidget.h"
11 #include "ui_VisualizationGraphWidget.h"
10
12
11 #include <Common/MimeTypesDef.h>
13 #include <Common/MimeTypesDef.h>
12 #include <Data/ArrayData.h>
14 #include <Data/ArrayData.h>
13 #include <Data/IDataSeries.h>
15 #include <Data/IDataSeries.h>
14 #include <Data/SpectrogramSeries.h>
16 #include <Data/SpectrogramSeries.h>
15 #include <DragAndDrop/DragDropHelper.h>
17 #include <DragAndDrop/DragDropHelper.h>
16 #include <Settings/SqpSettingsDefs.h>
18 #include <Settings/SqpSettingsDefs.h>
17 #include <SqpApplication.h>
19 #include <SqpApplication.h>
18 #include <Time/TimeController.h>
20 #include <Time/TimeController.h>
19 #include <Variable/Variable.h>
21 #include <Variable/Variable.h>
20 #include <Variable/VariableController.h>
22 #include <Variable/VariableController.h>
21
23
22 #include <unordered_map>
24 #include <unordered_map>
23
25
24 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
26 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
25
27
26 namespace {
28 namespace {
27
29
28 /// Key pressed to enable drag&drop in all modes
30 /// Key pressed to enable drag&drop in all modes
29 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
31 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
30
32
31 /// Key pressed to enable zoom on horizontal axis
33 /// Key pressed to enable zoom on horizontal axis
32 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
34 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
33
35
34 /// Key pressed to enable zoom on vertical axis
36 /// Key pressed to enable zoom on vertical axis
35 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
37 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
36
38
37 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
39 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
38 const auto PAN_SPEED = 5;
40 const auto PAN_SPEED = 5;
39
41
40 /// Key pressed to enable a calibration pan
42 /// Key pressed to enable a calibration pan
41 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
43 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
42
44
45 /// Key pressed to enable multi selection of selection zones
46 const auto MULTI_ZONE_SELECTION_MODIFIER = Qt::ControlModifier;
47
43 /// Minimum size for the zoom box, in percentage of the axis range
48 /// Minimum size for the zoom box, in percentage of the axis range
44 const auto ZOOM_BOX_MIN_SIZE = 0.8;
49 const auto ZOOM_BOX_MIN_SIZE = 0.8;
45
50
46 /// Format of the dates appearing in the label of a cursor
51 /// Format of the dates appearing in the label of a cursor
47 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
52 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
48
53
49 } // namespace
54 } // namespace
50
55
51 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
56 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
52
57
53 explicit VisualizationGraphWidgetPrivate(const QString &name)
58 explicit VisualizationGraphWidgetPrivate(const QString &name)
54 : m_Name{name},
59 : m_Name{name},
55 m_DoAcquisition{true},
60 m_DoAcquisition{true},
56 m_IsCalibration{false},
61 m_IsCalibration{false},
57 m_RenderingDelegate{nullptr}
62 m_RenderingDelegate{nullptr}
58 {
63 {
59 }
64 }
60
65
61 void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
66 void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
62 const SqpRange &range)
67 const SqpRange &range)
63 {
68 {
64 VisualizationGraphHelper::updateData(plottables, dataSeries, range);
69 VisualizationGraphHelper::updateData(plottables, dataSeries, range);
65
70
66 // Prevents that data has changed to update rendering
71 // Prevents that data has changed to update rendering
67 m_RenderingDelegate->onPlotUpdated();
72 m_RenderingDelegate->onPlotUpdated();
68 }
73 }
69
74
70 QString m_Name;
75 QString m_Name;
71 // 1 variable -> n qcpplot
76 // 1 variable -> n qcpplot
72 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
77 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
73 bool m_DoAcquisition;
78 bool m_DoAcquisition;
74 bool m_IsCalibration;
79 bool m_IsCalibration;
75 /// Delegate used to attach rendering features to the plot
80 /// Delegate used to attach rendering features to the plot
76 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
81 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
77
82
78 QCPItemRect *m_DrawingZoomRect = nullptr;
83 QCPItemRect *m_DrawingZoomRect = nullptr;
79 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
84 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
80
85
81 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
86 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
82 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
87 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
83
88
84 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
89 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
85 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
90 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
86 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
91 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
87
92
88 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
93 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
89 {
94 {
90 removeDrawingRect(plot);
95 removeDrawingRect(plot);
91
96
92 auto axisPos = posToAxisPos(pos, plot);
97 auto axisPos = posToAxisPos(pos, plot);
93
98
94 m_DrawingZoomRect = new QCPItemRect{&plot};
99 m_DrawingZoomRect = new QCPItemRect{&plot};
95 QPen p;
100 QPen p;
96 p.setWidth(2);
101 p.setWidth(2);
97 m_DrawingZoomRect->setPen(p);
102 m_DrawingZoomRect->setPen(p);
98
103
99 m_DrawingZoomRect->topLeft->setCoords(axisPos);
104 m_DrawingZoomRect->topLeft->setCoords(axisPos);
100 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
105 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
101 }
106 }
102
107
103 void removeDrawingRect(QCustomPlot &plot)
108 void removeDrawingRect(QCustomPlot &plot)
104 {
109 {
105 if (m_DrawingZoomRect) {
110 if (m_DrawingZoomRect) {
106 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
111 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
107 m_DrawingZoomRect = nullptr;
112 m_DrawingZoomRect = nullptr;
108 plot.replot(QCustomPlot::rpQueuedReplot);
113 plot.replot(QCustomPlot::rpQueuedReplot);
109 }
114 }
110 }
115 }
111
116
112 void startDrawingZone(const QPoint &pos, QCustomPlot &plot)
117 void startDrawingZone(const QPoint &pos, VisualizationGraphWidget *graph)
113 {
118 {
114 endDrawingZone(plot);
119 endDrawingZone(graph);
115
120
116 auto axisPos = posToAxisPos(pos, plot);
121 auto axisPos = posToAxisPos(pos, graph->plot());
117
122
118 m_DrawingZone = new VisualizationSelectionZoneItem{&plot};
123 m_DrawingZone = new VisualizationSelectionZoneItem{&graph->plot()};
119 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
124 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
120 m_DrawingZone->setEditionEnabled(false);
125 m_DrawingZone->setEditionEnabled(false);
121 }
126 }
122
127
123 void endDrawingZone(QCustomPlot &plot)
128 void endDrawingZone(VisualizationGraphWidget *graph)
124 {
129 {
125 if (m_DrawingZone) {
130 if (m_DrawingZone) {
126 auto drawingZoneRange = m_DrawingZone->range();
131 auto drawingZoneRange = m_DrawingZone->range();
127 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
132 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
128 m_DrawingZone->setEditionEnabled(true);
133 m_DrawingZone->setEditionEnabled(true);
129 m_SelectionZones.append(m_DrawingZone);
134 addSelectionZone(m_DrawingZone);
130 }
135 }
131 else {
136 else {
132 plot.removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
137 graph->plot().removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
133 }
138 }
134
139
135 plot.replot(QCustomPlot::rpQueuedReplot);
140 graph->plot().replot(QCustomPlot::rpQueuedReplot);
136 m_DrawingZone = nullptr;
141 m_DrawingZone = nullptr;
137 }
142 }
138 }
143 }
139
144
140 void setSelectionZonesEditionEnabled(bool value)
145 void setSelectionZonesEditionEnabled(bool value)
141 {
146 {
142 for (auto s : m_SelectionZones) {
147 for (auto s : m_SelectionZones) {
143 s->setEditionEnabled(value);
148 s->setEditionEnabled(value);
144 }
149 }
145 }
150 }
146
151
152 void addSelectionZone(VisualizationSelectionZoneItem *zone) { m_SelectionZones << zone; }
153
147 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
154 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
148 const QCustomPlot &plot) const
155 const QCustomPlot &plot) const
149 {
156 {
150 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
157 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
151 auto minDistanceToZone = -1;
158 auto minDistanceToZone = -1;
152 for (auto zone : m_SelectionZones) {
159 for (auto zone : m_SelectionZones) {
153 auto distanceToZone = zone->selectTest(pos, false);
160 auto distanceToZone = zone->selectTest(pos, false);
154 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
161 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
155 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
162 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
156 selectionZoneItemUnderCursor = zone;
163 selectionZoneItemUnderCursor = zone;
157 }
164 }
158 }
165 }
159
166
160 return selectionZoneItemUnderCursor;
167 return selectionZoneItemUnderCursor;
161 }
168 }
162
169
163 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
170 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
164 {
171 {
165 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
172 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
166 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
173 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
167 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
174 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
168 }
175 }
169
176
170 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
177 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
171 {
178 {
172 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
179 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
173 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
180 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
174 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
181 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
175 }
182 }
176 };
183 };
177
184
178 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
185 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
179 : VisualizationDragWidget{parent},
186 : VisualizationDragWidget{parent},
180 ui{new Ui::VisualizationGraphWidget},
187 ui{new Ui::VisualizationGraphWidget},
181 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
188 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
182 {
189 {
183 ui->setupUi(this);
190 ui->setupUi(this);
184
191
185 // 'Close' options : widget is deleted when closed
192 // 'Close' options : widget is deleted when closed
186 setAttribute(Qt::WA_DeleteOnClose);
193 setAttribute(Qt::WA_DeleteOnClose);
187
194
188 // Set qcpplot properties :
195 // Set qcpplot properties :
189 // - zoom is enabled
196 // - zoom is enabled
190 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
197 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
191 ui->widget->setInteractions(QCP::iRangeZoom | QCP::iSelectItems);
198 ui->widget->setInteractions(QCP::iRangeZoom);
192 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
199 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
193
200
194 // The delegate must be initialized after the ui as it uses the plot
201 // The delegate must be initialized after the ui as it uses the plot
195 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
202 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
196
203
197 // Init the cursors
204 // Init the cursors
198 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
205 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
199 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
206 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
200 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
207 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
201 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
208 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
202
209
203 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
210 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
204 connect(ui->widget, &QCustomPlot::mouseRelease, this,
211 connect(ui->widget, &QCustomPlot::mouseRelease, this,
205 &VisualizationGraphWidget::onMouseRelease);
212 &VisualizationGraphWidget::onMouseRelease);
206 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
213 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
207 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
214 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
208 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
215 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
209 &VisualizationGraphWidget::onMouseDoubleClick);
216 &VisualizationGraphWidget::onMouseDoubleClick);
210 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
217 connect(
211 &QCPAxis::rangeChanged),
218 ui->widget->xAxis,
212 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
219 static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(&QCPAxis::rangeChanged),
220 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
213
221
214 // Activates menu when right clicking on the graph
222 // Activates menu when right clicking on the graph
215 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
223 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
216 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
224 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
217 &VisualizationGraphWidget::onGraphMenuRequested);
225 &VisualizationGraphWidget::onGraphMenuRequested);
218
226
219 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
227 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
220 &VariableController::onRequestDataLoading);
228 &VariableController::onRequestDataLoading);
221
229
222 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
230 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
223 &VisualizationGraphWidget::onUpdateVarDisplaying);
231 &VisualizationGraphWidget::onUpdateVarDisplaying);
224
232
225 #ifdef Q_OS_MAC
233 #ifdef Q_OS_MAC
226 plot().setPlottingHint(QCP::phFastPolylines, true);
234 plot().setPlottingHint(QCP::phFastPolylines, true);
227 #endif
235 #endif
228 }
236 }
229
237
230
238
231 VisualizationGraphWidget::~VisualizationGraphWidget()
239 VisualizationGraphWidget::~VisualizationGraphWidget()
232 {
240 {
233 delete ui;
241 delete ui;
234 }
242 }
235
243
236 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
244 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
237 {
245 {
238 auto parent = parentWidget();
246 auto parent = parentWidget();
239 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
247 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
240 parent = parent->parentWidget();
248 parent = parent->parentWidget();
241 }
249 }
242
250
243 return qobject_cast<VisualizationZoneWidget *>(parent);
251 return qobject_cast<VisualizationZoneWidget *>(parent);
244 }
252 }
245
253
254 VisualizationWidget *VisualizationGraphWidget::parentVisualizationWidget() const
255 {
256 auto parent = parentWidget();
257 while (parent != nullptr && !qobject_cast<VisualizationWidget *>(parent)) {
258 parent = parent->parentWidget();
259 }
260
261 return qobject_cast<VisualizationWidget *>(parent);
262 }
263
246 void VisualizationGraphWidget::enableAcquisition(bool enable)
264 void VisualizationGraphWidget::enableAcquisition(bool enable)
247 {
265 {
248 impl->m_DoAcquisition = enable;
266 impl->m_DoAcquisition = enable;
249 }
267 }
250
268
251 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
269 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
252 {
270 {
253 // Uses delegate to create the qcpplot components according to the variable
271 // Uses delegate to create the qcpplot components according to the variable
254 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
272 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
255
273
256 if (auto dataSeries = variable->dataSeries()) {
274 if (auto dataSeries = variable->dataSeries()) {
257 // Set axes properties according to the units of the data series
275 // Set axes properties according to the units of the data series
258 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
276 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
259
277
260 // Sets rendering properties for the new plottables
278 // Sets rendering properties for the new plottables
261 // Warning: this method must be called after setAxesProperties(), as it can access to some
279 // Warning: this method must be called after setAxesProperties(), as it can access to some
262 // axes properties that have to be initialized
280 // axes properties that have to be initialized
263 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
281 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
264 }
282 }
265
283
266 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
284 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
267
285
268 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
286 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
269
287
270 this->enableAcquisition(false);
288 this->enableAcquisition(false);
271 this->setGraphRange(range);
289 this->setGraphRange(range);
272 this->enableAcquisition(true);
290 this->enableAcquisition(true);
273
291
274 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
292 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
275
293
276 emit variableAdded(variable);
294 emit variableAdded(variable);
277 }
295 }
278
296
279 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
297 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
280 {
298 {
281 // Each component associated to the variable :
299 // Each component associated to the variable :
282 // - is removed from qcpplot (which deletes it)
300 // - is removed from qcpplot (which deletes it)
283 // - is no longer referenced in the map
301 // - is no longer referenced in the map
284 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
302 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
285 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
303 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
286 emit variableAboutToBeRemoved(variable);
304 emit variableAboutToBeRemoved(variable);
287
305
288 auto &plottablesMap = variableIt->second;
306 auto &plottablesMap = variableIt->second;
289
307
290 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
308 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
291 plottableIt != plottableEnd;) {
309 plottableIt != plottableEnd;) {
292 ui->widget->removePlottable(plottableIt->second);
310 ui->widget->removePlottable(plottableIt->second);
293 plottableIt = plottablesMap.erase(plottableIt);
311 plottableIt = plottablesMap.erase(plottableIt);
294 }
312 }
295
313
296 impl->m_VariableToPlotMultiMap.erase(variableIt);
314 impl->m_VariableToPlotMultiMap.erase(variableIt);
297 }
315 }
298
316
299 // Updates graph
317 // Updates graph
300 ui->widget->replot();
318 ui->widget->replot();
301 }
319 }
302
320
303 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
321 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
304 {
322 {
305 auto variables = QList<std::shared_ptr<Variable> >{};
323 auto variables = QList<std::shared_ptr<Variable> >{};
306 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
324 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
307 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
325 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
308 variables << it->first;
326 variables << it->first;
309 }
327 }
310
328
311 return variables;
329 return variables;
312 }
330 }
313
331
314 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
332 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
315 {
333 {
316 if (!variable) {
334 if (!variable) {
317 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
335 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
318 return;
336 return;
319 }
337 }
320
338
321 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
339 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
322 }
340 }
323
341
324 SqpRange VisualizationGraphWidget::graphRange() const noexcept
342 SqpRange VisualizationGraphWidget::graphRange() const noexcept
325 {
343 {
326 auto graphRange = ui->widget->xAxis->range();
344 auto graphRange = ui->widget->xAxis->range();
327 return SqpRange{graphRange.lower, graphRange.upper};
345 return SqpRange{graphRange.lower, graphRange.upper};
328 }
346 }
329
347
330 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
348 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
331 {
349 {
332 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
350 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
333 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
351 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
334 ui->widget->replot();
352 ui->widget->replot();
335 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
353 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
336 }
354 }
337
355
338 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
356 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
339 {
357 {
340 QVector<SqpRange> ranges;
358 QVector<SqpRange> ranges;
341 for (auto zone : impl->m_SelectionZones) {
359 for (auto zone : impl->m_SelectionZones) {
342 ranges << zone->range();
360 ranges << zone->range();
343 }
361 }
344
362
345 return ranges;
363 return ranges;
346 }
364 }
347
365
348 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges)
366 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges)
349 {
367 {
350 for (const auto &range : ranges) {
368 for (const auto &range : ranges) {
369 // note: ownership is transfered to QCustomPlot
351 auto zone = new VisualizationSelectionZoneItem(&plot());
370 auto zone = new VisualizationSelectionZoneItem(&plot());
352 zone->setRange(range.m_TStart, range.m_TEnd);
371 zone->setRange(range.m_TStart, range.m_TEnd);
353 impl->m_SelectionZones << zone;
372 impl->addSelectionZone(zone);
354 }
373 }
355
374
356 plot().replot(QCustomPlot::rpQueuedReplot);
375 plot().replot(QCustomPlot::rpQueuedReplot);
357 }
376 }
358
377
359 void VisualizationGraphWidget::undoZoom()
378 void VisualizationGraphWidget::undoZoom()
360 {
379 {
361 auto zoom = impl->m_ZoomStack.pop();
380 auto zoom = impl->m_ZoomStack.pop();
362 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
381 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
363 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
382 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
364
383
365 axisX->setRange(zoom.first);
384 axisX->setRange(zoom.first);
366 axisY->setRange(zoom.second);
385 axisY->setRange(zoom.second);
367
386
368 plot().replot(QCustomPlot::rpQueuedReplot);
387 plot().replot(QCustomPlot::rpQueuedReplot);
369 }
388 }
370
389
371 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
390 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
372 {
391 {
373 if (visitor) {
392 if (visitor) {
374 visitor->visit(this);
393 visitor->visit(this);
375 }
394 }
376 else {
395 else {
377 qCCritical(LOG_VisualizationGraphWidget())
396 qCCritical(LOG_VisualizationGraphWidget())
378 << tr("Can't visit widget : the visitor is null");
397 << tr("Can't visit widget : the visitor is null");
379 }
398 }
380 }
399 }
381
400
382 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
401 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
383 {
402 {
384 auto isSpectrogram = [](const auto &variable) {
403 auto isSpectrogram = [](const auto &variable) {
385 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
404 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
386 };
405 };
387
406
388 // - A spectrogram series can't be dropped on graph with existing plottables
407 // - A spectrogram series can't be dropped on graph with existing plottables
389 // - No data series can be dropped on graph with existing spectrogram series
408 // - No data series can be dropped on graph with existing spectrogram series
390 return isSpectrogram(variable)
409 return isSpectrogram(variable)
391 ? impl->m_VariableToPlotMultiMap.empty()
410 ? impl->m_VariableToPlotMultiMap.empty()
392 : std::none_of(
411 : std::none_of(
393 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
412 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
394 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
413 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
395 }
414 }
396
415
397 bool VisualizationGraphWidget::contains(const Variable &variable) const
416 bool VisualizationGraphWidget::contains(const Variable &variable) const
398 {
417 {
399 // Finds the variable among the keys of the map
418 // Finds the variable among the keys of the map
400 auto variablePtr = &variable;
419 auto variablePtr = &variable;
401 auto findVariable
420 auto findVariable
402 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
421 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
403
422
404 auto end = impl->m_VariableToPlotMultiMap.cend();
423 auto end = impl->m_VariableToPlotMultiMap.cend();
405 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
424 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
406 return it != end;
425 return it != end;
407 }
426 }
408
427
409 QString VisualizationGraphWidget::name() const
428 QString VisualizationGraphWidget::name() const
410 {
429 {
411 return impl->m_Name;
430 return impl->m_Name;
412 }
431 }
413
432
414 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
433 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
415 {
434 {
416 auto mimeData = new QMimeData;
435 auto mimeData = new QMimeData;
417
436
418 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
437 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
419 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
438 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
420 && selectionZoneItemUnderCursor) {
439 && selectionZoneItemUnderCursor) {
421 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
440 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
422 selectionZoneItemUnderCursor->range()));
441 selectionZoneItemUnderCursor->range()));
423 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
442 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
424 selectionZoneItemUnderCursor->range()));
443 selectionZoneItemUnderCursor->range()));
425 }
444 }
426 else {
445 else {
427 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
446 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
428
447
429 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
448 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
430 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
449 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
431 }
450 }
432
451
433 return mimeData;
452 return mimeData;
434 }
453 }
435
454
436 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
455 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
437 {
456 {
438 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
457 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
439 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
458 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
440 && selectionZoneItemUnderCursor) {
459 && selectionZoneItemUnderCursor) {
441
460
442 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
461 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
443 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
462 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
444
463
445 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
464 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
446 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
465 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
447 .toSize();
466 .toSize();
448
467
449 auto pixmap = QPixmap(zoneSize);
468 auto pixmap = QPixmap(zoneSize);
450 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
469 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
451
470
452 return pixmap;
471 return pixmap;
453 }
472 }
454
473
455 return QPixmap();
474 return QPixmap();
456 }
475 }
457
476
458 bool VisualizationGraphWidget::isDragAllowed() const
477 bool VisualizationGraphWidget::isDragAllowed() const
459 {
478 {
460 return true;
479 return true;
461 }
480 }
462
481
463 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
482 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
464 {
483 {
465 if (highlighted) {
484 if (highlighted) {
466 plot().setBackground(QBrush(QColor("#BBD5EE")));
485 plot().setBackground(QBrush(QColor("#BBD5EE")));
467 }
486 }
468 else {
487 else {
469 plot().setBackground(QBrush(Qt::white));
488 plot().setBackground(QBrush(Qt::white));
470 }
489 }
471
490
472 plot().update();
491 plot().update();
473 }
492 }
474
493
475 void VisualizationGraphWidget::addVerticalCursor(double time)
494 void VisualizationGraphWidget::addVerticalCursor(double time)
476 {
495 {
477 impl->m_VerticalCursor->setPosition(time);
496 impl->m_VerticalCursor->setPosition(time);
478 impl->m_VerticalCursor->setVisible(true);
497 impl->m_VerticalCursor->setVisible(true);
479
498
480 auto text
499 auto text
481 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
500 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
482 impl->m_VerticalCursor->setLabelText(text);
501 impl->m_VerticalCursor->setLabelText(text);
483 }
502 }
484
503
485 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
504 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
486 {
505 {
487 impl->m_VerticalCursor->setAbsolutePosition(position);
506 impl->m_VerticalCursor->setAbsolutePosition(position);
488 impl->m_VerticalCursor->setVisible(true);
507 impl->m_VerticalCursor->setVisible(true);
489
508
490 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
509 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
491 auto text
510 auto text
492 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
511 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
493 impl->m_VerticalCursor->setLabelText(text);
512 impl->m_VerticalCursor->setLabelText(text);
494 }
513 }
495
514
496 void VisualizationGraphWidget::removeVerticalCursor()
515 void VisualizationGraphWidget::removeVerticalCursor()
497 {
516 {
498 impl->m_VerticalCursor->setVisible(false);
517 impl->m_VerticalCursor->setVisible(false);
499 plot().replot(QCustomPlot::rpQueuedReplot);
518 plot().replot(QCustomPlot::rpQueuedReplot);
500 }
519 }
501
520
502 void VisualizationGraphWidget::addHorizontalCursor(double value)
521 void VisualizationGraphWidget::addHorizontalCursor(double value)
503 {
522 {
504 impl->m_HorizontalCursor->setPosition(value);
523 impl->m_HorizontalCursor->setPosition(value);
505 impl->m_HorizontalCursor->setVisible(true);
524 impl->m_HorizontalCursor->setVisible(true);
506 impl->m_HorizontalCursor->setLabelText(QString::number(value));
525 impl->m_HorizontalCursor->setLabelText(QString::number(value));
507 }
526 }
508
527
509 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
528 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
510 {
529 {
511 impl->m_HorizontalCursor->setAbsolutePosition(position);
530 impl->m_HorizontalCursor->setAbsolutePosition(position);
512 impl->m_HorizontalCursor->setVisible(true);
531 impl->m_HorizontalCursor->setVisible(true);
513
532
514 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
533 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
515 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
534 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
516 }
535 }
517
536
518 void VisualizationGraphWidget::removeHorizontalCursor()
537 void VisualizationGraphWidget::removeHorizontalCursor()
519 {
538 {
520 impl->m_HorizontalCursor->setVisible(false);
539 impl->m_HorizontalCursor->setVisible(false);
521 plot().replot(QCustomPlot::rpQueuedReplot);
540 plot().replot(QCustomPlot::rpQueuedReplot);
522 }
541 }
523
542
524 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
543 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
525 {
544 {
526 Q_UNUSED(event);
545 Q_UNUSED(event);
527
546
528 // Prevents that all variables will be removed from graph when it will be closed
547 // Prevents that all variables will be removed from graph when it will be closed
529 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
548 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
530 emit variableAboutToBeRemoved(variableEntry.first);
549 emit variableAboutToBeRemoved(variableEntry.first);
531 }
550 }
532 }
551 }
533
552
534 void VisualizationGraphWidget::enterEvent(QEvent *event)
553 void VisualizationGraphWidget::enterEvent(QEvent *event)
535 {
554 {
536 Q_UNUSED(event);
555 Q_UNUSED(event);
537 impl->m_RenderingDelegate->showGraphOverlay(true);
556 impl->m_RenderingDelegate->showGraphOverlay(true);
538 }
557 }
539
558
540 void VisualizationGraphWidget::leaveEvent(QEvent *event)
559 void VisualizationGraphWidget::leaveEvent(QEvent *event)
541 {
560 {
542 Q_UNUSED(event);
561 Q_UNUSED(event);
543 impl->m_RenderingDelegate->showGraphOverlay(false);
562 impl->m_RenderingDelegate->showGraphOverlay(false);
544
563
545 if (auto parentZone = parentZoneWidget()) {
564 if (auto parentZone = parentZoneWidget()) {
546 parentZone->notifyMouseLeaveGraph(this);
565 parentZone->notifyMouseLeaveGraph(this);
547 }
566 }
548 else {
567 else {
549 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
568 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
550 }
569 }
551
570
552 if (impl->m_HoveredZone) {
571 if (impl->m_HoveredZone) {
553 impl->m_HoveredZone->setHovered(false);
572 impl->m_HoveredZone->setHovered(false);
554 impl->m_HoveredZone = nullptr;
573 impl->m_HoveredZone = nullptr;
555 }
574 }
556 }
575 }
557
576
558 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
577 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
559 {
578 {
560 return *ui->widget;
579 return *ui->widget;
561 }
580 }
562
581
563 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
582 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
564 {
583 {
565 QMenu graphMenu{};
584 QMenu graphMenu{};
566
585
567 // Iterates on variables (unique keys)
586 // Iterates on variables (unique keys)
568 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
587 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
569 end = impl->m_VariableToPlotMultiMap.cend();
588 end = impl->m_VariableToPlotMultiMap.cend();
570 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
589 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
571 // 'Remove variable' action
590 // 'Remove variable' action
572 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
591 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
573 [ this, var = it->first ]() { removeVariable(var); });
592 [ this, var = it->first ]() { removeVariable(var); });
574 }
593 }
575
594
576 if (!impl->m_ZoomStack.isEmpty()) {
595 if (!impl->m_ZoomStack.isEmpty()) {
577 if (!graphMenu.isEmpty()) {
596 if (!graphMenu.isEmpty()) {
578 graphMenu.addSeparator();
597 graphMenu.addSeparator();
579 }
598 }
580
599
581 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
600 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
582 }
601 }
583
602
584 if (!graphMenu.isEmpty()) {
603 if (!graphMenu.isEmpty()) {
585 graphMenu.exec(QCursor::pos());
604 graphMenu.exec(QCursor::pos());
586 }
605 }
587 }
606 }
588
607
589 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
608 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
590 {
609 {
591 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
610 qCDebug(LOG_VisualizationGraphWidget())
592 << QThread::currentThread()->objectName() << "DoAcqui"
611 << tr("TORM: VisualizationGraphWidget::onRangeChanged")
593 << impl->m_DoAcquisition;
612 << QThread::currentThread()->objectName() << "DoAcqui" << impl->m_DoAcquisition;
594
613
595 auto graphRange = SqpRange{t1.lower, t1.upper};
614 auto graphRange = SqpRange{t1.lower, t1.upper};
596 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
615 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
597
616
598 if (impl->m_DoAcquisition) {
617 if (impl->m_DoAcquisition) {
599 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
618 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
600
619
601 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
620 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
602 end = impl->m_VariableToPlotMultiMap.end();
621 end = impl->m_VariableToPlotMultiMap.end();
603 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
622 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
604 variableUnderGraphVector.push_back(it->first);
623 variableUnderGraphVector.push_back(it->first);
605 }
624 }
606 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
625 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
607 !impl->m_IsCalibration);
626 !impl->m_IsCalibration);
608
627
609 if (!impl->m_IsCalibration) {
628 if (!impl->m_IsCalibration) {
610 qCDebug(LOG_VisualizationGraphWidget())
629 qCDebug(LOG_VisualizationGraphWidget())
611 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
630 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
612 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
631 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
613 emit synchronize(graphRange, oldGraphRange);
632 emit synchronize(graphRange, oldGraphRange);
614 }
633 }
615 }
634 }
616
635
617 auto pos = mapFromGlobal(QCursor::pos());
636 auto pos = mapFromGlobal(QCursor::pos());
618 auto axisPos = impl->posToAxisPos(pos, plot());
637 auto axisPos = impl->posToAxisPos(pos, plot());
619 if (auto parentZone = parentZoneWidget()) {
638 if (auto parentZone = parentZoneWidget()) {
620 if (impl->pointIsInAxisRect(axisPos, plot())) {
639 if (impl->pointIsInAxisRect(axisPos, plot())) {
621 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
640 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
622 }
641 }
623 else {
642 else {
624 parentZone->notifyMouseLeaveGraph(this);
643 parentZone->notifyMouseLeaveGraph(this);
625 }
644 }
626 }
645 }
627 else {
646 else {
628 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
647 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
629 }
648 }
630 }
649 }
631
650
632 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
651 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
633 {
652 {
634 impl->m_RenderingDelegate->onMouseDoubleClick(event);
653 impl->m_RenderingDelegate->onMouseDoubleClick(event);
635 }
654 }
636
655
637 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
656 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
638 {
657 {
639 // Handles plot rendering when mouse is moving
658 // Handles plot rendering when mouse is moving
640 impl->m_RenderingDelegate->onMouseMove(event);
659 impl->m_RenderingDelegate->onMouseMove(event);
641
660
642 auto axisPos = impl->posToAxisPos(event->pos(), plot());
661 auto axisPos = impl->posToAxisPos(event->pos(), plot());
643
662
644 // Zoom box and zone drawing
663 // Zoom box and zone drawing
645 if (impl->m_DrawingZoomRect) {
664 if (impl->m_DrawingZoomRect) {
646 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
665 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
647 }
666 }
648 else if (impl->m_DrawingZone) {
667 else if (impl->m_DrawingZone) {
649 impl->m_DrawingZone->setEnd(axisPos.x());
668 impl->m_DrawingZone->setEnd(axisPos.x());
650 }
669 }
651
670
652 // Cursor
671 // Cursor
653 if (auto parentZone = parentZoneWidget()) {
672 if (auto parentZone = parentZoneWidget()) {
654 if (impl->pointIsInAxisRect(axisPos, plot())) {
673 if (impl->pointIsInAxisRect(axisPos, plot())) {
655 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
674 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
656 }
675 }
657 else {
676 else {
658 parentZone->notifyMouseLeaveGraph(this);
677 parentZone->notifyMouseLeaveGraph(this);
659 }
678 }
660 }
679 }
661 else {
680 else {
662 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
681 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
663 }
682 }
664
683
665 // Search for the selection zone under the mouse
684 // Search for the selection zone under the mouse
666 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
685 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
667 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
686 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
668 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
687 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
669
688
670 // Sets the appropriate cursor shape
689 // Sets the appropriate cursor shape
671 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
690 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
672 setCursor(cursorShape);
691 setCursor(cursorShape);
673
692
674 // Manages the hovered zone
693 // Manages the hovered zone
675 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
694 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
676 if (impl->m_HoveredZone) {
695 if (impl->m_HoveredZone) {
677 impl->m_HoveredZone->setHovered(false);
696 impl->m_HoveredZone->setHovered(false);
678 }
697 }
679 selectionZoneItemUnderCursor->setHovered(true);
698 selectionZoneItemUnderCursor->setHovered(true);
680 impl->m_HoveredZone = selectionZoneItemUnderCursor;
699 impl->m_HoveredZone = selectionZoneItemUnderCursor;
681 plot().replot(QCustomPlot::rpQueuedReplot);
700 plot().replot(QCustomPlot::rpQueuedReplot);
682 }
701 }
683 }
702 }
684 else {
703 else {
685 // There is no zone under the mouse or the interaction mode is not "selection zones"
704 // There is no zone under the mouse or the interaction mode is not "selection zones"
686 if (impl->m_HoveredZone) {
705 if (impl->m_HoveredZone) {
687 impl->m_HoveredZone->setHovered(false);
706 impl->m_HoveredZone->setHovered(false);
688 impl->m_HoveredZone = nullptr;
707 impl->m_HoveredZone = nullptr;
689 }
708 }
690
709
691 setCursor(Qt::ArrowCursor);
710 setCursor(Qt::ArrowCursor);
692 }
711 }
693
712
694 VisualizationDragWidget::mouseMoveEvent(event);
713 VisualizationDragWidget::mouseMoveEvent(event);
695 }
714 }
696
715
697 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
716 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
698 {
717 {
699 auto value = event->angleDelta().x() + event->angleDelta().y();
718 auto value = event->angleDelta().x() + event->angleDelta().y();
700 if (value != 0) {
719 if (value != 0) {
701
720
702 auto direction = value > 0 ? 1.0 : -1.0;
721 auto direction = value > 0 ? 1.0 : -1.0;
703 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
722 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
704 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
723 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
705 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
724 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
706
725
707 auto zoomOrientations = QFlags<Qt::Orientation>{};
726 auto zoomOrientations = QFlags<Qt::Orientation>{};
708 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
727 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
709 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
728 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
710
729
711 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
730 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
712
731
713 if (!isZoomX && !isZoomY) {
732 if (!isZoomX && !isZoomY) {
714 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
733 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
715 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
734 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
716
735
717 axis->setRange(axis->range() + diff);
736 axis->setRange(axis->range() + diff);
718
737
719 if (plot().noAntialiasingOnDrag()) {
738 if (plot().noAntialiasingOnDrag()) {
720 plot().setNotAntialiasedElements(QCP::aeAll);
739 plot().setNotAntialiasedElements(QCP::aeAll);
721 }
740 }
722
741
723 plot().replot(QCustomPlot::rpQueuedReplot);
742 plot().replot(QCustomPlot::rpQueuedReplot);
724 }
743 }
725 }
744 }
726 }
745 }
727
746
728 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
747 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
729 {
748 {
730 bool isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
749 bool isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
750 auto isSelectionZoneMode
751 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
731
752
732 if (!isDragDropClick) {
753 if (!isDragDropClick) {
733 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
754 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
734 // Starts a zoom box
755 // Starts a zoom box
735 impl->startDrawingRect(event->pos(), plot());
756 impl->startDrawingRect(event->pos(), plot());
736 }
757 }
737 else if (sqpApp->plotsInteractionMode()
758 else if (isSelectionZoneMode && impl->m_DrawingZone == nullptr) {
738 == SqpApplication::PlotsInteractionMode::SelectionZones
739 && impl->m_DrawingZone == nullptr) {
740 // Starts a new selection zone
759 // Starts a new selection zone
741 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
760 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
742 if (!zoneAtPos) {
761 if (!zoneAtPos) {
743 impl->startDrawingZone(event->pos(), plot());
762 impl->startDrawingZone(event->pos(), this);
744 }
763 }
745 }
764 }
746 }
765 }
747 else if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::None) {
766 else if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::None) {
748 plot().setInteraction(QCP::iRangeDrag, true);
767 plot().setInteraction(QCP::iRangeDrag, true);
749 }
768 }
750
769
751 // Allows mouse panning only in default mode
770 // Allows mouse panning only in default mode
752 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
771 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
753 == SqpApplication::PlotsInteractionMode::None
772 == SqpApplication::PlotsInteractionMode::None
754 && !isDragDropClick);
773 && !isDragDropClick);
755
774
756 // Allows zone edition only in selection zone mode without ALT pressed (ALT is for drag&drop)
775 // Allows zone edition only in selection zone mode without drag&drop
757 impl->setSelectionZonesEditionEnabled(
776 impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick);
758 sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
777
759 && !isDragDropClick);
778 // Selection
779 if (isSelectionZoneMode) {
780 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
781 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
782 if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton) {
783 if (!isMultiSelectionClick) {
784 parentVisualizationWidget()->selectionZoneManager().select(
785 {selectionZoneItemUnderCursor});
786 }
787 else {
788 parentVisualizationWidget()->selectionZoneManager().setSelected(
789 selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected()
790 || event->button() == Qt::RightButton);
791 }
792 }
793 else if (!isMultiSelectionClick && event->button() == Qt::LeftButton) {
794 parentVisualizationWidget()->selectionZoneManager().clearSelection();
795 }
796 else {
797 // No selection change
798 }
799 }
760
800
761 VisualizationDragWidget::mousePressEvent(event);
801 VisualizationDragWidget::mousePressEvent(event);
762 }
802 }
763
803
764 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
804 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
765 {
805 {
766 if (impl->m_DrawingZoomRect) {
806 if (impl->m_DrawingZoomRect) {
767
807
768 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
808 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
769 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
809 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
770
810
771 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
811 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
772 impl->m_DrawingZoomRect->bottomRight->coords().x()};
812 impl->m_DrawingZoomRect->bottomRight->coords().x()};
773
813
774 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
814 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
775 impl->m_DrawingZoomRect->bottomRight->coords().y()};
815 impl->m_DrawingZoomRect->bottomRight->coords().y()};
776
816
777 impl->removeDrawingRect(plot());
817 impl->removeDrawingRect(plot());
778
818
779 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
819 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
780 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
820 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
781 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
821 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
782 axisX->setRange(newAxisXRange);
822 axisX->setRange(newAxisXRange);
783 axisY->setRange(newAxisYRange);
823 axisY->setRange(newAxisYRange);
784
824
785 plot().replot(QCustomPlot::rpQueuedReplot);
825 plot().replot(QCustomPlot::rpQueuedReplot);
786 }
826 }
787 }
827 }
788
828
789 impl->endDrawingZone(plot());
829 impl->endDrawingZone(this);
790
830
791 impl->m_IsCalibration = false;
831 impl->m_IsCalibration = false;
792 }
832 }
793
833
794 void VisualizationGraphWidget::onDataCacheVariableUpdated()
834 void VisualizationGraphWidget::onDataCacheVariableUpdated()
795 {
835 {
796 auto graphRange = ui->widget->xAxis->range();
836 auto graphRange = ui->widget->xAxis->range();
797 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
837 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
798
838
799 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
839 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
800 auto variable = variableEntry.first;
840 auto variable = variableEntry.first;
801 qCDebug(LOG_VisualizationGraphWidget())
841 qCDebug(LOG_VisualizationGraphWidget())
802 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
842 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
803 qCDebug(LOG_VisualizationGraphWidget())
843 qCDebug(LOG_VisualizationGraphWidget())
804 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
844 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
805 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
845 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
806 impl->updateData(variableEntry.second, variable->dataSeries(), variable->range());
846 impl->updateData(variableEntry.second, variable->dataSeries(), variable->range());
807 }
847 }
808 }
848 }
809 }
849 }
810
850
811 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
851 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
812 const SqpRange &range)
852 const SqpRange &range)
813 {
853 {
814 auto it = impl->m_VariableToPlotMultiMap.find(variable);
854 auto it = impl->m_VariableToPlotMultiMap.find(variable);
815 if (it != impl->m_VariableToPlotMultiMap.end()) {
855 if (it != impl->m_VariableToPlotMultiMap.end()) {
816 impl->updateData(it->second, variable->dataSeries(), range);
856 impl->updateData(it->second, variable->dataSeries(), range);
817 }
857 }
818 }
858 }
@@ -1,272 +1,270
1 #include "Visualization/VisualizationSelectionZoneItem.h"
1 #include "Visualization/VisualizationSelectionZoneItem.h"
2
2
3 const QString &DEFAULT_COLOR = QStringLiteral("#E79D41");
4
3 struct VisualizationSelectionZoneItem::VisualizationSelectionZoneItemPrivate {
5 struct VisualizationSelectionZoneItem::VisualizationSelectionZoneItemPrivate {
4
6
5 QCustomPlot *m_Plot;
7 QCustomPlot *m_Plot;
6 double m_T1 = 0;
8 double m_T1 = 0;
7 double m_T2 = 0;
9 double m_T2 = 0;
8 QColor m_Color;
10 QColor m_Color;
9
11
10 bool m_IsEditionEnabled = true;
12 bool m_IsEditionEnabled = true;
11 double m_MovedOrinalT1 = 0;
13 double m_MovedOrinalT1 = 0;
12 double m_MovedOrinalT2 = 0;
14 double m_MovedOrinalT2 = 0;
13
15
14 QCPItemStraightLine *m_LeftLine;
16 QCPItemStraightLine *m_LeftLine;
15 QCPItemStraightLine *m_RightLine;
17 QCPItemStraightLine *m_RightLine;
16 QCPItemText *m_NameLabelItem = nullptr;
18 QCPItemText *m_NameLabelItem = nullptr;
17
19
18 enum class EditionMode { NoEdition, ResizeLeft, ResizeRight, Move };
20 enum class EditionMode { NoEdition, ResizeLeft, ResizeRight, Move };
19 EditionMode m_CurrentEditionMode;
21 EditionMode m_CurrentEditionMode;
20
22
21 VisualizationSelectionZoneItemPrivate(QCustomPlot *plot)
23 VisualizationSelectionZoneItemPrivate(QCustomPlot *plot)
22 : m_Plot(plot), m_Color(Qt::blue), m_CurrentEditionMode(EditionMode::NoEdition)
24 : m_Plot(plot), m_Color(Qt::blue), m_CurrentEditionMode(EditionMode::NoEdition)
23 {
25 {
24 }
26 }
25
27
26 void updatePosition(VisualizationSelectionZoneItem *item)
28 void updatePosition(VisualizationSelectionZoneItem *item)
27 {
29 {
28 item->topLeft->setCoords(m_T1, 0);
30 item->topLeft->setCoords(m_T1, 0);
29 item->bottomRight->setCoords(m_T2, 1);
31 item->bottomRight->setCoords(m_T2, 1);
30 }
32 }
31
33
32 EditionMode getEditionMode(const QPoint &pos, const VisualizationSelectionZoneItem *zoneItem)
34 EditionMode getEditionMode(const QPoint &pos, const VisualizationSelectionZoneItem *zoneItem)
33 {
35 {
34 auto distanceLeft = m_LeftLine->selectTest(pos, false);
36 auto distanceLeft = m_LeftLine->selectTest(pos, false);
35 auto distanceRight = m_RightLine->selectTest(pos, false);
37 auto distanceRight = m_RightLine->selectTest(pos, false);
36 auto distance = zoneItem->selectTest(pos, false);
38 auto distance = zoneItem->selectTest(pos, false);
37
39
38 if (distanceRight <= distance) {
40 if (distanceRight <= distance) {
39 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight;
41 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight;
40 }
42 }
41 else if (distanceLeft <= distance) {
43 else if (distanceLeft <= distance) {
42 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft;
44 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft;
43 }
45 }
44
46
45 return VisualizationSelectionZoneItemPrivate::EditionMode::Move;
47 return VisualizationSelectionZoneItemPrivate::EditionMode::Move;
46 }
48 }
47 };
49 };
48
50
49 VisualizationSelectionZoneItem::VisualizationSelectionZoneItem(QCustomPlot *plot)
51 VisualizationSelectionZoneItem::VisualizationSelectionZoneItem(QCustomPlot *plot)
50 : QCPItemRect(plot),
52 : QCPItemRect(plot),
51 impl{spimpl::make_unique_impl<VisualizationSelectionZoneItemPrivate>(plot)}
53 impl{spimpl::make_unique_impl<VisualizationSelectionZoneItemPrivate>(plot)}
52 {
54 {
53 topLeft->setTypeX(QCPItemPosition::ptPlotCoords);
55 topLeft->setTypeX(QCPItemPosition::ptPlotCoords);
54 topLeft->setTypeY(QCPItemPosition::ptAxisRectRatio);
56 topLeft->setTypeY(QCPItemPosition::ptAxisRectRatio);
55 bottomRight->setTypeX(QCPItemPosition::ptPlotCoords);
57 bottomRight->setTypeX(QCPItemPosition::ptPlotCoords);
56 bottomRight->setTypeY(QCPItemPosition::ptAxisRectRatio);
58 bottomRight->setTypeY(QCPItemPosition::ptAxisRectRatio);
59 setSelectable(false);
57
60
58 impl->m_RightLine = new QCPItemStraightLine(plot);
61 impl->m_RightLine = new QCPItemStraightLine(plot);
59 impl->m_RightLine->point1->setParentAnchor(topRight);
62 impl->m_RightLine->point1->setParentAnchor(topRight);
60 impl->m_RightLine->point2->setParentAnchor(bottomRight);
63 impl->m_RightLine->point2->setParentAnchor(bottomRight);
61 impl->m_RightLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
64 impl->m_RightLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
62 impl->m_RightLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
65 impl->m_RightLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
63 impl->m_RightLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
66 impl->m_RightLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
64 impl->m_RightLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
67 impl->m_RightLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
68 impl->m_RightLine->setSelectable(false);
65
69
66 impl->m_LeftLine = new QCPItemStraightLine(plot);
70 impl->m_LeftLine = new QCPItemStraightLine(plot);
67 impl->m_LeftLine->point1->setParentAnchor(topLeft);
71 impl->m_LeftLine->point1->setParentAnchor(topLeft);
68 impl->m_LeftLine->point2->setParentAnchor(bottomLeft);
72 impl->m_LeftLine->point2->setParentAnchor(bottomLeft);
69 impl->m_LeftLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
73 impl->m_LeftLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
70 impl->m_LeftLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
74 impl->m_LeftLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
71 impl->m_LeftLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
75 impl->m_LeftLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
72 impl->m_LeftLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
76 impl->m_LeftLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
73
74 impl->m_RightLine->setSelectable(false);
75 impl->m_LeftLine->setSelectable(false);
77 impl->m_LeftLine->setSelectable(false);
76
78
77 // connect(this, &VisualizationSelectionZoneItem::selectionChanged, impl->m_RightLine,
79 setColor(QColor(DEFAULT_COLOR));
78 // &QCPItemStraightLine::setSelected);
79 // connect(this, &VisualizationSelectionZoneItem::selectionChanged, impl->m_LeftLine,
80 // &QCPItemStraightLine::setSelected);
81
82 setColor(QColor("#E79D41"));
83 }
80 }
84
81
85 VisualizationSelectionZoneItem::~VisualizationSelectionZoneItem()
82 VisualizationSelectionZoneItem::~VisualizationSelectionZoneItem()
86 {
83 {
87 impl->m_Plot->removeItem(impl->m_RightLine);
84 impl->m_Plot->removeItem(impl->m_RightLine);
88 impl->m_Plot->removeItem(impl->m_LeftLine);
85 impl->m_Plot->removeItem(impl->m_LeftLine);
89 }
86 }
90
87
91 void VisualizationSelectionZoneItem::setName(const QString &name)
88 void VisualizationSelectionZoneItem::setName(const QString &name)
92 {
89 {
93 if (name.isEmpty() && impl->m_NameLabelItem) {
90 if (name.isEmpty() && impl->m_NameLabelItem) {
94 impl->m_Plot->removeItem(impl->m_NameLabelItem);
91 impl->m_Plot->removeItem(impl->m_NameLabelItem);
95 impl->m_NameLabelItem = nullptr;
92 impl->m_NameLabelItem = nullptr;
96 }
93 }
97 else if (!impl->m_NameLabelItem) {
94 else if (!impl->m_NameLabelItem) {
98 impl->m_NameLabelItem = new QCPItemText(impl->m_Plot);
95 impl->m_NameLabelItem = new QCPItemText(impl->m_Plot);
99 impl->m_NameLabelItem->setText(name);
96 impl->m_NameLabelItem->setText(name);
100 impl->m_NameLabelItem->setPositionAlignment(Qt::AlignHCenter | Qt::AlignTop);
97 impl->m_NameLabelItem->setPositionAlignment(Qt::AlignHCenter | Qt::AlignTop);
101 impl->m_NameLabelItem->setColor(impl->m_Color);
98 impl->m_NameLabelItem->setColor(impl->m_Color);
102 impl->m_NameLabelItem->position->setParentAnchor(top);
99 impl->m_NameLabelItem->position->setParentAnchor(top);
103 }
100 }
104 }
101 }
105
102
106 QString VisualizationSelectionZoneItem::name() const
103 QString VisualizationSelectionZoneItem::name() const
107 {
104 {
108 if (!impl->m_NameLabelItem) {
105 if (!impl->m_NameLabelItem) {
109 return QString();
106 return QString();
110 }
107 }
111
108
112 return impl->m_NameLabelItem->text();
109 return impl->m_NameLabelItem->text();
113 }
110 }
114
111
115 SqpRange VisualizationSelectionZoneItem::range() const
112 SqpRange VisualizationSelectionZoneItem::range() const
116 {
113 {
117 SqpRange range;
114 SqpRange range;
118 range.m_TStart = impl->m_T1 <= impl->m_T2 ? impl->m_T1 : impl->m_T2;
115 range.m_TStart = impl->m_T1 <= impl->m_T2 ? impl->m_T1 : impl->m_T2;
119 range.m_TEnd = impl->m_T1 > impl->m_T2 ? impl->m_T1 : impl->m_T2;
116 range.m_TEnd = impl->m_T1 > impl->m_T2 ? impl->m_T1 : impl->m_T2;
120 return range;
117 return range;
121 }
118 }
122
119
123 void VisualizationSelectionZoneItem::setRange(double tstart, double tend)
120 void VisualizationSelectionZoneItem::setRange(double tstart, double tend)
124 {
121 {
125 impl->m_T1 = tstart;
122 impl->m_T1 = tstart;
126 impl->m_T2 = tend;
123 impl->m_T2 = tend;
127 impl->updatePosition(this);
124 impl->updatePosition(this);
128 }
125 }
129
126
130 void VisualizationSelectionZoneItem::setStart(double tstart)
127 void VisualizationSelectionZoneItem::setStart(double tstart)
131 {
128 {
132 impl->m_T1 = tstart;
129 impl->m_T1 = tstart;
133 impl->updatePosition(this);
130 impl->updatePosition(this);
134 }
131 }
135
132
136 void VisualizationSelectionZoneItem::setEnd(double tend)
133 void VisualizationSelectionZoneItem::setEnd(double tend)
137 {
134 {
138 impl->m_T2 = tend;
135 impl->m_T2 = tend;
139 impl->updatePosition(this);
136 impl->updatePosition(this);
140 }
137 }
141
138
142 void VisualizationSelectionZoneItem::setColor(const QColor &color)
139 void VisualizationSelectionZoneItem::setColor(const QColor &color)
143 {
140 {
144 impl->m_Color = color;
141 impl->m_Color = color;
145
142
146 auto brushColor = color;
143 auto brushColor = color;
147 brushColor.setAlpha(40);
144 brushColor.setAlpha(40);
148 setBrush(QBrush(brushColor));
145 setBrush(QBrush(brushColor));
149 setPen(QPen(Qt::NoPen));
146 setPen(QPen(Qt::NoPen));
150
147
151 auto selectedBrushColor = brushColor;
148 auto selectedBrushColor = brushColor;
152 selectedBrushColor.setAlpha(65);
149 selectedBrushColor.setAlpha(65);
153 setSelectedBrush(QBrush(selectedBrushColor));
150 setSelectedBrush(QBrush(selectedBrushColor));
154 setSelectedPen(QPen(Qt::NoPen));
151 setSelectedPen(QPen(Qt::NoPen));
155
152
156 auto linePen = QPen(color);
153 auto linePen = QPen(color);
157 linePen.setStyle(Qt::SolidLine);
154 linePen.setStyle(Qt::SolidLine);
158 linePen.setWidth(2);
155 linePen.setWidth(2);
159
156
160 auto selectedLinePen = linePen;
157 auto selectedLinePen = linePen;
161 selectedLinePen.setColor(color.darker(30));
158 selectedLinePen.setColor(color.darker(30));
162
159
163 impl->m_LeftLine->setPen(linePen);
160 impl->m_LeftLine->setPen(linePen);
164 impl->m_RightLine->setPen(linePen);
161 impl->m_RightLine->setPen(linePen);
165
162
166 impl->m_LeftLine->setSelectedPen(selectedLinePen);
163 impl->m_LeftLine->setSelectedPen(selectedLinePen);
167 impl->m_RightLine->setSelectedPen(selectedLinePen);
164 impl->m_RightLine->setSelectedPen(selectedLinePen);
168 }
165 }
169
166
170 void VisualizationSelectionZoneItem::setEditionEnabled(bool value)
167 void VisualizationSelectionZoneItem::setEditionEnabled(bool value)
171 {
168 {
172 impl->m_IsEditionEnabled = value;
169 impl->m_IsEditionEnabled = value;
173 setSelectable(value);
170 setSelectable(value);
174 if (!value) {
171 if (!value) {
175 setSelected(false);
172 setSelected(false);
176 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
173 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
177 }
174 }
178 }
175 }
179
176
180 bool VisualizationSelectionZoneItem::isEditionEnabled() const
177 bool VisualizationSelectionZoneItem::isEditionEnabled() const
181 {
178 {
182 return impl->m_IsEditionEnabled;
179 return impl->m_IsEditionEnabled;
183 }
180 }
184
181
185 Qt::CursorShape
182 Qt::CursorShape
186 VisualizationSelectionZoneItem::curshorShapeForPosition(const QPoint &position) const
183 VisualizationSelectionZoneItem::curshorShapeForPosition(const QPoint &position) const
187 {
184 {
188 auto mode = impl->m_CurrentEditionMode
185 auto mode = impl->m_CurrentEditionMode
189 == VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition
186 == VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition
190 ? impl->getEditionMode(position, this)
187 ? impl->getEditionMode(position, this)
191 : impl->m_CurrentEditionMode;
188 : impl->m_CurrentEditionMode;
192 switch (mode) {
189 switch (mode) {
193 case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
190 case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
194 return Qt::SizeAllCursor;
191 return Qt::SizeAllCursor;
195 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
192 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
196 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight: // fallthrough
193 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight: // fallthrough
197 return Qt::SizeHorCursor;
194 return Qt::SizeHorCursor;
198 default:
195 default:
199 return Qt::ArrowCursor;
196 return Qt::ArrowCursor;
200 }
197 }
201 }
198 }
202
199
203 void VisualizationSelectionZoneItem::setHovered(bool value)
200 void VisualizationSelectionZoneItem::setHovered(bool value)
204 {
201 {
205 if (value) {
202 if (value) {
206 auto linePen = impl->m_LeftLine->pen();
203 auto linePen = impl->m_LeftLine->pen();
207 linePen.setStyle(Qt::DotLine);
204 linePen.setStyle(Qt::DotLine);
208 linePen.setWidth(3);
205 linePen.setWidth(3);
209
206
210 auto selectedLinePen = impl->m_LeftLine->selectedPen();
207 auto selectedLinePen = impl->m_LeftLine->selectedPen();
211 ;
208 ;
212 selectedLinePen.setStyle(Qt::DotLine);
209 selectedLinePen.setStyle(Qt::DotLine);
213 selectedLinePen.setWidth(3);
210 selectedLinePen.setWidth(3);
214
211
215 impl->m_LeftLine->setPen(linePen);
212 impl->m_LeftLine->setPen(linePen);
216 impl->m_RightLine->setPen(linePen);
213 impl->m_RightLine->setPen(linePen);
217
214
218 impl->m_LeftLine->setSelectedPen(selectedLinePen);
215 impl->m_LeftLine->setSelectedPen(selectedLinePen);
219 impl->m_RightLine->setSelectedPen(selectedLinePen);
216 impl->m_RightLine->setSelectedPen(selectedLinePen);
220 }
217 }
221 else {
218 else {
222 setColor(impl->m_Color);
219 setColor(impl->m_Color);
223 }
220 }
224 }
221 }
225
222
226 void VisualizationSelectionZoneItem::mousePressEvent(QMouseEvent *event, const QVariant &details)
223 void VisualizationSelectionZoneItem::mousePressEvent(QMouseEvent *event, const QVariant &details)
227 {
224 {
228 if (isEditionEnabled()) {
225 if (isEditionEnabled() && event->button() == Qt::LeftButton) {
229 impl->m_CurrentEditionMode = impl->getEditionMode(event->pos(), this);
226 impl->m_CurrentEditionMode = impl->getEditionMode(event->pos(), this);
230
227
231 impl->m_MovedOrinalT1 = impl->m_T1;
228 impl->m_MovedOrinalT1 = impl->m_T1;
232 impl->m_MovedOrinalT2 = impl->m_T2;
229 impl->m_MovedOrinalT2 = impl->m_T2;
233 }
230 }
234 else {
231 else {
232 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
235 event->ignore();
233 event->ignore();
236 }
234 }
237 }
235 }
238
236
239 void VisualizationSelectionZoneItem::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
237 void VisualizationSelectionZoneItem::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
240 {
238 {
241 if (isEditionEnabled()) {
239 if (isEditionEnabled()) {
242 auto axis = impl->m_Plot->axisRect()->axis(QCPAxis::atBottom);
240 auto axis = impl->m_Plot->axisRect()->axis(QCPAxis::atBottom);
243 auto diff = axis->pixelToCoord(event->pos().x()) - axis->pixelToCoord(startPos.x());
241 auto diff = axis->pixelToCoord(event->pos().x()) - axis->pixelToCoord(startPos.x());
244
242
245 switch (impl->m_CurrentEditionMode) {
243 switch (impl->m_CurrentEditionMode) {
246 case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
244 case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
247 setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff);
245 setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff);
248 break;
246 break;
249 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
247 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
250 setStart(impl->m_MovedOrinalT1 + diff);
248 setStart(impl->m_MovedOrinalT1 + diff);
251 break;
249 break;
252 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight:
250 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight:
253 setEnd(impl->m_MovedOrinalT2 + diff);
251 setEnd(impl->m_MovedOrinalT2 + diff);
254 break;
252 break;
255 // default:
253 default:
256 // unknown edition mode
254 break;
257 }
255 }
258 }
256 }
259 else {
257 else {
260 event->ignore();
258 event->ignore();
261 }
259 }
262 }
260 }
263
261
264 void VisualizationSelectionZoneItem::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
262 void VisualizationSelectionZoneItem::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
265 {
263 {
266 if (isEditionEnabled()) {
264 if (isEditionEnabled()) {
267 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
265 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
268 }
266 }
269 else {
267 else {
270 event->ignore();
268 event->ignore();
271 }
269 }
272 }
270 }
@@ -1,178 +1,197
1 #include "Visualization/VisualizationWidget.h"
1 #include "Visualization/VisualizationWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationGraphWidget.h"
3 #include "Visualization/VisualizationGraphWidget.h"
4 #include "Visualization/VisualizationSelectionZoneManager.h"
4 #include "Visualization/VisualizationTabWidget.h"
5 #include "Visualization/VisualizationTabWidget.h"
5 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/operations/FindVariableOperation.h"
7 #include "Visualization/operations/FindVariableOperation.h"
7 #include "Visualization/operations/GenerateVariableMenuOperation.h"
8 #include "Visualization/operations/GenerateVariableMenuOperation.h"
8 #include "Visualization/operations/RemoveVariableOperation.h"
9 #include "Visualization/operations/RemoveVariableOperation.h"
9 #include "Visualization/operations/RescaleAxeOperation.h"
10 #include "Visualization/operations/RescaleAxeOperation.h"
10 #include "Visualization/qcustomplot.h"
11 #include "Visualization/qcustomplot.h"
11
12
12 #include "ui_VisualizationWidget.h"
13 #include "ui_VisualizationWidget.h"
13
14
14 #include "DragAndDrop/DragDropHelper.h"
15 #include "DragAndDrop/DragDropHelper.h"
15 #include "SqpApplication.h"
16 #include "SqpApplication.h"
16
17
17 #include <QToolButton>
18 #include <QToolButton>
18
19
20 #include <memory>
21
19 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
22 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
20
23
24 struct VisualizationWidget::VisualizationWidgetPrivate {
25 std::unique_ptr<VisualizationSelectionZoneManager> m_ZoneSelectionManager = nullptr;
26
27 VisualizationWidgetPrivate()
28 : m_ZoneSelectionManager(std::make_unique<VisualizationSelectionZoneManager>())
29 {
30 }
31 };
32
21 VisualizationWidget::VisualizationWidget(QWidget *parent)
33 VisualizationWidget::VisualizationWidget(QWidget *parent)
22 : QWidget{parent}, ui{new Ui::VisualizationWidget}
34 : QWidget{parent},
35 ui{new Ui::VisualizationWidget},
36 impl{spimpl::make_unique_impl<VisualizationWidgetPrivate>()}
23 {
37 {
24 ui->setupUi(this);
38 ui->setupUi(this);
25
39
26 auto addTabViewButton = new QToolButton{ui->tabWidget};
40 auto addTabViewButton = new QToolButton{ui->tabWidget};
27 addTabViewButton->setText(tr("Add View"));
41 addTabViewButton->setText(tr("Add View"));
28 addTabViewButton->setCursor(Qt::ArrowCursor);
42 addTabViewButton->setCursor(Qt::ArrowCursor);
29 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
43 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
30
44
31 auto enableMinimumCornerWidgetSize = [this](bool enable) {
45 auto enableMinimumCornerWidgetSize = [this](bool enable) {
32
46
33 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
47 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
34 auto width = enable ? tabViewCornerWidget->width() : 0;
48 auto width = enable ? tabViewCornerWidget->width() : 0;
35 auto height = enable ? tabViewCornerWidget->height() : 0;
49 auto height = enable ? tabViewCornerWidget->height() : 0;
36 tabViewCornerWidget->setMinimumHeight(height);
50 tabViewCornerWidget->setMinimumHeight(height);
37 tabViewCornerWidget->setMinimumWidth(width);
51 tabViewCornerWidget->setMinimumWidth(width);
38 ui->tabWidget->setMinimumHeight(height);
52 ui->tabWidget->setMinimumHeight(height);
39 ui->tabWidget->setMinimumWidth(width);
53 ui->tabWidget->setMinimumWidth(width);
40 };
54 };
41
55
42 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
56 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
43 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
57 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
44 ui->tabWidget};
58 ui->tabWidget};
45 auto index = ui->tabWidget->addTab(widget, widget->name());
59 auto index = ui->tabWidget->addTab(widget, widget->name());
46 if (ui->tabWidget->count() > 0) {
60 if (ui->tabWidget->count() > 0) {
47 enableMinimumCornerWidgetSize(false);
61 enableMinimumCornerWidgetSize(false);
48 }
62 }
49 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
63 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
50 };
64 };
51
65
52 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
66 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
53 if (ui->tabWidget->count() == 1) {
67 if (ui->tabWidget->count() == 1) {
54 enableMinimumCornerWidgetSize(true);
68 enableMinimumCornerWidgetSize(true);
55 }
69 }
56
70
57 // Removes widget from tab and closes it
71 // Removes widget from tab and closes it
58 auto widget = ui->tabWidget->widget(index);
72 auto widget = ui->tabWidget->widget(index);
59 ui->tabWidget->removeTab(index);
73 ui->tabWidget->removeTab(index);
60 if (widget) {
74 if (widget) {
61 widget->close();
75 widget->close();
62 }
76 }
63
77
64 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
78 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
65
79
66 };
80 };
67
81
68 ui->tabWidget->setTabsClosable(true);
82 ui->tabWidget->setTabsClosable(true);
69
83
70 connect(addTabViewButton, &QToolButton::clicked, addTabView);
84 connect(addTabViewButton, &QToolButton::clicked, addTabView);
71 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
85 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
72
86
73 sqpApp->dragDropHelper().addDragDropTabBar(ui->tabWidget->tabBar());
87 sqpApp->dragDropHelper().addDragDropTabBar(ui->tabWidget->tabBar());
74
88
75 // Adds default tab
89 // Adds default tab
76 addTabView();
90 addTabView();
77 }
91 }
78
92
79 VisualizationWidget::~VisualizationWidget()
93 VisualizationWidget::~VisualizationWidget()
80 {
94 {
81 sqpApp->dragDropHelper().removeDragDropTabBar(ui->tabWidget->tabBar());
95 sqpApp->dragDropHelper().removeDragDropTabBar(ui->tabWidget->tabBar());
82 delete ui;
96 delete ui;
83 }
97 }
84
98
99 VisualizationSelectionZoneManager &VisualizationWidget::selectionZoneManager() const
100 {
101 return *impl->m_ZoneSelectionManager.get();
102 }
103
85 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
104 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
86 {
105 {
87 if (visitor) {
106 if (visitor) {
88 visitor->visitEnter(this);
107 visitor->visitEnter(this);
89
108
90 // Apply visitor for tab children
109 // Apply visitor for tab children
91 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
110 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
92 // Widgets different from tabs are not visited (no action)
111 // Widgets different from tabs are not visited (no action)
93 if (auto visualizationTabWidget
112 if (auto visualizationTabWidget
94 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
113 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
95 visualizationTabWidget->accept(visitor);
114 visualizationTabWidget->accept(visitor);
96 }
115 }
97 }
116 }
98
117
99 visitor->visitLeave(this);
118 visitor->visitLeave(this);
100 }
119 }
101 else {
120 else {
102 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
121 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
103 }
122 }
104 }
123 }
105
124
106 bool VisualizationWidget::canDrop(const Variable &variable) const
125 bool VisualizationWidget::canDrop(const Variable &variable) const
107 {
126 {
108 // The main widget can never accomodate a variable
127 // The main widget can never accomodate a variable
109 Q_UNUSED(variable);
128 Q_UNUSED(variable);
110 return false;
129 return false;
111 }
130 }
112
131
113 bool VisualizationWidget::contains(const Variable &variable) const
132 bool VisualizationWidget::contains(const Variable &variable) const
114 {
133 {
115 Q_UNUSED(variable);
134 Q_UNUSED(variable);
116 return false;
135 return false;
117 }
136 }
118
137
119 QString VisualizationWidget::name() const
138 QString VisualizationWidget::name() const
120 {
139 {
121 return QStringLiteral("MainView");
140 return QStringLiteral("MainView");
122 }
141 }
123
142
124 void VisualizationWidget::attachVariableMenu(
143 void VisualizationWidget::attachVariableMenu(
125 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
144 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
126 {
145 {
127 // Menu is generated only if there is a single variable
146 // Menu is generated only if there is a single variable
128 if (variables.size() == 1) {
147 if (variables.size() == 1) {
129 if (auto variable = variables.first()) {
148 if (auto variable = variables.first()) {
130 // Gets the containers of the variable
149 // Gets the containers of the variable
131 FindVariableOperation findVariableOperation{variable};
150 FindVariableOperation findVariableOperation{variable};
132 accept(&findVariableOperation);
151 accept(&findVariableOperation);
133 auto variableContainers = findVariableOperation.result();
152 auto variableContainers = findVariableOperation.result();
134
153
135 // Generates the actions that make it possible to visualize the variable
154 // Generates the actions that make it possible to visualize the variable
136 GenerateVariableMenuOperation generateVariableMenuOperation{
155 GenerateVariableMenuOperation generateVariableMenuOperation{
137 menu, variable, std::move(variableContainers)};
156 menu, variable, std::move(variableContainers)};
138 accept(&generateVariableMenuOperation);
157 accept(&generateVariableMenuOperation);
139 }
158 }
140 else {
159 else {
141 qCCritical(LOG_VisualizationWidget()) << tr(
160 qCCritical(LOG_VisualizationWidget()) << tr(
142 "Can't generate the menu relative to the visualization: the variable is null");
161 "Can't generate the menu relative to the visualization: the variable is null");
143 }
162 }
144 }
163 }
145 else {
164 else {
146 qCDebug(LOG_VisualizationWidget())
165 qCDebug(LOG_VisualizationWidget())
147 << tr("No generation of the menu related to the visualization: several variables are "
166 << tr("No generation of the menu related to the visualization: several variables are "
148 "selected");
167 "selected");
149 }
168 }
150 }
169 }
151
170
152 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
171 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
153 {
172 {
154 // Calls the operation of removing all references to the variable in the visualization
173 // Calls the operation of removing all references to the variable in the visualization
155 auto removeVariableOperation = RemoveVariableOperation{variable};
174 auto removeVariableOperation = RemoveVariableOperation{variable};
156 accept(&removeVariableOperation);
175 accept(&removeVariableOperation);
157 }
176 }
158
177
159 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
178 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
160 const SqpRange &range) noexcept
179 const SqpRange &range) noexcept
161 {
180 {
162 // Calls the operation of rescaling all graph that contrains variable in the visualization
181 // Calls the operation of rescaling all graph that contrains variable in the visualization
163 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
182 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
164 accept(&rescaleVariableOperation);
183 accept(&rescaleVariableOperation);
165 }
184 }
166
185
167 void VisualizationWidget::closeEvent(QCloseEvent *event)
186 void VisualizationWidget::closeEvent(QCloseEvent *event)
168 {
187 {
169 // Closes tabs in the widget
188 // Closes tabs in the widget
170 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
189 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
171 if (auto visualizationTabWidget
190 if (auto visualizationTabWidget
172 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
191 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
173 visualizationTabWidget->close();
192 visualizationTabWidget->close();
174 }
193 }
175 }
194 }
176
195
177 QWidget::closeEvent(event);
196 QWidget::closeEvent(event);
178 }
197 }
General Comments 0
You need to be logged in to leave comments. Login now