##// END OF EJS Templates
Link between selection zone item and event
trabillard -
r1347:12c6415397ca
parent child
Show More
@@ -1,58 +1,64
1 #ifndef SCIQLOP_CATALOGUEEVENTSWIDGET_H
1 #ifndef SCIQLOP_CATALOGUEEVENTSWIDGET_H
2 #define SCIQLOP_CATALOGUEEVENTSWIDGET_H
2 #define SCIQLOP_CATALOGUEEVENTSWIDGET_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 #include <QLoggingCategory>
6 #include <QWidget>
6 #include <QWidget>
7
7
8 class DBCatalogue;
8 class DBCatalogue;
9 class DBEvent;
9 class DBEvent;
10 class DBEventProduct;
10 class DBEventProduct;
11 class VisualizationWidget;
11 class VisualizationWidget;
12 class VisualizationSelectionZoneItem;
12
13
13 namespace Ui {
14 namespace Ui {
14 class CatalogueEventsWidget;
15 class CatalogueEventsWidget;
15 }
16 }
16
17
17 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueEventsWidget)
18 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueEventsWidget)
18
19
19 class CatalogueEventsWidget : public QWidget {
20 class CatalogueEventsWidget : public QWidget {
20 Q_OBJECT
21 Q_OBJECT
21
22
22 signals:
23 signals:
23 void eventsSelected(const QVector<std::shared_ptr<DBEvent> > &event);
24 void eventsSelected(const QVector<std::shared_ptr<DBEvent> > &event);
25 void eventsRemoved(const QVector<std::shared_ptr<DBEvent> > &event);
24 void eventProductsSelected(
26 void eventProductsSelected(
25 const QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > >
27 const QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > >
26 &eventproducts);
28 &eventproducts);
27 void selectionCleared();
29 void selectionCleared();
30 void selectionZoneAdded(const std::shared_ptr<DBEvent> &event, const QString &productId,
31 VisualizationSelectionZoneItem *selectionZone);
28
32
29 public:
33 public:
30 explicit CatalogueEventsWidget(QWidget *parent = 0);
34 explicit CatalogueEventsWidget(QWidget *parent = 0);
31 virtual ~CatalogueEventsWidget();
35 virtual ~CatalogueEventsWidget();
32
36
33 void setVisualizationWidget(VisualizationWidget *visualization);
37 void setVisualizationWidget(VisualizationWidget *visualization);
34
38
35 void addEvent(const std::shared_ptr<DBEvent> &event);
39 void addEvent(const std::shared_ptr<DBEvent> &event);
36 void setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges);
40 void setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges);
37
41
38 QVector<std::shared_ptr<DBCatalogue> > displayedCatalogues() const;
42 QVector<std::shared_ptr<DBCatalogue> > displayedCatalogues() const;
39 bool isAllEventsDisplayed() const;
43 bool isAllEventsDisplayed() const;
40 bool isEventDisplayed(const std::shared_ptr<DBEvent> &event) const;
44 bool isEventDisplayed(const std::shared_ptr<DBEvent> &event) const;
41
45
46 void refreshEvent(const std::shared_ptr<DBEvent> &event);
47
42 public slots:
48 public slots:
43 void populateWithCatalogues(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
49 void populateWithCatalogues(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
44 void populateWithAllEvents();
50 void populateWithAllEvents();
45 void clear();
51 void clear();
46 void refresh();
52 void refresh();
47
53
48 private:
54 private:
49 Ui::CatalogueEventsWidget *ui;
55 Ui::CatalogueEventsWidget *ui;
50
56
51 class CatalogueEventsWidgetPrivate;
57 class CatalogueEventsWidgetPrivate;
52 spimpl::unique_impl_ptr<CatalogueEventsWidgetPrivate> impl;
58 spimpl::unique_impl_ptr<CatalogueEventsWidgetPrivate> impl;
53
59
54 private slots:
60 private slots:
55 void emitSelection();
61 void emitSelection();
56 };
62 };
57
63
58 #endif // SCIQLOP_CATALOGUEEVENTSWIDGET_H
64 #endif // SCIQLOP_CATALOGUEEVENTSWIDGET_H
@@ -1,49 +1,51
1 #ifndef SCIQLOP_CATALOGUEINSPECTORWIDGET_H
1 #ifndef SCIQLOP_CATALOGUEINSPECTORWIDGET_H
2 #define SCIQLOP_CATALOGUEINSPECTORWIDGET_H
2 #define SCIQLOP_CATALOGUEINSPECTORWIDGET_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QWidget>
5 #include <QWidget>
6 #include <memory>
6 #include <memory>
7
7
8 namespace Ui {
8 namespace Ui {
9 class CatalogueInspectorWidget;
9 class CatalogueInspectorWidget;
10 }
10 }
11
11
12 class DBCatalogue;
12 class DBCatalogue;
13 class DBEvent;
13 class DBEvent;
14 class DBEventProduct;
14 class DBEventProduct;
15
15
16 class CatalogueInspectorWidget : public QWidget {
16 class CatalogueInspectorWidget : public QWidget {
17 Q_OBJECT
17 Q_OBJECT
18
18
19 signals:
19 signals:
20 void catalogueUpdated(const std::shared_ptr<DBCatalogue> &catalogue);
20 void catalogueUpdated(const std::shared_ptr<DBCatalogue> &catalogue);
21 void eventUpdated(const std::shared_ptr<DBEvent> &event);
21 void eventUpdated(const std::shared_ptr<DBEvent> &event);
22 void eventProductUpdated(const std::shared_ptr<DBEvent> &event,
22 void eventProductUpdated(const std::shared_ptr<DBEvent> &event,
23 const std::shared_ptr<DBEventProduct> &eventProduct);
23 const std::shared_ptr<DBEventProduct> &eventProduct);
24
24
25 public:
25 public:
26 explicit CatalogueInspectorWidget(QWidget *parent = 0);
26 explicit CatalogueInspectorWidget(QWidget *parent = 0);
27 virtual ~CatalogueInspectorWidget();
27 virtual ~CatalogueInspectorWidget();
28
28
29 /// Enum matching the pages inside the stacked widget
29 /// Enum matching the pages inside the stacked widget
30 enum class Page { Empty, CatalogueProperties, EventProperties };
30 enum class Page { Empty, CatalogueProperties, EventProperties };
31
31
32 Page currentPage() const;
32 Page currentPage() const;
33
33
34 void setEvent(const std::shared_ptr<DBEvent> &event);
34 void setEvent(const std::shared_ptr<DBEvent> &event);
35 void setEventProduct(const std::shared_ptr<DBEvent> &event,
35 void setEventProduct(const std::shared_ptr<DBEvent> &event,
36 const std::shared_ptr<DBEventProduct> &eventProduct);
36 const std::shared_ptr<DBEventProduct> &eventProduct);
37 void setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue);
37 void setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue);
38
38
39 void refresh();
40
39 public slots:
41 public slots:
40 void showPage(Page page);
42 void showPage(Page page);
41
43
42 private:
44 private:
43 Ui::CatalogueInspectorWidget *ui;
45 Ui::CatalogueInspectorWidget *ui;
44
46
45 class CatalogueInspectorWidgetPrivate;
47 class CatalogueInspectorWidgetPrivate;
46 spimpl::unique_impl_ptr<CatalogueInspectorWidgetPrivate> impl;
48 spimpl::unique_impl_ptr<CatalogueInspectorWidgetPrivate> impl;
47 };
49 };
48
50
49 #endif // SCIQLOP_CATALOGUEINSPECTORWIDGET_H
51 #endif // SCIQLOP_CATALOGUEINSPECTORWIDGET_H
@@ -1,156 +1,158
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 VisualizationWidget;
21 class VisualizationZoneWidget;
21 class VisualizationZoneWidget;
22 class VisualizationSelectionZoneItem;
22 class VisualizationSelectionZoneItem;
23
23
24 namespace Ui {
24 namespace Ui {
25 class VisualizationGraphWidget;
25 class VisualizationGraphWidget;
26 } // namespace Ui
26 } // namespace Ui
27
27
28 /// Defines options that can be associated with the graph
28 /// Defines options that can be associated with the graph
29 enum GraphFlag {
29 enum GraphFlag {
30 DisableAll = 0x0, ///< Disables acquisition and synchronization
30 DisableAll = 0x0, ///< Disables acquisition and synchronization
31 EnableAcquisition = 0x1, ///< When this flag is set, the change of the graph's range leads to
31 EnableAcquisition = 0x1, ///< When this flag is set, the change of the graph's range leads to
32 /// the acquisition of data
32 /// the acquisition of data
33 EnableSynchronization = 0x2, ///< When this flag is set, the change of the graph's range causes
33 EnableSynchronization = 0x2, ///< When this flag is set, the change of the graph's range causes
34 /// the call to the synchronization of the graphs contained in the
34 /// the call to the synchronization of the graphs contained in the
35 /// same zone of this graph
35 /// same zone of this graph
36 EnableAll = ~DisableAll ///< Enables acquisition and synchronization
36 EnableAll = ~DisableAll ///< Enables acquisition and synchronization
37 };
37 };
38
38
39 Q_DECLARE_FLAGS(GraphFlags, GraphFlag)
39 Q_DECLARE_FLAGS(GraphFlags, GraphFlag)
40 Q_DECLARE_OPERATORS_FOR_FLAGS(GraphFlags)
40 Q_DECLARE_OPERATORS_FOR_FLAGS(GraphFlags)
41
41
42 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
42 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
43 Q_OBJECT
43 Q_OBJECT
44
44
45 friend class QCustomPlotSynchronizer;
45 friend class QCustomPlotSynchronizer;
46 friend class VisualizationGraphRenderingDelegate;
46 friend class VisualizationGraphRenderingDelegate;
47
47
48 public:
48 public:
49 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
49 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
50 virtual ~VisualizationGraphWidget();
50 virtual ~VisualizationGraphWidget();
51
51
52 /// Returns the VisualizationZoneWidget which contains the graph or nullptr
52 /// Returns the VisualizationZoneWidget which contains the graph or nullptr
53 VisualizationZoneWidget *parentZoneWidget() const noexcept;
53 VisualizationZoneWidget *parentZoneWidget() const noexcept;
54
54
55 /// Returns the main VisualizationWidget which contains the graph or nullptr
55 /// Returns the main VisualizationWidget which contains the graph or nullptr
56 VisualizationWidget *parentVisualizationWidget() const;
56 VisualizationWidget *parentVisualizationWidget() const;
57
57
58 /// Sets graph options
58 /// Sets graph options
59 void setFlags(GraphFlags flags);
59 void setFlags(GraphFlags flags);
60
60
61 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
61 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
62
62
63 /// Removes a variable from the graph
63 /// Removes a variable from the graph
64 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
64 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
65
65
66 /// Returns the list of all variables used in the graph
66 /// Returns the list of all variables used in the graph
67 QList<std::shared_ptr<Variable> > variables() const;
67 QList<std::shared_ptr<Variable> > variables() const;
68
68
69 /// Sets the y-axis range based on the data of a variable
69 /// Sets the y-axis range based on the data of a variable
70 void setYRange(std::shared_ptr<Variable> variable);
70 void setYRange(std::shared_ptr<Variable> variable);
71 SqpRange graphRange() const noexcept;
71 SqpRange graphRange() const noexcept;
72 void setGraphRange(const SqpRange &range, bool calibration = false);
72 void setGraphRange(const SqpRange &range, bool calibration = false);
73 void setAutoRangeOnVariableInitialization(bool value);
73 void setAutoRangeOnVariableInitialization(bool value);
74
74
75 // Zones
75 // Zones
76 /// Returns the ranges of all the selection zones on the graph
76 /// Returns the ranges of all the selection zones on the graph
77 QVector<SqpRange> selectionZoneRanges() const;
77 QVector<SqpRange> selectionZoneRanges() const;
78 /// Adds new selection zones in the graph
78 /// Adds new selection zones in the graph
79 void addSelectionZones(const QVector<SqpRange> &ranges);
79 void addSelectionZones(const QVector<SqpRange> &ranges);
80 /// Adds a new selection zone in the graph
81 VisualizationSelectionZoneItem *addSelectionZone(const QString &name, const SqpRange &range);
80 /// Removes the specified selection zone
82 /// Removes the specified selection zone
81 void removeSelectionZone(VisualizationSelectionZoneItem *selectionZone);
83 void removeSelectionZone(VisualizationSelectionZoneItem *selectionZone);
82
84
83 /// Undo the last zoom done with a zoom box
85 /// Undo the last zoom done with a zoom box
84 void undoZoom();
86 void undoZoom();
85
87
86 // IVisualizationWidget interface
88 // IVisualizationWidget interface
87 void accept(IVisualizationWidgetVisitor *visitor) override;
89 void accept(IVisualizationWidgetVisitor *visitor) override;
88 bool canDrop(const Variable &variable) const override;
90 bool canDrop(const Variable &variable) const override;
89 bool contains(const Variable &variable) const override;
91 bool contains(const Variable &variable) const override;
90 QString name() const override;
92 QString name() const override;
91
93
92 // VisualisationDragWidget
94 // VisualisationDragWidget
93 QMimeData *mimeData(const QPoint &position) const override;
95 QMimeData *mimeData(const QPoint &position) const override;
94 QPixmap customDragPixmap(const QPoint &dragPosition) override;
96 QPixmap customDragPixmap(const QPoint &dragPosition) override;
95 bool isDragAllowed() const override;
97 bool isDragAllowed() const override;
96 void highlightForMerge(bool highlighted) override;
98 void highlightForMerge(bool highlighted) override;
97
99
98 // Cursors
100 // Cursors
99 /// Adds or moves the vertical cursor at the specified value on the x-axis
101 /// Adds or moves the vertical cursor at the specified value on the x-axis
100 void addVerticalCursor(double time);
102 void addVerticalCursor(double time);
101 /// Adds or moves the vertical cursor at the specified value on the x-axis
103 /// Adds or moves the vertical cursor at the specified value on the x-axis
102 void addVerticalCursorAtViewportPosition(double position);
104 void addVerticalCursorAtViewportPosition(double position);
103 void removeVerticalCursor();
105 void removeVerticalCursor();
104 /// Adds or moves the vertical cursor at the specified value on the y-axis
106 /// Adds or moves the vertical cursor at the specified value on the y-axis
105 void addHorizontalCursor(double value);
107 void addHorizontalCursor(double value);
106 /// Adds or moves the vertical cursor at the specified value on the y-axis
108 /// Adds or moves the vertical cursor at the specified value on the y-axis
107 void addHorizontalCursorAtViewportPosition(double position);
109 void addHorizontalCursorAtViewportPosition(double position);
108 void removeHorizontalCursor();
110 void removeHorizontalCursor();
109
111
110 signals:
112 signals:
111 void synchronize(const SqpRange &range, const SqpRange &oldRange);
113 void synchronize(const SqpRange &range, const SqpRange &oldRange);
112 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
114 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
113 bool synchronise);
115 bool synchronise);
114
116
115 /// Signal emitted when the variable is about to be removed from the graph
117 /// Signal emitted when the variable is about to be removed from the graph
116 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
118 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
117 /// Signal emitted when the variable has been added to the graph
119 /// Signal emitted when the variable has been added to the graph
118 void variableAdded(std::shared_ptr<Variable> var);
120 void variableAdded(std::shared_ptr<Variable> var);
119
121
120 protected:
122 protected:
121 void closeEvent(QCloseEvent *event) override;
123 void closeEvent(QCloseEvent *event) override;
122 void enterEvent(QEvent *event) override;
124 void enterEvent(QEvent *event) override;
123 void leaveEvent(QEvent *event) override;
125 void leaveEvent(QEvent *event) override;
124
126
125 QCustomPlot &plot() const noexcept;
127 QCustomPlot &plot() const noexcept;
126
128
127 private:
129 private:
128 Ui::VisualizationGraphWidget *ui;
130 Ui::VisualizationGraphWidget *ui;
129
131
130 class VisualizationGraphWidgetPrivate;
132 class VisualizationGraphWidgetPrivate;
131 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
133 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
132
134
133 private slots:
135 private slots:
134 /// Slot called when right clicking on the graph (displays a menu)
136 /// Slot called when right clicking on the graph (displays a menu)
135 void onGraphMenuRequested(const QPoint &pos) noexcept;
137 void onGraphMenuRequested(const QPoint &pos) noexcept;
136
138
137 /// Rescale the X axe to range parameter
139 /// Rescale the X axe to range parameter
138 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
140 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
139
141
140 /// Slot called when a mouse double click was made
142 /// Slot called when a mouse double click was made
141 void onMouseDoubleClick(QMouseEvent *event) noexcept;
143 void onMouseDoubleClick(QMouseEvent *event) noexcept;
142 /// Slot called when a mouse move was made
144 /// Slot called when a mouse move was made
143 void onMouseMove(QMouseEvent *event) noexcept;
145 void onMouseMove(QMouseEvent *event) noexcept;
144 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
146 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
145 void onMouseWheel(QWheelEvent *event) noexcept;
147 void onMouseWheel(QWheelEvent *event) noexcept;
146 /// Slot called when a mouse press was made, to activate the calibration of a graph
148 /// Slot called when a mouse press was made, to activate the calibration of a graph
147 void onMousePress(QMouseEvent *event) noexcept;
149 void onMousePress(QMouseEvent *event) noexcept;
148 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
150 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
149 void onMouseRelease(QMouseEvent *event) noexcept;
151 void onMouseRelease(QMouseEvent *event) noexcept;
150
152
151 void onDataCacheVariableUpdated();
153 void onDataCacheVariableUpdated();
152
154
153 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
155 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
154 };
156 };
155
157
156 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
158 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,68 +1,73
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 VisualizationGraphWidget;
8 class VisualizationGraphWidget;
9
9
10 class VisualizationSelectionZoneItem : public QCPItemRect {
10 class VisualizationSelectionZoneItem : public QCPItemRect {
11 Q_OBJECT
12
13 signals:
14 /// Signal emitted when the zone range is edited manually
15 void rangeEdited(const SqpRange &range);
11
16
12 public:
17 public:
13 VisualizationSelectionZoneItem(QCustomPlot *plot);
18 VisualizationSelectionZoneItem(QCustomPlot *plot);
14 virtual ~VisualizationSelectionZoneItem();
19 virtual ~VisualizationSelectionZoneItem();
15
20
16 VisualizationGraphWidget *parentGraphWidget() const noexcept;
21 VisualizationGraphWidget *parentGraphWidget() const noexcept;
17
22
18 void setName(const QString &name);
23 void setName(const QString &name);
19 QString name() const;
24 QString name() const;
20
25
21 SqpRange range() const;
26 SqpRange range() const;
22 void setRange(double tstart, double tend);
27 void setRange(double tstart, double tend);
23 void setStart(double tstart);
28 void setStart(double tstart);
24 void setEnd(double tend);
29 void setEnd(double tend);
25
30
26 void setColor(const QColor &color);
31 void setColor(const QColor &color);
27
32
28 void setEditionEnabled(bool value);
33 void setEditionEnabled(bool value);
29 bool isEditionEnabled() const;
34 bool isEditionEnabled() const;
30
35
31 /// Moves the item at the top of its QCPLayer. It will then receive the mouse events if multiple
36 /// Moves the item at the top of its QCPLayer. It will then receive the mouse events if multiple
32 /// items are stacked on top of each others.
37 /// items are stacked on top of each others.
33 void moveToTop();
38 void moveToTop();
34
39
35 Qt::CursorShape curshorShapeForPosition(const QPoint &position) const;
40 Qt::CursorShape curshorShapeForPosition(const QPoint &position) const;
36 void setHovered(bool value);
41 void setHovered(bool value);
37
42
38 /// Sets the zones which should be moved or reisized together with this zone
43 /// Sets the zones which should be moved or reisized together with this zone
39 void setAssociatedEditedZones(const QVector<VisualizationSelectionZoneItem *> &associatedZones);
44 void setAssociatedEditedZones(const QVector<VisualizationSelectionZoneItem *> &associatedZones);
40
45
41 /// Align the specified zones with this one, vertically with the left border
46 /// Align the specified zones with this one, vertically with the left border
42 bool alignZonesVerticallyOnLeft(const QVector<VisualizationSelectionZoneItem *> &zonesToAlign,
47 bool alignZonesVerticallyOnLeft(const QVector<VisualizationSelectionZoneItem *> &zonesToAlign,
43 bool allowResize);
48 bool allowResize);
44 /// Align the specified zones with this one, vertically with the right border
49 /// Align the specified zones with this one, vertically with the right border
45 bool alignZonesVerticallyOnRight(const QVector<VisualizationSelectionZoneItem *> &zonesToAlign,
50 bool alignZonesVerticallyOnRight(const QVector<VisualizationSelectionZoneItem *> &zonesToAlign,
46 bool allowResize);
51 bool allowResize);
47 /// Align the specified zones with this one, temporally with the left border
52 /// Align the specified zones with this one, temporally with the left border
48 bool alignZonesTemporallyOnLeft(const QVector<VisualizationSelectionZoneItem *> &zonesToAlign,
53 bool alignZonesTemporallyOnLeft(const QVector<VisualizationSelectionZoneItem *> &zonesToAlign,
49 bool allowResize);
54 bool allowResize);
50 /// Align the specified zones with this one, temporally with the right border
55 /// Align the specified zones with this one, temporally with the right border
51 bool alignZonesTemporallyOnRight(const QVector<VisualizationSelectionZoneItem *> &zonesToAlign,
56 bool alignZonesTemporallyOnRight(const QVector<VisualizationSelectionZoneItem *> &zonesToAlign,
52 bool allowResize);
57 bool allowResize);
53
58
54 protected:
59 protected:
55 void mousePressEvent(QMouseEvent *event, const QVariant &details) override;
60 void mousePressEvent(QMouseEvent *event, const QVariant &details) override;
56 void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) override;
61 void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) override;
57 void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) override;
62 void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) override;
58
63
59 void resizeLeft(double pixelDiff);
64 void resizeLeft(double pixelDiff);
60 void resizeRight(double pixelDiff);
65 void resizeRight(double pixelDiff);
61 void move(double pixelDiff);
66 void move(double pixelDiff);
62
67
63 private:
68 private:
64 class VisualizationSelectionZoneItemPrivate;
69 class VisualizationSelectionZoneItemPrivate;
65 spimpl::unique_impl_ptr<VisualizationSelectionZoneItemPrivate> impl;
70 spimpl::unique_impl_ptr<VisualizationSelectionZoneItemPrivate> impl;
66 };
71 };
67
72
68 #endif // SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
73 #endif // SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
@@ -1,147 +1,148
1 qxorm_dep = dependency('QxOrm', required : true, fallback:['QxOrm','qxorm_dep'])
1 qxorm_dep = dependency('QxOrm', required : true, fallback:['QxOrm','qxorm_dep'])
2 catalogueapi_dep = dependency('CatalogueAPI', required : true, fallback:['CatalogueAPI','CatalogueAPI_dep'])
2 catalogueapi_dep = dependency('CatalogueAPI', required : true, fallback:['CatalogueAPI','CatalogueAPI_dep'])
3
3
4 gui_moc_headers = [
4 gui_moc_headers = [
5 'include/DataSource/DataSourceWidget.h',
5 'include/DataSource/DataSourceWidget.h',
6 'include/Settings/SqpSettingsDialog.h',
6 'include/Settings/SqpSettingsDialog.h',
7 'include/Settings/SqpSettingsGeneralWidget.h',
7 'include/Settings/SqpSettingsGeneralWidget.h',
8 'include/SidePane/SqpSidePane.h',
8 'include/SidePane/SqpSidePane.h',
9 'include/SqpApplication.h',
9 'include/SqpApplication.h',
10 'include/DragAndDrop/DragDropScroller.h',
10 'include/DragAndDrop/DragDropScroller.h',
11 'include/DragAndDrop/DragDropTabSwitcher.h',
11 'include/DragAndDrop/DragDropTabSwitcher.h',
12 'include/TimeWidget/TimeWidget.h',
12 'include/TimeWidget/TimeWidget.h',
13 'include/Variable/VariableInspectorWidget.h',
13 'include/Variable/VariableInspectorWidget.h',
14 'include/Variable/RenameVariableDialog.h',
14 'include/Variable/RenameVariableDialog.h',
15 'include/Visualization/qcustomplot.h',
15 'include/Visualization/qcustomplot.h',
16 'include/Visualization/VisualizationGraphWidget.h',
16 'include/Visualization/VisualizationGraphWidget.h',
17 'include/Visualization/VisualizationTabWidget.h',
17 'include/Visualization/VisualizationTabWidget.h',
18 'include/Visualization/VisualizationWidget.h',
18 'include/Visualization/VisualizationWidget.h',
19 'include/Visualization/VisualizationZoneWidget.h',
19 'include/Visualization/VisualizationZoneWidget.h',
20 'include/Visualization/VisualizationDragDropContainer.h',
20 'include/Visualization/VisualizationDragDropContainer.h',
21 'include/Visualization/VisualizationDragWidget.h',
21 'include/Visualization/VisualizationDragWidget.h',
22 'include/Visualization/ColorScaleEditor.h',
22 'include/Visualization/ColorScaleEditor.h',
23 'include/Visualization/VisualizationSelectionZoneItem.h',
23 'include/Actions/SelectionZoneAction.h',
24 'include/Actions/SelectionZoneAction.h',
24 'include/Visualization/VisualizationMultiZoneSelectionDialog.h',
25 'include/Visualization/VisualizationMultiZoneSelectionDialog.h',
25 'include/Catalogue/CatalogueExplorer.h',
26 'include/Catalogue/CatalogueExplorer.h',
26 'include/Catalogue/CatalogueEventsWidget.h',
27 'include/Catalogue/CatalogueEventsWidget.h',
27 'include/Catalogue/CatalogueSideBarWidget.h',
28 'include/Catalogue/CatalogueSideBarWidget.h',
28 'include/Catalogue/CatalogueInspectorWidget.h',
29 'include/Catalogue/CatalogueInspectorWidget.h',
29 'include/Catalogue/CatalogueEventsModel.h',
30 'include/Catalogue/CatalogueEventsModel.h',
30 'include/Catalogue/CreateEventDialog.h',
31 'include/Catalogue/CreateEventDialog.h',
31 'include/Catalogue/CatalogueTreeModel.h'
32 'include/Catalogue/CatalogueTreeModel.h'
32 ]
33 ]
33
34
34 gui_ui_files = [
35 gui_ui_files = [
35 'ui/DataSource/DataSourceWidget.ui',
36 'ui/DataSource/DataSourceWidget.ui',
36 'ui/Settings/SqpSettingsDialog.ui',
37 'ui/Settings/SqpSettingsDialog.ui',
37 'ui/Settings/SqpSettingsGeneralWidget.ui',
38 'ui/Settings/SqpSettingsGeneralWidget.ui',
38 'ui/SidePane/SqpSidePane.ui',
39 'ui/SidePane/SqpSidePane.ui',
39 'ui/TimeWidget/TimeWidget.ui',
40 'ui/TimeWidget/TimeWidget.ui',
40 'ui/Variable/VariableInspectorWidget.ui',
41 'ui/Variable/VariableInspectorWidget.ui',
41 'ui/Variable/RenameVariableDialog.ui',
42 'ui/Variable/RenameVariableDialog.ui',
42 'ui/Variable/VariableMenuHeaderWidget.ui',
43 'ui/Variable/VariableMenuHeaderWidget.ui',
43 'ui/Visualization/VisualizationGraphWidget.ui',
44 'ui/Visualization/VisualizationGraphWidget.ui',
44 'ui/Visualization/VisualizationTabWidget.ui',
45 'ui/Visualization/VisualizationTabWidget.ui',
45 'ui/Visualization/VisualizationWidget.ui',
46 'ui/Visualization/VisualizationWidget.ui',
46 'ui/Visualization/VisualizationZoneWidget.ui',
47 'ui/Visualization/VisualizationZoneWidget.ui',
47 'ui/Visualization/ColorScaleEditor.ui',
48 'ui/Visualization/ColorScaleEditor.ui',
48 'ui/Visualization/VisualizationMultiZoneSelectionDialog.ui',
49 'ui/Visualization/VisualizationMultiZoneSelectionDialog.ui',
49 'ui/Catalogue/CatalogueExplorer.ui',
50 'ui/Catalogue/CatalogueExplorer.ui',
50 'ui/Catalogue/CatalogueEventsWidget.ui',
51 'ui/Catalogue/CatalogueEventsWidget.ui',
51 'ui/Catalogue/CatalogueSideBarWidget.ui',
52 'ui/Catalogue/CatalogueSideBarWidget.ui',
52 'ui/Catalogue/CatalogueInspectorWidget.ui',
53 'ui/Catalogue/CatalogueInspectorWidget.ui',
53 'ui/Catalogue/CreateEventDialog.ui'
54 'ui/Catalogue/CreateEventDialog.ui'
54 ]
55 ]
55
56
56 gui_qresources = ['resources/sqpguiresources.qrc']
57 gui_qresources = ['resources/sqpguiresources.qrc']
57
58
58 rcc_gen = generator(rcc,
59 rcc_gen = generator(rcc,
59 output : 'qrc_@BASENAME@.cpp',
60 output : 'qrc_@BASENAME@.cpp',
60 arguments : [
61 arguments : [
61 '--output',
62 '--output',
62 '@OUTPUT@',
63 '@OUTPUT@',
63 '@INPUT@',
64 '@INPUT@',
64 '@EXTRA_ARGS@'])
65 '@EXTRA_ARGS@'])
65
66
66 rcc_files = rcc_gen.process(gui_qresources, extra_args : ['-name', 'sqpguiresources'])
67 rcc_files = rcc_gen.process(gui_qresources, extra_args : ['-name', 'sqpguiresources'])
67
68
68 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
69 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
69 ui_files : gui_ui_files)
70 ui_files : gui_ui_files)
70
71
71 gui_sources = [
72 gui_sources = [
72 'src/SqpApplication.cpp',
73 'src/SqpApplication.cpp',
73 'src/DragAndDrop/DragDropGuiController.cpp',
74 'src/DragAndDrop/DragDropGuiController.cpp',
74 'src/DragAndDrop/DragDropScroller.cpp',
75 'src/DragAndDrop/DragDropScroller.cpp',
75 'src/DragAndDrop/DragDropTabSwitcher.cpp',
76 'src/DragAndDrop/DragDropTabSwitcher.cpp',
76 'src/Common/ColorUtils.cpp',
77 'src/Common/ColorUtils.cpp',
77 'src/Common/VisualizationDef.cpp',
78 'src/Common/VisualizationDef.cpp',
78 'src/DataSource/DataSourceTreeWidgetItem.cpp',
79 'src/DataSource/DataSourceTreeWidgetItem.cpp',
79 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
80 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
80 'src/DataSource/DataSourceWidget.cpp',
81 'src/DataSource/DataSourceWidget.cpp',
81 'src/DataSource/DataSourceTreeWidget.cpp',
82 'src/DataSource/DataSourceTreeWidget.cpp',
82 'src/Settings/SqpSettingsDialog.cpp',
83 'src/Settings/SqpSettingsDialog.cpp',
83 'src/Settings/SqpSettingsGeneralWidget.cpp',
84 'src/Settings/SqpSettingsGeneralWidget.cpp',
84 'src/SidePane/SqpSidePane.cpp',
85 'src/SidePane/SqpSidePane.cpp',
85 'src/TimeWidget/TimeWidget.cpp',
86 'src/TimeWidget/TimeWidget.cpp',
86 'src/Variable/VariableInspectorWidget.cpp',
87 'src/Variable/VariableInspectorWidget.cpp',
87 'src/Variable/VariableInspectorTableView.cpp',
88 'src/Variable/VariableInspectorTableView.cpp',
88 'src/Variable/VariableMenuHeaderWidget.cpp',
89 'src/Variable/VariableMenuHeaderWidget.cpp',
89 'src/Variable/RenameVariableDialog.cpp',
90 'src/Variable/RenameVariableDialog.cpp',
90 'src/Visualization/VisualizationGraphHelper.cpp',
91 'src/Visualization/VisualizationGraphHelper.cpp',
91 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
92 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
92 'src/Visualization/VisualizationGraphWidget.cpp',
93 'src/Visualization/VisualizationGraphWidget.cpp',
93 'src/Visualization/VisualizationTabWidget.cpp',
94 'src/Visualization/VisualizationTabWidget.cpp',
94 'src/Visualization/VisualizationWidget.cpp',
95 'src/Visualization/VisualizationWidget.cpp',
95 'src/Visualization/VisualizationZoneWidget.cpp',
96 'src/Visualization/VisualizationZoneWidget.cpp',
96 'src/Visualization/qcustomplot.cpp',
97 'src/Visualization/qcustomplot.cpp',
97 'src/Visualization/QCustomPlotSynchronizer.cpp',
98 'src/Visualization/QCustomPlotSynchronizer.cpp',
98 'src/Visualization/operations/FindVariableOperation.cpp',
99 'src/Visualization/operations/FindVariableOperation.cpp',
99 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
100 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
100 'src/Visualization/operations/MenuBuilder.cpp',
101 'src/Visualization/operations/MenuBuilder.cpp',
101 'src/Visualization/operations/RemoveVariableOperation.cpp',
102 'src/Visualization/operations/RemoveVariableOperation.cpp',
102 'src/Visualization/operations/RescaleAxeOperation.cpp',
103 'src/Visualization/operations/RescaleAxeOperation.cpp',
103 'src/Visualization/VisualizationDragDropContainer.cpp',
104 'src/Visualization/VisualizationDragDropContainer.cpp',
104 'src/Visualization/VisualizationDragWidget.cpp',
105 'src/Visualization/VisualizationDragWidget.cpp',
105 'src/Visualization/AxisRenderingUtils.cpp',
106 'src/Visualization/AxisRenderingUtils.cpp',
106 'src/Visualization/PlottablesRenderingUtils.cpp',
107 'src/Visualization/PlottablesRenderingUtils.cpp',
107 'src/Visualization/MacScrollBarStyle.cpp',
108 'src/Visualization/MacScrollBarStyle.cpp',
108 'src/Visualization/VisualizationCursorItem.cpp',
109 'src/Visualization/VisualizationCursorItem.cpp',
109 'src/Visualization/ColorScaleEditor.cpp',
110 'src/Visualization/ColorScaleEditor.cpp',
110 'src/Visualization/SqpColorScale.cpp',
111 'src/Visualization/SqpColorScale.cpp',
111 'src/Visualization/QCPColorMapIterator.cpp',
112 'src/Visualization/QCPColorMapIterator.cpp',
112 'src/Visualization/VisualizationSelectionZoneItem.cpp',
113 'src/Visualization/VisualizationSelectionZoneItem.cpp',
113 'src/Visualization/VisualizationSelectionZoneManager.cpp',
114 'src/Visualization/VisualizationSelectionZoneManager.cpp',
114 'src/Actions/SelectionZoneAction.cpp',
115 'src/Actions/SelectionZoneAction.cpp',
115 'src/Actions/ActionsGuiController.cpp',
116 'src/Actions/ActionsGuiController.cpp',
116 'src/Visualization/VisualizationActionManager.cpp',
117 'src/Visualization/VisualizationActionManager.cpp',
117 'src/Visualization/VisualizationMultiZoneSelectionDialog.cpp',
118 'src/Visualization/VisualizationMultiZoneSelectionDialog.cpp',
118 'src/Catalogue/CatalogueExplorer.cpp',
119 'src/Catalogue/CatalogueExplorer.cpp',
119 'src/Catalogue/CatalogueEventsWidget.cpp',
120 'src/Catalogue/CatalogueEventsWidget.cpp',
120 'src/Catalogue/CatalogueSideBarWidget.cpp',
121 'src/Catalogue/CatalogueSideBarWidget.cpp',
121 'src/Catalogue/CatalogueInspectorWidget.cpp',
122 'src/Catalogue/CatalogueInspectorWidget.cpp',
122 'src/Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.cpp',
123 'src/Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.cpp',
123 'src/Catalogue/CatalogueTreeItems/CatalogueTreeItem.cpp',
124 'src/Catalogue/CatalogueTreeItems/CatalogueTreeItem.cpp',
124 'src/Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.cpp',
125 'src/Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.cpp',
125 'src/Catalogue/CatalogueEventsModel.cpp',
126 'src/Catalogue/CatalogueEventsModel.cpp',
126 'src/Catalogue/CatalogueExplorerHelper.cpp',
127 'src/Catalogue/CatalogueExplorerHelper.cpp',
127 'src/Catalogue/CatalogueActionManager.cpp',
128 'src/Catalogue/CatalogueActionManager.cpp',
128 'src/Catalogue/CreateEventDialog.cpp',
129 'src/Catalogue/CreateEventDialog.cpp',
129 'src/Catalogue/CatalogueTreeModel.cpp'
130 'src/Catalogue/CatalogueTreeModel.cpp'
130 ]
131 ]
131
132
132 gui_inc = include_directories(['include'])
133 gui_inc = include_directories(['include'])
133
134
134 sciqlop_gui_lib = library('sciqlopgui',
135 sciqlop_gui_lib = library('sciqlopgui',
135 gui_sources,
136 gui_sources,
136 gui_moc_files,
137 gui_moc_files,
137 rcc_files,
138 rcc_files,
138 include_directories : [gui_inc],
139 include_directories : [gui_inc],
139 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep],
140 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep],
140 install : true
141 install : true
141 )
142 )
142
143
143 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
144 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
144 include_directories : gui_inc,
145 include_directories : gui_inc,
145 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep])
146 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep])
146
147
147
148
@@ -1,579 +1,590
1 #include "Catalogue/CatalogueEventsWidget.h"
1 #include "Catalogue/CatalogueEventsWidget.h"
2 #include "ui_CatalogueEventsWidget.h"
2 #include "ui_CatalogueEventsWidget.h"
3
3
4 #include <Catalogue/CatalogueController.h>
4 #include <Catalogue/CatalogueController.h>
5 #include <Catalogue/CatalogueEventsModel.h>
5 #include <Catalogue/CatalogueEventsModel.h>
6 #include <Catalogue/CatalogueExplorerHelper.h>
6 #include <Catalogue/CatalogueExplorerHelper.h>
7 #include <CatalogueDao.h>
7 #include <CatalogueDao.h>
8 #include <DBCatalogue.h>
8 #include <DBCatalogue.h>
9 #include <DBEventProduct.h>
9 #include <DBEventProduct.h>
10 #include <DataSource/DataSourceController.h>
10 #include <DataSource/DataSourceController.h>
11 #include <DataSource/DataSourceItem.h>
11 #include <DataSource/DataSourceItem.h>
12 #include <SqpApplication.h>
12 #include <SqpApplication.h>
13 #include <Variable/Variable.h>
13 #include <Variable/Variable.h>
14 #include <Variable/VariableController.h>
14 #include <Variable/VariableController.h>
15 #include <Visualization/VisualizationGraphWidget.h>
15 #include <Visualization/VisualizationGraphWidget.h>
16 #include <Visualization/VisualizationTabWidget.h>
16 #include <Visualization/VisualizationTabWidget.h>
17 #include <Visualization/VisualizationWidget.h>
17 #include <Visualization/VisualizationWidget.h>
18 #include <Visualization/VisualizationZoneWidget.h>
18 #include <Visualization/VisualizationZoneWidget.h>
19
19
20 #include <QDialog>
20 #include <QDialog>
21 #include <QDialogButtonBox>
21 #include <QDialogButtonBox>
22 #include <QListWidget>
22 #include <QListWidget>
23 #include <QMessageBox>
23 #include <QMessageBox>
24
24
25 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
25 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
26
26
27 /// Fixed size of the validation column
27 /// Fixed size of the validation column
28 const auto VALIDATION_COLUMN_SIZE = 35;
28 const auto VALIDATION_COLUMN_SIZE = 35;
29
29
30 /// Percentage added to the range of a event when it is displayed
30 /// Percentage added to the range of a event when it is displayed
31 const auto EVENT_RANGE_MARGE = 30; // in %
31 const auto EVENT_RANGE_MARGE = 30; // in %
32
32
33 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
33 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
34
34
35 CatalogueEventsModel *m_Model = nullptr;
35 CatalogueEventsModel *m_Model = nullptr;
36 QStringList m_ZonesForTimeMode;
36 QStringList m_ZonesForTimeMode;
37 QString m_ZoneForGraphMode;
37 QString m_ZoneForGraphMode;
38 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
38 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
39 bool m_AllEventDisplayed = false;
39 bool m_AllEventDisplayed = false;
40 QVector<VisualizationGraphWidget *> m_CustomGraphs;
40 QVector<VisualizationGraphWidget *> m_CustomGraphs;
41
41
42 VisualizationWidget *m_VisualizationWidget = nullptr;
42 VisualizationWidget *m_VisualizationWidget = nullptr;
43
43
44 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget)
44 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget)
45 {
45 {
46 widget->ui->treeView->setSortingEnabled(false);
46 widget->ui->treeView->setSortingEnabled(false);
47 m_Model->setEvents(events);
47 m_Model->setEvents(events);
48 widget->ui->treeView->setSortingEnabled(true);
48 widget->ui->treeView->setSortingEnabled(true);
49
49
50 for (auto event : events) {
50 for (auto event : events) {
51 if (sqpApp->catalogueController().eventHasChanges(event)) {
51 if (sqpApp->catalogueController().eventHasChanges(event)) {
52 auto index = m_Model->indexOf(event);
52 auto index = m_Model->indexOf(event);
53 widget->setEventChanges(event, true);
53 widget->setEventChanges(event, true);
54 }
54 }
55 }
55 }
56 }
56 }
57
57
58 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
58 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
59 {
59 {
60 treeView->setSortingEnabled(false);
60 treeView->setSortingEnabled(false);
61 m_Model->addEvent(event);
61 m_Model->addEvent(event);
62 treeView->setSortingEnabled(true);
62 treeView->setSortingEnabled(true);
63 }
63 }
64
64
65 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
65 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
66 {
66 {
67 treeView->setSortingEnabled(false);
67 treeView->setSortingEnabled(false);
68 m_Model->removeEvent(event);
68 m_Model->removeEvent(event);
69 treeView->setSortingEnabled(true);
69 treeView->setSortingEnabled(true);
70 }
70 }
71
71
72 QStringList getAvailableVisualizationZoneList() const
72 QStringList getAvailableVisualizationZoneList() const
73 {
73 {
74 if (m_VisualizationWidget) {
74 if (m_VisualizationWidget) {
75 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
75 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
76 return tab->availableZoneWidgets();
76 return tab->availableZoneWidgets();
77 }
77 }
78 }
78 }
79
79
80 return QStringList{};
80 return QStringList{};
81 }
81 }
82
82
83 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
83 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
84 bool allowMultiSelection, const QPoint &location)
84 bool allowMultiSelection, const QPoint &location)
85 {
85 {
86 auto availableZones = getAvailableVisualizationZoneList();
86 auto availableZones = getAvailableVisualizationZoneList();
87 if (availableZones.isEmpty()) {
87 if (availableZones.isEmpty()) {
88 return QStringList{};
88 return QStringList{};
89 }
89 }
90
90
91 QDialog d(parent, Qt::Tool);
91 QDialog d(parent, Qt::Tool);
92 d.setWindowTitle("Choose a zone");
92 d.setWindowTitle("Choose a zone");
93 auto layout = new QVBoxLayout{&d};
93 auto layout = new QVBoxLayout{&d};
94 layout->setContentsMargins(0, 0, 0, 0);
94 layout->setContentsMargins(0, 0, 0, 0);
95 auto listWidget = new QListWidget{&d};
95 auto listWidget = new QListWidget{&d};
96 layout->addWidget(listWidget);
96 layout->addWidget(listWidget);
97
97
98 QSet<QListWidgetItem *> checkedItems;
98 QSet<QListWidgetItem *> checkedItems;
99 for (auto zone : availableZones) {
99 for (auto zone : availableZones) {
100 auto item = new QListWidgetItem{zone};
100 auto item = new QListWidgetItem{zone};
101 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
101 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
102 if (selectedZones.contains(zone)) {
102 if (selectedZones.contains(zone)) {
103 item->setCheckState(Qt::Checked);
103 item->setCheckState(Qt::Checked);
104 checkedItems << item;
104 checkedItems << item;
105 }
105 }
106 else {
106 else {
107 item->setCheckState(Qt::Unchecked);
107 item->setCheckState(Qt::Unchecked);
108 }
108 }
109
109
110 listWidget->addItem(item);
110 listWidget->addItem(item);
111 }
111 }
112
112
113 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
113 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
114 layout->addWidget(buttonBox);
114 layout->addWidget(buttonBox);
115
115
116 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
116 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
117 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
117 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
118
118
119 QObject::connect(listWidget, &QListWidget::itemChanged,
119 QObject::connect(listWidget, &QListWidget::itemChanged,
120 [&checkedItems, allowMultiSelection, listWidget](auto item) {
120 [&checkedItems, allowMultiSelection, listWidget](auto item) {
121 if (item->checkState() == Qt::Checked) {
121 if (item->checkState() == Qt::Checked) {
122 if (!allowMultiSelection) {
122 if (!allowMultiSelection) {
123 for (auto checkedItem : checkedItems) {
123 for (auto checkedItem : checkedItems) {
124 listWidget->blockSignals(true);
124 listWidget->blockSignals(true);
125 checkedItem->setCheckState(Qt::Unchecked);
125 checkedItem->setCheckState(Qt::Unchecked);
126 listWidget->blockSignals(false);
126 listWidget->blockSignals(false);
127 }
127 }
128
128
129 checkedItems.clear();
129 checkedItems.clear();
130 }
130 }
131 checkedItems << item;
131 checkedItems << item;
132 }
132 }
133 else {
133 else {
134 checkedItems.remove(item);
134 checkedItems.remove(item);
135 }
135 }
136 });
136 });
137
137
138 QStringList result;
138 QStringList result;
139
139
140 d.setMinimumWidth(120);
140 d.setMinimumWidth(120);
141 d.resize(d.minimumSizeHint());
141 d.resize(d.minimumSizeHint());
142 d.move(location);
142 d.move(location);
143 if (d.exec() == QDialog::Accepted) {
143 if (d.exec() == QDialog::Accepted) {
144 for (auto item : checkedItems) {
144 for (auto item : checkedItems) {
145 result += item->text();
145 result += item->text();
146 }
146 }
147 }
147 }
148 else {
148 else {
149 result = selectedZones;
149 result = selectedZones;
150 }
150 }
151
151
152 return result;
152 return result;
153 }
153 }
154
154
155 void updateForTimeMode(QTreeView *treeView)
155 void updateForTimeMode(QTreeView *treeView)
156 {
156 {
157 auto selectedRows = treeView->selectionModel()->selectedRows();
157 auto selectedRows = treeView->selectionModel()->selectedRows();
158
158
159 if (selectedRows.count() == 1) {
159 if (selectedRows.count() == 1) {
160 auto event = m_Model->getEvent(selectedRows.first());
160 auto event = m_Model->getEvent(selectedRows.first());
161 if (event) {
161 if (event) {
162 if (m_VisualizationWidget) {
162 if (m_VisualizationWidget) {
163 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
163 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
164
164
165 for (auto zoneName : m_ZonesForTimeMode) {
165 for (auto zoneName : m_ZonesForTimeMode) {
166 if (auto zone = tab->getZoneWithName(zoneName)) {
166 if (auto zone = tab->getZoneWithName(zoneName)) {
167 SqpRange eventRange;
167 SqpRange eventRange;
168 eventRange.m_TStart = event->getTStart();
168 eventRange.m_TStart = event->getTStart();
169 eventRange.m_TEnd = event->getTEnd();
169 eventRange.m_TEnd = event->getTEnd();
170 zone->setZoneRange(eventRange);
170 zone->setZoneRange(eventRange);
171 }
171 }
172 }
172 }
173 }
173 }
174 else {
174 else {
175 qCWarning(LOG_CatalogueEventsWidget())
175 qCWarning(LOG_CatalogueEventsWidget())
176 << "updateTimeZone: no tab found in the visualization";
176 << "updateTimeZone: no tab found in the visualization";
177 }
177 }
178 }
178 }
179 else {
179 else {
180 qCWarning(LOG_CatalogueEventsWidget())
180 qCWarning(LOG_CatalogueEventsWidget())
181 << "updateTimeZone: visualization widget not found";
181 << "updateTimeZone: visualization widget not found";
182 }
182 }
183 }
183 }
184 }
184 }
185 else {
185 else {
186 qCWarning(LOG_CatalogueEventsWidget())
186 qCWarning(LOG_CatalogueEventsWidget())
187 << "updateTimeZone: not compatible with multiple events selected";
187 << "updateTimeZone: not compatible with multiple events selected";
188 }
188 }
189 }
189 }
190
190
191 QVector<SqpRange> getGraphRanges(const std::shared_ptr<DBEvent> &event)
191 QVector<SqpRange> getGraphRanges(const std::shared_ptr<DBEvent> &event)
192 {
192 {
193 // Retrieves the range of each product and the maximum size
193 // Retrieves the range of each product and the maximum size
194 QVector<SqpRange> graphRanges;
194 QVector<SqpRange> graphRanges;
195 double maxDt = 0;
195 double maxDt = 0;
196 for (auto eventProduct : event->getEventProducts()) {
196 for (auto eventProduct : event->getEventProducts()) {
197 SqpRange eventRange;
197 SqpRange eventRange;
198 eventRange.m_TStart = eventProduct.getTStart();
198 eventRange.m_TStart = eventProduct.getTStart();
199 eventRange.m_TEnd = eventProduct.getTEnd();
199 eventRange.m_TEnd = eventProduct.getTEnd();
200 graphRanges << eventRange;
200 graphRanges << eventRange;
201
201
202 auto dt = eventRange.m_TEnd - eventRange.m_TStart;
202 auto dt = eventRange.m_TEnd - eventRange.m_TStart;
203 if (dt > maxDt) {
203 if (dt > maxDt) {
204 maxDt = dt;
204 maxDt = dt;
205 }
205 }
206 }
206 }
207
207
208 // Adds the marge
208 // Adds the marge
209 maxDt *= (100.0 + EVENT_RANGE_MARGE) / 100.0;
209 maxDt *= (100.0 + EVENT_RANGE_MARGE) / 100.0;
210
210
211 // Corrects the graph ranges so that they all have the same size
211 // Corrects the graph ranges so that they all have the same size
212 QVector<SqpRange> correctedGraphRanges;
212 QVector<SqpRange> correctedGraphRanges;
213 for (auto range : graphRanges) {
213 for (auto range : graphRanges) {
214 auto dt = range.m_TEnd - range.m_TStart;
214 auto dt = range.m_TEnd - range.m_TStart;
215 auto diff = qAbs((maxDt - dt) / 2.0);
215 auto diff = qAbs((maxDt - dt) / 2.0);
216
216
217 SqpRange correctedRange;
217 SqpRange correctedRange;
218 correctedRange.m_TStart = range.m_TStart - diff;
218 correctedRange.m_TStart = range.m_TStart - diff;
219 correctedRange.m_TEnd = range.m_TEnd + diff;
219 correctedRange.m_TEnd = range.m_TEnd + diff;
220
220
221 correctedGraphRanges << correctedRange;
221 correctedGraphRanges << correctedRange;
222 }
222 }
223
223
224 return correctedGraphRanges;
224 return correctedGraphRanges;
225 }
225 }
226
226
227 void updateForGraphMode(QTreeView *treeView)
227 void updateForGraphMode(CatalogueEventsWidget *catalogueEventWidget)
228 {
228 {
229 auto selectedRows = treeView->selectionModel()->selectedRows();
229 auto selectedRows = catalogueEventWidget->ui->treeView->selectionModel()->selectedRows();
230 if (selectedRows.count() != 1) {
230 if (selectedRows.count() != 1) {
231 qCWarning(LOG_CatalogueEventsWidget())
231 qCWarning(LOG_CatalogueEventsWidget())
232 << "updateGraphMode: not compatible with multiple events selected";
232 << "updateGraphMode: not compatible with multiple events selected";
233 return;
233 return;
234 }
234 }
235
235
236 if (!m_VisualizationWidget) {
236 if (!m_VisualizationWidget) {
237 qCWarning(LOG_CatalogueEventsWidget())
237 qCWarning(LOG_CatalogueEventsWidget())
238 << "updateGraphMode: visualization widget not found";
238 << "updateGraphMode: visualization widget not found";
239 return;
239 return;
240 }
240 }
241
241
242 auto event = m_Model->getEvent(selectedRows.first());
242 auto event = m_Model->getEvent(selectedRows.first());
243 if (!event) {
243 if (!event) {
244 // A event product is probably selected
244 // A event product is probably selected
245 qCInfo(LOG_CatalogueEventsWidget()) << "updateGraphMode: no events are selected";
245 qCInfo(LOG_CatalogueEventsWidget()) << "updateGraphMode: no events are selected";
246 return;
246 return;
247 }
247 }
248
248
249 auto tab = m_VisualizationWidget->currentTabWidget();
249 auto tab = m_VisualizationWidget->currentTabWidget();
250 if (!tab) {
250 if (!tab) {
251 qCWarning(LOG_CatalogueEventsWidget())
251 qCWarning(LOG_CatalogueEventsWidget())
252 << "updateGraphMode: no tab found in the visualization";
252 << "updateGraphMode: no tab found in the visualization";
253 return;
253 return;
254 }
254 }
255
255
256 auto zone = tab->getZoneWithName(m_ZoneForGraphMode);
256 auto zone = tab->getZoneWithName(m_ZoneForGraphMode);
257 if (!zone) {
257 if (!zone) {
258 qCWarning(LOG_CatalogueEventsWidget()) << "updateGraphMode: zone not found";
258 qCWarning(LOG_CatalogueEventsWidget()) << "updateGraphMode: zone not found";
259 return;
259 return;
260 }
260 }
261
261
262 // Close the previous graph and delete the asociated variables
262 // Close the previous graph and delete the asociated variables
263 for (auto graph : m_CustomGraphs) {
263 for (auto graph : m_CustomGraphs) {
264 graph->close();
264 graph->close();
265 auto variables = graph->variables().toVector();
265 auto variables = graph->variables().toVector();
266
266
267 QMetaObject::invokeMethod(&sqpApp->variableController(), "deleteVariables",
267 QMetaObject::invokeMethod(&sqpApp->variableController(), "deleteVariables",
268 Qt::QueuedConnection,
268 Qt::QueuedConnection,
269 Q_ARG(QVector<std::shared_ptr<Variable> >, variables));
269 Q_ARG(QVector<std::shared_ptr<Variable> >, variables));
270 }
270 }
271 m_CustomGraphs.clear();
271 m_CustomGraphs.clear();
272
272
273 // Calculates the range of each graph which will be created
273 // Calculates the range of each graph which will be created
274 auto graphRange = getGraphRanges(event);
274 auto graphRange = getGraphRanges(event);
275
275
276 // Loops through the event products and create the graph
276 // Loops through the event products and create the graph
277 auto itRange = graphRange.cbegin();
277 auto itRange = graphRange.cbegin();
278 for (auto eventProduct : event->getEventProducts()) {
278 for (auto eventProduct : event->getEventProducts()) {
279 auto productId = eventProduct.getProductId();
279 auto productId = eventProduct.getProductId();
280
280
281 auto range = *itRange;
281 auto range = *itRange;
282 ++itRange;
282 ++itRange;
283
283
284 SqpRange productRange;
284 SqpRange productRange;
285 productRange.m_TStart = eventProduct.getTStart();
285 productRange.m_TStart = eventProduct.getTStart();
286 productRange.m_TEnd = eventProduct.getTEnd();
286 productRange.m_TEnd = eventProduct.getTEnd();
287
287
288 auto context = new QObject{treeView};
288 auto context = new QObject{catalogueEventWidget};
289 QObject::connect(
289 QObject::connect(
290 &sqpApp->variableController(), &VariableController::variableAdded, context,
290 &sqpApp->variableController(), &VariableController::variableAdded, context,
291 [this, zone, context, range, productRange, productId](auto variable) {
291 [this, catalogueEventWidget, zone, context, event, range, productRange,
292 productId](auto variable) {
292
293
293 if (variable->metadata().value(DataSourceItem::ID_DATA_KEY).toString()
294 if (variable->metadata().value(DataSourceItem::ID_DATA_KEY).toString()
294 == productId) {
295 == productId) {
295 auto graph = zone->createGraph(variable);
296 auto graph = zone->createGraph(variable);
296 graph->setAutoRangeOnVariableInitialization(false);
297 graph->setAutoRangeOnVariableInitialization(false);
297
298
298 graph->addSelectionZones({productRange});
299 auto selectionZone
300 = graph->addSelectionZone(event->getName(), productRange);
301 emit catalogueEventWidget->selectionZoneAdded(event, productId,
302 selectionZone);
299 m_CustomGraphs << graph;
303 m_CustomGraphs << graph;
300
304
301 graph->setGraphRange(range, true);
305 graph->setGraphRange(range, true);
302
306
303 // Removes the graph from the graph list if it is closed manually
307 // Removes the graph from the graph list if it is closed manually
304 QObject::connect(graph, &VisualizationGraphWidget::destroyed,
308 QObject::connect(graph, &VisualizationGraphWidget::destroyed,
305 [this, graph]() { m_CustomGraphs.removeAll(graph); });
309 [this, graph]() { m_CustomGraphs.removeAll(graph); });
306
310
307 delete context; // removes the connection
311 delete context; // removes the connection
308 }
312 }
309 },
313 },
310 Qt::QueuedConnection);
314 Qt::QueuedConnection);
311
315
312 QMetaObject::invokeMethod(&sqpApp->dataSourceController(),
316 QMetaObject::invokeMethod(&sqpApp->dataSourceController(),
313 "requestVariableFromProductIdKey", Qt::QueuedConnection,
317 "requestVariableFromProductIdKey", Qt::QueuedConnection,
314 Q_ARG(QString, productId));
318 Q_ARG(QString, productId));
315 }
319 }
316 }
320 }
317
321
318 void getSelectedItems(
322 void getSelectedItems(
319 QTreeView *treeView, QVector<std::shared_ptr<DBEvent> > &events,
323 QTreeView *treeView, QVector<std::shared_ptr<DBEvent> > &events,
320 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > &eventProducts)
324 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > &eventProducts)
321 {
325 {
322 for (auto rowIndex : treeView->selectionModel()->selectedRows()) {
326 for (auto rowIndex : treeView->selectionModel()->selectedRows()) {
323 auto itemType = m_Model->itemTypeOf(rowIndex);
327 auto itemType = m_Model->itemTypeOf(rowIndex);
324 if (itemType == CatalogueEventsModel::ItemType::Event) {
328 if (itemType == CatalogueEventsModel::ItemType::Event) {
325 events << m_Model->getEvent(rowIndex);
329 events << m_Model->getEvent(rowIndex);
326 }
330 }
327 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
331 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
328 eventProducts << qMakePair(m_Model->getParentEvent(rowIndex),
332 eventProducts << qMakePair(m_Model->getParentEvent(rowIndex),
329 m_Model->getEventProduct(rowIndex));
333 m_Model->getEventProduct(rowIndex));
330 }
334 }
331 }
335 }
332 }
336 }
333 };
337 };
334
338
335 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
339 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
336 : QWidget(parent),
340 : QWidget(parent),
337 ui(new Ui::CatalogueEventsWidget),
341 ui(new Ui::CatalogueEventsWidget),
338 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
342 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
339 {
343 {
340 ui->setupUi(this);
344 ui->setupUi(this);
341
345
342 impl->m_Model = new CatalogueEventsModel{this};
346 impl->m_Model = new CatalogueEventsModel{this};
343 ui->treeView->setModel(impl->m_Model);
347 ui->treeView->setModel(impl->m_Model);
344
348
345 ui->treeView->setSortingEnabled(true);
349 ui->treeView->setSortingEnabled(true);
346 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
350 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
347 ui->treeView->setDragEnabled(true);
351 ui->treeView->setDragEnabled(true);
348
352
349 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
353 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
350 if (checked) {
354 if (checked) {
351 ui->btnChart->setChecked(false);
355 ui->btnChart->setChecked(false);
352 impl->m_ZonesForTimeMode
356 impl->m_ZonesForTimeMode
353 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
357 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
354 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
358 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
355
359
356 impl->updateForTimeMode(ui->treeView);
360 impl->updateForTimeMode(ui->treeView);
357 }
361 }
358 });
362 });
359
363
360 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
364 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
361 if (checked) {
365 if (checked) {
362 ui->btnTime->setChecked(false);
366 ui->btnTime->setChecked(false);
363 impl->m_ZoneForGraphMode
367 impl->m_ZoneForGraphMode
364 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
368 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
365 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
369 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
366 .value(0);
370 .value(0);
367
371
368 impl->updateForGraphMode(ui->treeView);
372 impl->updateForGraphMode(this);
369 }
373 }
370 });
374 });
371
375
372 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
376 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
373 QVector<std::shared_ptr<DBEvent> > events;
377 QVector<std::shared_ptr<DBEvent> > events;
374 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
378 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
375 impl->getSelectedItems(ui->treeView, events, eventProducts);
379 impl->getSelectedItems(ui->treeView, events, eventProducts);
376
380
377 if (!events.isEmpty() && eventProducts.isEmpty()) {
381 if (!events.isEmpty() && eventProducts.isEmpty()) {
378
382
379 if (QMessageBox::warning(this, tr("Remove Event(s)"),
383 if (QMessageBox::warning(this, tr("Remove Event(s)"),
380 tr("The selected event(s) will be permanently removed "
384 tr("The selected event(s) will be permanently removed "
381 "from the repository!\nAre you sure you want to continue?"),
385 "from the repository!\nAre you sure you want to continue?"),
382 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
386 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
383 == QMessageBox::Yes) {
387 == QMessageBox::Yes) {
384
388
385 for (auto event : events) {
389 for (auto event : events) {
386 sqpApp->catalogueController().removeEvent(event);
390 sqpApp->catalogueController().removeEvent(event);
387 impl->removeEvent(event, ui->treeView);
391 impl->removeEvent(event, ui->treeView);
388 }
392 }
393
394 emit this->eventsRemoved(events);
389 }
395 }
390 }
396 }
391 });
397 });
392
398
393 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueEventsWidget::emitSelection);
399 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueEventsWidget::emitSelection);
394 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
400 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
395 &CatalogueEventsWidget::emitSelection);
401 &CatalogueEventsWidget::emitSelection);
396
402
397 ui->btnRemove->setEnabled(false); // Disabled by default when nothing is selected
403 ui->btnRemove->setEnabled(false); // Disabled by default when nothing is selected
398 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
404 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
399 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
405 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
400 ui->btnChart->setEnabled(isNotMultiSelection);
406 ui->btnChart->setEnabled(isNotMultiSelection);
401 ui->btnTime->setEnabled(isNotMultiSelection);
407 ui->btnTime->setEnabled(isNotMultiSelection);
402
408
403 if (isNotMultiSelection && ui->btnTime->isChecked()) {
409 if (isNotMultiSelection && ui->btnTime->isChecked()) {
404 impl->updateForTimeMode(ui->treeView);
410 impl->updateForTimeMode(ui->treeView);
405 }
411 }
406 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
412 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
407 impl->updateForGraphMode(ui->treeView);
413 impl->updateForGraphMode(this);
408 }
414 }
409
415
410 QVector<std::shared_ptr<DBEvent> > events;
416 QVector<std::shared_ptr<DBEvent> > events;
411 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
417 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
412 impl->getSelectedItems(ui->treeView, events, eventProducts);
418 impl->getSelectedItems(ui->treeView, events, eventProducts);
413 ui->btnRemove->setEnabled(!events.isEmpty() && eventProducts.isEmpty());
419 ui->btnRemove->setEnabled(!events.isEmpty() && eventProducts.isEmpty());
414 });
420 });
415
421
416 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
422 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
417 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Tags,
423 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Tags,
418 QHeaderView::Stretch);
424 QHeaderView::Stretch);
419 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
425 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
420 QHeaderView::Fixed);
426 QHeaderView::Fixed);
421 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
427 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
422 QHeaderView::Interactive);
428 QHeaderView::Interactive);
423 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
429 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
424 VALIDATION_COLUMN_SIZE);
430 VALIDATION_COLUMN_SIZE);
425 ui->treeView->header()->setSortIndicatorShown(true);
431 ui->treeView->header()->setSortIndicatorShown(true);
426
432
427 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
433 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
428 auto allEvents = impl->m_Model->events();
434 auto allEvents = impl->m_Model->events();
429 for (auto event : allEvents) {
435 for (auto event : allEvents) {
430 setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event));
436 setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event));
431 }
437 }
432 });
438 });
433
439
434 populateWithAllEvents();
440 populateWithAllEvents();
435 }
441 }
436
442
437 CatalogueEventsWidget::~CatalogueEventsWidget()
443 CatalogueEventsWidget::~CatalogueEventsWidget()
438 {
444 {
439 delete ui;
445 delete ui;
440 }
446 }
441
447
442 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
448 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
443 {
449 {
444 impl->m_VisualizationWidget = visualization;
450 impl->m_VisualizationWidget = visualization;
445 }
451 }
446
452
447 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
453 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
448 {
454 {
449 impl->addEvent(event, ui->treeView);
455 impl->addEvent(event, ui->treeView);
450 }
456 }
451
457
452 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
458 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
453 {
459 {
454 impl->m_Model->refreshEvent(event);
460 impl->m_Model->refreshEvent(event);
455
461
456 auto eventIndex = impl->m_Model->indexOf(event);
462 auto eventIndex = impl->m_Model->indexOf(event);
457 auto validationIndex
463 auto validationIndex
458 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
464 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
459
465
460 if (validationIndex.isValid()) {
466 if (validationIndex.isValid()) {
461 if (hasChanges) {
467 if (hasChanges) {
462 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
468 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
463 auto widget = CatalogueExplorerHelper::buildValidationWidget(
469 auto widget = CatalogueExplorerHelper::buildValidationWidget(
464 ui->treeView,
470 ui->treeView,
465 [this, event]() {
471 [this, event]() {
466 sqpApp->catalogueController().saveEvent(event);
472 sqpApp->catalogueController().saveEvent(event);
467 setEventChanges(event, false);
473 setEventChanges(event, false);
468 },
474 },
469 [this, event]() {
475 [this, event]() {
470 bool removed = false;
476 bool removed = false;
471 sqpApp->catalogueController().discardEvent(event, removed);
477 sqpApp->catalogueController().discardEvent(event, removed);
472 if (removed) {
478 if (removed) {
473 impl->m_Model->removeEvent(event);
479 impl->m_Model->removeEvent(event);
474 }
480 }
475 else {
481 else {
476 setEventChanges(event, false);
482 setEventChanges(event, false);
477 impl->m_Model->refreshEvent(event, true);
483 impl->m_Model->refreshEvent(event, true);
478 }
484 }
479 emitSelection();
485 emitSelection();
480 });
486 });
481 ui->treeView->setIndexWidget(validationIndex, widget);
487 ui->treeView->setIndexWidget(validationIndex, widget);
482 }
488 }
483 }
489 }
484 else {
490 else {
485 // Note: the widget is destroyed
491 // Note: the widget is destroyed
486 ui->treeView->setIndexWidget(validationIndex, nullptr);
492 ui->treeView->setIndexWidget(validationIndex, nullptr);
487 }
493 }
488 }
494 }
489 else {
495 else {
490 qCWarning(LOG_CatalogueEventsWidget())
496 qCWarning(LOG_CatalogueEventsWidget())
491 << "setEventChanges: the event is not displayed in the model.";
497 << "setEventChanges: the event is not displayed in the model.";
492 }
498 }
493 }
499 }
494
500
495 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
501 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
496 {
502 {
497 return impl->m_DisplayedCatalogues;
503 return impl->m_DisplayedCatalogues;
498 }
504 }
499
505
500 bool CatalogueEventsWidget::isAllEventsDisplayed() const
506 bool CatalogueEventsWidget::isAllEventsDisplayed() const
501 {
507 {
502 return impl->m_AllEventDisplayed;
508 return impl->m_AllEventDisplayed;
503 }
509 }
504
510
505 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
511 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
506 {
512 {
507 return impl->m_Model->indexOf(event).isValid();
513 return impl->m_Model->indexOf(event).isValid();
508 }
514 }
509
515
516 void CatalogueEventsWidget::refreshEvent(const std::shared_ptr<DBEvent> &event)
517 {
518 impl->m_Model->refreshEvent(event, true);
519 }
520
510 void CatalogueEventsWidget::populateWithCatalogues(
521 void CatalogueEventsWidget::populateWithCatalogues(
511 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
522 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
512 {
523 {
513 impl->m_DisplayedCatalogues = catalogues;
524 impl->m_DisplayedCatalogues = catalogues;
514 impl->m_AllEventDisplayed = false;
525 impl->m_AllEventDisplayed = false;
515
526
516 QSet<QUuid> eventIds;
527 QSet<QUuid> eventIds;
517 QVector<std::shared_ptr<DBEvent> > events;
528 QVector<std::shared_ptr<DBEvent> > events;
518
529
519 for (auto catalogue : catalogues) {
530 for (auto catalogue : catalogues) {
520 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
531 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
521 for (auto event : catalogueEvents) {
532 for (auto event : catalogueEvents) {
522 if (!eventIds.contains(event->getUniqId())) {
533 if (!eventIds.contains(event->getUniqId())) {
523 events << event;
534 events << event;
524 eventIds.insert(event->getUniqId());
535 eventIds.insert(event->getUniqId());
525 }
536 }
526 }
537 }
527 }
538 }
528
539
529 impl->setEvents(events, this);
540 impl->setEvents(events, this);
530 }
541 }
531
542
532 void CatalogueEventsWidget::populateWithAllEvents()
543 void CatalogueEventsWidget::populateWithAllEvents()
533 {
544 {
534 impl->m_DisplayedCatalogues.clear();
545 impl->m_DisplayedCatalogues.clear();
535 impl->m_AllEventDisplayed = true;
546 impl->m_AllEventDisplayed = true;
536
547
537 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
548 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
538
549
539 QVector<std::shared_ptr<DBEvent> > events;
550 QVector<std::shared_ptr<DBEvent> > events;
540 for (auto event : allEvents) {
551 for (auto event : allEvents) {
541 events << event;
552 events << event;
542 }
553 }
543
554
544 impl->setEvents(events, this);
555 impl->setEvents(events, this);
545 }
556 }
546
557
547 void CatalogueEventsWidget::clear()
558 void CatalogueEventsWidget::clear()
548 {
559 {
549 impl->m_DisplayedCatalogues.clear();
560 impl->m_DisplayedCatalogues.clear();
550 impl->m_AllEventDisplayed = false;
561 impl->m_AllEventDisplayed = false;
551 impl->setEvents({}, this);
562 impl->setEvents({}, this);
552 }
563 }
553
564
554 void CatalogueEventsWidget::refresh()
565 void CatalogueEventsWidget::refresh()
555 {
566 {
556 if (isAllEventsDisplayed()) {
567 if (isAllEventsDisplayed()) {
557 populateWithAllEvents();
568 populateWithAllEvents();
558 }
569 }
559 else if (!impl->m_DisplayedCatalogues.isEmpty()) {
570 else if (!impl->m_DisplayedCatalogues.isEmpty()) {
560 populateWithCatalogues(impl->m_DisplayedCatalogues);
571 populateWithCatalogues(impl->m_DisplayedCatalogues);
561 }
572 }
562 }
573 }
563
574
564 void CatalogueEventsWidget::emitSelection()
575 void CatalogueEventsWidget::emitSelection()
565 {
576 {
566 QVector<std::shared_ptr<DBEvent> > events;
577 QVector<std::shared_ptr<DBEvent> > events;
567 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
578 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
568 impl->getSelectedItems(ui->treeView, events, eventProducts);
579 impl->getSelectedItems(ui->treeView, events, eventProducts);
569
580
570 if (!events.isEmpty() && eventProducts.isEmpty()) {
581 if (!events.isEmpty() && eventProducts.isEmpty()) {
571 emit eventsSelected(events);
582 emit eventsSelected(events);
572 }
583 }
573 else if (events.isEmpty() && !eventProducts.isEmpty()) {
584 else if (events.isEmpty() && !eventProducts.isEmpty()) {
574 emit eventProductsSelected(eventProducts);
585 emit eventProductsSelected(eventProducts);
575 }
586 }
576 else {
587 else {
577 emit selectionCleared();
588 emit selectionCleared();
578 }
589 }
579 }
590 }
@@ -1,126 +1,171
1 #include "Catalogue/CatalogueExplorer.h"
1 #include "Catalogue/CatalogueExplorer.h"
2 #include "ui_CatalogueExplorer.h"
2 #include "ui_CatalogueExplorer.h"
3
3
4 #include <Catalogue/CatalogueActionManager.h>
4 #include <Catalogue/CatalogueActionManager.h>
5 #include <Catalogue/CatalogueController.h>
5 #include <Catalogue/CatalogueController.h>
6 #include <SqpApplication.h>
6 #include <SqpApplication.h>
7 #include <Visualization/VisualizationGraphWidget.h>
8 #include <Visualization/VisualizationSelectionZoneItem.h>
7 #include <Visualization/VisualizationWidget.h>
9 #include <Visualization/VisualizationWidget.h>
8
10
9 #include <DBCatalogue.h>
11 #include <DBCatalogue.h>
10 #include <DBEvent.h>
12 #include <DBEvent.h>
13 #include <DBEventProduct.h>
14
15 #include <unordered_map>
11
16
12 struct CatalogueExplorer::CatalogueExplorerPrivate {
17 struct CatalogueExplorer::CatalogueExplorerPrivate {
13 CatalogueActionManager m_ActionManager;
18 CatalogueActionManager m_ActionManager;
19 std::unordered_map<std::shared_ptr<DBEvent>, QVector<VisualizationSelectionZoneItem *> >
20 m_SelectionZonesPerEvents;
14
21
15 CatalogueExplorerPrivate(CatalogueExplorer *catalogueExplorer)
22 CatalogueExplorerPrivate(CatalogueExplorer *catalogueExplorer)
16 : m_ActionManager(catalogueExplorer)
23 : m_ActionManager(catalogueExplorer)
17 {
24 {
18 }
25 }
19 };
26 };
20
27
21 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
28 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
22 : QDialog(parent, Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint),
29 : QDialog(parent, Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint),
23 ui(new Ui::CatalogueExplorer),
30 ui(new Ui::CatalogueExplorer),
24 impl{spimpl::make_unique_impl<CatalogueExplorerPrivate>(this)}
31 impl{spimpl::make_unique_impl<CatalogueExplorerPrivate>(this)}
25 {
32 {
26 ui->setupUi(this);
33 ui->setupUi(this);
27
34
28 impl->m_ActionManager.installSelectionZoneActions();
35 impl->m_ActionManager.installSelectionZoneActions();
29
36
37 // Updates events and inspector when something is selected in the catalogue widget
30 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto catalogues) {
38 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto catalogues) {
31 if (catalogues.count() == 1) {
39 if (catalogues.count() == 1) {
32 ui->inspector->setCatalogue(catalogues.first());
40 ui->inspector->setCatalogue(catalogues.first());
33 }
41 }
34 else {
42 else {
35 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
43 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
36 }
44 }
37
45
38 ui->events->populateWithCatalogues(catalogues);
46 ui->events->populateWithCatalogues(catalogues);
39 });
47 });
40
48
41 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databases) {
49 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databases) {
42 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
50 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
43 });
51 });
44
52
45 connect(ui->catalogues, &CatalogueSideBarWidget::trashSelected, [this]() {
53 connect(ui->catalogues, &CatalogueSideBarWidget::trashSelected, [this]() {
46 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
54 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
47 ui->events->clear();
55 ui->events->clear();
48 });
56 });
49
57
50 connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected, [this]() {
58 connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected, [this]() {
51 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
59 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
52 ui->events->populateWithAllEvents();
60 ui->events->populateWithAllEvents();
53 });
61 });
54
62
55 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databaseList) {
63 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databaseList) {
56 QVector<std::shared_ptr<DBCatalogue> > catalogueList;
64 QVector<std::shared_ptr<DBCatalogue> > catalogueList;
57 for (auto database : databaseList) {
65 for (auto database : databaseList) {
58 catalogueList.append(ui->catalogues->getCatalogues(database));
66 catalogueList.append(ui->catalogues->getCatalogues(database));
59 }
67 }
60 ui->events->populateWithCatalogues(catalogueList);
68 ui->events->populateWithCatalogues(catalogueList);
61 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
69 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
62 });
70 });
63
71
64 connect(ui->catalogues, &CatalogueSideBarWidget::selectionCleared, [this]() {
72 connect(ui->catalogues, &CatalogueSideBarWidget::selectionCleared, [this]() {
65 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
73 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
66 ui->events->clear();
74 ui->events->clear();
67 });
75 });
68
76
77 // Updates the inspectot when something is selected in the events
69 connect(ui->events, &CatalogueEventsWidget::eventsSelected, [this](auto events) {
78 connect(ui->events, &CatalogueEventsWidget::eventsSelected, [this](auto events) {
70 if (events.count() == 1) {
79 if (events.count() == 1) {
71 ui->inspector->setEvent(events.first());
80 ui->inspector->setEvent(events.first());
72 }
81 }
73 else {
82 else {
74 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
83 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
75 }
84 }
76 });
85 });
77
86
78 connect(ui->events, &CatalogueEventsWidget::eventProductsSelected, [this](auto eventProducts) {
87 connect(ui->events, &CatalogueEventsWidget::eventProductsSelected, [this](auto eventProducts) {
79 if (eventProducts.count() == 1) {
88 if (eventProducts.count() == 1) {
80 ui->inspector->setEventProduct(eventProducts.first().first,
89 ui->inspector->setEventProduct(eventProducts.first().first,
81 eventProducts.first().second);
90 eventProducts.first().second);
82 }
91 }
83 else {
92 else {
84 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
93 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
85 }
94 }
86 });
95 });
87
96
88 connect(ui->events, &CatalogueEventsWidget::selectionCleared,
97 connect(ui->events, &CatalogueEventsWidget::selectionCleared,
89 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
98 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
90
99
100 // Manage Selection Zones associated to events
101 connect(ui->events, &CatalogueEventsWidget::selectionZoneAdded,
102 [this](auto event, auto productId, auto zone) {
103 impl->m_SelectionZonesPerEvents[event] << zone;
104 connect(zone, &VisualizationSelectionZoneItem::rangeEdited,
105 [event, productId, this](auto range) {
106 auto productList = event->getEventProducts();
107 for (auto &product : productList) {
108 if (product.getProductId() == productId) {
109 product.setTStart(range.m_TStart);
110 product.setTEnd(range.m_TEnd);
111 }
112 }
113 event->setEventProducts(productList);
114 sqpApp->catalogueController().updateEvent(event);
115 ui->events->refreshEvent(event);
116 ui->events->setEventChanges(event, true);
117 ui->inspector->refresh();
118 });
119 });
120
121 connect(ui->events, &CatalogueEventsWidget::eventsRemoved, [this](auto events) {
122 for (auto event : events) {
123 auto associatedSelectionZonesIt = impl->m_SelectionZonesPerEvents.find(event);
124 if (associatedSelectionZonesIt != impl->m_SelectionZonesPerEvents.cend()) {
125 for (auto selectionZone : associatedSelectionZonesIt->second) {
126 auto parentGraph = selectionZone->parentGraphWidget();
127 parentGraph->removeSelectionZone(selectionZone);
128 }
129
130 impl->m_SelectionZonesPerEvents.erase(event);
131 }
132 }
133 });
134
135 // Updates changes from the inspector
91 connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated, [this](auto catalogue) {
136 connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated, [this](auto catalogue) {
92 sqpApp->catalogueController().updateCatalogue(catalogue);
137 sqpApp->catalogueController().updateCatalogue(catalogue);
93 ui->catalogues->setCatalogueChanges(catalogue, true);
138 ui->catalogues->setCatalogueChanges(catalogue, true);
94 });
139 });
95
140
96 connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated, [this](auto event) {
141 connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated, [this](auto event) {
97 sqpApp->catalogueController().updateEvent(event);
142 sqpApp->catalogueController().updateEvent(event);
98 ui->events->setEventChanges(event, true);
143 ui->events->setEventChanges(event, true);
99 });
144 });
100
145
101 connect(ui->inspector, &CatalogueInspectorWidget::eventProductUpdated,
146 connect(ui->inspector, &CatalogueInspectorWidget::eventProductUpdated,
102 [this](auto event, auto eventProduct) {
147 [this](auto event, auto eventProduct) {
103 sqpApp->catalogueController().updateEventProduct(eventProduct);
148 sqpApp->catalogueController().updateEventProduct(eventProduct);
104 ui->events->setEventChanges(event, true);
149 ui->events->setEventChanges(event, true);
105 });
150 });
106 }
151 }
107
152
108 CatalogueExplorer::~CatalogueExplorer()
153 CatalogueExplorer::~CatalogueExplorer()
109 {
154 {
110 delete ui;
155 delete ui;
111 }
156 }
112
157
113 void CatalogueExplorer::setVisualizationWidget(VisualizationWidget *visualization)
158 void CatalogueExplorer::setVisualizationWidget(VisualizationWidget *visualization)
114 {
159 {
115 ui->events->setVisualizationWidget(visualization);
160 ui->events->setVisualizationWidget(visualization);
116 }
161 }
117
162
118 CatalogueEventsWidget &CatalogueExplorer::eventsWidget() const
163 CatalogueEventsWidget &CatalogueExplorer::eventsWidget() const
119 {
164 {
120 return *ui->events;
165 return *ui->events;
121 }
166 }
122
167
123 CatalogueSideBarWidget &CatalogueExplorer::sideBarWidget() const
168 CatalogueSideBarWidget &CatalogueExplorer::sideBarWidget() const
124 {
169 {
125 return *ui->catalogues;
170 return *ui->catalogues;
126 }
171 }
@@ -1,211 +1,227
1 #include "Catalogue/CatalogueInspectorWidget.h"
1 #include "Catalogue/CatalogueInspectorWidget.h"
2 #include "ui_CatalogueInspectorWidget.h"
2 #include "ui_CatalogueInspectorWidget.h"
3
3
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5 #include <DBCatalogue.h>
5 #include <DBCatalogue.h>
6 #include <DBEvent.h>
6 #include <DBEvent.h>
7 #include <DBEventProduct.h>
7 #include <DBEventProduct.h>
8 #include <DBTag.h>
8 #include <DBTag.h>
9
9
10 struct CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate {
10 struct CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate {
11 std::shared_ptr<DBCatalogue> m_DisplayedCatalogue = nullptr;
11 std::shared_ptr<DBCatalogue> m_DisplayedCatalogue = nullptr;
12 std::shared_ptr<DBEvent> m_DisplayedEvent = nullptr;
12 std::shared_ptr<DBEvent> m_DisplayedEvent = nullptr;
13 std::shared_ptr<DBEventProduct> m_DisplayedEventProduct = nullptr;
13 std::shared_ptr<DBEventProduct> m_DisplayedEventProduct = nullptr;
14
14
15 void connectCatalogueUpdateSignals(CatalogueInspectorWidget *inspector,
15 void connectCatalogueUpdateSignals(CatalogueInspectorWidget *inspector,
16 Ui::CatalogueInspectorWidget *ui);
16 Ui::CatalogueInspectorWidget *ui);
17 void connectEventUpdateSignals(CatalogueInspectorWidget *inspector,
17 void connectEventUpdateSignals(CatalogueInspectorWidget *inspector,
18 Ui::CatalogueInspectorWidget *ui);
18 Ui::CatalogueInspectorWidget *ui);
19 };
19 };
20
20
21 CatalogueInspectorWidget::CatalogueInspectorWidget(QWidget *parent)
21 CatalogueInspectorWidget::CatalogueInspectorWidget(QWidget *parent)
22 : QWidget(parent),
22 : QWidget(parent),
23 ui(new Ui::CatalogueInspectorWidget),
23 ui(new Ui::CatalogueInspectorWidget),
24 impl{spimpl::make_unique_impl<CatalogueInspectorWidgetPrivate>()}
24 impl{spimpl::make_unique_impl<CatalogueInspectorWidgetPrivate>()}
25 {
25 {
26 ui->setupUi(this);
26 ui->setupUi(this);
27 showPage(Page::Empty);
27 showPage(Page::Empty);
28
28
29 impl->connectCatalogueUpdateSignals(this, ui);
29 impl->connectCatalogueUpdateSignals(this, ui);
30 impl->connectEventUpdateSignals(this, ui);
30 impl->connectEventUpdateSignals(this, ui);
31 }
31 }
32
32
33 CatalogueInspectorWidget::~CatalogueInspectorWidget()
33 CatalogueInspectorWidget::~CatalogueInspectorWidget()
34 {
34 {
35 delete ui;
35 delete ui;
36 }
36 }
37
37
38 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectCatalogueUpdateSignals(
38 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectCatalogueUpdateSignals(
39 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
39 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
40 {
40 {
41 connect(ui->leCatalogueName, &QLineEdit::editingFinished, [ui, inspector, this]() {
41 connect(ui->leCatalogueName, &QLineEdit::editingFinished, [ui, inspector, this]() {
42 if (ui->leCatalogueName->text() != m_DisplayedCatalogue->getName()) {
42 if (ui->leCatalogueName->text() != m_DisplayedCatalogue->getName()) {
43 m_DisplayedCatalogue->setName(ui->leCatalogueName->text());
43 m_DisplayedCatalogue->setName(ui->leCatalogueName->text());
44 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
44 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
45 }
45 }
46 });
46 });
47
47
48 connect(ui->leCatalogueAuthor, &QLineEdit::editingFinished, [ui, inspector, this]() {
48 connect(ui->leCatalogueAuthor, &QLineEdit::editingFinished, [ui, inspector, this]() {
49 if (ui->leCatalogueAuthor->text() != m_DisplayedCatalogue->getAuthor()) {
49 if (ui->leCatalogueAuthor->text() != m_DisplayedCatalogue->getAuthor()) {
50 m_DisplayedCatalogue->setAuthor(ui->leCatalogueAuthor->text());
50 m_DisplayedCatalogue->setAuthor(ui->leCatalogueAuthor->text());
51 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
51 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
52 }
52 }
53 });
53 });
54 }
54 }
55
55
56 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectEventUpdateSignals(
56 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectEventUpdateSignals(
57 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
57 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
58 {
58 {
59 connect(ui->leEventName, &QLineEdit::editingFinished, [ui, inspector, this]() {
59 connect(ui->leEventName, &QLineEdit::editingFinished, [ui, inspector, this]() {
60 if (ui->leEventName->text() != m_DisplayedEvent->getName()) {
60 if (ui->leEventName->text() != m_DisplayedEvent->getName()) {
61 m_DisplayedEvent->setName(ui->leEventName->text());
61 m_DisplayedEvent->setName(ui->leEventName->text());
62 emit inspector->eventUpdated(m_DisplayedEvent);
62 emit inspector->eventUpdated(m_DisplayedEvent);
63 }
63 }
64 });
64 });
65
65
66 connect(ui->leEventTags, &QLineEdit::editingFinished, [ui, inspector, this]() {
66 connect(ui->leEventTags, &QLineEdit::editingFinished, [ui, inspector, this]() {
67 auto tags = ui->leEventTags->text().split(QRegExp("\\s+"), QString::SkipEmptyParts);
67 auto tags = ui->leEventTags->text().split(QRegExp("\\s+"), QString::SkipEmptyParts);
68 std::list<QString> tagNames;
68 std::list<QString> tagNames;
69 for (auto tag : tags) {
69 for (auto tag : tags) {
70 tagNames.push_back(tag);
70 tagNames.push_back(tag);
71 }
71 }
72
72
73 if (m_DisplayedEvent->getTagsNames() != tagNames) {
73 if (m_DisplayedEvent->getTagsNames() != tagNames) {
74 m_DisplayedEvent->setTagsNames(tagNames);
74 m_DisplayedEvent->setTagsNames(tagNames);
75 emit inspector->eventUpdated(m_DisplayedEvent);
75 emit inspector->eventUpdated(m_DisplayedEvent);
76 }
76 }
77 });
77 });
78
78
79 connect(ui->leEventProduct, &QLineEdit::editingFinished, [ui, inspector, this]() {
79 connect(ui->leEventProduct, &QLineEdit::editingFinished, [ui, inspector, this]() {
80 if (ui->leEventProduct->text() != m_DisplayedEventProduct->getProductId()) {
80 if (ui->leEventProduct->text() != m_DisplayedEventProduct->getProductId()) {
81 auto oldProductId = m_DisplayedEventProduct->getProductId();
81 auto oldProductId = m_DisplayedEventProduct->getProductId();
82 m_DisplayedEventProduct->setProductId(ui->leEventProduct->text());
82 m_DisplayedEventProduct->setProductId(ui->leEventProduct->text());
83
83
84 auto eventProducts = m_DisplayedEvent->getEventProducts();
84 auto eventProducts = m_DisplayedEvent->getEventProducts();
85 for (auto &eventProduct : eventProducts) {
85 for (auto &eventProduct : eventProducts) {
86 if (eventProduct.getProductId() == oldProductId) {
86 if (eventProduct.getProductId() == oldProductId) {
87 eventProduct.setProductId(m_DisplayedEventProduct->getProductId());
87 eventProduct.setProductId(m_DisplayedEventProduct->getProductId());
88 }
88 }
89 }
89 }
90 m_DisplayedEvent->setEventProducts(eventProducts);
90 m_DisplayedEvent->setEventProducts(eventProducts);
91
91
92 emit inspector->eventUpdated(m_DisplayedEvent);
92 emit inspector->eventUpdated(m_DisplayedEvent);
93 }
93 }
94 });
94 });
95
95
96 connect(ui->dateTimeEventTStart, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
96 connect(ui->dateTimeEventTStart, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
97 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTStart->dateTime());
97 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTStart->dateTime());
98 if (time != m_DisplayedEventProduct->getTStart()) {
98 if (time != m_DisplayedEventProduct->getTStart()) {
99 m_DisplayedEventProduct->setTStart(time);
99 m_DisplayedEventProduct->setTStart(time);
100
100
101 auto eventProducts = m_DisplayedEvent->getEventProducts();
101 auto eventProducts = m_DisplayedEvent->getEventProducts();
102 for (auto &eventProduct : eventProducts) {
102 for (auto &eventProduct : eventProducts) {
103 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
103 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
104 eventProduct.setTStart(m_DisplayedEventProduct->getTStart());
104 eventProduct.setTStart(m_DisplayedEventProduct->getTStart());
105 }
105 }
106 }
106 }
107 m_DisplayedEvent->setEventProducts(eventProducts);
107 m_DisplayedEvent->setEventProducts(eventProducts);
108
108
109 emit inspector->eventUpdated(m_DisplayedEvent);
109 emit inspector->eventUpdated(m_DisplayedEvent);
110 }
110 }
111 });
111 });
112
112
113 connect(ui->dateTimeEventTEnd, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
113 connect(ui->dateTimeEventTEnd, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
114 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTEnd->dateTime());
114 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTEnd->dateTime());
115 if (time != m_DisplayedEventProduct->getTEnd()) {
115 if (time != m_DisplayedEventProduct->getTEnd()) {
116 m_DisplayedEventProduct->setTEnd(time);
116 m_DisplayedEventProduct->setTEnd(time);
117
117
118 auto eventProducts = m_DisplayedEvent->getEventProducts();
118 auto eventProducts = m_DisplayedEvent->getEventProducts();
119 for (auto &eventProduct : eventProducts) {
119 for (auto &eventProduct : eventProducts) {
120 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
120 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
121 eventProduct.setTEnd(m_DisplayedEventProduct->getTEnd());
121 eventProduct.setTEnd(m_DisplayedEventProduct->getTEnd());
122 }
122 }
123 }
123 }
124 m_DisplayedEvent->setEventProducts(eventProducts);
124 m_DisplayedEvent->setEventProducts(eventProducts);
125
125
126 emit inspector->eventUpdated(m_DisplayedEvent);
126 emit inspector->eventUpdated(m_DisplayedEvent);
127 }
127 }
128 });
128 });
129 }
129 }
130
130
131 void CatalogueInspectorWidget::showPage(CatalogueInspectorWidget::Page page)
131 void CatalogueInspectorWidget::showPage(CatalogueInspectorWidget::Page page)
132 {
132 {
133 ui->stackedWidget->setCurrentIndex(static_cast<int>(page));
133 ui->stackedWidget->setCurrentIndex(static_cast<int>(page));
134 }
134 }
135
135
136 CatalogueInspectorWidget::Page CatalogueInspectorWidget::currentPage() const
136 CatalogueInspectorWidget::Page CatalogueInspectorWidget::currentPage() const
137 {
137 {
138 return static_cast<Page>(ui->stackedWidget->currentIndex());
138 return static_cast<Page>(ui->stackedWidget->currentIndex());
139 }
139 }
140
140
141 void CatalogueInspectorWidget::setEvent(const std::shared_ptr<DBEvent> &event)
141 void CatalogueInspectorWidget::setEvent(const std::shared_ptr<DBEvent> &event)
142 {
142 {
143 impl->m_DisplayedEvent = event;
143 impl->m_DisplayedEvent = event;
144
144
145 blockSignals(true);
145 blockSignals(true);
146
146
147 showPage(Page::EventProperties);
147 showPage(Page::EventProperties);
148 ui->leEventName->setEnabled(true);
148 ui->leEventName->setEnabled(true);
149 ui->leEventName->setText(event->getName());
149 ui->leEventName->setText(event->getName());
150 ui->leEventProduct->setEnabled(false);
150 ui->leEventProduct->setEnabled(false);
151 ui->leEventProduct->setText(
151 ui->leEventProduct->setText(
152 QString::number(event->getEventProducts().size()).append(" product(s)"));
152 QString::number(event->getEventProducts().size()).append(" product(s)"));
153
153
154 QString tagList;
154 QString tagList;
155 auto tags = event->getTagsNames();
155 auto tags = event->getTagsNames();
156 for (auto tag : tags) {
156 for (auto tag : tags) {
157 tagList += tag;
157 tagList += tag;
158 tagList += ' ';
158 tagList += ' ';
159 }
159 }
160
160
161 ui->leEventTags->setEnabled(true);
161 ui->leEventTags->setEnabled(true);
162 ui->leEventTags->setText(tagList);
162 ui->leEventTags->setText(tagList);
163
163
164 ui->dateTimeEventTStart->setEnabled(false);
164 ui->dateTimeEventTStart->setEnabled(false);
165 ui->dateTimeEventTEnd->setEnabled(false);
165 ui->dateTimeEventTEnd->setEnabled(false);
166
166
167 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(event->getTStart()));
167 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(event->getTStart()));
168 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(event->getTEnd()));
168 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(event->getTEnd()));
169
169
170 blockSignals(false);
170 blockSignals(false);
171 }
171 }
172
172
173 void CatalogueInspectorWidget::setEventProduct(const std::shared_ptr<DBEvent> &event,
173 void CatalogueInspectorWidget::setEventProduct(const std::shared_ptr<DBEvent> &event,
174 const std::shared_ptr<DBEventProduct> &eventProduct)
174 const std::shared_ptr<DBEventProduct> &eventProduct)
175 {
175 {
176
176
177 impl->m_DisplayedEvent = event;
177 impl->m_DisplayedEvent = event;
178 impl->m_DisplayedEventProduct = eventProduct;
178 impl->m_DisplayedEventProduct = eventProduct;
179
179
180 blockSignals(true);
180 blockSignals(true);
181
181
182 showPage(Page::EventProperties);
182 showPage(Page::EventProperties);
183 ui->leEventName->setEnabled(false);
183 ui->leEventName->setEnabled(false);
184 ui->leEventName->setText(event->getName());
184 ui->leEventName->setText(event->getName());
185 ui->leEventProduct->setEnabled(false);
185 ui->leEventProduct->setEnabled(false);
186 ui->leEventProduct->setText(eventProduct->getProductId());
186 ui->leEventProduct->setText(eventProduct->getProductId());
187
187
188 ui->leEventTags->setEnabled(false);
188 ui->leEventTags->setEnabled(false);
189 ui->leEventTags->clear();
189 ui->leEventTags->clear();
190
190
191 ui->dateTimeEventTStart->setEnabled(true);
191 ui->dateTimeEventTStart->setEnabled(true);
192 ui->dateTimeEventTEnd->setEnabled(true);
192 ui->dateTimeEventTEnd->setEnabled(true);
193
193
194 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(eventProduct->getTStart()));
194 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(eventProduct->getTStart()));
195 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(eventProduct->getTEnd()));
195 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(eventProduct->getTEnd()));
196
196
197 blockSignals(false);
197 blockSignals(false);
198 }
198 }
199
199
200 void CatalogueInspectorWidget::setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue)
200 void CatalogueInspectorWidget::setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue)
201 {
201 {
202 impl->m_DisplayedCatalogue = catalogue;
202 impl->m_DisplayedCatalogue = catalogue;
203
203
204 blockSignals(true);
204 blockSignals(true);
205
205
206 showPage(Page::CatalogueProperties);
206 showPage(Page::CatalogueProperties);
207 ui->leCatalogueName->setText(catalogue->getName());
207 ui->leCatalogueName->setText(catalogue->getName());
208 ui->leCatalogueAuthor->setText(catalogue->getAuthor());
208 ui->leCatalogueAuthor->setText(catalogue->getAuthor());
209
209
210 blockSignals(false);
210 blockSignals(false);
211 }
211 }
212
213 void CatalogueInspectorWidget::refresh()
214 {
215 switch (static_cast<Page>(ui->stackedWidget->currentIndex())) {
216 case Page::CatalogueProperties:
217 setCatalogue(impl->m_DisplayedCatalogue);
218 break;
219 case Page::EventProperties: {
220 auto isEventShowed = ui->leEventName->isEnabled();
221 setEvent(impl->m_DisplayedEvent);
222 if (!isEventShowed && impl->m_DisplayedEvent) {
223 setEventProduct(impl->m_DisplayedEvent, impl->m_DisplayedEventProduct);
224 }
225 }
226 }
227 }
@@ -1,1041 +1,1055
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/VisualizationMultiZoneSelectionDialog.h"
7 #include "Visualization/VisualizationMultiZoneSelectionDialog.h"
8 #include "Visualization/VisualizationSelectionZoneItem.h"
8 #include "Visualization/VisualizationSelectionZoneItem.h"
9 #include "Visualization/VisualizationSelectionZoneManager.h"
9 #include "Visualization/VisualizationSelectionZoneManager.h"
10 #include "Visualization/VisualizationWidget.h"
10 #include "Visualization/VisualizationWidget.h"
11 #include "Visualization/VisualizationZoneWidget.h"
11 #include "Visualization/VisualizationZoneWidget.h"
12 #include "ui_VisualizationGraphWidget.h"
12 #include "ui_VisualizationGraphWidget.h"
13
13
14 #include <Actions/ActionsGuiController.h>
14 #include <Actions/ActionsGuiController.h>
15 #include <Common/MimeTypesDef.h>
15 #include <Common/MimeTypesDef.h>
16 #include <Data/ArrayData.h>
16 #include <Data/ArrayData.h>
17 #include <Data/IDataSeries.h>
17 #include <Data/IDataSeries.h>
18 #include <Data/SpectrogramSeries.h>
18 #include <Data/SpectrogramSeries.h>
19 #include <DragAndDrop/DragDropGuiController.h>
19 #include <DragAndDrop/DragDropGuiController.h>
20 #include <Settings/SqpSettingsDefs.h>
20 #include <Settings/SqpSettingsDefs.h>
21 #include <SqpApplication.h>
21 #include <SqpApplication.h>
22 #include <Time/TimeController.h>
22 #include <Time/TimeController.h>
23 #include <Variable/Variable.h>
23 #include <Variable/Variable.h>
24 #include <Variable/VariableController.h>
24 #include <Variable/VariableController.h>
25
25
26 #include <unordered_map>
26 #include <unordered_map>
27
27
28 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
28 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
29
29
30 namespace {
30 namespace {
31
31
32 /// Key pressed to enable drag&drop in all modes
32 /// Key pressed to enable drag&drop in all modes
33 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
33 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
34
34
35 /// Key pressed to enable zoom on horizontal axis
35 /// Key pressed to enable zoom on horizontal axis
36 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
36 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
37
37
38 /// Key pressed to enable zoom on vertical axis
38 /// Key pressed to enable zoom on vertical axis
39 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
39 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
40
40
41 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
41 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
42 const auto PAN_SPEED = 5;
42 const auto PAN_SPEED = 5;
43
43
44 /// Key pressed to enable a calibration pan
44 /// Key pressed to enable a calibration pan
45 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
45 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
46
46
47 /// Key pressed to enable multi selection of selection zones
47 /// Key pressed to enable multi selection of selection zones
48 const auto MULTI_ZONE_SELECTION_MODIFIER = Qt::ControlModifier;
48 const auto MULTI_ZONE_SELECTION_MODIFIER = Qt::ControlModifier;
49
49
50 /// Minimum size for the zoom box, in percentage of the axis range
50 /// Minimum size for the zoom box, in percentage of the axis range
51 const auto ZOOM_BOX_MIN_SIZE = 0.8;
51 const auto ZOOM_BOX_MIN_SIZE = 0.8;
52
52
53 /// Format of the dates appearing in the label of a cursor
53 /// Format of the dates appearing in the label of a cursor
54 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
54 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
55
55
56 } // namespace
56 } // namespace
57
57
58 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
58 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
59
59
60 explicit VisualizationGraphWidgetPrivate(const QString &name)
60 explicit VisualizationGraphWidgetPrivate(const QString &name)
61 : m_Name{name},
61 : m_Name{name},
62 m_Flags{GraphFlag::EnableAll},
62 m_Flags{GraphFlag::EnableAll},
63 m_IsCalibration{false},
63 m_IsCalibration{false},
64 m_RenderingDelegate{nullptr}
64 m_RenderingDelegate{nullptr}
65 {
65 {
66 }
66 }
67
67
68 void updateData(PlottablesMap &plottables, std::shared_ptr<Variable> variable,
68 void updateData(PlottablesMap &plottables, std::shared_ptr<Variable> variable,
69 const SqpRange &range)
69 const SqpRange &range)
70 {
70 {
71 VisualizationGraphHelper::updateData(plottables, variable, range);
71 VisualizationGraphHelper::updateData(plottables, variable, range);
72
72
73 // Prevents that data has changed to update rendering
73 // Prevents that data has changed to update rendering
74 m_RenderingDelegate->onPlotUpdated();
74 m_RenderingDelegate->onPlotUpdated();
75 }
75 }
76
76
77 QString m_Name;
77 QString m_Name;
78 // 1 variable -> n qcpplot
78 // 1 variable -> n qcpplot
79 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
79 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
80 GraphFlags m_Flags;
80 GraphFlags m_Flags;
81 bool m_IsCalibration;
81 bool m_IsCalibration;
82 /// Delegate used to attach rendering features to the plot
82 /// Delegate used to attach rendering features to the plot
83 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
83 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
84
84
85 QCPItemRect *m_DrawingZoomRect = nullptr;
85 QCPItemRect *m_DrawingZoomRect = nullptr;
86 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
86 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
87
87
88 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
88 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
89 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
89 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
90
90
91 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
91 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
92 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
92 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
93 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
93 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
94
94
95 bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even
95 bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even
96
96
97 bool m_VariableAutoRangeOnInit = true;
97 bool m_VariableAutoRangeOnInit = true;
98
98
99 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
99 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
100 {
100 {
101 removeDrawingRect(plot);
101 removeDrawingRect(plot);
102
102
103 auto axisPos = posToAxisPos(pos, plot);
103 auto axisPos = posToAxisPos(pos, plot);
104
104
105 m_DrawingZoomRect = new QCPItemRect{&plot};
105 m_DrawingZoomRect = new QCPItemRect{&plot};
106 QPen p;
106 QPen p;
107 p.setWidth(2);
107 p.setWidth(2);
108 m_DrawingZoomRect->setPen(p);
108 m_DrawingZoomRect->setPen(p);
109
109
110 m_DrawingZoomRect->topLeft->setCoords(axisPos);
110 m_DrawingZoomRect->topLeft->setCoords(axisPos);
111 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
111 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
112 }
112 }
113
113
114 void removeDrawingRect(QCustomPlot &plot)
114 void removeDrawingRect(QCustomPlot &plot)
115 {
115 {
116 if (m_DrawingZoomRect) {
116 if (m_DrawingZoomRect) {
117 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
117 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
118 m_DrawingZoomRect = nullptr;
118 m_DrawingZoomRect = nullptr;
119 plot.replot(QCustomPlot::rpQueuedReplot);
119 plot.replot(QCustomPlot::rpQueuedReplot);
120 }
120 }
121 }
121 }
122
122
123 void startDrawingZone(const QPoint &pos, VisualizationGraphWidget *graph)
123 void startDrawingZone(const QPoint &pos, VisualizationGraphWidget *graph)
124 {
124 {
125 endDrawingZone(graph);
125 endDrawingZone(graph);
126
126
127 auto axisPos = posToAxisPos(pos, graph->plot());
127 auto axisPos = posToAxisPos(pos, graph->plot());
128
128
129 m_DrawingZone = new VisualizationSelectionZoneItem{&graph->plot()};
129 m_DrawingZone = new VisualizationSelectionZoneItem{&graph->plot()};
130 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
130 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
131 m_DrawingZone->setEditionEnabled(false);
131 m_DrawingZone->setEditionEnabled(false);
132 }
132 }
133
133
134 void endDrawingZone(VisualizationGraphWidget *graph)
134 void endDrawingZone(VisualizationGraphWidget *graph)
135 {
135 {
136 if (m_DrawingZone) {
136 if (m_DrawingZone) {
137 auto drawingZoneRange = m_DrawingZone->range();
137 auto drawingZoneRange = m_DrawingZone->range();
138 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
138 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
139 m_DrawingZone->setEditionEnabled(true);
139 m_DrawingZone->setEditionEnabled(true);
140 addSelectionZone(m_DrawingZone);
140 addSelectionZone(m_DrawingZone);
141 }
141 }
142 else {
142 else {
143 graph->plot().removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
143 graph->plot().removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
144 }
144 }
145
145
146 graph->plot().replot(QCustomPlot::rpQueuedReplot);
146 graph->plot().replot(QCustomPlot::rpQueuedReplot);
147 m_DrawingZone = nullptr;
147 m_DrawingZone = nullptr;
148 }
148 }
149 }
149 }
150
150
151 void setSelectionZonesEditionEnabled(bool value)
151 void setSelectionZonesEditionEnabled(bool value)
152 {
152 {
153 for (auto s : m_SelectionZones) {
153 for (auto s : m_SelectionZones) {
154 s->setEditionEnabled(value);
154 s->setEditionEnabled(value);
155 }
155 }
156 }
156 }
157
157
158 void addSelectionZone(VisualizationSelectionZoneItem *zone) { m_SelectionZones << zone; }
158 void addSelectionZone(VisualizationSelectionZoneItem *zone) { m_SelectionZones << zone; }
159
159
160 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
160 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
161 const QCustomPlot &plot) const
161 const QCustomPlot &plot) const
162 {
162 {
163 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
163 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
164 auto minDistanceToZone = -1;
164 auto minDistanceToZone = -1;
165 for (auto zone : m_SelectionZones) {
165 for (auto zone : m_SelectionZones) {
166 auto distanceToZone = zone->selectTest(pos, false);
166 auto distanceToZone = zone->selectTest(pos, false);
167 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
167 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
168 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
168 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
169 selectionZoneItemUnderCursor = zone;
169 selectionZoneItemUnderCursor = zone;
170 }
170 }
171 }
171 }
172
172
173 return selectionZoneItemUnderCursor;
173 return selectionZoneItemUnderCursor;
174 }
174 }
175
175
176 QVector<VisualizationSelectionZoneItem *> selectionZonesAt(const QPoint &pos,
176 QVector<VisualizationSelectionZoneItem *> selectionZonesAt(const QPoint &pos,
177 const QCustomPlot &plot) const
177 const QCustomPlot &plot) const
178 {
178 {
179 QVector<VisualizationSelectionZoneItem *> zones;
179 QVector<VisualizationSelectionZoneItem *> zones;
180 for (auto zone : m_SelectionZones) {
180 for (auto zone : m_SelectionZones) {
181 auto distanceToZone = zone->selectTest(pos, false);
181 auto distanceToZone = zone->selectTest(pos, false);
182 if (distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
182 if (distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
183 zones << zone;
183 zones << zone;
184 }
184 }
185 }
185 }
186
186
187 return zones;
187 return zones;
188 }
188 }
189
189
190 void moveSelectionZoneOnTop(VisualizationSelectionZoneItem *zone, QCustomPlot &plot)
190 void moveSelectionZoneOnTop(VisualizationSelectionZoneItem *zone, QCustomPlot &plot)
191 {
191 {
192 if (!m_SelectionZones.isEmpty() && m_SelectionZones.last() != zone) {
192 if (!m_SelectionZones.isEmpty() && m_SelectionZones.last() != zone) {
193 zone->moveToTop();
193 zone->moveToTop();
194 m_SelectionZones.removeAll(zone);
194 m_SelectionZones.removeAll(zone);
195 m_SelectionZones.append(zone);
195 m_SelectionZones.append(zone);
196 }
196 }
197 }
197 }
198
198
199 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
199 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
200 {
200 {
201 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
201 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
202 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
202 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
203 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
203 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
204 }
204 }
205
205
206 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
206 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
207 {
207 {
208 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
208 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
209 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
209 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
210 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
210 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
211 }
211 }
212 };
212 };
213
213
214 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
214 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
215 : VisualizationDragWidget{parent},
215 : VisualizationDragWidget{parent},
216 ui{new Ui::VisualizationGraphWidget},
216 ui{new Ui::VisualizationGraphWidget},
217 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
217 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
218 {
218 {
219 ui->setupUi(this);
219 ui->setupUi(this);
220
220
221 // 'Close' options : widget is deleted when closed
221 // 'Close' options : widget is deleted when closed
222 setAttribute(Qt::WA_DeleteOnClose);
222 setAttribute(Qt::WA_DeleteOnClose);
223
223
224 // Set qcpplot properties :
224 // Set qcpplot properties :
225 // - zoom is enabled
225 // - zoom is enabled
226 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
226 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
227 ui->widget->setInteractions(QCP::iRangeZoom);
227 ui->widget->setInteractions(QCP::iRangeZoom);
228 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
228 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
229
229
230 // The delegate must be initialized after the ui as it uses the plot
230 // The delegate must be initialized after the ui as it uses the plot
231 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
231 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
232
232
233 // Init the cursors
233 // Init the cursors
234 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
234 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
235 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
235 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
236 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
236 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
237 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
237 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
238
238
239 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
239 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
240 connect(ui->widget, &QCustomPlot::mouseRelease, this,
240 connect(ui->widget, &QCustomPlot::mouseRelease, this,
241 &VisualizationGraphWidget::onMouseRelease);
241 &VisualizationGraphWidget::onMouseRelease);
242 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
242 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
243 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
243 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
244 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
244 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
245 &VisualizationGraphWidget::onMouseDoubleClick);
245 &VisualizationGraphWidget::onMouseDoubleClick);
246 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
246 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
247 &QCPAxis::rangeChanged),
247 &QCPAxis::rangeChanged),
248 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
248 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
249
249
250 // Activates menu when right clicking on the graph
250 // Activates menu when right clicking on the graph
251 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
251 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
252 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
252 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
253 &VisualizationGraphWidget::onGraphMenuRequested);
253 &VisualizationGraphWidget::onGraphMenuRequested);
254
254
255 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
255 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
256 &VariableController::onRequestDataLoading);
256 &VariableController::onRequestDataLoading);
257
257
258 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
258 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
259 &VisualizationGraphWidget::onUpdateVarDisplaying);
259 &VisualizationGraphWidget::onUpdateVarDisplaying);
260
260
261 #ifdef Q_OS_MAC
261 #ifdef Q_OS_MAC
262 plot().setPlottingHint(QCP::phFastPolylines, true);
262 plot().setPlottingHint(QCP::phFastPolylines, true);
263 #endif
263 #endif
264 }
264 }
265
265
266
266
267 VisualizationGraphWidget::~VisualizationGraphWidget()
267 VisualizationGraphWidget::~VisualizationGraphWidget()
268 {
268 {
269 delete ui;
269 delete ui;
270 }
270 }
271
271
272 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
272 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
273 {
273 {
274 auto parent = parentWidget();
274 auto parent = parentWidget();
275 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
275 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
276 parent = parent->parentWidget();
276 parent = parent->parentWidget();
277 }
277 }
278
278
279 return qobject_cast<VisualizationZoneWidget *>(parent);
279 return qobject_cast<VisualizationZoneWidget *>(parent);
280 }
280 }
281
281
282 VisualizationWidget *VisualizationGraphWidget::parentVisualizationWidget() const
282 VisualizationWidget *VisualizationGraphWidget::parentVisualizationWidget() const
283 {
283 {
284 auto parent = parentWidget();
284 auto parent = parentWidget();
285 while (parent != nullptr && !qobject_cast<VisualizationWidget *>(parent)) {
285 while (parent != nullptr && !qobject_cast<VisualizationWidget *>(parent)) {
286 parent = parent->parentWidget();
286 parent = parent->parentWidget();
287 }
287 }
288
288
289 return qobject_cast<VisualizationWidget *>(parent);
289 return qobject_cast<VisualizationWidget *>(parent);
290 }
290 }
291
291
292 void VisualizationGraphWidget::setFlags(GraphFlags flags)
292 void VisualizationGraphWidget::setFlags(GraphFlags flags)
293 {
293 {
294 impl->m_Flags = std::move(flags);
294 impl->m_Flags = std::move(flags);
295 }
295 }
296
296
297 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
297 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
298 {
298 {
299 /// Lambda used to set graph's units and range according to the variable passed in parameter
299 /// Lambda used to set graph's units and range according to the variable passed in parameter
300 auto loadRange = [this](std::shared_ptr<Variable> variable, const SqpRange &range) {
300 auto loadRange = [this](std::shared_ptr<Variable> variable, const SqpRange &range) {
301 impl->m_RenderingDelegate->setAxesUnits(*variable);
301 impl->m_RenderingDelegate->setAxesUnits(*variable);
302
302
303 this->setFlags(GraphFlag::DisableAll);
303 this->setFlags(GraphFlag::DisableAll);
304 setGraphRange(range);
304 setGraphRange(range);
305 this->setFlags(GraphFlag::EnableAll);
305 this->setFlags(GraphFlag::EnableAll);
306
306
307 emit requestDataLoading({variable}, range, false);
307 emit requestDataLoading({variable}, range, false);
308 };
308 };
309
309
310 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
310 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
311
311
312 // Calls update of graph's range and units when the data of the variable have been initialized.
312 // Calls update of graph's range and units when the data of the variable have been initialized.
313 // Note: we use QueuedConnection here as the update event must be called in the UI thread
313 // Note: we use QueuedConnection here as the update event must be called in the UI thread
314 connect(variable.get(), &Variable::dataInitialized, this,
314 connect(variable.get(), &Variable::dataInitialized, this,
315 [ varW = std::weak_ptr<Variable>{variable}, range, loadRange, this ]() {
315 [ varW = std::weak_ptr<Variable>{variable}, range, loadRange, this ]() {
316 if (auto var = varW.lock()) {
316 if (auto var = varW.lock()) {
317 // If the variable is the first added in the graph, we load its range
317 // If the variable is the first added in the graph, we load its range
318 auto firstVariableInGraph = range == INVALID_RANGE;
318 auto firstVariableInGraph = range == INVALID_RANGE;
319 auto loadedRange = graphRange();
319 auto loadedRange = graphRange();
320 if (impl->m_VariableAutoRangeOnInit) {
320 if (impl->m_VariableAutoRangeOnInit) {
321 loadedRange = firstVariableInGraph ? var->range() : range;
321 loadedRange = firstVariableInGraph ? var->range() : range;
322 }
322 }
323 loadRange(var, loadedRange);
323 loadRange(var, loadedRange);
324 setYRange(var);
324 setYRange(var);
325 }
325 }
326 },
326 },
327 Qt::QueuedConnection);
327 Qt::QueuedConnection);
328
328
329 // Uses delegate to create the qcpplot components according to the variable
329 // Uses delegate to create the qcpplot components according to the variable
330 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
330 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
331
331
332 // Sets graph properties
332 // Sets graph properties
333 impl->m_RenderingDelegate->setGraphProperties(*variable, createdPlottables);
333 impl->m_RenderingDelegate->setGraphProperties(*variable, createdPlottables);
334
334
335 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
335 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
336
336
337 // If the variable already has its data loaded, load its units and its range in the graph
337 // If the variable already has its data loaded, load its units and its range in the graph
338 if (variable->dataSeries() != nullptr) {
338 if (variable->dataSeries() != nullptr) {
339 loadRange(variable, range);
339 loadRange(variable, range);
340 }
340 }
341
341
342 emit variableAdded(variable);
342 emit variableAdded(variable);
343 }
343 }
344
344
345 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
345 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
346 {
346 {
347 // Each component associated to the variable :
347 // Each component associated to the variable :
348 // - is removed from qcpplot (which deletes it)
348 // - is removed from qcpplot (which deletes it)
349 // - is no longer referenced in the map
349 // - is no longer referenced in the map
350 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
350 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
351 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
351 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
352 emit variableAboutToBeRemoved(variable);
352 emit variableAboutToBeRemoved(variable);
353
353
354 auto &plottablesMap = variableIt->second;
354 auto &plottablesMap = variableIt->second;
355
355
356 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
356 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
357 plottableIt != plottableEnd;) {
357 plottableIt != plottableEnd;) {
358 ui->widget->removePlottable(plottableIt->second);
358 ui->widget->removePlottable(plottableIt->second);
359 plottableIt = plottablesMap.erase(plottableIt);
359 plottableIt = plottablesMap.erase(plottableIt);
360 }
360 }
361
361
362 impl->m_VariableToPlotMultiMap.erase(variableIt);
362 impl->m_VariableToPlotMultiMap.erase(variableIt);
363 }
363 }
364
364
365 // Updates graph
365 // Updates graph
366 ui->widget->replot();
366 ui->widget->replot();
367 }
367 }
368
368
369 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
369 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
370 {
370 {
371 auto variables = QList<std::shared_ptr<Variable> >{};
371 auto variables = QList<std::shared_ptr<Variable> >{};
372 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
372 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
373 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
373 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
374 variables << it->first;
374 variables << it->first;
375 }
375 }
376
376
377 return variables;
377 return variables;
378 }
378 }
379
379
380 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
380 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
381 {
381 {
382 if (!variable) {
382 if (!variable) {
383 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
383 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
384 return;
384 return;
385 }
385 }
386
386
387 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
387 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
388 }
388 }
389
389
390 SqpRange VisualizationGraphWidget::graphRange() const noexcept
390 SqpRange VisualizationGraphWidget::graphRange() const noexcept
391 {
391 {
392 auto graphRange = ui->widget->xAxis->range();
392 auto graphRange = ui->widget->xAxis->range();
393 return SqpRange{graphRange.lower, graphRange.upper};
393 return SqpRange{graphRange.lower, graphRange.upper};
394 }
394 }
395
395
396 void VisualizationGraphWidget::setGraphRange(const SqpRange &range, bool calibration)
396 void VisualizationGraphWidget::setGraphRange(const SqpRange &range, bool calibration)
397 {
397 {
398 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
398 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
399
399
400 if (calibration) {
400 if (calibration) {
401 impl->m_IsCalibration = true;
401 impl->m_IsCalibration = true;
402 }
402 }
403
403
404 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
404 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
405 ui->widget->replot();
405 ui->widget->replot();
406
406
407 if (calibration) {
407 if (calibration) {
408 impl->m_IsCalibration = false;
408 impl->m_IsCalibration = false;
409 }
409 }
410
410
411 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
411 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
412 }
412 }
413
413
414 void VisualizationGraphWidget::setAutoRangeOnVariableInitialization(bool value)
414 void VisualizationGraphWidget::setAutoRangeOnVariableInitialization(bool value)
415 {
415 {
416 impl->m_VariableAutoRangeOnInit = value;
416 impl->m_VariableAutoRangeOnInit = value;
417 }
417 }
418
418
419 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
419 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
420 {
420 {
421 QVector<SqpRange> ranges;
421 QVector<SqpRange> ranges;
422 for (auto zone : impl->m_SelectionZones) {
422 for (auto zone : impl->m_SelectionZones) {
423 ranges << zone->range();
423 ranges << zone->range();
424 }
424 }
425
425
426 return ranges;
426 return ranges;
427 }
427 }
428
428
429 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges)
429 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges)
430 {
430 {
431 for (const auto &range : ranges) {
431 for (const auto &range : ranges) {
432 // note: ownership is transfered to QCustomPlot
432 // note: ownership is transfered to QCustomPlot
433 auto zone = new VisualizationSelectionZoneItem(&plot());
433 auto zone = new VisualizationSelectionZoneItem(&plot());
434 zone->setRange(range.m_TStart, range.m_TEnd);
434 zone->setRange(range.m_TStart, range.m_TEnd);
435 impl->addSelectionZone(zone);
435 impl->addSelectionZone(zone);
436 }
436 }
437
437
438 plot().replot(QCustomPlot::rpQueuedReplot);
438 plot().replot(QCustomPlot::rpQueuedReplot);
439 }
439 }
440
440
441 VisualizationSelectionZoneItem *VisualizationGraphWidget::addSelectionZone(const QString &name,
442 const SqpRange &range)
443 {
444 // note: ownership is transfered to QCustomPlot
445 auto zone = new VisualizationSelectionZoneItem(&plot());
446 zone->setName(name);
447 zone->setRange(range.m_TStart, range.m_TEnd);
448 impl->addSelectionZone(zone);
449
450 plot().replot(QCustomPlot::rpQueuedReplot);
451
452 return zone;
453 }
454
441 void VisualizationGraphWidget::removeSelectionZone(VisualizationSelectionZoneItem *selectionZone)
455 void VisualizationGraphWidget::removeSelectionZone(VisualizationSelectionZoneItem *selectionZone)
442 {
456 {
443 parentVisualizationWidget()->selectionZoneManager().setSelected(selectionZone, false);
457 parentVisualizationWidget()->selectionZoneManager().setSelected(selectionZone, false);
444
458
445 if (impl->m_HoveredZone == selectionZone) {
459 if (impl->m_HoveredZone == selectionZone) {
446 impl->m_HoveredZone = nullptr;
460 impl->m_HoveredZone = nullptr;
447 setCursor(Qt::ArrowCursor);
461 setCursor(Qt::ArrowCursor);
448 }
462 }
449
463
450 impl->m_SelectionZones.removeAll(selectionZone);
464 impl->m_SelectionZones.removeAll(selectionZone);
451 plot().removeItem(selectionZone);
465 plot().removeItem(selectionZone);
452 plot().replot(QCustomPlot::rpQueuedReplot);
466 plot().replot(QCustomPlot::rpQueuedReplot);
453 }
467 }
454
468
455 void VisualizationGraphWidget::undoZoom()
469 void VisualizationGraphWidget::undoZoom()
456 {
470 {
457 auto zoom = impl->m_ZoomStack.pop();
471 auto zoom = impl->m_ZoomStack.pop();
458 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
472 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
459 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
473 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
460
474
461 axisX->setRange(zoom.first);
475 axisX->setRange(zoom.first);
462 axisY->setRange(zoom.second);
476 axisY->setRange(zoom.second);
463
477
464 plot().replot(QCustomPlot::rpQueuedReplot);
478 plot().replot(QCustomPlot::rpQueuedReplot);
465 }
479 }
466
480
467 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
481 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
468 {
482 {
469 if (visitor) {
483 if (visitor) {
470 visitor->visit(this);
484 visitor->visit(this);
471 }
485 }
472 else {
486 else {
473 qCCritical(LOG_VisualizationGraphWidget())
487 qCCritical(LOG_VisualizationGraphWidget())
474 << tr("Can't visit widget : the visitor is null");
488 << tr("Can't visit widget : the visitor is null");
475 }
489 }
476 }
490 }
477
491
478 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
492 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
479 {
493 {
480 auto isSpectrogram = [](const auto &variable) {
494 auto isSpectrogram = [](const auto &variable) {
481 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
495 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
482 };
496 };
483
497
484 // - A spectrogram series can't be dropped on graph with existing plottables
498 // - A spectrogram series can't be dropped on graph with existing plottables
485 // - No data series can be dropped on graph with existing spectrogram series
499 // - No data series can be dropped on graph with existing spectrogram series
486 return isSpectrogram(variable)
500 return isSpectrogram(variable)
487 ? impl->m_VariableToPlotMultiMap.empty()
501 ? impl->m_VariableToPlotMultiMap.empty()
488 : std::none_of(
502 : std::none_of(
489 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
503 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
490 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
504 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
491 }
505 }
492
506
493 bool VisualizationGraphWidget::contains(const Variable &variable) const
507 bool VisualizationGraphWidget::contains(const Variable &variable) const
494 {
508 {
495 // Finds the variable among the keys of the map
509 // Finds the variable among the keys of the map
496 auto variablePtr = &variable;
510 auto variablePtr = &variable;
497 auto findVariable
511 auto findVariable
498 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
512 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
499
513
500 auto end = impl->m_VariableToPlotMultiMap.cend();
514 auto end = impl->m_VariableToPlotMultiMap.cend();
501 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
515 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
502 return it != end;
516 return it != end;
503 }
517 }
504
518
505 QString VisualizationGraphWidget::name() const
519 QString VisualizationGraphWidget::name() const
506 {
520 {
507 return impl->m_Name;
521 return impl->m_Name;
508 }
522 }
509
523
510 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
524 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
511 {
525 {
512 auto mimeData = new QMimeData;
526 auto mimeData = new QMimeData;
513
527
514 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
528 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
515 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
529 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
516 && selectionZoneItemUnderCursor) {
530 && selectionZoneItemUnderCursor) {
517 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
531 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
518 selectionZoneItemUnderCursor->range()));
532 selectionZoneItemUnderCursor->range()));
519 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
533 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
520 selectionZoneItemUnderCursor->range()));
534 selectionZoneItemUnderCursor->range()));
521 }
535 }
522 else {
536 else {
523 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
537 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
524
538
525 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
539 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
526 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
540 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
527 }
541 }
528
542
529 return mimeData;
543 return mimeData;
530 }
544 }
531
545
532 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
546 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
533 {
547 {
534 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
548 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
535 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
549 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
536 && selectionZoneItemUnderCursor) {
550 && selectionZoneItemUnderCursor) {
537
551
538 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
552 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
539 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
553 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
540
554
541 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
555 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
542 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
556 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
543 .toSize();
557 .toSize();
544
558
545 auto pixmap = QPixmap(zoneSize);
559 auto pixmap = QPixmap(zoneSize);
546 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
560 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
547
561
548 return pixmap;
562 return pixmap;
549 }
563 }
550
564
551 return QPixmap();
565 return QPixmap();
552 }
566 }
553
567
554 bool VisualizationGraphWidget::isDragAllowed() const
568 bool VisualizationGraphWidget::isDragAllowed() const
555 {
569 {
556 return true;
570 return true;
557 }
571 }
558
572
559 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
573 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
560 {
574 {
561 if (highlighted) {
575 if (highlighted) {
562 plot().setBackground(QBrush(QColor("#BBD5EE")));
576 plot().setBackground(QBrush(QColor("#BBD5EE")));
563 }
577 }
564 else {
578 else {
565 plot().setBackground(QBrush(Qt::white));
579 plot().setBackground(QBrush(Qt::white));
566 }
580 }
567
581
568 plot().update();
582 plot().update();
569 }
583 }
570
584
571 void VisualizationGraphWidget::addVerticalCursor(double time)
585 void VisualizationGraphWidget::addVerticalCursor(double time)
572 {
586 {
573 impl->m_VerticalCursor->setPosition(time);
587 impl->m_VerticalCursor->setPosition(time);
574 impl->m_VerticalCursor->setVisible(true);
588 impl->m_VerticalCursor->setVisible(true);
575
589
576 auto text
590 auto text
577 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
591 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
578 impl->m_VerticalCursor->setLabelText(text);
592 impl->m_VerticalCursor->setLabelText(text);
579 }
593 }
580
594
581 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
595 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
582 {
596 {
583 impl->m_VerticalCursor->setAbsolutePosition(position);
597 impl->m_VerticalCursor->setAbsolutePosition(position);
584 impl->m_VerticalCursor->setVisible(true);
598 impl->m_VerticalCursor->setVisible(true);
585
599
586 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
600 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
587 auto text
601 auto text
588 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
602 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
589 impl->m_VerticalCursor->setLabelText(text);
603 impl->m_VerticalCursor->setLabelText(text);
590 }
604 }
591
605
592 void VisualizationGraphWidget::removeVerticalCursor()
606 void VisualizationGraphWidget::removeVerticalCursor()
593 {
607 {
594 impl->m_VerticalCursor->setVisible(false);
608 impl->m_VerticalCursor->setVisible(false);
595 plot().replot(QCustomPlot::rpQueuedReplot);
609 plot().replot(QCustomPlot::rpQueuedReplot);
596 }
610 }
597
611
598 void VisualizationGraphWidget::addHorizontalCursor(double value)
612 void VisualizationGraphWidget::addHorizontalCursor(double value)
599 {
613 {
600 impl->m_HorizontalCursor->setPosition(value);
614 impl->m_HorizontalCursor->setPosition(value);
601 impl->m_HorizontalCursor->setVisible(true);
615 impl->m_HorizontalCursor->setVisible(true);
602 impl->m_HorizontalCursor->setLabelText(QString::number(value));
616 impl->m_HorizontalCursor->setLabelText(QString::number(value));
603 }
617 }
604
618
605 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
619 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
606 {
620 {
607 impl->m_HorizontalCursor->setAbsolutePosition(position);
621 impl->m_HorizontalCursor->setAbsolutePosition(position);
608 impl->m_HorizontalCursor->setVisible(true);
622 impl->m_HorizontalCursor->setVisible(true);
609
623
610 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
624 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
611 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
625 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
612 }
626 }
613
627
614 void VisualizationGraphWidget::removeHorizontalCursor()
628 void VisualizationGraphWidget::removeHorizontalCursor()
615 {
629 {
616 impl->m_HorizontalCursor->setVisible(false);
630 impl->m_HorizontalCursor->setVisible(false);
617 plot().replot(QCustomPlot::rpQueuedReplot);
631 plot().replot(QCustomPlot::rpQueuedReplot);
618 }
632 }
619
633
620 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
634 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
621 {
635 {
622 Q_UNUSED(event);
636 Q_UNUSED(event);
623
637
624 // Prevents that all variables will be removed from graph when it will be closed
638 // Prevents that all variables will be removed from graph when it will be closed
625 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
639 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
626 emit variableAboutToBeRemoved(variableEntry.first);
640 emit variableAboutToBeRemoved(variableEntry.first);
627 }
641 }
628 }
642 }
629
643
630 void VisualizationGraphWidget::enterEvent(QEvent *event)
644 void VisualizationGraphWidget::enterEvent(QEvent *event)
631 {
645 {
632 Q_UNUSED(event);
646 Q_UNUSED(event);
633 impl->m_RenderingDelegate->showGraphOverlay(true);
647 impl->m_RenderingDelegate->showGraphOverlay(true);
634 }
648 }
635
649
636 void VisualizationGraphWidget::leaveEvent(QEvent *event)
650 void VisualizationGraphWidget::leaveEvent(QEvent *event)
637 {
651 {
638 Q_UNUSED(event);
652 Q_UNUSED(event);
639 impl->m_RenderingDelegate->showGraphOverlay(false);
653 impl->m_RenderingDelegate->showGraphOverlay(false);
640
654
641 if (auto parentZone = parentZoneWidget()) {
655 if (auto parentZone = parentZoneWidget()) {
642 parentZone->notifyMouseLeaveGraph(this);
656 parentZone->notifyMouseLeaveGraph(this);
643 }
657 }
644 else {
658 else {
645 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
659 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
646 }
660 }
647
661
648 if (impl->m_HoveredZone) {
662 if (impl->m_HoveredZone) {
649 impl->m_HoveredZone->setHovered(false);
663 impl->m_HoveredZone->setHovered(false);
650 impl->m_HoveredZone = nullptr;
664 impl->m_HoveredZone = nullptr;
651 }
665 }
652 }
666 }
653
667
654 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
668 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
655 {
669 {
656 return *ui->widget;
670 return *ui->widget;
657 }
671 }
658
672
659 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
673 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
660 {
674 {
661 QMenu graphMenu{};
675 QMenu graphMenu{};
662
676
663 // Iterates on variables (unique keys)
677 // Iterates on variables (unique keys)
664 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
678 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
665 end = impl->m_VariableToPlotMultiMap.cend();
679 end = impl->m_VariableToPlotMultiMap.cend();
666 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
680 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
667 // 'Remove variable' action
681 // 'Remove variable' action
668 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
682 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
669 [ this, var = it->first ]() { removeVariable(var); });
683 [ this, var = it->first ]() { removeVariable(var); });
670 }
684 }
671
685
672 if (!impl->m_ZoomStack.isEmpty()) {
686 if (!impl->m_ZoomStack.isEmpty()) {
673 if (!graphMenu.isEmpty()) {
687 if (!graphMenu.isEmpty()) {
674 graphMenu.addSeparator();
688 graphMenu.addSeparator();
675 }
689 }
676
690
677 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
691 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
678 }
692 }
679
693
680 // Selection Zone Actions
694 // Selection Zone Actions
681 auto selectionZoneItem = impl->selectionZoneAt(pos, plot());
695 auto selectionZoneItem = impl->selectionZoneAt(pos, plot());
682 if (selectionZoneItem) {
696 if (selectionZoneItem) {
683 auto selectedItems = parentVisualizationWidget()->selectionZoneManager().selectedItems();
697 auto selectedItems = parentVisualizationWidget()->selectionZoneManager().selectedItems();
684 selectedItems.removeAll(selectionZoneItem);
698 selectedItems.removeAll(selectionZoneItem);
685 selectedItems.prepend(selectionZoneItem); // Put the current selection zone first
699 selectedItems.prepend(selectionZoneItem); // Put the current selection zone first
686
700
687 auto zoneActions = sqpApp->actionsGuiController().selectionZoneActions();
701 auto zoneActions = sqpApp->actionsGuiController().selectionZoneActions();
688 if (!zoneActions.isEmpty() && !graphMenu.isEmpty()) {
702 if (!zoneActions.isEmpty() && !graphMenu.isEmpty()) {
689 graphMenu.addSeparator();
703 graphMenu.addSeparator();
690 }
704 }
691
705
692 QHash<QString, QMenu *> subMenus;
706 QHash<QString, QMenu *> subMenus;
693 QHash<QString, bool> subMenusEnabled;
707 QHash<QString, bool> subMenusEnabled;
694
708
695 for (auto zoneAction : zoneActions) {
709 for (auto zoneAction : zoneActions) {
696
710
697 auto isEnabled = zoneAction->isEnabled(selectedItems);
711 auto isEnabled = zoneAction->isEnabled(selectedItems);
698
712
699 auto menu = &graphMenu;
713 auto menu = &graphMenu;
700 for (auto subMenuName : zoneAction->subMenuList()) {
714 for (auto subMenuName : zoneAction->subMenuList()) {
701 if (!subMenus.contains(subMenuName)) {
715 if (!subMenus.contains(subMenuName)) {
702 menu = menu->addMenu(subMenuName);
716 menu = menu->addMenu(subMenuName);
703 subMenus[subMenuName] = menu;
717 subMenus[subMenuName] = menu;
704 subMenusEnabled[subMenuName] = isEnabled;
718 subMenusEnabled[subMenuName] = isEnabled;
705 }
719 }
706 else {
720 else {
707 menu = subMenus.value(subMenuName);
721 menu = subMenus.value(subMenuName);
708 if (isEnabled) {
722 if (isEnabled) {
709 // The sub menu is enabled if at least one of its actions is enabled
723 // The sub menu is enabled if at least one of its actions is enabled
710 subMenusEnabled[subMenuName] = true;
724 subMenusEnabled[subMenuName] = true;
711 }
725 }
712 }
726 }
713 }
727 }
714
728
715 auto action = menu->addAction(zoneAction->name());
729 auto action = menu->addAction(zoneAction->name());
716 action->setEnabled(isEnabled);
730 action->setEnabled(isEnabled);
717 action->setShortcut(zoneAction->displayedShortcut());
731 action->setShortcut(zoneAction->displayedShortcut());
718 QObject::connect(action, &QAction::triggered,
732 QObject::connect(action, &QAction::triggered,
719 [zoneAction, selectedItems]() { zoneAction->execute(selectedItems); });
733 [zoneAction, selectedItems]() { zoneAction->execute(selectedItems); });
720 }
734 }
721
735
722 for (auto it = subMenus.cbegin(); it != subMenus.cend(); ++it) {
736 for (auto it = subMenus.cbegin(); it != subMenus.cend(); ++it) {
723 it.value()->setEnabled(subMenusEnabled[it.key()]);
737 it.value()->setEnabled(subMenusEnabled[it.key()]);
724 }
738 }
725 }
739 }
726
740
727 if (!graphMenu.isEmpty()) {
741 if (!graphMenu.isEmpty()) {
728 graphMenu.exec(QCursor::pos());
742 graphMenu.exec(QCursor::pos());
729 }
743 }
730 }
744 }
731
745
732 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
746 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
733 {
747 {
734 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
748 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
735 << QThread::currentThread()->objectName() << "DoAcqui"
749 << QThread::currentThread()->objectName() << "DoAcqui"
736 << impl->m_Flags.testFlag(GraphFlag::EnableAcquisition);
750 << impl->m_Flags.testFlag(GraphFlag::EnableAcquisition);
737
751
738 auto graphRange = SqpRange{t1.lower, t1.upper};
752 auto graphRange = SqpRange{t1.lower, t1.upper};
739 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
753 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
740
754
741 if (impl->m_Flags.testFlag(GraphFlag::EnableAcquisition)) {
755 if (impl->m_Flags.testFlag(GraphFlag::EnableAcquisition)) {
742 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
756 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
743
757
744 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
758 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
745 end = impl->m_VariableToPlotMultiMap.end();
759 end = impl->m_VariableToPlotMultiMap.end();
746 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
760 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
747 variableUnderGraphVector.push_back(it->first);
761 variableUnderGraphVector.push_back(it->first);
748 }
762 }
749 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
763 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
750 !impl->m_IsCalibration);
764 !impl->m_IsCalibration);
751 }
765 }
752
766
753 if (impl->m_Flags.testFlag(GraphFlag::EnableSynchronization) && !impl->m_IsCalibration) {
767 if (impl->m_Flags.testFlag(GraphFlag::EnableSynchronization) && !impl->m_IsCalibration) {
754 qCDebug(LOG_VisualizationGraphWidget())
768 qCDebug(LOG_VisualizationGraphWidget())
755 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
769 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
756 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
770 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
757 emit synchronize(graphRange, oldGraphRange);
771 emit synchronize(graphRange, oldGraphRange);
758 }
772 }
759
773
760 auto pos = mapFromGlobal(QCursor::pos());
774 auto pos = mapFromGlobal(QCursor::pos());
761 auto axisPos = impl->posToAxisPos(pos, plot());
775 auto axisPos = impl->posToAxisPos(pos, plot());
762 if (auto parentZone = parentZoneWidget()) {
776 if (auto parentZone = parentZoneWidget()) {
763 if (impl->pointIsInAxisRect(axisPos, plot())) {
777 if (impl->pointIsInAxisRect(axisPos, plot())) {
764 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
778 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
765 }
779 }
766 else {
780 else {
767 parentZone->notifyMouseLeaveGraph(this);
781 parentZone->notifyMouseLeaveGraph(this);
768 }
782 }
769 }
783 }
770 else {
784 else {
771 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
785 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
772 }
786 }
773
787
774 // Quits calibration
788 // Quits calibration
775 impl->m_IsCalibration = false;
789 impl->m_IsCalibration = false;
776 }
790 }
777
791
778 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
792 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
779 {
793 {
780 impl->m_RenderingDelegate->onMouseDoubleClick(event);
794 impl->m_RenderingDelegate->onMouseDoubleClick(event);
781 }
795 }
782
796
783 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
797 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
784 {
798 {
785 // Handles plot rendering when mouse is moving
799 // Handles plot rendering when mouse is moving
786 impl->m_RenderingDelegate->onMouseMove(event);
800 impl->m_RenderingDelegate->onMouseMove(event);
787
801
788 auto axisPos = impl->posToAxisPos(event->pos(), plot());
802 auto axisPos = impl->posToAxisPos(event->pos(), plot());
789
803
790 // Zoom box and zone drawing
804 // Zoom box and zone drawing
791 if (impl->m_DrawingZoomRect) {
805 if (impl->m_DrawingZoomRect) {
792 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
806 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
793 }
807 }
794 else if (impl->m_DrawingZone) {
808 else if (impl->m_DrawingZone) {
795 impl->m_DrawingZone->setEnd(axisPos.x());
809 impl->m_DrawingZone->setEnd(axisPos.x());
796 }
810 }
797
811
798 // Cursor
812 // Cursor
799 if (auto parentZone = parentZoneWidget()) {
813 if (auto parentZone = parentZoneWidget()) {
800 if (impl->pointIsInAxisRect(axisPos, plot())) {
814 if (impl->pointIsInAxisRect(axisPos, plot())) {
801 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
815 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
802 }
816 }
803 else {
817 else {
804 parentZone->notifyMouseLeaveGraph(this);
818 parentZone->notifyMouseLeaveGraph(this);
805 }
819 }
806 }
820 }
807 else {
821 else {
808 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
822 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
809 }
823 }
810
824
811 // Search for the selection zone under the mouse
825 // Search for the selection zone under the mouse
812 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
826 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
813 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
827 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
814 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
828 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
815
829
816 // Sets the appropriate cursor shape
830 // Sets the appropriate cursor shape
817 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
831 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
818 setCursor(cursorShape);
832 setCursor(cursorShape);
819
833
820 // Manages the hovered zone
834 // Manages the hovered zone
821 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
835 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
822 if (impl->m_HoveredZone) {
836 if (impl->m_HoveredZone) {
823 impl->m_HoveredZone->setHovered(false);
837 impl->m_HoveredZone->setHovered(false);
824 }
838 }
825 selectionZoneItemUnderCursor->setHovered(true);
839 selectionZoneItemUnderCursor->setHovered(true);
826 impl->m_HoveredZone = selectionZoneItemUnderCursor;
840 impl->m_HoveredZone = selectionZoneItemUnderCursor;
827 plot().replot(QCustomPlot::rpQueuedReplot);
841 plot().replot(QCustomPlot::rpQueuedReplot);
828 }
842 }
829 }
843 }
830 else {
844 else {
831 // There is no zone under the mouse or the interaction mode is not "selection zones"
845 // There is no zone under the mouse or the interaction mode is not "selection zones"
832 if (impl->m_HoveredZone) {
846 if (impl->m_HoveredZone) {
833 impl->m_HoveredZone->setHovered(false);
847 impl->m_HoveredZone->setHovered(false);
834 impl->m_HoveredZone = nullptr;
848 impl->m_HoveredZone = nullptr;
835 }
849 }
836
850
837 setCursor(Qt::ArrowCursor);
851 setCursor(Qt::ArrowCursor);
838 }
852 }
839
853
840 impl->m_HasMovedMouse = true;
854 impl->m_HasMovedMouse = true;
841 VisualizationDragWidget::mouseMoveEvent(event);
855 VisualizationDragWidget::mouseMoveEvent(event);
842 }
856 }
843
857
844 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
858 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
845 {
859 {
846 auto value = event->angleDelta().x() + event->angleDelta().y();
860 auto value = event->angleDelta().x() + event->angleDelta().y();
847 if (value != 0) {
861 if (value != 0) {
848
862
849 auto direction = value > 0 ? 1.0 : -1.0;
863 auto direction = value > 0 ? 1.0 : -1.0;
850 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
864 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
851 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
865 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
852 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
866 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
853
867
854 auto zoomOrientations = QFlags<Qt::Orientation>{};
868 auto zoomOrientations = QFlags<Qt::Orientation>{};
855 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
869 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
856 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
870 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
857
871
858 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
872 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
859
873
860 if (!isZoomX && !isZoomY) {
874 if (!isZoomX && !isZoomY) {
861 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
875 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
862 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
876 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
863
877
864 axis->setRange(axis->range() + diff);
878 axis->setRange(axis->range() + diff);
865
879
866 if (plot().noAntialiasingOnDrag()) {
880 if (plot().noAntialiasingOnDrag()) {
867 plot().setNotAntialiasedElements(QCP::aeAll);
881 plot().setNotAntialiasedElements(QCP::aeAll);
868 }
882 }
869
883
870 plot().replot(QCustomPlot::rpQueuedReplot);
884 plot().replot(QCustomPlot::rpQueuedReplot);
871 }
885 }
872 }
886 }
873 }
887 }
874
888
875 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
889 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
876 {
890 {
877 auto isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
891 auto isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
878 auto isSelectionZoneMode
892 auto isSelectionZoneMode
879 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
893 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
880 auto isLeftClick = event->buttons().testFlag(Qt::LeftButton);
894 auto isLeftClick = event->buttons().testFlag(Qt::LeftButton);
881
895
882 if (!isDragDropClick && isLeftClick) {
896 if (!isDragDropClick && isLeftClick) {
883 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
897 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
884 // Starts a zoom box
898 // Starts a zoom box
885 impl->startDrawingRect(event->pos(), plot());
899 impl->startDrawingRect(event->pos(), plot());
886 }
900 }
887 else if (isSelectionZoneMode && impl->m_DrawingZone == nullptr) {
901 else if (isSelectionZoneMode && impl->m_DrawingZone == nullptr) {
888 // Starts a new selection zone
902 // Starts a new selection zone
889 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
903 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
890 if (!zoneAtPos) {
904 if (!zoneAtPos) {
891 impl->startDrawingZone(event->pos(), this);
905 impl->startDrawingZone(event->pos(), this);
892 }
906 }
893 }
907 }
894 }
908 }
895
909
896 // Allows mouse panning only in default mode
910 // Allows mouse panning only in default mode
897 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
911 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
898 == SqpApplication::PlotsInteractionMode::None
912 == SqpApplication::PlotsInteractionMode::None
899 && !isDragDropClick);
913 && !isDragDropClick);
900
914
901 // Allows zone edition only in selection zone mode without drag&drop
915 // Allows zone edition only in selection zone mode without drag&drop
902 impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick);
916 impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick);
903
917
904 // Selection / Deselection
918 // Selection / Deselection
905 if (isSelectionZoneMode) {
919 if (isSelectionZoneMode) {
906 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
920 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
907 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
921 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
908
922
909
923
910 if (selectionZoneItemUnderCursor && !selectionZoneItemUnderCursor->selected()
924 if (selectionZoneItemUnderCursor && !selectionZoneItemUnderCursor->selected()
911 && !isMultiSelectionClick) {
925 && !isMultiSelectionClick) {
912 parentVisualizationWidget()->selectionZoneManager().select(
926 parentVisualizationWidget()->selectionZoneManager().select(
913 {selectionZoneItemUnderCursor});
927 {selectionZoneItemUnderCursor});
914 }
928 }
915 else if (!selectionZoneItemUnderCursor && !isMultiSelectionClick && isLeftClick) {
929 else if (!selectionZoneItemUnderCursor && !isMultiSelectionClick && isLeftClick) {
916 parentVisualizationWidget()->selectionZoneManager().clearSelection();
930 parentVisualizationWidget()->selectionZoneManager().clearSelection();
917 }
931 }
918 else {
932 else {
919 // No selection change
933 // No selection change
920 }
934 }
921
935
922 if (selectionZoneItemUnderCursor && isLeftClick) {
936 if (selectionZoneItemUnderCursor && isLeftClick) {
923 selectionZoneItemUnderCursor->setAssociatedEditedZones(
937 selectionZoneItemUnderCursor->setAssociatedEditedZones(
924 parentVisualizationWidget()->selectionZoneManager().selectedItems());
938 parentVisualizationWidget()->selectionZoneManager().selectedItems());
925 }
939 }
926 }
940 }
927
941
928
942
929 impl->m_HasMovedMouse = false;
943 impl->m_HasMovedMouse = false;
930 VisualizationDragWidget::mousePressEvent(event);
944 VisualizationDragWidget::mousePressEvent(event);
931 }
945 }
932
946
933 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
947 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
934 {
948 {
935 if (impl->m_DrawingZoomRect) {
949 if (impl->m_DrawingZoomRect) {
936
950
937 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
951 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
938 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
952 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
939
953
940 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
954 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
941 impl->m_DrawingZoomRect->bottomRight->coords().x()};
955 impl->m_DrawingZoomRect->bottomRight->coords().x()};
942
956
943 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
957 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
944 impl->m_DrawingZoomRect->bottomRight->coords().y()};
958 impl->m_DrawingZoomRect->bottomRight->coords().y()};
945
959
946 impl->removeDrawingRect(plot());
960 impl->removeDrawingRect(plot());
947
961
948 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
962 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
949 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
963 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
950 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
964 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
951 axisX->setRange(newAxisXRange);
965 axisX->setRange(newAxisXRange);
952 axisY->setRange(newAxisYRange);
966 axisY->setRange(newAxisYRange);
953
967
954 plot().replot(QCustomPlot::rpQueuedReplot);
968 plot().replot(QCustomPlot::rpQueuedReplot);
955 }
969 }
956 }
970 }
957
971
958 impl->endDrawingZone(this);
972 impl->endDrawingZone(this);
959
973
960 // Selection / Deselection
974 // Selection / Deselection
961 auto isSelectionZoneMode
975 auto isSelectionZoneMode
962 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
976 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
963 if (isSelectionZoneMode) {
977 if (isSelectionZoneMode) {
964 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
978 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
965 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
979 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
966 if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton
980 if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton
967 && !impl->m_HasMovedMouse) {
981 && !impl->m_HasMovedMouse) {
968
982
969 auto zonesUnderCursor = impl->selectionZonesAt(event->pos(), plot());
983 auto zonesUnderCursor = impl->selectionZonesAt(event->pos(), plot());
970 if (zonesUnderCursor.count() > 1) {
984 if (zonesUnderCursor.count() > 1) {
971 // There are multiple zones under the mouse.
985 // There are multiple zones under the mouse.
972 // Performs the selection with a selection dialog.
986 // Performs the selection with a selection dialog.
973 VisualizationMultiZoneSelectionDialog dialog{this};
987 VisualizationMultiZoneSelectionDialog dialog{this};
974 dialog.setZones(zonesUnderCursor);
988 dialog.setZones(zonesUnderCursor);
975 dialog.move(mapToGlobal(event->pos() - QPoint(dialog.width() / 2, 20)));
989 dialog.move(mapToGlobal(event->pos() - QPoint(dialog.width() / 2, 20)));
976 dialog.activateWindow();
990 dialog.activateWindow();
977 dialog.raise();
991 dialog.raise();
978 if (dialog.exec() == QDialog::Accepted) {
992 if (dialog.exec() == QDialog::Accepted) {
979 auto selection = dialog.selectedZones();
993 auto selection = dialog.selectedZones();
980
994
981 if (!isMultiSelectionClick) {
995 if (!isMultiSelectionClick) {
982 parentVisualizationWidget()->selectionZoneManager().clearSelection();
996 parentVisualizationWidget()->selectionZoneManager().clearSelection();
983 }
997 }
984
998
985 for (auto it = selection.cbegin(); it != selection.cend(); ++it) {
999 for (auto it = selection.cbegin(); it != selection.cend(); ++it) {
986 auto zone = it.key();
1000 auto zone = it.key();
987 auto isSelected = it.value();
1001 auto isSelected = it.value();
988 parentVisualizationWidget()->selectionZoneManager().setSelected(zone,
1002 parentVisualizationWidget()->selectionZoneManager().setSelected(zone,
989 isSelected);
1003 isSelected);
990
1004
991 if (isSelected) {
1005 if (isSelected) {
992 // Puts the zone on top of the stack so it can be moved or resized
1006 // Puts the zone on top of the stack so it can be moved or resized
993 impl->moveSelectionZoneOnTop(zone, plot());
1007 impl->moveSelectionZoneOnTop(zone, plot());
994 }
1008 }
995 }
1009 }
996 }
1010 }
997 }
1011 }
998 else {
1012 else {
999 if (!isMultiSelectionClick) {
1013 if (!isMultiSelectionClick) {
1000 parentVisualizationWidget()->selectionZoneManager().select(
1014 parentVisualizationWidget()->selectionZoneManager().select(
1001 {selectionZoneItemUnderCursor});
1015 {selectionZoneItemUnderCursor});
1002 impl->moveSelectionZoneOnTop(selectionZoneItemUnderCursor, plot());
1016 impl->moveSelectionZoneOnTop(selectionZoneItemUnderCursor, plot());
1003 }
1017 }
1004 else {
1018 else {
1005 parentVisualizationWidget()->selectionZoneManager().setSelected(
1019 parentVisualizationWidget()->selectionZoneManager().setSelected(
1006 selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected()
1020 selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected()
1007 || event->button() == Qt::RightButton);
1021 || event->button() == Qt::RightButton);
1008 }
1022 }
1009 }
1023 }
1010 }
1024 }
1011 else {
1025 else {
1012 // No selection change
1026 // No selection change
1013 }
1027 }
1014 }
1028 }
1015 }
1029 }
1016
1030
1017 void VisualizationGraphWidget::onDataCacheVariableUpdated()
1031 void VisualizationGraphWidget::onDataCacheVariableUpdated()
1018 {
1032 {
1019 auto graphRange = ui->widget->xAxis->range();
1033 auto graphRange = ui->widget->xAxis->range();
1020 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
1034 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
1021
1035
1022 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
1036 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
1023 auto variable = variableEntry.first;
1037 auto variable = variableEntry.first;
1024 qCDebug(LOG_VisualizationGraphWidget())
1038 qCDebug(LOG_VisualizationGraphWidget())
1025 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
1039 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
1026 qCDebug(LOG_VisualizationGraphWidget())
1040 qCDebug(LOG_VisualizationGraphWidget())
1027 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
1041 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
1028 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
1042 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
1029 impl->updateData(variableEntry.second, variable, variable->range());
1043 impl->updateData(variableEntry.second, variable, variable->range());
1030 }
1044 }
1031 }
1045 }
1032 }
1046 }
1033
1047
1034 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
1048 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
1035 const SqpRange &range)
1049 const SqpRange &range)
1036 {
1050 {
1037 auto it = impl->m_VariableToPlotMultiMap.find(variable);
1051 auto it = impl->m_VariableToPlotMultiMap.find(variable);
1038 if (it != impl->m_VariableToPlotMultiMap.end()) {
1052 if (it != impl->m_VariableToPlotMultiMap.end()) {
1039 impl->updateData(it->second, variable, range);
1053 impl->updateData(it->second, variable, range);
1040 }
1054 }
1041 }
1055 }
@@ -1,440 +1,443
1 #include "Visualization/VisualizationSelectionZoneItem.h"
1 #include "Visualization/VisualizationSelectionZoneItem.h"
2 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/VisualizationGraphWidget.h"
3 #include "Visualization/VisualizationSelectionZoneManager.h"
3 #include "Visualization/VisualizationSelectionZoneManager.h"
4 #include "Visualization/VisualizationWidget.h"
4 #include "Visualization/VisualizationWidget.h"
5
5
6 const QString &DEFAULT_COLOR = QStringLiteral("#E79D41");
6 const QString &DEFAULT_COLOR = QStringLiteral("#E79D41");
7
7
8 struct VisualizationSelectionZoneItem::VisualizationSelectionZoneItemPrivate {
8 struct VisualizationSelectionZoneItem::VisualizationSelectionZoneItemPrivate {
9
9
10 QCustomPlot *m_Plot;
10 QCustomPlot *m_Plot;
11 double m_T1 = 0;
11 double m_T1 = 0;
12 double m_T2 = 0;
12 double m_T2 = 0;
13 QColor m_Color;
13 QColor m_Color;
14
14
15 bool m_IsEditionEnabled = true;
15 bool m_IsEditionEnabled = true;
16 double m_MovedOrinalT1 = 0;
16 double m_MovedOrinalT1 = 0;
17 double m_MovedOrinalT2 = 0;
17 double m_MovedOrinalT2 = 0;
18
18
19 QCPItemStraightLine *m_LeftLine;
19 QCPItemStraightLine *m_LeftLine;
20 QCPItemStraightLine *m_RightLine;
20 QCPItemStraightLine *m_RightLine;
21 QCPItemText *m_NameLabelItem = nullptr;
21 QCPItemText *m_NameLabelItem = nullptr;
22
22
23 enum class EditionMode { NoEdition, ResizeLeft, ResizeRight, Move };
23 enum class EditionMode { NoEdition, ResizeLeft, ResizeRight, Move };
24 EditionMode m_CurrentEditionMode;
24 EditionMode m_CurrentEditionMode;
25
25
26 QVector<VisualizationSelectionZoneItem *> m_AssociatedEditedZones;
26 QVector<VisualizationSelectionZoneItem *> m_AssociatedEditedZones;
27
27
28 VisualizationSelectionZoneItemPrivate(QCustomPlot *plot)
28 VisualizationSelectionZoneItemPrivate(QCustomPlot *plot)
29 : m_Plot(plot), m_Color(Qt::blue), m_CurrentEditionMode(EditionMode::NoEdition)
29 : m_Plot(plot), m_Color(Qt::blue), m_CurrentEditionMode(EditionMode::NoEdition)
30 {
30 {
31 }
31 }
32
32
33 void updatePosition(VisualizationSelectionZoneItem *item)
33 void updatePosition(VisualizationSelectionZoneItem *item)
34 {
34 {
35 item->topLeft->setCoords(m_T1, 0);
35 item->topLeft->setCoords(m_T1, 0);
36 item->bottomRight->setCoords(m_T2, 1);
36 item->bottomRight->setCoords(m_T2, 1);
37 }
37 }
38
38
39 EditionMode getEditionMode(const QPoint &pos, const VisualizationSelectionZoneItem *zoneItem)
39 EditionMode getEditionMode(const QPoint &pos, const VisualizationSelectionZoneItem *zoneItem)
40 {
40 {
41 auto distanceLeft = m_LeftLine->selectTest(pos, false);
41 auto distanceLeft = m_LeftLine->selectTest(pos, false);
42 auto distanceRight = m_RightLine->selectTest(pos, false);
42 auto distanceRight = m_RightLine->selectTest(pos, false);
43 auto distance = zoneItem->selectTest(pos, false);
43 auto distance = zoneItem->selectTest(pos, false);
44
44
45 if (distanceRight <= distance) {
45 if (distanceRight <= distance) {
46 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight;
46 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight;
47 }
47 }
48 else if (distanceLeft <= distance) {
48 else if (distanceLeft <= distance) {
49 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft;
49 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft;
50 }
50 }
51
51
52 return VisualizationSelectionZoneItemPrivate::EditionMode::Move;
52 return VisualizationSelectionZoneItemPrivate::EditionMode::Move;
53 }
53 }
54
54
55 double pixelSizeToAxisXSize(double pixels)
55 double pixelSizeToAxisXSize(double pixels)
56 {
56 {
57 auto axis = m_Plot->axisRect()->axis(QCPAxis::atBottom);
57 auto axis = m_Plot->axisRect()->axis(QCPAxis::atBottom);
58 return axis->pixelToCoord(pixels) - axis->pixelToCoord(0);
58 return axis->pixelToCoord(pixels) - axis->pixelToCoord(0);
59 }
59 }
60
60
61 bool alignZones(VisualizationSelectionZoneItem *referenceZone,
61 bool alignZones(VisualizationSelectionZoneItem *referenceZone,
62 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool alignOnLeft,
62 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool alignOnLeft,
63 bool allowResize, bool vertically)
63 bool allowResize, bool vertically)
64 {
64 {
65 auto result = false;
65 auto result = false;
66
66
67 auto referenceTime
67 auto referenceTime
68 = alignOnLeft ? referenceZone->range().m_TStart : referenceZone->range().m_TEnd;
68 = alignOnLeft ? referenceZone->range().m_TStart : referenceZone->range().m_TEnd;
69
69
70 auto referenceBottomAxis = m_Plot->axisRect()->axis(QCPAxis::atBottom);
70 auto referenceBottomAxis = m_Plot->axisRect()->axis(QCPAxis::atBottom);
71 auto referenceVerticalPosition = referenceBottomAxis->coordToPixel(referenceTime);
71 auto referenceVerticalPosition = referenceBottomAxis->coordToPixel(referenceTime);
72
72
73 for (auto otherZone : zonesToAlign) {
73 for (auto otherZone : zonesToAlign) {
74
74
75 auto otherZoneRange = otherZone->range();
75 auto otherZoneRange = otherZone->range();
76 auto newZoneStart = otherZoneRange.m_TStart;
76 auto newZoneStart = otherZoneRange.m_TStart;
77 auto newZoneEnd = otherZoneRange.m_TEnd;
77 auto newZoneEnd = otherZoneRange.m_TEnd;
78
78
79 auto alignedTime = referenceTime;
79 auto alignedTime = referenceTime;
80 if (vertically) {
80 if (vertically) {
81 auto otherZoneAxis = otherZone->parentPlot()->axisRect()->axis(QCPAxis::atBottom);
81 auto otherZoneAxis = otherZone->parentPlot()->axisRect()->axis(QCPAxis::atBottom);
82 alignedTime = otherZoneAxis->pixelToCoord(referenceVerticalPosition);
82 alignedTime = otherZoneAxis->pixelToCoord(referenceVerticalPosition);
83 }
83 }
84
84
85 if (alignOnLeft) {
85 if (alignOnLeft) {
86 newZoneStart = alignedTime;
86 newZoneStart = alignedTime;
87 if (!allowResize) {
87 if (!allowResize) {
88 newZoneEnd = alignedTime + (otherZoneRange.m_TEnd - otherZoneRange.m_TStart);
88 newZoneEnd = alignedTime + (otherZoneRange.m_TEnd - otherZoneRange.m_TStart);
89 }
89 }
90 }
90 }
91 else { // align on right
91 else { // align on right
92 newZoneEnd = alignedTime;
92 newZoneEnd = alignedTime;
93 if (!allowResize) {
93 if (!allowResize) {
94 newZoneStart = alignedTime - (otherZoneRange.m_TEnd - otherZoneRange.m_TStart);
94 newZoneStart = alignedTime - (otherZoneRange.m_TEnd - otherZoneRange.m_TStart);
95 }
95 }
96 }
96 }
97
97
98 if (newZoneStart < newZoneEnd) {
98 if (newZoneStart < newZoneEnd) {
99 result = true;
99 result = true;
100 otherZone->setRange(newZoneStart, newZoneEnd);
100 otherZone->setRange(newZoneStart, newZoneEnd);
101 otherZone->parentPlot()->replot();
101 otherZone->parentPlot()->replot();
102 }
102 }
103 }
103 }
104
104
105 return result;
105 return result;
106 }
106 }
107 };
107 };
108
108
109 VisualizationSelectionZoneItem::VisualizationSelectionZoneItem(QCustomPlot *plot)
109 VisualizationSelectionZoneItem::VisualizationSelectionZoneItem(QCustomPlot *plot)
110 : QCPItemRect(plot),
110 : QCPItemRect(plot),
111 impl{spimpl::make_unique_impl<VisualizationSelectionZoneItemPrivate>(plot)}
111 impl{spimpl::make_unique_impl<VisualizationSelectionZoneItemPrivate>(plot)}
112 {
112 {
113 topLeft->setTypeX(QCPItemPosition::ptPlotCoords);
113 topLeft->setTypeX(QCPItemPosition::ptPlotCoords);
114 topLeft->setTypeY(QCPItemPosition::ptAxisRectRatio);
114 topLeft->setTypeY(QCPItemPosition::ptAxisRectRatio);
115 bottomRight->setTypeX(QCPItemPosition::ptPlotCoords);
115 bottomRight->setTypeX(QCPItemPosition::ptPlotCoords);
116 bottomRight->setTypeY(QCPItemPosition::ptAxisRectRatio);
116 bottomRight->setTypeY(QCPItemPosition::ptAxisRectRatio);
117 setSelectable(false);
117 setSelectable(false);
118
118
119 impl->m_RightLine = new QCPItemStraightLine(plot);
119 impl->m_RightLine = new QCPItemStraightLine(plot);
120 impl->m_RightLine->point1->setParentAnchor(topRight);
120 impl->m_RightLine->point1->setParentAnchor(topRight);
121 impl->m_RightLine->point2->setParentAnchor(bottomRight);
121 impl->m_RightLine->point2->setParentAnchor(bottomRight);
122 impl->m_RightLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
122 impl->m_RightLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
123 impl->m_RightLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
123 impl->m_RightLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
124 impl->m_RightLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
124 impl->m_RightLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
125 impl->m_RightLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
125 impl->m_RightLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
126 impl->m_RightLine->setSelectable(false);
126 impl->m_RightLine->setSelectable(false);
127
127
128 impl->m_LeftLine = new QCPItemStraightLine(plot);
128 impl->m_LeftLine = new QCPItemStraightLine(plot);
129 impl->m_LeftLine->point1->setParentAnchor(topLeft);
129 impl->m_LeftLine->point1->setParentAnchor(topLeft);
130 impl->m_LeftLine->point2->setParentAnchor(bottomLeft);
130 impl->m_LeftLine->point2->setParentAnchor(bottomLeft);
131 impl->m_LeftLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
131 impl->m_LeftLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
132 impl->m_LeftLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
132 impl->m_LeftLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
133 impl->m_LeftLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
133 impl->m_LeftLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
134 impl->m_LeftLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
134 impl->m_LeftLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
135 impl->m_LeftLine->setSelectable(false);
135 impl->m_LeftLine->setSelectable(false);
136
136
137 connect(this, &VisualizationSelectionZoneItem::selectionChanged, impl->m_RightLine,
137 connect(this, &VisualizationSelectionZoneItem::selectionChanged, impl->m_RightLine,
138 &QCPItemStraightLine::setSelected);
138 &QCPItemStraightLine::setSelected);
139 connect(this, &VisualizationSelectionZoneItem::selectionChanged, impl->m_LeftLine,
139 connect(this, &VisualizationSelectionZoneItem::selectionChanged, impl->m_LeftLine,
140 &QCPItemStraightLine::setSelected);
140 &QCPItemStraightLine::setSelected);
141
141
142 setColor(QColor(DEFAULT_COLOR));
142 setColor(QColor(DEFAULT_COLOR));
143 }
143 }
144
144
145 VisualizationSelectionZoneItem::~VisualizationSelectionZoneItem()
145 VisualizationSelectionZoneItem::~VisualizationSelectionZoneItem()
146 {
146 {
147 }
147 }
148
148
149 VisualizationGraphWidget *VisualizationSelectionZoneItem::parentGraphWidget() const noexcept
149 VisualizationGraphWidget *VisualizationSelectionZoneItem::parentGraphWidget() const noexcept
150 {
150 {
151 auto parent = impl->m_Plot->parentWidget();
151 auto parent = impl->m_Plot->parentWidget();
152 while (parent != nullptr && !qobject_cast<VisualizationGraphWidget *>(parent)) {
152 while (parent != nullptr && !qobject_cast<VisualizationGraphWidget *>(parent)) {
153 parent = parent->parentWidget();
153 parent = parent->parentWidget();
154 }
154 }
155
155
156 return qobject_cast<VisualizationGraphWidget *>(parent);
156 return qobject_cast<VisualizationGraphWidget *>(parent);
157 }
157 }
158
158
159 void VisualizationSelectionZoneItem::setName(const QString &name)
159 void VisualizationSelectionZoneItem::setName(const QString &name)
160 {
160 {
161 if (name.isEmpty() && impl->m_NameLabelItem) {
161 if (name.isEmpty() && impl->m_NameLabelItem) {
162 impl->m_Plot->removeItem(impl->m_NameLabelItem);
162 impl->m_Plot->removeItem(impl->m_NameLabelItem);
163 impl->m_NameLabelItem = nullptr;
163 impl->m_NameLabelItem = nullptr;
164 }
164 }
165 else if (!impl->m_NameLabelItem) {
165 else if (!impl->m_NameLabelItem) {
166 impl->m_NameLabelItem = new QCPItemText(impl->m_Plot);
166 impl->m_NameLabelItem = new QCPItemText(impl->m_Plot);
167 impl->m_NameLabelItem->setText(name);
167 impl->m_NameLabelItem->setText(name);
168 impl->m_NameLabelItem->setPositionAlignment(Qt::AlignHCenter | Qt::AlignTop);
168 impl->m_NameLabelItem->setPositionAlignment(Qt::AlignHCenter | Qt::AlignTop);
169 impl->m_NameLabelItem->setColor(impl->m_Color);
169 impl->m_NameLabelItem->setColor(impl->m_Color);
170 impl->m_NameLabelItem->position->setParentAnchor(top);
170 impl->m_NameLabelItem->position->setParentAnchor(top);
171 }
171 }
172 }
172 }
173
173
174 QString VisualizationSelectionZoneItem::name() const
174 QString VisualizationSelectionZoneItem::name() const
175 {
175 {
176 if (!impl->m_NameLabelItem) {
176 if (!impl->m_NameLabelItem) {
177 return QString();
177 return QString();
178 }
178 }
179
179
180 return impl->m_NameLabelItem->text();
180 return impl->m_NameLabelItem->text();
181 }
181 }
182
182
183 SqpRange VisualizationSelectionZoneItem::range() const
183 SqpRange VisualizationSelectionZoneItem::range() const
184 {
184 {
185 SqpRange range;
185 SqpRange range;
186 range.m_TStart = impl->m_T1 <= impl->m_T2 ? impl->m_T1 : impl->m_T2;
186 range.m_TStart = impl->m_T1 <= impl->m_T2 ? impl->m_T1 : impl->m_T2;
187 range.m_TEnd = impl->m_T1 > impl->m_T2 ? impl->m_T1 : impl->m_T2;
187 range.m_TEnd = impl->m_T1 > impl->m_T2 ? impl->m_T1 : impl->m_T2;
188 return range;
188 return range;
189 }
189 }
190
190
191 void VisualizationSelectionZoneItem::setRange(double tstart, double tend)
191 void VisualizationSelectionZoneItem::setRange(double tstart, double tend)
192 {
192 {
193 impl->m_T1 = tstart;
193 impl->m_T1 = tstart;
194 impl->m_T2 = tend;
194 impl->m_T2 = tend;
195 impl->updatePosition(this);
195 impl->updatePosition(this);
196 }
196 }
197
197
198 void VisualizationSelectionZoneItem::setStart(double tstart)
198 void VisualizationSelectionZoneItem::setStart(double tstart)
199 {
199 {
200 impl->m_T1 = tstart;
200 impl->m_T1 = tstart;
201 impl->updatePosition(this);
201 impl->updatePosition(this);
202 }
202 }
203
203
204 void VisualizationSelectionZoneItem::setEnd(double tend)
204 void VisualizationSelectionZoneItem::setEnd(double tend)
205 {
205 {
206 impl->m_T2 = tend;
206 impl->m_T2 = tend;
207 impl->updatePosition(this);
207 impl->updatePosition(this);
208 }
208 }
209
209
210 void VisualizationSelectionZoneItem::setColor(const QColor &color)
210 void VisualizationSelectionZoneItem::setColor(const QColor &color)
211 {
211 {
212 impl->m_Color = color;
212 impl->m_Color = color;
213
213
214 auto brushColor = color;
214 auto brushColor = color;
215 brushColor.setAlpha(80);
215 brushColor.setAlpha(80);
216 setBrush(QBrush(brushColor));
216 setBrush(QBrush(brushColor));
217 setPen(QPen(Qt::NoPen));
217 setPen(QPen(Qt::NoPen));
218
218
219 auto selectedBrushColor = brushColor;
219 auto selectedBrushColor = brushColor;
220 selectedBrushColor.setAlpha(150);
220 selectedBrushColor.setAlpha(150);
221 setSelectedBrush(QBrush(selectedBrushColor));
221 setSelectedBrush(QBrush(selectedBrushColor));
222 setSelectedPen(QPen(Qt::NoPen));
222 setSelectedPen(QPen(Qt::NoPen));
223
223
224 auto linePen = QPen(color);
224 auto linePen = QPen(color);
225 linePen.setStyle(Qt::SolidLine);
225 linePen.setStyle(Qt::SolidLine);
226 linePen.setWidth(4);
226 linePen.setWidth(4);
227
227
228 auto selectedLinePen = linePen;
228 auto selectedLinePen = linePen;
229 selectedLinePen.setColor(color.darker(120));
229 selectedLinePen.setColor(color.darker(120));
230 selectedLinePen.setWidth(4);
230 selectedLinePen.setWidth(4);
231
231
232 impl->m_LeftLine->setPen(linePen);
232 impl->m_LeftLine->setPen(linePen);
233 impl->m_RightLine->setPen(linePen);
233 impl->m_RightLine->setPen(linePen);
234
234
235 impl->m_LeftLine->setSelectedPen(selectedLinePen);
235 impl->m_LeftLine->setSelectedPen(selectedLinePen);
236 impl->m_RightLine->setSelectedPen(selectedLinePen);
236 impl->m_RightLine->setSelectedPen(selectedLinePen);
237 }
237 }
238
238
239 void VisualizationSelectionZoneItem::setEditionEnabled(bool value)
239 void VisualizationSelectionZoneItem::setEditionEnabled(bool value)
240 {
240 {
241 impl->m_IsEditionEnabled = value;
241 impl->m_IsEditionEnabled = value;
242 setSelectable(value);
242 setSelectable(value);
243 if (!value) {
243 if (!value) {
244 setSelected(false);
244 setSelected(false);
245 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
245 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
246 }
246 }
247 }
247 }
248
248
249 bool VisualizationSelectionZoneItem::isEditionEnabled() const
249 bool VisualizationSelectionZoneItem::isEditionEnabled() const
250 {
250 {
251 return impl->m_IsEditionEnabled;
251 return impl->m_IsEditionEnabled;
252 }
252 }
253
253
254 void VisualizationSelectionZoneItem::moveToTop()
254 void VisualizationSelectionZoneItem::moveToTop()
255 {
255 {
256 moveToLayer(layer(), false);
256 moveToLayer(layer(), false);
257 }
257 }
258
258
259 Qt::CursorShape
259 Qt::CursorShape
260 VisualizationSelectionZoneItem::curshorShapeForPosition(const QPoint &position) const
260 VisualizationSelectionZoneItem::curshorShapeForPosition(const QPoint &position) const
261 {
261 {
262 auto mode = impl->m_CurrentEditionMode
262 auto mode = impl->m_CurrentEditionMode
263 == VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition
263 == VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition
264 ? impl->getEditionMode(position, this)
264 ? impl->getEditionMode(position, this)
265 : impl->m_CurrentEditionMode;
265 : impl->m_CurrentEditionMode;
266 switch (mode) {
266 switch (mode) {
267 case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
267 case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
268 return Qt::SizeAllCursor;
268 return Qt::SizeAllCursor;
269 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
269 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
270 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight: // fallthrough
270 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight: // fallthrough
271 return Qt::SizeHorCursor;
271 return Qt::SizeHorCursor;
272 default:
272 default:
273 return Qt::ArrowCursor;
273 return Qt::ArrowCursor;
274 }
274 }
275 }
275 }
276
276
277 void VisualizationSelectionZoneItem::setHovered(bool value)
277 void VisualizationSelectionZoneItem::setHovered(bool value)
278 {
278 {
279 if (value) {
279 if (value) {
280 auto linePen = impl->m_LeftLine->pen();
280 auto linePen = impl->m_LeftLine->pen();
281 linePen.setStyle(Qt::DotLine);
281 linePen.setStyle(Qt::DotLine);
282 linePen.setWidth(3);
282 linePen.setWidth(3);
283
283
284 auto selectedLinePen = impl->m_LeftLine->selectedPen();
284 auto selectedLinePen = impl->m_LeftLine->selectedPen();
285 ;
285 ;
286 selectedLinePen.setStyle(Qt::DotLine);
286 selectedLinePen.setStyle(Qt::DotLine);
287 selectedLinePen.setWidth(3);
287 selectedLinePen.setWidth(3);
288
288
289 impl->m_LeftLine->setPen(linePen);
289 impl->m_LeftLine->setPen(linePen);
290 impl->m_RightLine->setPen(linePen);
290 impl->m_RightLine->setPen(linePen);
291
291
292 impl->m_LeftLine->setSelectedPen(selectedLinePen);
292 impl->m_LeftLine->setSelectedPen(selectedLinePen);
293 impl->m_RightLine->setSelectedPen(selectedLinePen);
293 impl->m_RightLine->setSelectedPen(selectedLinePen);
294 }
294 }
295 else {
295 else {
296 setColor(impl->m_Color);
296 setColor(impl->m_Color);
297 }
297 }
298 }
298 }
299
299
300 void VisualizationSelectionZoneItem::setAssociatedEditedZones(
300 void VisualizationSelectionZoneItem::setAssociatedEditedZones(
301 const QVector<VisualizationSelectionZoneItem *> &associatedZones)
301 const QVector<VisualizationSelectionZoneItem *> &associatedZones)
302 {
302 {
303 impl->m_AssociatedEditedZones = associatedZones;
303 impl->m_AssociatedEditedZones = associatedZones;
304 impl->m_AssociatedEditedZones.removeAll(this);
304 impl->m_AssociatedEditedZones.removeAll(this);
305 }
305 }
306
306
307 bool VisualizationSelectionZoneItem::alignZonesVerticallyOnLeft(
307 bool VisualizationSelectionZoneItem::alignZonesVerticallyOnLeft(
308 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
308 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
309 {
309 {
310 return impl->alignZones(this, zonesToAlign, true, allowResize, true);
310 return impl->alignZones(this, zonesToAlign, true, allowResize, true);
311 }
311 }
312
312
313 bool VisualizationSelectionZoneItem::alignZonesVerticallyOnRight(
313 bool VisualizationSelectionZoneItem::alignZonesVerticallyOnRight(
314 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
314 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
315 {
315 {
316 return impl->alignZones(this, zonesToAlign, false, allowResize, true);
316 return impl->alignZones(this, zonesToAlign, false, allowResize, true);
317 }
317 }
318
318
319 bool VisualizationSelectionZoneItem::alignZonesTemporallyOnLeft(
319 bool VisualizationSelectionZoneItem::alignZonesTemporallyOnLeft(
320 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
320 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
321 {
321 {
322 return impl->alignZones(this, zonesToAlign, true, allowResize, false);
322 return impl->alignZones(this, zonesToAlign, true, allowResize, false);
323 }
323 }
324
324
325 bool VisualizationSelectionZoneItem::alignZonesTemporallyOnRight(
325 bool VisualizationSelectionZoneItem::alignZonesTemporallyOnRight(
326 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
326 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
327 {
327 {
328 return impl->alignZones(this, zonesToAlign, false, allowResize, false);
328 return impl->alignZones(this, zonesToAlign, false, allowResize, false);
329 }
329 }
330
330
331 void VisualizationSelectionZoneItem::mousePressEvent(QMouseEvent *event, const QVariant &details)
331 void VisualizationSelectionZoneItem::mousePressEvent(QMouseEvent *event, const QVariant &details)
332 {
332 {
333 Q_UNUSED(details);
333 Q_UNUSED(details);
334
334
335 if (isEditionEnabled() && event->button() == Qt::LeftButton) {
335 if (isEditionEnabled() && event->button() == Qt::LeftButton) {
336 impl->m_CurrentEditionMode = impl->getEditionMode(event->pos(), this);
336 impl->m_CurrentEditionMode = impl->getEditionMode(event->pos(), this);
337
337
338 impl->m_MovedOrinalT1 = impl->m_T1;
338 impl->m_MovedOrinalT1 = impl->m_T1;
339 impl->m_MovedOrinalT2 = impl->m_T2;
339 impl->m_MovedOrinalT2 = impl->m_T2;
340 for (auto associatedZone : impl->m_AssociatedEditedZones) {
340 for (auto associatedZone : impl->m_AssociatedEditedZones) {
341 associatedZone->impl->m_MovedOrinalT1 = associatedZone->impl->m_T1;
341 associatedZone->impl->m_MovedOrinalT1 = associatedZone->impl->m_T1;
342 associatedZone->impl->m_MovedOrinalT2 = associatedZone->impl->m_T2;
342 associatedZone->impl->m_MovedOrinalT2 = associatedZone->impl->m_T2;
343 }
343 }
344 }
344 }
345 else {
345 else {
346 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
346 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
347 event->ignore();
347 event->ignore();
348 }
348 }
349 }
349 }
350
350
351 void VisualizationSelectionZoneItem::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
351 void VisualizationSelectionZoneItem::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
352 {
352 {
353 if (isEditionEnabled()) {
353 if (isEditionEnabled()) {
354 if (!selected()) {
354 if (!selected()) {
355 // Force the item to be selected during the edition
355 // Force the item to be selected during the edition
356 parentGraphWidget()->parentVisualizationWidget()->selectionZoneManager().setSelected(
356 parentGraphWidget()->parentVisualizationWidget()->selectionZoneManager().setSelected(
357 this, true);
357 this, true);
358 }
358 }
359
359
360 auto axis = impl->m_Plot->axisRect()->axis(QCPAxis::atBottom);
360 auto axis = impl->m_Plot->axisRect()->axis(QCPAxis::atBottom);
361 auto pixelDiff = event->pos().x() - startPos.x();
361 auto pixelDiff = event->pos().x() - startPos.x();
362 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
362 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
363
363
364 switch (impl->m_CurrentEditionMode) {
364 switch (impl->m_CurrentEditionMode) {
365 case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
365 case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
366 setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff);
366 setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff);
367 for (auto associatedZone : impl->m_AssociatedEditedZones) {
367 for (auto associatedZone : impl->m_AssociatedEditedZones) {
368 associatedZone->move(pixelDiff);
368 associatedZone->move(pixelDiff);
369 }
369 }
370 break;
370 break;
371 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
371 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
372 setStart(impl->m_MovedOrinalT1 + diff);
372 setStart(impl->m_MovedOrinalT1 + diff);
373 for (auto associatedZone : impl->m_AssociatedEditedZones) {
373 for (auto associatedZone : impl->m_AssociatedEditedZones) {
374 impl->m_MovedOrinalT1 < impl->m_MovedOrinalT2
374 impl->m_MovedOrinalT1 < impl->m_MovedOrinalT2
375 ? associatedZone->resizeLeft(pixelDiff)
375 ? associatedZone->resizeLeft(pixelDiff)
376 : associatedZone->resizeRight(pixelDiff);
376 : associatedZone->resizeRight(pixelDiff);
377 }
377 }
378 break;
378 break;
379 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight:
379 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight:
380 setEnd(impl->m_MovedOrinalT2 + diff);
380 setEnd(impl->m_MovedOrinalT2 + diff);
381 for (auto associatedZone : impl->m_AssociatedEditedZones) {
381 for (auto associatedZone : impl->m_AssociatedEditedZones) {
382 impl->m_MovedOrinalT1 < impl->m_MovedOrinalT2
382 impl->m_MovedOrinalT1 < impl->m_MovedOrinalT2
383 ? associatedZone->resizeRight(pixelDiff)
383 ? associatedZone->resizeRight(pixelDiff)
384 : associatedZone->resizeLeft(pixelDiff);
384 : associatedZone->resizeLeft(pixelDiff);
385 }
385 }
386 break;
386 break;
387 default:
387 default:
388 break;
388 break;
389 }
389 }
390
390
391 emit rangeEdited(range());
392
391 for (auto associatedZone : impl->m_AssociatedEditedZones) {
393 for (auto associatedZone : impl->m_AssociatedEditedZones) {
392 associatedZone->parentPlot()->replot();
394 associatedZone->parentPlot()->replot();
395 emit associatedZone->rangeEdited(associatedZone->range());
393 }
396 }
394 }
397 }
395 else {
398 else {
396 event->ignore();
399 event->ignore();
397 }
400 }
398 }
401 }
399
402
400 void VisualizationSelectionZoneItem::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
403 void VisualizationSelectionZoneItem::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
401 {
404 {
402 Q_UNUSED(startPos);
405 Q_UNUSED(startPos);
403
406
404 if (isEditionEnabled()) {
407 if (isEditionEnabled()) {
405 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
408 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
406 }
409 }
407 else {
410 else {
408 event->ignore();
411 event->ignore();
409 }
412 }
410
413
411 impl->m_AssociatedEditedZones.clear();
414 impl->m_AssociatedEditedZones.clear();
412 }
415 }
413
416
414 void VisualizationSelectionZoneItem::resizeLeft(double pixelDiff)
417 void VisualizationSelectionZoneItem::resizeLeft(double pixelDiff)
415 {
418 {
416 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
419 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
417 if (impl->m_MovedOrinalT1 <= impl->m_MovedOrinalT2) {
420 if (impl->m_MovedOrinalT1 <= impl->m_MovedOrinalT2) {
418 setStart(impl->m_MovedOrinalT1 + diff);
421 setStart(impl->m_MovedOrinalT1 + diff);
419 }
422 }
420 else {
423 else {
421 setEnd(impl->m_MovedOrinalT2 + diff);
424 setEnd(impl->m_MovedOrinalT2 + diff);
422 }
425 }
423 }
426 }
424
427
425 void VisualizationSelectionZoneItem::resizeRight(double pixelDiff)
428 void VisualizationSelectionZoneItem::resizeRight(double pixelDiff)
426 {
429 {
427 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
430 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
428 if (impl->m_MovedOrinalT1 > impl->m_MovedOrinalT2) {
431 if (impl->m_MovedOrinalT1 > impl->m_MovedOrinalT2) {
429 setStart(impl->m_MovedOrinalT1 + diff);
432 setStart(impl->m_MovedOrinalT1 + diff);
430 }
433 }
431 else {
434 else {
432 setEnd(impl->m_MovedOrinalT2 + diff);
435 setEnd(impl->m_MovedOrinalT2 + diff);
433 }
436 }
434 }
437 }
435
438
436 void VisualizationSelectionZoneItem::move(double pixelDiff)
439 void VisualizationSelectionZoneItem::move(double pixelDiff)
437 {
440 {
438 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
441 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
439 setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff);
442 setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff);
440 }
443 }
General Comments 0
You need to be logged in to leave comments. Login now