##// END OF EJS Templates
Switched to new TS impl but quite broken!...
jeandet -
r1420:3c3e24550401
parent child
Show More
@@ -13,8 +13,14 QT5_WRAP_UI(UiGenerated_SRCS
13 13 add_executable(sciqlopapp WIN32 ${app_SRCS} ${UiGenerated_SRCS})
14 14 if(NOT BUILD_SHARED_LIBS)
15 15 add_definitions(-DQT_STATICPLUGIN)
16 target_link_libraries(sciqlopapp mockplugin)
17 target_link_libraries(sciqlopapp amdaplugin)
16 if(BUILD_PLUGINS)
17 target_link_libraries(sciqlopapp mockplugin)
18 target_link_libraries(sciqlopapp amdaplugin)
19 endif()
20 endif()
21
22 if(NOT BUILD_PLUGINS)
23 add_definitions(-DSQP_NO_PLUGINS)
18 24 endif()
19 25
20 26 target_link_libraries(sciqlopapp
@@ -44,10 +44,12 const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins");
44 44 int main(int argc, char* argv[])
45 45 {
46 46 #ifdef QT_STATICPLUGIN
47 #ifndef SQP_NO_PLUGINS
47 48 Q_IMPORT_PLUGIN(MockPlugin)
48 49 Q_IMPORT_PLUGIN(AmdaPlugin)
49 50 Q_INIT_RESOURCE(amdaresources);
50 51 #endif
52 #endif
51 53 Q_INIT_RESOURCE(sqpguiresources);
52 54
53 55 SqpApplication::setOrganizationName("LPP");
@@ -1,1 +1,1
1 Subproject commit 00b9e6e4b7f57c09175c396576ac6e30f45a14ff
1 Subproject commit a8a4e48c21af5a28ad3f56582db7bbec0fe76978
@@ -11,11 +11,12
11 11
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableInspectorWidget)
13 13
14 class Variable;
14 class Variable2;
15 15
16 16 class QProgressBarItemDelegate;
17 17
18 namespace Ui {
18 namespace Ui
19 {
19 20 class VariableInspectorWidget;
20 21 } // Ui
21 22
@@ -24,11 +25,12 class VariableInspectorWidget;
24 25 * which it is possible to view the loaded variables, handle them or trigger their display in
25 26 * visualization
26 27 */
27 class VariableInspectorWidget : public QWidget {
28 class VariableInspectorWidget : public QWidget
29 {
28 30 Q_OBJECT
29 31
30 32 public:
31 explicit VariableInspectorWidget(QWidget *parent = 0);
33 explicit VariableInspectorWidget(QWidget* parent = 0);
32 34 virtual ~VariableInspectorWidget();
33 35
34 36 signals:
@@ -40,18 +42,18 signals:
40 42 * @remarks To make the dynamic addition of menus work, the connections to this signal must be
41 43 * in Qt :: DirectConnection
42 44 */
43 void tableMenuAboutToBeDisplayed(QMenu *tableMenu,
44 const QVector<std::shared_ptr<Variable> > &variables);
45 void tableMenuAboutToBeDisplayed(
46 QMenu* tableMenu, const QVector<std::shared_ptr<Variable2>>& variables);
45 47
46 48 private:
47 Ui::VariableInspectorWidget *ui;
49 Ui::VariableInspectorWidget* ui;
48 50
49 QProgressBarItemDelegate *m_ProgressBarItemDelegate;
51 QProgressBarItemDelegate* m_ProgressBarItemDelegate;
50 52 VariableModel2* m_model;
51 53
52 54 private slots:
53 55 /// Slot called when right clicking on an variable in the table (displays a menu)
54 void onTableMenuRequested(const QPoint &pos) noexcept;
56 void onTableMenuRequested(const QPoint& pos) noexcept;
55 57 /// Refreshes instantly the variable view
56 58 void refresh() noexcept;
57 59 };
@@ -6,11 +6,12
6 6
7 7 #include <memory>
8 8
9 namespace Ui {
9 namespace Ui
10 {
10 11 class VariableMenuHeaderWidget;
11 12 } // Ui
12 13
13 class Variable;
14 class Variable2;
14 15
15 16 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableMenuHeaderWidget)
16 17
@@ -19,19 +20,20 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableMenuHeaderWidget)
19 20 * variable inspector
20 21 * @sa VariableInspectorWidget
21 22 */
22 class VariableMenuHeaderWidget : public QWidget {
23 class VariableMenuHeaderWidget : public QWidget
24 {
23 25 public:
24 26 /**
25 27 * Ctor
26 28 * @param variables the list of variables used to generate the header
27 29 * @param parent the parent widget
28 30 */
29 explicit VariableMenuHeaderWidget(const QVector<std::shared_ptr<Variable> > &variables,
30 QWidget *parent = 0);
31 explicit VariableMenuHeaderWidget(
32 const QVector<std::shared_ptr<Variable2>>& variables, QWidget* parent = 0);
31 33 virtual ~VariableMenuHeaderWidget() noexcept;
32 34
33 35 private:
34 Ui::VariableMenuHeaderWidget *ui;
36 Ui::VariableMenuHeaderWidget* ui;
35 37 };
36 38
37 39 #endif // SCIQLOP_VARIABLEMENUHEADERWIDGET_H
@@ -12,33 +12,35 class IDataSeries;
12 12 class QCPAxis;
13 13 class QCustomPlot;
14 14 class SqpColorScale;
15 class Variable;
15 class Variable2;
16 16
17 17 /// Formats a data value according to the axis on which it is present
18 QString formatValue(double value, const QCPAxis &axis);
18 QString formatValue(double value, const QCPAxis& axis);
19 19
20 20 /**
21 21 * Helper used to handle axes rendering
22 22 */
23 struct IAxisHelper {
23 struct IAxisHelper
24 {
24 25 virtual ~IAxisHelper() noexcept = default;
25 26
26 27 /// Set properties of the plot's axes and the color scale associated to plot passed as
27 28 /// parameters
28 29 /// @param plot the plot for which to set axe properties
29 30 /// @param colorScale the color scale for which to set properties
30 virtual void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) = 0;
31 virtual void setProperties(QCustomPlot& plot, SqpColorScale& colorScale) = 0;
31 32
32 33 /// Set the units of the plot's axes and the color scale associated to plot passed as
33 34 /// parameters
34 35 /// @param plot the plot for which to set axe units
35 36 /// @param colorScale the color scale for which to set unit
36 virtual void setUnits(QCustomPlot &plot, SqpColorScale &colorScale) = 0;
37 virtual void setUnits(QCustomPlot& plot, SqpColorScale& colorScale) = 0;
37 38 };
38 39
39 struct IAxisHelperFactory {
40 struct IAxisHelperFactory
41 {
40 42 /// Creates IPlottablesHelper according to the type of data series a variable holds
41 static std::unique_ptr<IAxisHelper> create(const Variable &variable) noexcept;
43 static std::unique_ptr<IAxisHelper> create(Variable2& variable) noexcept;
42 44 };
43 45
44 46 #endif // SCIQLOP_AXISRENDERINGUTILS_H
@@ -1,21 +1,22
1 1 #ifndef SCIQLOP_IVARIABLECONTAINER_H
2 2 #define SCIQLOP_IVARIABLECONTAINER_H
3 3
4 class Variable;
4 class Variable2;
5 5
6 6 /**
7 7 * @brief The IVariableContainer interface represents an UI object that can accommodate a variable
8 8 */
9 class IVariableContainer {
9 class IVariableContainer
10 {
10 11
11 12 public:
12 13 virtual ~IVariableContainer() = default;
13 14
14 15 /// Checks if the container can handle the variable passed in parameter
15 virtual bool canDrop(const Variable &variable) const = 0;
16 virtual bool canDrop(Variable2& variable) const = 0;
16 17
17 18 /// Checks if the container contains the variable passed in parameter
18 virtual bool contains(const Variable &variable) const = 0;
19 virtual bool contains(Variable2& variable) const = 0;
19 20 };
20 21
21 22
@@ -13,22 +13,24 Q_DECLARE_LOGGING_CATEGORY(LOG_PlottablesRenderingUtils)
13 13
14 14 class QCPColorScale;
15 15 class QCustomPlot;
16 class Variable;
16 class Variable2;
17 17
18 18 /**
19 19 * Helper used to handle plottables rendering
20 20 */
21 struct IPlottablesHelper {
21 struct IPlottablesHelper
22 {
22 23 virtual ~IPlottablesHelper() noexcept = default;
23 24
24 25 /// Set properties of the plottables passed as parameter
25 26 /// @param plottables the plottables for which to set properties
26 virtual void setProperties(PlottablesMap &plottables) = 0;
27 virtual void setProperties(PlottablesMap& plottables) = 0;
27 28 };
28 29
29 struct IPlottablesHelperFactory {
30 struct IPlottablesHelperFactory
31 {
30 32 /// Creates IPlottablesHelper according to the type of data series a variable holds
31 static std::unique_ptr<IPlottablesHelper> create(const Variable &variable) noexcept;
33 static std::unique_ptr<IPlottablesHelper> create(Variable2& variable) noexcept;
32 34 };
33 35
34 36 #endif // SCIQLOP_PLOTTABLESRENDERINGUTILS_H
@@ -15,13 +15,14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphHelper)
15 15 class IDataSeries;
16 16 class QCPAbstractPlottable;
17 17 class QCustomPlot;
18 class Variable;
18 class Variable2;
19 19
20 20 /**
21 21 * @brief The VisualizationGraphHelper class aims to create the QCustomPlot components relative to a
22 22 * variable, depending on the data series of this variable
23 23 */
24 struct VisualizationGraphHelper {
24 struct VisualizationGraphHelper
25 {
25 26 /**
26 27 * Creates (if possible) the QCustomPlot components relative to the variable passed in
27 28 * parameter, and adds these to the plot passed in parameter.
@@ -30,12 +31,12 struct VisualizationGraphHelper {
30 31 * components.
31 32 * @return the list of the components created
32 33 */
33 static PlottablesMap create(std::shared_ptr<Variable> variable, QCustomPlot &plot) noexcept;
34 static PlottablesMap create(std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept;
34 35
35 static void updateData(PlottablesMap &plottables, std::shared_ptr<Variable> variable,
36 const DateTimeRange &dateTime);
36 static void updateData(PlottablesMap& plottables, std::shared_ptr<Variable2> variable,
37 const DateTimeRange& dateTime);
37 38
38 static void setYAxisRange(std::shared_ptr<Variable> variable, QCustomPlot &plot) noexcept;
39 static void setYAxisRange(std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept;
39 40 };
40 41
41 42 #endif // SCIQLOP_VISUALIZATIONGRAPHHELPER_H
@@ -9,28 +9,29 class IDataSeries;
9 9 class QCustomPlot;
10 10 class QMouseEvent;
11 11 class Unit;
12 class Variable;
12 class Variable2;
13 13 class VisualizationGraphWidget;
14 14
15 class VisualizationGraphRenderingDelegate {
15 class VisualizationGraphRenderingDelegate
16 {
16 17 public:
17 18 /// Ctor
18 19 /// @param graphWidget the graph widget to which the delegate is associated
19 20 /// @remarks the graph widget must exist throughout the life cycle of the delegate
20 explicit VisualizationGraphRenderingDelegate(VisualizationGraphWidget &graphWidget);
21 explicit VisualizationGraphRenderingDelegate(VisualizationGraphWidget& graphWidget);
21 22
22 void onMouseDoubleClick(QMouseEvent *event) noexcept;
23 void updateTooltip(QMouseEvent *event) noexcept;
23 void onMouseDoubleClick(QMouseEvent* event) noexcept;
24 void updateTooltip(QMouseEvent* event) noexcept;
24 25 /// Updates rendering when data of plot changed
25 26 void onPlotUpdated() noexcept;
26 27
27 28 /// Sets units of the plot's axes according to the properties of the variable passed as
28 29 /// parameter
29 void setAxesUnits(const Variable &variable) noexcept;
30 void setAxesUnits(Variable2& variable) noexcept;
30 31
31 32 /// Sets graph properties of the plottables passed as parameter, from the variable that
32 33 /// generated these
33 void setGraphProperties(const Variable &variable, PlottablesMap &plottables) noexcept;
34 void setGraphProperties(Variable2& variable, PlottablesMap& plottables) noexcept;
34 35
35 36
36 37 /// Shows or hides graph overlay (name, close button, etc.)
@@ -5,8 +5,8
5 5 #include "Visualization/VisualizationDragWidget.h"
6 6
7 7 #include <QLoggingCategory>
8 #include <QWidget>
9 8 #include <QUuid>
9 #include <QWidget>
10 10
11 11 #include <memory>
12 12
@@ -18,18 +18,20 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
18 18
19 19 class QCPRange;
20 20 class QCustomPlot;
21 class Variable;
21 class Variable2;
22 22 class VisualizationWidget;
23 23 class VisualizationZoneWidget;
24 24 class VisualizationSelectionZoneItem;
25 25
26 namespace Ui {
26 namespace Ui
27 {
27 28 class VisualizationGraphWidget;
28 29 } // namespace Ui
29 30
30 31 /// Defines options that can be associated with the graph
31 enum GraphFlag {
32 DisableAll = 0x0, ///< Disables acquisition and synchronization
32 enum GraphFlag
33 {
34 DisableAll = 0x0, ///< Disables acquisition and synchronization
33 35 EnableAcquisition = 0x1, ///< When this flag is set, the change of the graph's range leads to
34 36 /// the acquisition of data
35 37 EnableSynchronization = 0x2, ///< When this flag is set, the change of the graph's range causes
@@ -41,66 +43,68 enum GraphFlag {
41 43 Q_DECLARE_FLAGS(GraphFlags, GraphFlag)
42 44 Q_DECLARE_OPERATORS_FOR_FLAGS(GraphFlags)
43 45
44 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
46 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget
47 {
45 48 Q_OBJECT
46 49
47 50 friend class QCustomPlotSynchronizer;
48 51 friend class VisualizationGraphRenderingDelegate;
49 52
50 53 public:
51 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
54 explicit VisualizationGraphWidget(const QString& name = {}, QWidget* parent = 0);
52 55 virtual ~VisualizationGraphWidget();
53 56
54 57 /// Returns the VisualizationZoneWidget which contains the graph or nullptr
55 VisualizationZoneWidget *parentZoneWidget() const noexcept;
58 VisualizationZoneWidget* parentZoneWidget() const noexcept;
56 59
57 60 /// Returns the main VisualizationWidget which contains the graph or nullptr
58 VisualizationWidget *parentVisualizationWidget() const;
61 VisualizationWidget* parentVisualizationWidget() const;
59 62
60 63 /// Sets graph options
61 64 void setFlags(GraphFlags flags);
62 65
63 void addVariable(std::shared_ptr<Variable> variable, DateTimeRange range);
66 void addVariable(std::shared_ptr<Variable2> variable, DateTimeRange range);
64 67
65 68 /// Removes a variable from the graph
66 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
69 void removeVariable(std::shared_ptr<Variable2> variable) noexcept;
67 70
68 71 /// Returns the list of all variables used in the graph
69 std::vector<std::shared_ptr<Variable> > variables() const;
72 std::vector<std::shared_ptr<Variable2>> variables() const;
70 73
71 74 /// Sets the y-axis range based on the data of a variable
72 void setYRange(std::shared_ptr<Variable> variable);
75 void setYRange(std::shared_ptr<Variable2> variable);
73 76 DateTimeRange graphRange() const noexcept;
74 void setGraphRange(const DateTimeRange &range, bool updateVar=false, bool forward=false);
77 void setGraphRange(const DateTimeRange& range, bool updateVar = false, bool forward = false);
75 78 void setAutoRangeOnVariableInitialization(bool value);
76 79
77 80 // Zones
78 81 /// Returns the ranges of all the selection zones on the graph
79 82 QVector<DateTimeRange> selectionZoneRanges() const;
80 83 /// Adds new selection zones in the graph
81 void addSelectionZones(const QVector<DateTimeRange> &ranges);
84 void addSelectionZones(const QVector<DateTimeRange>& ranges);
82 85 /// Adds a new selection zone in the graph
83 VisualizationSelectionZoneItem *addSelectionZone(const QString &name, const DateTimeRange &range);
86 VisualizationSelectionZoneItem* addSelectionZone(
87 const QString& name, const DateTimeRange& range);
84 88 /// Removes the specified selection zone
85 void removeSelectionZone(VisualizationSelectionZoneItem *selectionZone);
89 void removeSelectionZone(VisualizationSelectionZoneItem* selectionZone);
86 90
87 91 /// Undo the last zoom done with a zoom box
88 92 void undoZoom();
89 93
90 void zoom(double factor, int center, Qt::Orientation orientation, bool forward=true);
91 void move(double factor, Qt::Orientation orientation, bool forward=true);
92 void move(double dx, double dy, bool forward=true);
93 void transform(const DateTimeRangeTransformation& tranformation, bool forward=true);
94 void zoom(double factor, int center, Qt::Orientation orientation, bool forward = true);
95 void move(double factor, Qt::Orientation orientation, bool forward = true);
96 void move(double dx, double dy, bool forward = true);
97 void transform(const DateTimeRangeTransformation& tranformation, bool forward = true);
94 98
95 99 // IVisualizationWidget interface
96 void accept(IVisualizationWidgetVisitor *visitor) override;
97 bool canDrop(const Variable &variable) const override;
98 bool contains(const Variable &variable) const override;
100 void accept(IVisualizationWidgetVisitor* visitor) override;
101 bool canDrop(Variable2& variable) const override;
102 bool contains(Variable2& variable) const override;
99 103 QString name() const override;
100 104
101 105 // VisualisationDragWidget
102 QMimeData *mimeData(const QPoint &position) const override;
103 QPixmap customDragPixmap(const QPoint &dragPosition) override;
106 QMimeData* mimeData(const QPoint& position) const override;
107 QPixmap customDragPixmap(const QPoint& dragPosition) override;
104 108 bool isDragAllowed() const override;
105 109 void highlightForMerge(bool highlighted) override;
106 110
@@ -117,65 +121,65 public:
117 121 void removeHorizontalCursor();
118 122
119 123 signals:
120 void synchronize(const DateTimeRange &range, const DateTimeRange &oldRange);
121 void changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange &range);
124 void synchronize(const DateTimeRange& range, const DateTimeRange& oldRange);
125 void changeRange(const std::shared_ptr<Variable2>& variable, const DateTimeRange& range);
122 126
123 127 /// Signal emitted when the variable is about to be removed from the graph
124 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
128 void variableAboutToBeRemoved(std::shared_ptr<Variable2> var);
125 129 /// Signal emitted when the variable has been added to the graph
126 void variableAdded(std::shared_ptr<Variable> var);
130 void variableAdded(std::shared_ptr<Variable2> var);
127 131
128 132
129 void zoom_sig(double factor, int center, Qt::Orientation orientation, bool forward=true);
130 void move_sig(double factor, Qt::Orientation orientation, bool forward=true);
131 void move_sig(double dx, double dy, bool forward=true);
132 void transform_sig(const DateTimeRangeTransformation& tranformation, bool forward=true);
133 void setrange_sig(const DateTimeRange& range, bool updateVar=false, bool forward=true);
133 void zoom_sig(double factor, int center, Qt::Orientation orientation, bool forward = true);
134 void move_sig(double factor, Qt::Orientation orientation, bool forward = true);
135 void move_sig(double dx, double dy, bool forward = true);
136 void transform_sig(const DateTimeRangeTransformation& tranformation, bool forward = true);
137 void setrange_sig(const DateTimeRange& range, bool updateVar = false, bool forward = true);
134 138
135 139 protected:
136 void closeEvent(QCloseEvent *event) override;
137 void enterEvent(QEvent *event) override;
138 void leaveEvent(QEvent *event) override;
139 void wheelEvent(QWheelEvent * event) override;
140 void mouseMoveEvent(QMouseEvent *event) override;
141 void mouseReleaseEvent(QMouseEvent *event) override;
142 void mousePressEvent(QMouseEvent *event) override;
143 void mouseDoubleClickEvent(QMouseEvent *event) override;
144 void keyReleaseEvent(QKeyEvent * event) override;
145 void keyPressEvent(QKeyEvent * event) override;
146
147 QCustomPlot &plot() const noexcept;
140 void closeEvent(QCloseEvent* event) override;
141 void enterEvent(QEvent* event) override;
142 void leaveEvent(QEvent* event) override;
143 void wheelEvent(QWheelEvent* event) override;
144 void mouseMoveEvent(QMouseEvent* event) override;
145 void mouseReleaseEvent(QMouseEvent* event) override;
146 void mousePressEvent(QMouseEvent* event) override;
147 void mouseDoubleClickEvent(QMouseEvent* event) override;
148 void keyReleaseEvent(QKeyEvent* event) override;
149 void keyPressEvent(QKeyEvent* event) override;
150
151 QCustomPlot& plot() const noexcept;
148 152
149 153 private:
150 Ui::VisualizationGraphWidget *ui;
154 Ui::VisualizationGraphWidget* ui;
151 155
152 156 class VisualizationGraphWidgetPrivate;
153 157 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
154 158
155 159 private slots:
156 160 /// Slot called when right clicking on the graph (displays a menu)
157 void onGraphMenuRequested(const QPoint &pos) noexcept;
161 void onGraphMenuRequested(const QPoint& pos) noexcept;
158 162
159 163 /// Rescale the X axe to range parameter
160 // void onRangeChanged(const QCPRange &newRange, const QCPRange &oldRange);
164 // void onRangeChanged(const QCPRange &newRange, const QCPRange &oldRange);
161 165
162 166 /// Slot called when a mouse double click was made
163 void onMouseDoubleClick(QMouseEvent *event) noexcept;
167 void onMouseDoubleClick(QMouseEvent* event) noexcept;
164 168 /// Slot called when a mouse move was made
165 void onMouseMove(QMouseEvent *event) noexcept;
169 void onMouseMove(QMouseEvent* event) noexcept;
166 170 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
167 void onMouseWheel(QWheelEvent *event) noexcept;
171 void onMouseWheel(QWheelEvent* event) noexcept;
168 172 /// Slot called when a mouse press was made, to activate the calibration of a graph
169 void onMousePress(QMouseEvent *event) noexcept;
173 void onMousePress(QMouseEvent* event) noexcept;
170 174 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
171 void onMouseRelease(QMouseEvent *event) noexcept;
175 void onMouseRelease(QMouseEvent* event) noexcept;
172 176
173 177 void onDataCacheVariableUpdated();
174 178
175 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const DateTimeRange &range);
179 void onUpdateVarDisplaying(std::shared_ptr<Variable2> variable, const DateTimeRange& range);
176 180
177 181 void variableUpdated(QUuid id);
178 void variableDeleted(const std::shared_ptr<Variable>&);
182 void variableDeleted(const std::shared_ptr<Variable2>&);
179 183 };
180 184
181 185 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -14,29 +14,31 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget)
14 14 class Variable;
15 15 class VisualizationZoneWidget;
16 16
17 namespace Ui {
17 namespace Ui
18 {
18 19 class VisualizationTabWidget;
19 20 } // namespace Ui
20 21
21 class VisualizationTabWidget : public QWidget, public IVisualizationWidget {
22 class VisualizationTabWidget : public QWidget, public IVisualizationWidget
23 {
22 24 Q_OBJECT
23 25
24 26 public:
25 explicit VisualizationTabWidget(const QString &name = {}, QWidget *parent = 0);
27 explicit VisualizationTabWidget(const QString& name = {}, QWidget* parent = 0);
26 28 virtual ~VisualizationTabWidget();
27 29
28 30 /// Adds a zone widget
29 void addZone(VisualizationZoneWidget *zoneWidget);
31 void addZone(VisualizationZoneWidget* zoneWidget);
30 32
31 33 /// Inserts a zone widget at the specified position
32 void insertZone(int index, VisualizationZoneWidget *zoneWidget);
34 void insertZone(int index, VisualizationZoneWidget* zoneWidget);
33 35
34 36 /// Returns the list of zone widget names in the order they are displayed
35 37 QStringList availableZoneWidgets() const;
36 38
37 39 /// Returns the zone with the specified name.
38 40 /// If multiple zone with the same name exist, the first one is returned.
39 VisualizationZoneWidget *getZoneWithName(const QString &zoneName);
41 VisualizationZoneWidget* getZoneWithName(const QString& zoneName);
40 42
41 43 /**
42 44 * Creates a zone using a variable. The variable will be displayed in a new graph of the new
@@ -44,7 +46,7 public:
44 46 * @param variable the variable for which to create the zone
45 47 * @return the pointer to the created zone
46 48 */
47 VisualizationZoneWidget *createZone(std::shared_ptr<Variable> variable);
49 VisualizationZoneWidget* createZone(std::shared_ptr<Variable2> variable);
48 50
49 51 /**
50 52 * Creates a zone using a list of variables. The variables will be displayed in a new graph of
@@ -53,36 +55,36 public:
53 55 * @param index The index where the zone should be inserted in the layout
54 56 * @return the pointer to the created zone
55 57 */
56 VisualizationZoneWidget *createZone(const std::vector<std::shared_ptr<Variable> > &variables,
57 int index);
58 VisualizationZoneWidget* createZone(
59 const std::vector<std::shared_ptr<Variable2>>& variables, int index);
58 60
59 61 /**
60 62 * Creates a zone which is empty (no variables). The zone is inserted at the specified index.
61 63 * @param index The index where the zone should be inserted in the layout
62 64 * @return the pointer to the created zone
63 65 */
64 VisualizationZoneWidget *createEmptyZone(int index);
66 VisualizationZoneWidget* createEmptyZone(int index);
65 67
66 68 // IVisualizationWidget interface
67 void accept(IVisualizationWidgetVisitor *visitor) override;
68 bool canDrop(const Variable &variable) const override;
69 bool contains(const Variable &variable) const override;
69 void accept(IVisualizationWidgetVisitor* visitor) override;
70 bool canDrop(Variable2& variable) const override;
71 bool contains(Variable2& variable) const override;
70 72 QString name() const override;
71 73
72 74 protected:
73 void closeEvent(QCloseEvent *event) override;
75 void closeEvent(QCloseEvent* event) override;
74 76
75 77 private:
76 78 /// @return the layout of tab in which zones are added
77 QLayout &tabLayout() const noexcept;
79 QLayout& tabLayout() const noexcept;
78 80
79 Ui::VisualizationTabWidget *ui;
81 Ui::VisualizationTabWidget* ui;
80 82
81 83 class VisualizationTabWidgetPrivate;
82 84 spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl;
83 85
84 86 private slots:
85 void dropMimeData(int index, const QMimeData *mimeData);
87 void dropMimeData(int index, const QMimeData* mimeData);
86 88 };
87 89
88 90 #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H
@@ -12,30 +12,32
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationWidget)
13 13
14 14 class QMenu;
15 class Variable;
15 class Variable2;
16 16 class VisualizationTabWidget;
17 17 class VisualizationSelectionZoneManager;
18 18
19 namespace Ui {
19 namespace Ui
20 {
20 21 class VisualizationWidget;
21 22 } // namespace Ui
22 23
23 class VisualizationWidget : public QWidget, public IVisualizationWidget {
24 class VisualizationWidget : public QWidget, public IVisualizationWidget
25 {
24 26 Q_OBJECT
25 27
26 28 public:
27 explicit VisualizationWidget(QWidget *parent = 0);
29 explicit VisualizationWidget(QWidget* parent = 0);
28 30 virtual ~VisualizationWidget();
29 31
30 32 /// Returns the class which manage the selection of selection zone across the visualization
31 VisualizationSelectionZoneManager &selectionZoneManager() const;
33 VisualizationSelectionZoneManager& selectionZoneManager() const;
32 34
33 VisualizationTabWidget *currentTabWidget() const;
35 VisualizationTabWidget* currentTabWidget() const;
34 36
35 37 // IVisualizationWidget interface
36 void accept(IVisualizationWidgetVisitor *visitor) override;
37 bool canDrop(const Variable &variable) const override;
38 bool contains(const Variable &variable) const override;
38 void accept(IVisualizationWidgetVisitor* visitor) override;
39 bool canDrop(Variable2& variable) const override;
40 bool contains(Variable2& variable) const override;
39 41 QString name() const override;
40 42
41 43 public slots:
@@ -44,19 +46,19 public slots:
44 46 * @param menu the parent menu of the generated menu
45 47 * @param variables the variables for which to generate the menu
46 48 */
47 void attachVariableMenu(QMenu *menu,
48 const QVector<std::shared_ptr<Variable> > &variables) noexcept;
49 void attachVariableMenu(
50 QMenu* menu, const QVector<std::shared_ptr<Variable2>>& variables) noexcept;
49 51
50 52 /// Slot called when a variable is about to be deleted from SciQlop
51 void onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept;
53 void onVariableAboutToBeDeleted(std::shared_ptr<Variable2> variable) noexcept;
52 54
53 void onRangeChanged(std::shared_ptr<Variable> variable, const DateTimeRange &range) noexcept;
55 void onRangeChanged(std::shared_ptr<Variable2> variable, const DateTimeRange& range) noexcept;
54 56
55 57 protected:
56 void closeEvent(QCloseEvent *event) override;
58 void closeEvent(QCloseEvent* event) override;
57 59
58 60 private:
59 Ui::VisualizationWidget *ui;
61 Ui::VisualizationWidget* ui;
60 62
61 63 class VisualizationWidgetPrivate;
62 64 spimpl::unique_impl_ptr<VisualizationWidgetPrivate> impl;
@@ -14,29 +14,31
14 14
15 15 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
16 16
17 namespace Ui {
17 namespace Ui
18 {
18 19 class VisualizationZoneWidget;
19 20 } // namespace Ui
20 21
21 class Variable;
22 class Variable2;
22 23 class VisualizationGraphWidget;
23 24
24 class VisualizationZoneWidget : public VisualizationDragWidget, public IVisualizationWidget {
25 class VisualizationZoneWidget : public VisualizationDragWidget, public IVisualizationWidget
26 {
25 27 Q_OBJECT
26 28
27 29 public:
28 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
30 explicit VisualizationZoneWidget(const QString& name = {}, QWidget* parent = 0);
29 31 virtual ~VisualizationZoneWidget();
30 32
31 33 /// Sets the range of the zone, only works if there is at least one graph in the zone
32 34 /// Note: calibrations between graphs are lost.
33 void setZoneRange(const DateTimeRange &range);
35 void setZoneRange(const DateTimeRange& range);
34 36
35 37 /// Adds a graph widget
36 void addGraph(VisualizationGraphWidget *graphWidget);
38 void addGraph(VisualizationGraphWidget* graphWidget);
37 39
38 40 /// Inserts a graph widget
39 void insertGraph(int index, VisualizationGraphWidget *graphWidget);
41 void insertGraph(int index, VisualizationGraphWidget* graphWidget);
40 42
41 43 /**
42 44 * Creates a graph using a variable. The variable will be displayed in the new graph.
@@ -44,7 +46,7 public:
44 46 * @param variable the variable for which to create the graph
45 47 * @return the pointer to the created graph
46 48 */
47 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
49 VisualizationGraphWidget* createGraph(std::shared_ptr<Variable2> variable);
48 50
49 51 /**
50 52 * Creates a graph using a variable. The variable will be displayed in the new graph.
@@ -53,7 +55,7 public:
53 55 * @param index The index where the graph should be inserted in the layout
54 56 * @return the pointer to the created graph
55 57 */
56 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable, int index);
58 VisualizationGraphWidget* createGraph(std::shared_ptr<Variable2> variable, int index);
57 59
58 60 /**
59 61 * Creates a graph using a list of variables. The variables will be displayed in the new graph.
@@ -62,45 +64,45 public:
62 64 * @param index The index where the graph should be inserted in the layout
63 65 * @return the pointer to the created graph
64 66 */
65 VisualizationGraphWidget *createGraph( std::vector<std::shared_ptr<Variable> > variables,
66 int index);
67 VisualizationGraphWidget* createGraph(
68 std::vector<std::shared_ptr<Variable2>> variables, int index);
67 69
68 70 /// Returns the first graph in the zone or nullptr if there is no graph inside
69 VisualizationGraphWidget *firstGraph() const;
71 VisualizationGraphWidget* firstGraph() const;
70 72
71 73 /// Closes all graphes inside the zone
72 74 void closeAllGraphs();
73 75
74 76 // IVisualizationWidget interface
75 void accept(IVisualizationWidgetVisitor *visitor) override;
76 bool canDrop(const Variable &variable) const override;
77 bool contains(const Variable &variable) const override;
77 void accept(IVisualizationWidgetVisitor* visitor) override;
78 bool canDrop(Variable2& variable) const override;
79 bool contains(Variable2& variable) const override;
78 80 QString name() const override;
79 81
80 82 // VisualisationDragWidget
81 QMimeData *mimeData(const QPoint &position) const override;
83 QMimeData* mimeData(const QPoint& position) const override;
82 84 bool isDragAllowed() const override;
83 85
84 void notifyMouseMoveInGraph(const QPointF &graphPosition, const QPointF &plotPosition,
85 VisualizationGraphWidget *graphWidget);
86 void notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget);
86 void notifyMouseMoveInGraph(const QPointF& graphPosition, const QPointF& plotPosition,
87 VisualizationGraphWidget* graphWidget);
88 void notifyMouseLeaveGraph(VisualizationGraphWidget* graphWidget);
87 89
88 90 protected:
89 void closeEvent(QCloseEvent *event) override;
91 void closeEvent(QCloseEvent* event) override;
90 92
91 93 private:
92 Ui::VisualizationZoneWidget *ui;
94 Ui::VisualizationZoneWidget* ui;
93 95
94 96 class VisualizationZoneWidgetPrivate;
95 97 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
96 98
97 99 private slots:
98 void onVariableAdded(std::shared_ptr<Variable> variable);
100 void onVariableAdded(std::shared_ptr<Variable2> variable);
99 101 /// Slot called when a variable is about to be removed from a graph contained in the zone
100 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
102 void onVariableAboutToBeRemoved(std::shared_ptr<Variable2> variable);
101 103
102 void dropMimeData(int index, const QMimeData *mimeData);
103 void dropMimeDataOnGraph(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
104 void dropMimeData(int index, const QMimeData* mimeData);
105 void dropMimeDataOnGraph(VisualizationDragWidget* dragWidget, const QMimeData* mimeData);
104 106 };
105 107
106 108 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -8,31 +8,32
8 8 #include <set>
9 9
10 10 class IVisualizationWidget;
11 class Variable;
11 class Variable2;
12 12
13 13 /**
14 14 * @brief The FindVariableOperation class defines an operation that traverses all of visualization
15 15 * widgets to determine which ones contain the variable passed as parameter. The result of the
16 16 * operation is the list of widgets that contain the variable.
17 17 */
18 class FindVariableOperation : public IVisualizationWidgetVisitor {
18 class FindVariableOperation : public IVisualizationWidgetVisitor
19 {
19 20 public:
20 21 /**
21 22 * Ctor
22 23 * @param variable the variable to find
23 24 */
24 explicit FindVariableOperation(std::shared_ptr<Variable> variable);
25 explicit FindVariableOperation(std::shared_ptr<Variable2> variable);
25 26
26 void visitEnter(VisualizationWidget *widget) override final;
27 void visitLeave(VisualizationWidget *widget) override final;
28 void visitEnter(VisualizationTabWidget *tabWidget) override final;
29 void visitLeave(VisualizationTabWidget *tabWidget) override final;
30 void visitEnter(VisualizationZoneWidget *zoneWidget) override final;
31 void visitLeave(VisualizationZoneWidget *zoneWidget) override final;
32 void visit(VisualizationGraphWidget *graphWidget) override final;
27 void visitEnter(VisualizationWidget* widget) override final;
28 void visitLeave(VisualizationWidget* widget) override final;
29 void visitEnter(VisualizationTabWidget* tabWidget) override final;
30 void visitLeave(VisualizationTabWidget* tabWidget) override final;
31 void visitEnter(VisualizationZoneWidget* zoneWidget) override final;
32 void visitLeave(VisualizationZoneWidget* zoneWidget) override final;
33 void visit(VisualizationGraphWidget* graphWidget) override final;
33 34
34 35 /// @return the widgets that contain the variable
35 std::set<IVisualizationWidget *> result() const noexcept;
36 std::set<IVisualizationWidget*> result() const noexcept;
36 37
37 38 private:
38 39 class FindVariableOperationPrivate;
@@ -11,7 +11,7
11 11
12 12 class QMenu;
13 13 class IVisualizationWidget;
14 class Variable;
14 class Variable2;
15 15
16 16 Q_DECLARE_LOGGING_CATEGORY(LOG_GenerateVariableMenuOperation)
17 17
@@ -20,7 +20,8 Q_DECLARE_LOGGING_CATEGORY(LOG_GenerateVariableMenuOperation)
20 20 * visualization widgets to determine which can accommodate a variable. The result of the operation
21 21 * is a menu that contains actions to add the variable into the containers.
22 22 */
23 class GenerateVariableMenuOperation : public IVisualizationWidgetVisitor {
23 class GenerateVariableMenuOperation : public IVisualizationWidgetVisitor
24 {
24 25 public:
25 26 /**
26 27 * Ctor
@@ -29,16 +30,16 public:
29 30 * @param variableContainers the containers that already contain the variable for which to
30 31 * generate the menu
31 32 */
32 explicit GenerateVariableMenuOperation(QMenu *menu, std::shared_ptr<Variable> variable,
33 std::set<IVisualizationWidget *> variableContainers);
34
35 void visitEnter(VisualizationWidget *widget) override final;
36 void visitLeave(VisualizationWidget *widget) override final;
37 void visitEnter(VisualizationTabWidget *tabWidget) override final;
38 void visitLeave(VisualizationTabWidget *tabWidget) override final;
39 void visitEnter(VisualizationZoneWidget *zoneWidget) override final;
40 void visitLeave(VisualizationZoneWidget *zoneWidget) override final;
41 void visit(VisualizationGraphWidget *graphWidget) override final;
33 explicit GenerateVariableMenuOperation(QMenu* menu, std::shared_ptr<Variable2> variable,
34 std::set<IVisualizationWidget*> variableContainers);
35
36 void visitEnter(VisualizationWidget* widget) override final;
37 void visitLeave(VisualizationWidget* widget) override final;
38 void visitEnter(VisualizationTabWidget* tabWidget) override final;
39 void visitLeave(VisualizationTabWidget* tabWidget) override final;
40 void visitEnter(VisualizationZoneWidget* zoneWidget) override final;
41 void visitLeave(VisualizationZoneWidget* zoneWidget) override final;
42 void visit(VisualizationGraphWidget* graphWidget) override final;
42 43
43 44 private:
44 45 class GenerateVariableMenuOperationPrivate;
@@ -9,7 +9,7
9 9
10 10 #include <memory>
11 11
12 class Variable;
12 class Variable2;
13 13
14 14 Q_DECLARE_LOGGING_CATEGORY(LOG_RemoveVariableOperation)
15 15
@@ -17,21 +17,22 Q_DECLARE_LOGGING_CATEGORY(LOG_RemoveVariableOperation)
17 17 * @brief The RemoveVariableOperation class defines an operation that traverses all of visualization
18 18 * widgets to remove a variable if they contain it
19 19 */
20 class RemoveVariableOperation : public IVisualizationWidgetVisitor {
20 class RemoveVariableOperation : public IVisualizationWidgetVisitor
21 {
21 22 public:
22 23 /**
23 24 * Ctor
24 25 * @param variable the variable to remove from widgets
25 26 */
26 explicit RemoveVariableOperation(std::shared_ptr<Variable> variable);
27
28 void visitEnter(VisualizationWidget *widget) override final;
29 void visitLeave(VisualizationWidget *widget) override final;
30 void visitEnter(VisualizationTabWidget *tabWidget) override final;
31 void visitLeave(VisualizationTabWidget *tabWidget) override final;
32 void visitEnter(VisualizationZoneWidget *zoneWidget) override final;
33 void visitLeave(VisualizationZoneWidget *zoneWidget) override final;
34 void visit(VisualizationGraphWidget *graphWidget) override final;
27 explicit RemoveVariableOperation(std::shared_ptr<Variable2> variable);
28
29 void visitEnter(VisualizationWidget* widget) override final;
30 void visitLeave(VisualizationWidget* widget) override final;
31 void visitEnter(VisualizationTabWidget* tabWidget) override final;
32 void visitLeave(VisualizationTabWidget* tabWidget) override final;
33 void visitEnter(VisualizationZoneWidget* zoneWidget) override final;
34 void visitLeave(VisualizationZoneWidget* zoneWidget) override final;
35 void visit(VisualizationGraphWidget* graphWidget) override final;
35 36
36 37 private:
37 38 class RemoveVariableOperationPrivate;
@@ -10,7 +10,7
10 10
11 11 #include <memory>
12 12
13 class Variable;
13 class Variable2;
14 14
15 15 Q_DECLARE_LOGGING_CATEGORY(LOG_RescaleAxeOperation)
16 16
@@ -18,21 +18,22 Q_DECLARE_LOGGING_CATEGORY(LOG_RescaleAxeOperation)
18 18 * @brief The RescaleAxeOperation class defines an operation that traverses all of visualization
19 19 * widgets to remove a variable if they contain it
20 20 */
21 class RescaleAxeOperation : public IVisualizationWidgetVisitor {
21 class RescaleAxeOperation : public IVisualizationWidgetVisitor
22 {
22 23 public:
23 24 /**
24 25 * Ctor
25 26 * @param variable the variable to remove from widgets
26 27 */
27 explicit RescaleAxeOperation(std::shared_ptr<Variable> variable, const DateTimeRange &range);
28
29 void visitEnter(VisualizationWidget *widget) override final;
30 void visitLeave(VisualizationWidget *widget) override final;
31 void visitEnter(VisualizationTabWidget *tabWidget) override final;
32 void visitLeave(VisualizationTabWidget *tabWidget) override final;
33 void visitEnter(VisualizationZoneWidget *zoneWidget) override final;
34 void visitLeave(VisualizationZoneWidget *zoneWidget) override final;
35 void visit(VisualizationGraphWidget *graphWidget) override final;
28 explicit RescaleAxeOperation(std::shared_ptr<Variable2> variable, const DateTimeRange& range);
29
30 void visitEnter(VisualizationWidget* widget) override final;
31 void visitLeave(VisualizationWidget* widget) override final;
32 void visitEnter(VisualizationTabWidget* tabWidget) override final;
33 void visitLeave(VisualizationTabWidget* tabWidget) override final;
34 void visitEnter(VisualizationZoneWidget* zoneWidget) override final;
35 void visitLeave(VisualizationZoneWidget* zoneWidget) override final;
36 void visit(VisualizationGraphWidget* graphWidget) override final;
36 37
37 38 private:
38 39 class RescaleAxeOperationPrivate;
@@ -23,39 +23,40
23 23 Q_LOGGING_CATEGORY(LOG_DragDropGuiController, "DragDropGuiController")
24 24
25 25
26 struct DragDropGuiController::DragDropGuiControllerPrivate {
26 struct DragDropGuiController::DragDropGuiControllerPrivate
27 {
27 28
28 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
29 VisualizationDragWidget* m_CurrentDragWidget = nullptr;
29 30 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
30 QLabel *m_PlaceHolderLabel;
31 QWidget *m_PlaceBackground;
31 QLabel* m_PlaceHolderLabel;
32 QWidget* m_PlaceBackground;
32 33 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
33 34 std::unique_ptr<DragDropTabSwitcher> m_DragDropTabSwitcher = nullptr;
34 35 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
35 36 // QTemporaryFile to have a name which is not generated.
36 37
37 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
38 VisualizationDragWidget* m_HighlightedDragWidget = nullptr;
38 39
39 40 QMetaObject::Connection m_DragWidgetDestroyedConnection;
40 41 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
41 42
42 QList<QWidget *> m_WidgetToClose;
43 QList<QWidget*> m_WidgetToClose;
43 44
44 45 explicit DragDropGuiControllerPrivate()
45 : m_PlaceHolder{std::make_unique<QWidget>()},
46 m_DragDropScroller{std::make_unique<DragDropScroller>()},
47 m_DragDropTabSwitcher{std::make_unique<DragDropTabSwitcher>()}
46 : m_PlaceHolder { std::make_unique<QWidget>() }
47 , m_DragDropScroller { std::make_unique<DragDropScroller>() }
48 , m_DragDropTabSwitcher { std::make_unique<DragDropTabSwitcher>() }
48 49 {
49 50
50 auto layout = new QVBoxLayout{m_PlaceHolder.get()};
51 auto layout = new QVBoxLayout { m_PlaceHolder.get() };
51 52 layout->setSpacing(0);
52 53 layout->setContentsMargins(0, 0, 0, 0);
53 54
54 m_PlaceHolderLabel = new QLabel{"", m_PlaceHolder.get()};
55 m_PlaceHolderLabel = new QLabel { "", m_PlaceHolder.get() };
55 56 m_PlaceHolderLabel->setMinimumHeight(25);
56 57 layout->addWidget(m_PlaceHolderLabel);
57 58
58 m_PlaceBackground = new QWidget{m_PlaceHolder.get()};
59 m_PlaceBackground = new QWidget { m_PlaceHolder.get() };
59 60 m_PlaceBackground->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
60 61 layout->addWidget(m_PlaceBackground);
61 62
@@ -65,14 +66,16 struct DragDropGuiController::DragDropGuiControllerPrivate {
65 66 m_ImageTempUrl = QDir::temp().absoluteFilePath("Sciqlop_graph.png");
66 67 }
67 68
68 void preparePlaceHolder(DragDropGuiController::PlaceHolderType type,
69 const QString &topLabelText) const
69 void preparePlaceHolder(
70 DragDropGuiController::PlaceHolderType type, const QString& topLabelText) const
70 71 {
71 if (m_CurrentDragWidget) {
72 if (m_CurrentDragWidget)
73 {
72 74 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
73 75 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
74 76 }
75 else {
77 else
78 {
76 79 // Configuration of the placeHolder when there is no dragWidget
77 80 // (for instance with a drag from a variable)
78 81
@@ -80,7 +83,8 struct DragDropGuiController::DragDropGuiControllerPrivate {
80 83 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
81 84 }
82 85
83 switch (type) {
86 switch (type)
87 {
84 88 case DragDropGuiController::PlaceHolderType::Graph:
85 89 m_PlaceBackground->setStyleSheet(
86 90 "background-color: #BBD5EE; border: 1px solid #2A7FD4");
@@ -100,7 +104,7 struct DragDropGuiController::DragDropGuiControllerPrivate {
100 104
101 105
102 106 DragDropGuiController::DragDropGuiController()
103 : impl{spimpl::make_unique_impl<DragDropGuiControllerPrivate>()}
107 : impl { spimpl::make_unique_impl<DragDropGuiControllerPrivate>() }
104 108 {
105 109 }
106 110
@@ -115,35 +119,36 void DragDropGuiController::resetDragAndDrop()
115 119 impl->m_HighlightedDragWidget = nullptr;
116 120 }
117 121
118 void DragDropGuiController::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
122 void DragDropGuiController::setCurrentDragWidget(VisualizationDragWidget* dragWidget)
119 123 {
120 if (impl->m_CurrentDragWidget) {
124 if (impl->m_CurrentDragWidget)
125 {
121 126
122 127 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
123 128 }
124 129
125 if (dragWidget) {
130 if (dragWidget)
131 {
126 132 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
127 impl->m_DragWidgetDestroyedConnection
128 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
129 [this]() { impl->m_CurrentDragWidget = nullptr; });
133 impl->m_DragWidgetDestroyedConnection = QObject::connect(dragWidget,
134 &VisualizationDragWidget::destroyed, [this]() { impl->m_CurrentDragWidget = nullptr; });
130 135 }
131 136
132 137 impl->m_CurrentDragWidget = dragWidget;
133 138 }
134 139
135 VisualizationDragWidget *DragDropGuiController::getCurrentDragWidget() const
140 VisualizationDragWidget* DragDropGuiController::getCurrentDragWidget() const
136 141 {
137 142 return impl->m_CurrentDragWidget;
138 143 }
139 144
140 QWidget &DragDropGuiController::placeHolder() const
145 QWidget& DragDropGuiController::placeHolder() const
141 146 {
142 147 return *impl->m_PlaceHolder;
143 148 }
144 149
145 void DragDropGuiController::insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
146 const QString &topLabelText)
150 void DragDropGuiController::insertPlaceHolder(
151 QVBoxLayout* layout, int index, PlaceHolderType type, const QString& topLabelText)
147 152 {
148 153 removePlaceHolder();
149 154 impl->preparePlaceHolder(type, topLabelText);
@@ -154,7 +159,8 void DragDropGuiController::insertPlaceHolder(QVBoxLayout *layout, int index, Pl
154 159 void DragDropGuiController::removePlaceHolder()
155 160 {
156 161 auto parentWidget = impl->m_PlaceHolder->parentWidget();
157 if (parentWidget) {
162 if (parentWidget)
163 {
158 164 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
159 165 impl->m_PlaceHolder->setParent(nullptr);
160 166 impl->m_PlaceHolder->hide();
@@ -166,57 +172,59 bool DragDropGuiController::isPlaceHolderSet() const
166 172 return impl->m_PlaceHolder->parentWidget();
167 173 }
168 174
169 void DragDropGuiController::addDragDropScrollArea(QScrollArea *scrollArea)
175 void DragDropGuiController::addDragDropScrollArea(QScrollArea* scrollArea)
170 176 {
171 177 impl->m_DragDropScroller->addScrollArea(scrollArea);
172 178 }
173 179
174 void DragDropGuiController::removeDragDropScrollArea(QScrollArea *scrollArea)
180 void DragDropGuiController::removeDragDropScrollArea(QScrollArea* scrollArea)
175 181 {
176 182 impl->m_DragDropScroller->removeScrollArea(scrollArea);
177 183 }
178 184
179 void DragDropGuiController::addDragDropTabBar(QTabBar *tabBar)
185 void DragDropGuiController::addDragDropTabBar(QTabBar* tabBar)
180 186 {
181 187 impl->m_DragDropTabSwitcher->addTabBar(tabBar);
182 188 }
183 189
184 void DragDropGuiController::removeDragDropTabBar(QTabBar *tabBar)
190 void DragDropGuiController::removeDragDropTabBar(QTabBar* tabBar)
185 191 {
186 192 impl->m_DragDropTabSwitcher->removeTabBar(tabBar);
187 193 }
188 194
189 QUrl DragDropGuiController::imageTemporaryUrl(const QImage &image) const
195 QUrl DragDropGuiController::imageTemporaryUrl(const QImage& image) const
190 196 {
191 197 image.save(impl->m_ImageTempUrl);
192 198 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
193 199 }
194 200
195 void DragDropGuiController::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
201 void DragDropGuiController::setHightlightedDragWidget(VisualizationDragWidget* dragWidget)
196 202 {
197 if (impl->m_HighlightedDragWidget) {
203 if (impl->m_HighlightedDragWidget)
204 {
198 205 impl->m_HighlightedDragWidget->highlightForMerge(false);
199 206 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
200 207 }
201 208
202 if (dragWidget) {
209 if (dragWidget)
210 {
203 211 dragWidget->highlightForMerge(true);
204 212
205 213 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
206 214 impl->m_DragWidgetDestroyedConnection
207 215 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
208 [this]() { impl->m_HighlightedDragWidget = nullptr; });
216 [this]() { impl->m_HighlightedDragWidget = nullptr; });
209 217 }
210 218
211 219 impl->m_HighlightedDragWidget = dragWidget;
212 220 }
213 221
214 VisualizationDragWidget *DragDropGuiController::getHightlightedDragWidget() const
222 VisualizationDragWidget* DragDropGuiController::getHightlightedDragWidget() const
215 223 {
216 224 return impl->m_HighlightedDragWidget;
217 225 }
218 226
219 void DragDropGuiController::delayedCloseWidget(QWidget *widget)
227 void DragDropGuiController::delayedCloseWidget(QWidget* widget)
220 228 {
221 229 widget->hide();
222 230 impl->m_WidgetToClose << widget;
@@ -224,7 +232,8 void DragDropGuiController::delayedCloseWidget(QWidget *widget)
224 232
225 233 void DragDropGuiController::doCloseWidgets()
226 234 {
227 for (auto widget : impl->m_WidgetToClose) {
235 for (auto widget : impl->m_WidgetToClose)
236 {
228 237 widget->close();
229 238 }
230 239
@@ -232,9 +241,10 void DragDropGuiController::doCloseWidgets()
232 241 }
233 242
234 243 bool DragDropGuiController::checkMimeDataForVisualization(
235 const QMimeData *mimeData, VisualizationDragDropContainer *dropContainer)
244 const QMimeData* mimeData, VisualizationDragDropContainer* dropContainer)
236 245 {
237 if (!mimeData || !dropContainer) {
246 if (!mimeData || !dropContainer)
247 {
238 248 qCWarning(LOG_DragDropGuiController()) << QObject::tr(
239 249 "DragDropGuiController::checkMimeDataForVisualization, invalid input parameters.");
240 250 Q_ASSERT(false);
@@ -243,61 +253,75 bool DragDropGuiController::checkMimeDataForVisualization(
243 253
244 254 auto result = false;
245 255
246 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
256 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST))
257 {
247 258 auto variables = sqpApp->variableController().variables(
248 259 Variable::variablesIDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
249 260
250 if (variables.size() == 1) {
261 if (variables.size() == 1)
262 {
251 263
252 264 auto variable = variables[0];
253 if (variable->dataSeries() != nullptr) {
265 if (variable->data() != nullptr)
266 {
254 267
255 268 // Check that the variable is not already in a graph
256 269
257 270 auto parent = dropContainer->parentWidget();
258 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
271 while (parent && qobject_cast<VisualizationWidget*>(parent) == nullptr)
272 {
259 273 parent = parent->parentWidget(); // Search for the top level VisualizationWidget
260 274 }
261 275
262 if (parent) {
263 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
276 if (parent)
277 {
278 auto visualizationWidget = static_cast<VisualizationWidget*>(parent);
264 279
265 FindVariableOperation findVariableOperation{variable};
280 FindVariableOperation findVariableOperation { variable };
266 281 visualizationWidget->accept(&findVariableOperation);
267 282 auto variableContainers = findVariableOperation.result();
268 if (variableContainers.empty()) {
283 if (variableContainers.empty())
284 {
269 285 result = true;
270 286 }
271 else {
287 else
288 {
272 289 // result = false: the variable already exist in the visualisation
273 290 }
274 291 }
275 else {
292 else
293 {
276 294 qCWarning(LOG_DragDropGuiController()) << QObject::tr(
277 295 "DragDropGuiController::checkMimeDataForVisualization, the parent "
278 296 "VisualizationWidget cannot be found. Cannot check if the variable is "
279 297 "already used or not.");
280 298 }
281 299 }
282 else {
300 else
301 {
283 302 // result = false: the variable is not fully loaded
284 303 }
285 304 }
286 else {
305 else
306 {
287 307 // result = false: cannot drop multiple variables in the visualisation
288 308 }
289 309 }
290 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
310 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST))
311 {
291 312 auto productDataList = sqpApp->dataSourceController().productsDataForMimeData(
292 313 mimeData->data(MIME_TYPE_PRODUCT_LIST));
293 if (productDataList.count() == 1) {
314 if (productDataList.count() == 1)
315 {
294 316 result = true;
295 317 }
296 else {
318 else
319 {
297 320 // result = false: cannot drop multiple products in the visualisation
298 321 }
299 322 }
300 else {
323 else
324 {
301 325 // Other MIME data
302 326 // no special rules, accepted by default
303 327 result = true;
@@ -1,10 +1,10
1 #include <DataSource/DataSourceController.h>
1 2 #include <Variable/RenameVariableDialog.h>
2 3 #include <Variable/Variable.h>
3 4 #include <Variable/VariableController2.h>
4 5 #include <Variable/VariableInspectorWidget.h>
5 6 #include <Variable/VariableMenuHeaderWidget.h>
6 7 #include <Variable/VariableModel2.h>
7 #include <DataSource/DataSourceController.h>
8 8
9 9 #include <ui_VariableInspectorWidget.h>
10 10
@@ -19,22 +19,25
19 19 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
20 20
21 21
22 class QProgressBarItemDelegate : public QStyledItemDelegate {
22 class QProgressBarItemDelegate : public QStyledItemDelegate
23 {
23 24
24 25 public:
25 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
26 QProgressBarItemDelegate(QObject* parent) : QStyledItemDelegate { parent } {}
26 27
27 void paint(QPainter *painter, const QStyleOptionViewItem &option,
28 const QModelIndex &index) const
28 void paint(
29 QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
29 30 {
30 31 auto data = index.data(Qt::DisplayRole);
31 32 auto progressData = index.data(VariableRoles::ProgressRole);
32 if (data.isValid() && progressData.isValid()) {
33 if (data.isValid() && progressData.isValid())
34 {
33 35 auto name = data.value<QString>();
34 36 auto progress = progressData.value<double>();
35 if (progress > 0) {
37 if (progress > 0)
38 {
36 39 auto cancelButtonWidth = 20;
37 auto progressBarOption = QStyleOptionProgressBar{};
40 auto progressBarOption = QStyleOptionProgressBar {};
38 41 auto progressRect = option.rect;
39 42 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
40 43 progressBarOption.rect = progressRect;
@@ -47,66 +50,75 public:
47 50 progressBarOption.textAlignment = Qt::AlignCenter;
48 51
49 52
50 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
51 painter);
53 QApplication::style()->drawControl(
54 QStyle::CE_ProgressBar, &progressBarOption, painter);
52 55
53 56 // Cancel button
54 57 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
55 option.rect.height());
56 auto buttonOption = QStyleOptionButton{};
58 option.rect.height());
59 auto buttonOption = QStyleOptionButton {};
57 60 buttonOption.rect = buttonRect;
58 61 buttonOption.text = "X";
59 62
60 63 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
61 64 }
62 else {
65 else
66 {
63 67 QStyledItemDelegate::paint(painter, option, index);
64 68 }
65 69 }
66 else {
70 else
71 {
67 72 QStyledItemDelegate::paint(painter, option, index);
68 73 }
69 74 }
70 75
71 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
72 const QModelIndex &index)
76 bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option,
77 const QModelIndex& index)
73 78 {
74 if (event->type() == QEvent::MouseButtonRelease) {
79 if (event->type() == QEvent::MouseButtonRelease)
80 {
75 81 auto data = index.data(Qt::DisplayRole);
76 82 auto progressData = index.data(VariableRoles::ProgressRole);
77 if (data.isValid() && progressData.isValid()) {
83 if (data.isValid() && progressData.isValid())
84 {
78 85 auto cancelButtonWidth = 20;
79 86 auto progressRect = option.rect;
80 87 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
81 88 // Cancel button
82 89 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
83 option.rect.height());
90 option.rect.height());
84 91
85 auto e = (QMouseEvent *)event;
92 auto e = (QMouseEvent*)event;
86 93 auto clickX = e->x();
87 94 auto clickY = e->y();
88 95
89 auto x = buttonRect.left(); // the X coordinate
90 auto y = buttonRect.top(); // the Y coordinate
91 auto w = buttonRect.width(); // button width
96 auto x = buttonRect.left(); // the X coordinate
97 auto y = buttonRect.top(); // the Y coordinate
98 auto w = buttonRect.width(); // button width
92 99 auto h = buttonRect.height(); // button height
93 100
94 if (clickX > x && clickX < x + w) {
95 if (clickY > y && clickY < y + h) {
96 //auto& variableModel = sqpApp->variableModel();
97 //variableModel->abortProgress(index);
101 if (clickX > x && clickX < x + w)
102 {
103 if (clickY > y && clickY < y + h)
104 {
105 // auto& variableModel = sqpApp->variableModel();
106 // variableModel->abortProgress(index);
98 107 }
99 108 return true;
100 109 }
101 else {
110 else
111 {
102 112 return QStyledItemDelegate::editorEvent(event, model, option, index);
103 113 }
104 114 }
105 else {
115 else
116 {
106 117 return QStyledItemDelegate::editorEvent(event, model, option, index);
107 118 }
108 119 }
109 else {
120 else
121 {
110 122 return QStyledItemDelegate::editorEvent(event, model, option, index);
111 123 }
112 124
@@ -115,10 +127,10 public:
115 127 }
116 128 };
117 129
118 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
119 : QWidget{parent},
120 ui{new Ui::VariableInspectorWidget},
121 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
130 VariableInspectorWidget::VariableInspectorWidget(QWidget* parent)
131 : QWidget { parent }
132 , ui { new Ui::VariableInspectorWidget }
133 , m_ProgressBarItemDelegate { new QProgressBarItemDelegate { this } }
122 134 {
123 135 ui->setupUi(this);
124 136
@@ -128,9 +140,7 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
128 140
129 141 m_model = new VariableModel2();
130 142 ui->tableView->setModel(m_model);
131 connect(m_model, &VariableModel2::createVariable,
132 [](const QVariantHash &productData)
133 {
143 connect(m_model, &VariableModel2::createVariable, [](const QVariantHash& productData) {
134 144 sqpApp->dataSourceController().requestVariable(productData);
135 145 });
136 146 auto vc = &(sqpApp->variableController());
@@ -140,16 +150,17 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
140 150
141 151 // Adds extra signal/slot between view and model, so the view can be updated instantly when
142 152 // there is a change of data in the model
143 //connect(m_model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
153 // connect(m_model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
144 154 // SLOT(refresh()));
145 155
146 //ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
156 // ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
147 157 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
148 158
149 159 // Fixes column sizes
150 160 auto model = ui->tableView->model();
151 161 const auto count = model->columnCount();
152 for (auto i = 0; i < count; ++i) {
162 for (auto i = 0; i < count; ++i)
163 {
153 164 ui->tableView->setColumnWidth(
154 165 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
155 166 }
@@ -161,7 +172,7 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
161 172 // Connection to show a menu when right clicking on the tree
162 173 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
163 174 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
164 &VariableInspectorWidget::onTableMenuRequested);
175 &VariableInspectorWidget::onTableMenuRequested);
165 176 }
166 177
167 178 VariableInspectorWidget::~VariableInspectorWidget()
@@ -169,50 +180,55 VariableInspectorWidget::~VariableInspectorWidget()
169 180 delete ui;
170 181 }
171 182
172 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
183 void VariableInspectorWidget::onTableMenuRequested(const QPoint& pos) noexcept
173 184 {
174 185 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
175 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
176 for (const auto &selectedRow : qAsConst(selectedRows)) {
177 if (auto selectedVariable = this->m_model->variables()[selectedRow.row()]) {
186 auto selectedVariables = QVector<std::shared_ptr<Variable2>> {};
187 for (const auto& selectedRow : qAsConst(selectedRows))
188 {
189 if (auto selectedVariable = this->m_model->variables()[selectedRow.row()])
190 {
178 191 selectedVariables.push_back(selectedVariable);
179 192 }
180 193 }
181 194
182 QMenu tableMenu{};
195 QMenu tableMenu {};
183 196
184 197 // Emits a signal so that potential receivers can populate the menu before displaying it
185 198 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
186 199
187 200 // Adds menu-specific actions
188 if (!selectedVariables.isEmpty()) {
201 if (!selectedVariables.isEmpty())
202 {
189 203 tableMenu.addSeparator();
190 204
191 205 // 'Rename' and 'Duplicate' actions (only if one variable selected)
192 if (selectedVariables.size() == 1) {
206 if (selectedVariables.size() == 1)
207 {
193 208 auto selectedVariable = selectedVariables.front();
194 209
195 auto duplicateFun = [varW = std::weak_ptr<Variable>(selectedVariable)]()
196 {
197 if (auto var = varW.lock()) {
210 auto duplicateFun = [varW = std::weak_ptr<Variable2>(selectedVariable)]() {
211 if (auto var = varW.lock())
212 {
198 213 sqpApp->variableController().cloneVariable(var);
199 214 }
200 215 };
201 216
202 217 tableMenu.addAction(tr("Duplicate"), duplicateFun);
203 218
204 auto renameFun = [ varW = std::weak_ptr<Variable>(selectedVariable), this ]()
205 {
206 if (auto var = varW.lock()) {
219 auto renameFun = [varW = std::weak_ptr<Variable2>(selectedVariable), this]() {
220 if (auto var = varW.lock())
221 {
207 222 // Generates forbidden names (names associated to existing variables)
208 223 auto allVariables = sqpApp->variableController().variables();
209 224 auto forbiddenNames = QVector<QString>(allVariables.size());
210 225 std::transform(allVariables.cbegin(), allVariables.cend(),
211 forbiddenNames.begin(),
212 [](const auto &variable) { return variable->name(); });
226 forbiddenNames.begin(),
227 [](const auto& variable) { return variable->name(); });
213 228
214 RenameVariableDialog dialog{var->name(), forbiddenNames, this};
215 if (dialog.exec() == QDialog::Accepted) {
229 RenameVariableDialog dialog { var->name(), forbiddenNames, this };
230 if (dialog.exec() == QDialog::Accepted)
231 {
216 232 var->setName(dialog.name());
217 233 }
218 234 }
@@ -223,18 +239,20 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
223 239
224 240 // 'Delete' action
225 241 auto deleteFun = [&selectedVariables]() {
226 for(const auto& var:selectedVariables)
242 for (const auto& var : selectedVariables)
227 243 sqpApp->variableController().deleteVariable(var);
228 244 };
229 245
230 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
246 tableMenu.addAction(QIcon { ":/icones/delete.png" }, tr("Delete"), deleteFun);
231 247 }
232 248
233 if (!tableMenu.isEmpty()) {
249 if (!tableMenu.isEmpty())
250 {
234 251 // Generates menu header (inserted before first action)
235 252 auto firstAction = tableMenu.actions().first();
236 auto headerAction = new QWidgetAction{&tableMenu};
237 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
253 auto headerAction = new QWidgetAction { &tableMenu };
254 headerAction->setDefaultWidget(
255 new VariableMenuHeaderWidget { selectedVariables, &tableMenu });
238 256 tableMenu.insertAction(firstAction, headerAction);
239 257
240 258 // Displays menu
@@ -1,13 +1,13
1 1 #include "Variable/VariableMenuHeaderWidget.h"
2 #include "Variable/Variable.h"
2 #include "Variable/Variable2.h"
3 3
4 4 #include <ui_VariableMenuHeaderWidget.h>
5 5
6 6 Q_LOGGING_CATEGORY(LOG_VariableMenuHeaderWidget, "VariableMenuHeaderWidget")
7 7
8 8 VariableMenuHeaderWidget::VariableMenuHeaderWidget(
9 const QVector<std::shared_ptr<Variable> > &variables, QWidget *parent)
10 : QWidget{parent}, ui{new Ui::VariableMenuHeaderWidget}
9 const QVector<std::shared_ptr<Variable2>>& variables, QWidget* parent)
10 : QWidget { parent }, ui { new Ui::VariableMenuHeaderWidget }
11 11 {
12 12 ui->setupUi(this);
13 13
@@ -15,19 +15,24 VariableMenuHeaderWidget::VariableMenuHeaderWidget(
15 15 // - the variable name if there is only one variable in the list
16 16 // - 'x variables' where x is the number of variables otherwise
17 17 const auto nbVariables = variables.size();
18 if (nbVariables == 1) {
19 if (auto variable = variables.first()) {
18 if (nbVariables == 1)
19 {
20 if (auto variable = variables.first())
21 {
20 22 ui->label->setText(variable->name());
21 23 }
22 else {
24 else
25 {
23 26 qCCritical(LOG_VariableMenuHeaderWidget())
24 27 << tr("Can't get the name of the variable : variable is null");
25 28 }
26 29 }
27 else if (nbVariables > 1) {
30 else if (nbVariables > 1)
31 {
28 32 ui->label->setText(tr("%1 variables").arg(nbVariables));
29 33 }
30 else {
34 else
35 {
31 36 ui->label->setText(tr("No variable"));
32 37 }
33 38 }
@@ -1,17 +1,18
1 1 #include "Visualization/AxisRenderingUtils.h"
2 2
3 #include <Data/ScalarSeries.h>
4 #include <Data/SpectrogramSeries.h>
5 #include <Data/VectorSeries.h>
3 #include <Data/ScalarTimeSerie.h>
4 #include <Data/SpectrogramTimeSerie.h>
5 #include <Data/VectorTimeSerie.h>
6 6
7 #include <Variable/Variable.h>
7 #include <Variable/Variable2.h>
8 8
9 9 #include <Visualization/SqpColorScale.h>
10 10 #include <Visualization/qcustomplot.h>
11 11
12 12 Q_LOGGING_CATEGORY(LOG_AxisRenderingUtils, "AxisRenderingUtils")
13 13
14 namespace {
14 namespace
15 {
15 16
16 17 /// Format for datetimes on a axis
17 18 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
@@ -23,17 +24,20 const auto NUMBER_PRECISION = 9;
23 24 /// non-time data
24 25 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis, QCPAxis::ScaleType scaleType)
25 26 {
26 if (isTimeAxis) {
27 if (isTimeAxis)
28 {
27 29 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
28 30 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
29 31 dateTicker->setDateTimeSpec(Qt::UTC);
30 32
31 33 return dateTicker;
32 34 }
33 else if (scaleType == QCPAxis::stLogarithmic) {
35 else if (scaleType == QCPAxis::stLogarithmic)
36 {
34 37 return QSharedPointer<QCPAxisTickerLog>::create();
35 38 }
36 else {
39 else
40 {
37 41 // default ticker
38 42 return QSharedPointer<QCPAxisTicker>::create();
39 43 }
@@ -45,36 +49,38 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis, QCPAxis::ScaleType sca
45 49 * @param unit the unit to set for the axis
46 50 * @param scaleType the scale type to set for the axis
47 51 */
48 void setAxisProperties(QCPAxis &axis, const Unit &unit,
49 QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
52 void setAxisProperties(QCPAxis& axis, const std::string& unit, bool isTime,
53 QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
50 54 {
51 55 // label (unit name)
52 axis.setLabel(unit.m_Name);
56 axis.setLabel(QString::fromStdString(unit));
53 57
54 58 // scale type
55 59 axis.setScaleType(scaleType);
56 if (scaleType == QCPAxis::stLogarithmic) {
60 if (scaleType == QCPAxis::stLogarithmic)
61 {
57 62 // Scientific notation
58 63 axis.setNumberPrecision(0);
59 64 axis.setNumberFormat("eb");
60 65 }
61 66
62 67 // ticker (depending on the type of unit)
63 axis.setTicker(axisTicker(unit.m_TimeUnit, scaleType));
68 axis.setTicker(axisTicker(isTime, scaleType));
64 69 }
65 70
66 71 /**
67 72 * Delegate used to set axes properties
68 73 */
69 74 template <typename T, typename Enabled = void>
70 struct AxisSetter {
71 static void setProperties(QCustomPlot &, SqpColorScale &)
75 struct AxisSetter
76 {
77 static void setProperties(QCustomPlot&, SqpColorScale&)
72 78 {
73 79 // Default implementation does nothing
74 80 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
75 81 }
76 82
77 static void setUnits(T &, QCustomPlot &, SqpColorScale &)
83 static void setUnits(T&, QCustomPlot&, SqpColorScale&)
78 84 {
79 85 // Default implementation does nothing
80 86 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis units: unmanaged type of data";
@@ -87,24 +93,20 struct AxisSetter {
87 93 * @sa VectorSeries
88 94 */
89 95 template <typename T>
90 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
91 or std::is_base_of<VectorSeries, T>::value> > {
92 static void setProperties(QCustomPlot &, SqpColorScale &)
96 struct AxisSetter<T,
97 typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value
98 or std::is_base_of<VectorTimeSerie, T>::value>>
99 {
100 static void setProperties(QCustomPlot&, SqpColorScale&)
93 101 {
94 102 // Nothing to do
95 103 }
96 104
97 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
105 static void setUnits(T& dataSeries, QCustomPlot& plot, SqpColorScale&)
98 106 {
99 dataSeries.lockRead();
100 auto xAxisUnit = dataSeries.xAxisUnit();
101 auto valuesUnit = dataSeries.valuesUnit();
102 dataSeries.unlock();
103
104 // setAxisProperties(*plot.xAxis, xAxisUnit);
105 // This is cheating but it's ok ;)
106 setAxisProperties(*plot.xAxis, Unit{"s", true});
107 setAxisProperties(*plot.yAxis, valuesUnit);
107 auto serie = dynamic_cast<TimeSeries::ITimeSerie*>(&dataSeries);
108 setAxisProperties(*plot.xAxis, "s", true);
109 setAxisProperties(*plot.yAxis, serie->unit(1), false);
108 110 }
109 111 };
110 112
@@ -113,18 +115,20 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>:
113 115 * @sa SpectrogramSeries
114 116 */
115 117 template <typename T>
116 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
117 static void setProperties(QCustomPlot &plot, SqpColorScale &colorScale)
118 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
119 {
120 static void setProperties(QCustomPlot& plot, SqpColorScale& colorScale)
118 121 {
119 122 // Displays color scale in plot
120 123 plot.plotLayout()->insertRow(0);
121 124 plot.plotLayout()->addElement(0, 0, colorScale.m_Scale);
122 125 colorScale.m_Scale->setType(QCPAxis::atTop);
123 colorScale.m_Scale->setMinimumMargins(QMargins{0, 0, 0, 0});
126 colorScale.m_Scale->setMinimumMargins(QMargins { 0, 0, 0, 0 });
124 127
125 128 // Aligns color scale with axes
126 129 auto marginGroups = plot.axisRect()->marginGroups();
127 for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it) {
130 for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it)
131 {
128 132 colorScale.m_Scale->setMarginGroup(it.key(), it.value());
129 133 }
130 134
@@ -132,19 +136,13 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries
132 136 colorScale.m_AutomaticThreshold = true;
133 137 }
134 138
135 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
139 static void setUnits(T& dataSeries, QCustomPlot& plot, SqpColorScale& colorScale)
136 140 {
137 dataSeries.lockRead();
138 auto xAxisUnit = dataSeries.xAxisUnit();
139 auto yAxisUnit = dataSeries.yAxisUnit();
140 auto valuesUnit = dataSeries.valuesUnit();
141 dataSeries.unlock();
142
143 //setAxisProperties(*plot.xAxis, xAxisUnit);
144 // This is cheating but it's ok ;)
145 setAxisProperties(*plot.xAxis, Unit{"s", true});
146 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
147 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
141 auto serie = dynamic_cast<TimeSeries::ITimeSerie*>(&dataSeries);
142 setAxisProperties(*plot.xAxis, "s", true);
143 setAxisProperties(*plot.yAxis, serie->unit(1), false, QCPAxis::stLogarithmic);
144 setAxisProperties(
145 *colorScale.m_Scale->axis(), serie->unit(2), false, QCPAxis::stLogarithmic);
148 146 }
149 147 };
150 148
@@ -153,57 +151,63 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries
153 151 * @tparam T the data series' type
154 152 */
155 153 template <typename T>
156 struct AxisHelper : public IAxisHelper {
157 explicit AxisHelper(std::shared_ptr<T> dataSeries) : m_DataSeries{dataSeries} {}
154 struct AxisHelper : public IAxisHelper
155 {
156 explicit AxisHelper(T* dataSeries) : m_DataSeries { dataSeries } {}
158 157
159 void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
158 void setProperties(QCustomPlot& plot, SqpColorScale& colorScale) override
160 159 {
161 160 AxisSetter<T>::setProperties(plot, colorScale);
162 161 }
163 162
164 void setUnits(QCustomPlot &plot, SqpColorScale &colorScale) override
163 void setUnits(QCustomPlot& plot, SqpColorScale& colorScale) override
165 164 {
166 if (m_DataSeries) {
165 if (m_DataSeries)
166 {
167 167 AxisSetter<T>::setUnits(*m_DataSeries, plot, colorScale);
168 168 }
169 else {
169 else
170 {
170 171 qCCritical(LOG_AxisRenderingUtils()) << "Can't set units: inconsistency between the "
171 172 "type of data series and the type supposed";
172 173 }
173 174 }
174 175
175 std::shared_ptr<T> m_DataSeries;
176 T* m_DataSeries;
176 177 };
177 178
178 179 } // namespace
179 180
180 QString formatValue(double value, const QCPAxis &axis)
181 QString formatValue(double value, const QCPAxis& axis)
181 182 {
182 183 // If the axis is a time axis, formats the value as a date
183 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
184 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker()))
185 {
184 186 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
185 187 }
186 else {
188 else
189 {
187 190 return QString::number(value, NUMBER_FORMAT, NUMBER_PRECISION);
188 191 }
189 192 }
190 193
191 std::unique_ptr<IAxisHelper> IAxisHelperFactory::create(const Variable &variable) noexcept
194 std::unique_ptr<IAxisHelper> IAxisHelperFactory::create(Variable2& variable) noexcept
192 195 {
193 switch (variable.type()) {
196 switch (variable.type())
197 {
194 198 case DataSeriesType::SCALAR:
195 return std::make_unique<AxisHelper<ScalarSeries> >(
196 std::dynamic_pointer_cast<ScalarSeries>(variable.dataSeries()));
199 return std::make_unique<AxisHelper<ScalarTimeSerie>>(
200 dynamic_cast<ScalarTimeSerie*>(variable.data()->base()));
197 201 case DataSeriesType::SPECTROGRAM:
198 return std::make_unique<AxisHelper<SpectrogramSeries> >(
199 std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()));
202 return std::make_unique<AxisHelper<SpectrogramTimeSerie>>(
203 dynamic_cast<SpectrogramTimeSerie*>(variable.data()->base()));
200 204 case DataSeriesType::VECTOR:
201 return std::make_unique<AxisHelper<VectorSeries> >(
202 std::dynamic_pointer_cast<VectorSeries>(variable.dataSeries()));
205 return std::make_unique<AxisHelper<VectorTimeSerie>>(
206 dynamic_cast<VectorTimeSerie*>(variable.data()->base()));
203 207 default:
204 208 // Creates default helper
205 209 break;
206 210 }
207 211
208 return std::make_unique<AxisHelper<IDataSeries> >(nullptr);
212 return std::make_unique<AxisHelper<TimeSeries::ITimeSerie>>(nullptr);
209 213 }
@@ -6,20 +6,22
6 6 #include <Data/SpectrogramSeries.h>
7 7 #include <Data/VectorSeries.h>
8 8
9 #include <Variable/Variable.h>
9 #include <Variable/Variable2.h>
10 10
11 11 #include <Visualization/qcustomplot.h>
12 12
13 13 Q_LOGGING_CATEGORY(LOG_PlottablesRenderingUtils, "PlottablesRenderingUtils")
14 14
15 namespace {
15 namespace
16 {
16 17
17 18 /**
18 19 * Delegate used to set plottables properties
19 20 */
20 21 template <typename T, typename Enabled = void>
21 struct PlottablesSetter {
22 static void setProperties(PlottablesMap &)
22 struct PlottablesSetter
23 {
24 static void setProperties(PlottablesMap&)
23 25 {
24 26 // Default implementation does nothing
25 27 qCCritical(LOG_PlottablesRenderingUtils())
@@ -33,26 +35,28 struct PlottablesSetter {
33 35 * @sa VectorSeries
34 36 */
35 37 template <typename T>
36 struct PlottablesSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
37 or std::is_base_of<VectorSeries, T>::value> > {
38 static void setProperties(PlottablesMap &plottables)
38 struct PlottablesSetter<T,
39 typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value
40 or std::is_base_of<VectorTimeSerie, T>::value>>
41 {
42 static void setProperties(PlottablesMap& plottables)
39 43 {
40 44 // Finds the plottable with the highest index to determine the number of colors to generate
41 45 auto end = plottables.cend();
42 auto maxPlottableIndexIt
43 = std::max_element(plottables.cbegin(), end, [](const auto &it1, const auto &it2) {
44 return it1.first < it2.first;
45 });
46 auto maxPlottableIndexIt = std::max_element(plottables.cbegin(), end,
47 [](const auto& it1, const auto& it2) { return it1.first < it2.first; });
46 48 auto componentCount = maxPlottableIndexIt != end ? maxPlottableIndexIt->first + 1 : 0;
47 49
48 50 // Generates colors for each component
49 51 auto colors = ColorUtils::colors(Qt::blue, Qt::red, componentCount);
50 52
51 53 // For each component of the data series, creates a QCPGraph to add to the plot
52 for (auto i = 0; i < componentCount; ++i) {
54 for (auto i = 0; i < componentCount; ++i)
55 {
53 56 auto graphIt = plottables.find(i);
54 if (graphIt != end) {
55 graphIt->second->setPen(QPen{colors.at(i)});
57 if (graphIt != end)
58 {
59 graphIt->second->setPen(QPen { colors.at(i) });
56 60 }
57 61 }
58 62 }
@@ -64,30 +68,36 struct PlottablesSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSerie
64 68 */
65 69 template <typename T>
66 70 struct PlottablesSetter<T,
67 typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
68 static void setProperties(PlottablesMap &plottables)
71 typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
72 {
73 static void setProperties(PlottablesMap& plottables)
69 74 {
70 75 // Checks that for a spectrogram there is only one plottable, that is a colormap
71 if (plottables.size() != 1) {
76 if (plottables.size() != 1)
77 {
72 78 return;
73 79 }
74 80
75 if (auto colormap = dynamic_cast<QCPColorMap *>(plottables.begin()->second)) {
81 if (auto colormap = dynamic_cast<QCPColorMap*>(plottables.begin()->second))
82 {
76 83 colormap->setInterpolate(false); // No value interpolation
77 84 colormap->setTightBoundary(true);
78 85
79 86 // Finds color scale in the colormap's plot to associate with it
80 87 auto plot = colormap->parentPlot();
81 88 auto plotElements = plot->plotLayout()->elements(false);
82 for (auto plotElement : plotElements) {
83 if (auto colorScale = dynamic_cast<QCPColorScale *>(plotElement)) {
89 for (auto plotElement : plotElements)
90 {
91 if (auto colorScale = dynamic_cast<QCPColorScale*>(plotElement))
92 {
84 93 colormap->setColorScale(colorScale);
85 94 }
86 95 }
87 96
88 97 colormap->rescaleDataRange();
89 98 }
90 else {
99 else
100 {
91 101 qCCritical(LOG_PlottablesRenderingUtils()) << "Can't get colormap of the spectrogram";
92 102 }
93 103 }
@@ -98,8 +108,9 struct PlottablesSetter<T,
98 108 * @tparam T the data series' type
99 109 */
100 110 template <typename T>
101 struct PlottablesHelper : public IPlottablesHelper {
102 void setProperties(PlottablesMap &plottables) override
111 struct PlottablesHelper : public IPlottablesHelper
112 {
113 void setProperties(PlottablesMap& plottables) override
103 114 {
104 115 PlottablesSetter<T>::setProperties(plottables);
105 116 }
@@ -107,20 +118,20 struct PlottablesHelper : public IPlottablesHelper {
107 118
108 119 } // namespace
109 120
110 std::unique_ptr<IPlottablesHelper>
111 IPlottablesHelperFactory::create(const Variable &variable) noexcept
121 std::unique_ptr<IPlottablesHelper> IPlottablesHelperFactory::create(Variable2& variable) noexcept
112 122 {
113 switch (variable.type()) {
123 switch (variable.type())
124 {
114 125 case DataSeriesType::SCALAR:
115 return std::make_unique<PlottablesHelper<ScalarSeries> >();
126 return std::make_unique<PlottablesHelper<ScalarTimeSerie>>();
116 127 case DataSeriesType::SPECTROGRAM:
117 return std::make_unique<PlottablesHelper<SpectrogramSeries> >();
128 return std::make_unique<PlottablesHelper<SpectrogramTimeSerie>>();
118 129 case DataSeriesType::VECTOR:
119 return std::make_unique<PlottablesHelper<VectorSeries> >();
130 return std::make_unique<PlottablesHelper<VectorTimeSerie>>();
120 131 default:
121 132 // Returns default helper
122 133 break;
123 134 }
124 135
125 return std::make_unique<PlottablesHelper<IDataSeries> >();
136 return std::make_unique<PlottablesHelper<IDataSeries>>();
126 137 }
@@ -2,19 +2,21
2 2 #include "Visualization/qcustomplot.h"
3 3
4 4 #include <Data/DataSeriesUtils.h>
5 #include <Data/ScalarSeries.h>
6 #include <Data/SpectrogramSeries.h>
7 #include <Data/VectorSeries.h>
5 #include <Data/ScalarTimeSerie.h>
6 #include <Data/SpectrogramTimeSerie.h>
7 #include <Data/VectorTimeSerie.h>
8 8
9 #include <Variable/Variable.h>
9 #include <Variable/Variable2.h>
10 10
11 11 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
12 12
13 namespace {
13 namespace
14 {
14 15
15 class SqpDataContainer : public QCPGraphDataContainer {
16 class SqpDataContainer : public QCPGraphDataContainer
17 {
16 18 public:
17 void appendGraphData(const QCPGraphData &data) { mData.append(data); }
19 void appendGraphData(const QCPGraphData& data) { mData.append(data); }
18 20 };
19 21
20 22 /**
@@ -24,23 +26,20 public:
24 26 * @remarks Default implementation can't create plottables
25 27 */
26 28 template <typename T, typename Enabled = void>
27 struct PlottablesCreator {
28 static PlottablesMap createPlottables(QCustomPlot &)
29 {
30 qCCritical(LOG_DataSeries())
31 << QObject::tr("Can't create plottables: unmanaged data series type");
32 return {};
33 }
29 struct PlottablesCreator
30 {
31 static PlottablesMap createPlottables(QCustomPlot&) { return {}; }
34 32 };
35 33
36 PlottablesMap createGraphs(QCustomPlot &plot, int nbGraphs)
34 PlottablesMap createGraphs(QCustomPlot& plot, int nbGraphs)
37 35 {
38 PlottablesMap result{};
36 PlottablesMap result {};
39 37
40 38 // Creates {nbGraphs} QCPGraph to add to the plot
41 for (auto i = 0; i < nbGraphs; ++i) {
39 for (auto i = 0; i < nbGraphs; ++i)
40 {
42 41 auto graph = plot.addGraph();
43 result.insert({i, graph});
42 result.insert({ i, graph });
44 43 }
45 44
46 45 plot.replot();
@@ -53,8 +52,9 PlottablesMap createGraphs(QCustomPlot &plot, int nbGraphs)
53 52 * @sa ScalarSeries
54 53 */
55 54 template <typename T>
56 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value> > {
57 static PlottablesMap createPlottables(QCustomPlot &plot) { return createGraphs(plot, 1); }
55 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>>
56 {
57 static PlottablesMap createPlottables(QCustomPlot& plot) { return createGraphs(plot, 1); }
58 58 };
59 59
60 60 /**
@@ -62,8 +62,9 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<ScalarSeri
62 62 * @sa VectorSeries
63 63 */
64 64 template <typename T>
65 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<VectorSeries, T>::value> > {
66 static PlottablesMap createPlottables(QCustomPlot &plot) { return createGraphs(plot, 3); }
65 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<VectorTimeSerie, T>::value>>
66 {
67 static PlottablesMap createPlottables(QCustomPlot& plot) { return createGraphs(plot, 3); }
67 68 };
68 69
69 70 /**
@@ -72,11 +73,12 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<VectorSeri
72 73 */
73 74 template <typename T>
74 75 struct PlottablesCreator<T,
75 typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
76 static PlottablesMap createPlottables(QCustomPlot &plot)
76 typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
77 {
78 static PlottablesMap createPlottables(QCustomPlot& plot)
77 79 {
78 PlottablesMap result{};
79 result.insert({0, new QCPColorMap{plot.xAxis, plot.yAxis}});
80 PlottablesMap result {};
81 result.insert({ 0, new QCPColorMap { plot.xAxis, plot.yAxis } });
80 82
81 83 plot.replot();
82 84
@@ -91,14 +93,15 struct PlottablesCreator<T,
91 93 * @remarks Default implementation can't update plottables
92 94 */
93 95 template <typename T, typename Enabled = void>
94 struct PlottablesUpdater {
95 static void setPlotYAxisRange(T &, const DateTimeRange &, QCustomPlot &)
96 struct PlottablesUpdater
97 {
98 static void setPlotYAxisRange(T&, const DateTimeRange&, QCustomPlot&)
96 99 {
97 100 qCCritical(LOG_VisualizationGraphHelper())
98 101 << QObject::tr("Can't set plot y-axis range: unmanaged data series type");
99 102 }
100 103
101 static void updatePlottables(T &, PlottablesMap &, const DateTimeRange &, bool)
104 static void updatePlottables(T&, PlottablesMap&, const DateTimeRange&, bool)
102 105 {
103 106 qCCritical(LOG_VisualizationGraphHelper())
104 107 << QObject::tr("Can't update plottables: unmanaged data series type");
@@ -111,154 +114,223 struct PlottablesUpdater {
111 114 * @sa VectorSeries
112 115 */
113 116 template <typename T>
114 struct PlottablesUpdater<T,
115 typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
116 or std::is_base_of<VectorSeries, T>::value> > {
117 static void setPlotYAxisRange(T &dataSeries, const DateTimeRange &xAxisRange, QCustomPlot &plot)
117 struct PlottablesUpdater<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>>
118 {
119 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
118 120 {
119 121 auto minValue = 0., maxValue = 0.;
120
121 dataSeries.lockRead();
122 auto valuesBounds = dataSeries.valuesBounds(xAxisRange.m_TStart, xAxisRange.m_TEnd);
123 auto end = dataSeries.cend();
124 if (valuesBounds.first != end && valuesBounds.second != end) {
125 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
126
127 minValue = rangeValue(valuesBounds.first->minValue());
128 maxValue = rangeValue(valuesBounds.second->maxValue());
122 if (auto serie = dynamic_cast<ScalarTimeSerie*>(&dataSeries))
123 {
124 maxValue = (*std::max_element(std::begin(*serie), std::end(*serie))).v();
125 minValue = (*std::min_element(std::begin(*serie), std::end(*serie))).v();
129 126 }
130 dataSeries.unlock();
131
132 plot.yAxis->setRange(QCPRange{minValue, maxValue});
127 plot.yAxis->setRange(QCPRange { minValue, maxValue });
133 128 }
134 129
135 static void updatePlottables(T &dataSeries, PlottablesMap &plottables, const DateTimeRange &range,
136 bool rescaleAxes)
130 static void updatePlottables(
131 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
137 132 {
138 133
139 134 // For each plottable to update, resets its data
140 std::map<int, QSharedPointer<SqpDataContainer> > dataContainers{};
141 for (const auto &plottable : plottables) {
142 if (auto graph = dynamic_cast<QCPGraph *>(plottable.second)) {
135 for (const auto& plottable : plottables)
136 {
137 if (auto graph = dynamic_cast<QCPGraph*>(plottable.second))
138 {
143 139 auto dataContainer = QSharedPointer<SqpDataContainer>::create();
140 if (auto serie = dynamic_cast<ScalarTimeSerie*>(&dataSeries))
141 {
142 std::for_each(
143 std::begin(*serie), std::end(*serie), [&dataContainer](const auto& value) {
144 dataContainer->appendGraphData(QCPGraphData(value.t(), value.v()));
145 });
146 }
144 147 graph->setData(dataContainer);
145
146 dataContainers.insert({plottable.first, dataContainer});
147 }
148 }
149 dataSeries.lockRead();
150
151 // - Gets the data of the series included in the current range
152 // - Updates each plottable by adding, for each data item, a point that takes x-axis data
153 // and value data. The correct value is retrieved according to the index of the component
154 auto subDataIts = dataSeries.xAxisRange(range.m_TStart, range.m_TEnd);
155 for (auto it = subDataIts.first; it != subDataIts.second; ++it) {
156 for (const auto &dataContainer : dataContainers) {
157 auto componentIndex = dataContainer.first;
158 dataContainer.second->appendGraphData(
159 QCPGraphData(it->x(), it->value(componentIndex)));
160 148 }
161 149 }
162 150
163 dataSeries.unlock();
164
165 if (!plottables.empty()) {
151 if (!plottables.empty())
152 {
166 153 auto plot = plottables.begin()->second->parentPlot();
167 154
168 if (rescaleAxes) {
155 if (rescaleAxes)
156 {
169 157 plot->rescaleAxes();
170 158 }
171 159 }
172 160 }
173 161 };
174 162
175 /**
176 * Specialization of PlottablesUpdater for spectrograms
177 * @sa SpectrogramSeries
178 */
163
179 164 template <typename T>
180 struct PlottablesUpdater<T,
181 typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
182 static void setPlotYAxisRange(T &dataSeries, const DateTimeRange &xAxisRange, QCustomPlot &plot)
165 struct PlottablesUpdater<T, typename std::enable_if_t<std::is_base_of<VectorTimeSerie, T>::value>>
166 {
167 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
183 168 {
184 double min, max;
185 std::tie(min, max) = dataSeries.yBounds();
186
187 if (!std::isnan(min) && !std::isnan(max)) {
188 plot.yAxis->setRange(QCPRange{min, max});
169 double minValue = 0., maxValue = 0.;
170 if (auto serie = dynamic_cast<VectorTimeSerie*>(&dataSeries))
171 {
172 std::for_each(
173 std::begin(*serie), std::end(*serie), [&minValue, &maxValue](const auto& v) {
174 minValue = std::min({ minValue, v.v().x, v.v().y, v.v().z });
175 maxValue = std::max({ maxValue, v.v().x, v.v().y, v.v().z });
176 });
189 177 }
178
179 plot.yAxis->setRange(QCPRange { minValue, maxValue });
190 180 }
191 181
192 static void updatePlottables(T &dataSeries, PlottablesMap &plottables, const DateTimeRange &range,
193 bool rescaleAxes)
182 static void updatePlottables(
183 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
194 184 {
195 if (plottables.empty()) {
196 qCDebug(LOG_VisualizationGraphHelper())
197 << QObject::tr("Can't update spectrogram: no colormap has been associated");
198 return;
199 }
200
201 // Gets the colormap to update (normally there is only one colormap)
202 Q_ASSERT(plottables.size() == 1);
203 auto colormap = dynamic_cast<QCPColorMap *>(plottables.at(0));
204 Q_ASSERT(colormap != nullptr);
205
206 dataSeries.lockRead();
207
208 // Processing spectrogram data for display in QCustomPlot
209 auto its = dataSeries.xAxisRange(range.m_TStart, range.m_TEnd);
210 185
211 // Computes logarithmic y-axis resolution for the spectrogram
212 auto yData = its.first->y();
213 auto yResolution = DataSeriesUtils::resolution(yData.begin(), yData.end(), true);
214
215 // Generates mesh for colormap
216 auto mesh = DataSeriesUtils::regularMesh(
217 its.first, its.second, DataSeriesUtils::Resolution{dataSeries.xResolution()},
218 yResolution);
219
220 dataSeries.unlock();
221
222 colormap->data()->setSize(mesh.m_NbX, mesh.m_NbY);
223 if (!mesh.isEmpty()) {
224 colormap->data()->setRange(
225 QCPRange{mesh.m_XMin, mesh.xMax()},
226 // y-axis range is converted to linear values
227 QCPRange{std::pow(10, mesh.m_YMin), std::pow(10, mesh.yMax())});
228
229 // Sets values
230 auto index = 0;
231 for (auto it = mesh.m_Data.begin(), end = mesh.m_Data.end(); it != end; ++it, ++index) {
232 auto xIndex = index % mesh.m_NbX;
233 auto yIndex = index / mesh.m_NbX;
234
235 colormap->data()->setCell(xIndex, yIndex, *it);
236
237 // Makes the NaN values to be transparent in the colormap
238 if (std::isnan(*it)) {
239 colormap->data()->setAlpha(xIndex, yIndex, 0);
186 // For each plottable to update, resets its data
187 for (const auto& plottable : plottables)
188 {
189 if (auto graph = dynamic_cast<QCPGraph*>(plottable.second))
190 {
191 auto dataContainer = QSharedPointer<SqpDataContainer>::create();
192 if (auto serie = dynamic_cast<VectorTimeSerie*>(&dataSeries))
193 {
194 switch (plottable.first)
195 {
196 case 0:
197 std::for_each(std::begin(*serie), std::end(*serie),
198 [&dataContainer](const auto& value) {
199 dataContainer->appendGraphData(
200 QCPGraphData(value.t(), value.v().x));
201 });
202 break;
203 case 1:
204 std::for_each(std::begin(*serie), std::end(*serie),
205 [&dataContainer](const auto& value) {
206 dataContainer->appendGraphData(
207 QCPGraphData(value.t(), value.v().y));
208 });
209 break;
210 case 2:
211 std::for_each(std::begin(*serie), std::end(*serie),
212 [&dataContainer](const auto& value) {
213 dataContainer->appendGraphData(
214 QCPGraphData(value.t(), value.v().z));
215 });
216 break;
217 default:
218 break;
219 }
240 220 }
221 graph->setData(dataContainer);
241 222 }
242 223 }
243 224
244 // Rescales axes
245 auto plot = colormap->parentPlot();
225 if (!plottables.empty())
226 {
227 auto plot = plottables.begin()->second->parentPlot();
246 228
247 if (rescaleAxes) {
248 plot->rescaleAxes();
229 if (rescaleAxes)
230 {
231 plot->rescaleAxes();
232 }
249 233 }
250 234 }
251 235 };
252 236
253 237 /**
238 * Specialization of PlottablesUpdater for spectrograms
239 * @sa SpectrogramSeries
240 */
241 template <typename T>
242 struct PlottablesUpdater<T,
243 typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
244 {
245 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
246 {
247 // TODO
248 // double min, max;
249 // std::tie(min, max) = dataSeries.yBounds();
250
251 // if (!std::isnan(min) && !std::isnan(max))
252 // {
253 // plot.yAxis->setRange(QCPRange { min, max });
254 // }
255 }
256
257 static void updatePlottables(
258 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
259 {
260 // TODO
261 // if (plottables.empty())
262 // {
263 // qCDebug(LOG_VisualizationGraphHelper())
264 // << QObject::tr("Can't update spectrogram: no colormap has been
265 // associated");
266 // return;
267 // }
268
269 // // Gets the colormap to update (normally there is only one colormap)
270 // Q_ASSERT(plottables.size() == 1);
271 // auto colormap = dynamic_cast<QCPColorMap*>(plottables.at(0));
272 // Q_ASSERT(colormap != nullptr);
273
274 // dataSeries.lockRead();
275
276 // // Processing spectrogram data for display in QCustomPlot
277 // auto its = dataSeries.xAxisRange(range.m_TStart, range.m_TEnd);
278
279 // // Computes logarithmic y-axis resolution for the spectrogram
280 // auto yData = its.first->y();
281 // auto yResolution = DataSeriesUtils::resolution(yData.begin(), yData.end(), true);
282
283 // // Generates mesh for colormap
284 // auto mesh = DataSeriesUtils::regularMesh(its.first, its.second,
285 // DataSeriesUtils::Resolution { dataSeries.xResolution() }, yResolution);
286
287 // dataSeries.unlock();
288
289 // colormap->data()->setSize(mesh.m_NbX, mesh.m_NbY);
290 // if (!mesh.isEmpty())
291 // {
292 // colormap->data()->setRange(QCPRange { mesh.m_XMin, mesh.xMax() },
293 // // y-axis range is converted to linear values
294 // QCPRange { std::pow(10, mesh.m_YMin), std::pow(10, mesh.yMax()) });
295
296 // // Sets values
297 // auto index = 0;
298 // for (auto it = mesh.m_Data.begin(), end = mesh.m_Data.end(); it != end; ++it,
299 // ++index)
300 // {
301 // auto xIndex = index % mesh.m_NbX;
302 // auto yIndex = index / mesh.m_NbX;
303
304 // colormap->data()->setCell(xIndex, yIndex, *it);
305
306 // // Makes the NaN values to be transparent in the colormap
307 // if (std::isnan(*it))
308 // {
309 // colormap->data()->setAlpha(xIndex, yIndex, 0);
310 // }
311 // }
312 // }
313
314 // // Rescales axes
315 // auto plot = colormap->parentPlot();
316
317 // if (rescaleAxes)
318 // {
319 // plot->rescaleAxes();
320 // }
321 }
322 };
323
324 /**
254 325 * Helper used to create/update plottables
255 326 */
256 struct IPlottablesHelper {
327 struct IPlottablesHelper
328 {
257 329 virtual ~IPlottablesHelper() noexcept = default;
258 virtual PlottablesMap create(QCustomPlot &plot) const = 0;
259 virtual void setYAxisRange(const DateTimeRange &xAxisRange, QCustomPlot &plot) const = 0;
260 virtual void update(PlottablesMap &plottables, const DateTimeRange &range,
261 bool rescaleAxes = false) const = 0;
330 virtual PlottablesMap create(QCustomPlot& plot) const = 0;
331 virtual void setYAxisRange(const DateTimeRange& xAxisRange, QCustomPlot& plot) const = 0;
332 virtual void update(
333 PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes = false) const = 0;
262 334 };
263 335
264 336 /**
@@ -266,95 +338,105 struct IPlottablesHelper {
266 338 * @tparam T the data series' type
267 339 */
268 340 template <typename T>
269 struct PlottablesHelper : public IPlottablesHelper {
270 explicit PlottablesHelper(std::shared_ptr<T> dataSeries) : m_DataSeries{dataSeries} {}
341 struct PlottablesHelper : public IPlottablesHelper
342 {
343 explicit PlottablesHelper(T* dataSeries) : m_DataSeries { dataSeries } {}
271 344
272 PlottablesMap create(QCustomPlot &plot) const override
345 PlottablesMap create(QCustomPlot& plot) const override
273 346 {
274 347 return PlottablesCreator<T>::createPlottables(plot);
275 348 }
276 349
277 void update(PlottablesMap &plottables, const DateTimeRange &range, bool rescaleAxes) const override
350 void update(
351 PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes) const override
278 352 {
279 if (m_DataSeries) {
353 if (m_DataSeries)
354 {
280 355 PlottablesUpdater<T>::updatePlottables(*m_DataSeries, plottables, range, rescaleAxes);
281 356 }
282 else {
357 else
358 {
283 359 qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency "
284 360 "between the type of data series and the "
285 361 "type supposed";
286 362 }
287 363 }
288 364
289 void setYAxisRange(const DateTimeRange &xAxisRange, QCustomPlot &plot) const override
365 void setYAxisRange(const DateTimeRange& xAxisRange, QCustomPlot& plot) const override
290 366 {
291 if (m_DataSeries) {
367 if (m_DataSeries)
368 {
292 369 PlottablesUpdater<T>::setPlotYAxisRange(*m_DataSeries, xAxisRange, plot);
293 370 }
294 else {
371 else
372 {
295 373 qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency "
296 374 "between the type of data series and the "
297 375 "type supposed";
298 376 }
299 377 }
300 378
301 std::shared_ptr<T> m_DataSeries;
379 T* m_DataSeries;
302 380 };
303 381
304 382 /// Creates IPlottablesHelper according to the type of data series a variable holds
305 std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<Variable> variable) noexcept
383 std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<Variable2> variable) noexcept
306 384 {
307 switch (variable->type()) {
385 switch (variable->type())
386 {
308 387 case DataSeriesType::SCALAR:
309 return std::make_unique<PlottablesHelper<ScalarSeries> >(
310 std::dynamic_pointer_cast<ScalarSeries>(variable->dataSeries()));
388 return std::make_unique<PlottablesHelper<ScalarTimeSerie>>(
389 dynamic_cast<ScalarTimeSerie*>(variable->data()->base()));
311 390 case DataSeriesType::SPECTROGRAM:
312 return std::make_unique<PlottablesHelper<SpectrogramSeries> >(
313 std::dynamic_pointer_cast<SpectrogramSeries>(variable->dataSeries()));
391 return std::make_unique<PlottablesHelper<SpectrogramTimeSerie>>(
392 dynamic_cast<SpectrogramTimeSerie*>(variable->data()->base()));
314 393 case DataSeriesType::VECTOR:
315 return std::make_unique<PlottablesHelper<VectorSeries> >(
316 std::dynamic_pointer_cast<VectorSeries>(variable->dataSeries()));
394 return std::make_unique<PlottablesHelper<VectorTimeSerie>>(
395 dynamic_cast<VectorTimeSerie*>(variable->data()->base()));
317 396 default:
318 397 // Creates default helper
319 398 break;
320 399 }
321 400
322 return std::make_unique<PlottablesHelper<IDataSeries> >(nullptr);
401 return std::make_unique<PlottablesHelper<TimeSeries::ITimeSerie>>(nullptr);
323 402 }
324 403
325 404 } // namespace
326 405
327 PlottablesMap VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
328 QCustomPlot &plot) noexcept
406 PlottablesMap VisualizationGraphHelper::create(
407 std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept
329 408 {
330 if (variable) {
409 if (variable)
410 {
331 411 auto helper = createHelper(variable);
332 412 auto plottables = helper->create(plot);
333 413 return plottables;
334 414 }
335 else {
415 else
416 {
336 417 qCDebug(LOG_VisualizationGraphHelper())
337 418 << QObject::tr("Can't create graph plottables : the variable is null");
338 return PlottablesMap{};
419 return PlottablesMap {};
339 420 }
340 421 }
341 422
342 void VisualizationGraphHelper::setYAxisRange(std::shared_ptr<Variable> variable,
343 QCustomPlot &plot) noexcept
423 void VisualizationGraphHelper::setYAxisRange(
424 std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept
344 425 {
345 if (variable) {
426 if (variable)
427 {
346 428 auto helper = createHelper(variable);
347 429 helper->setYAxisRange(variable->range(), plot);
348 430 }
349 else {
431 else
432 {
350 433 qCDebug(LOG_VisualizationGraphHelper())
351 434 << QObject::tr("Can't set y-axis range of plot: the variable is null");
352 435 }
353 436 }
354 437
355 void VisualizationGraphHelper::updateData(PlottablesMap &plottables,
356 std::shared_ptr<Variable> variable,
357 const DateTimeRange &dateTime)
438 void VisualizationGraphHelper::updateData(
439 PlottablesMap& plottables, std::shared_ptr<Variable2> variable, const DateTimeRange& dateTime)
358 440 {
359 441 auto helper = createHelper(variable);
360 442 helper->update(plottables, dateTime);
@@ -13,7 +13,8
13 13
14 14 #include <SqpApplication.h>
15 15
16 namespace {
16 namespace
17 {
17 18
18 19 /// Name of the axes layer in QCustomPlot
19 20 const auto AXES_LAYER = QStringLiteral("axes");
@@ -34,15 +35,15 const auto GRAPH_TOOLTIP_FORMAT = QStringLiteral("key: %1\nvalue: %2");
34 35 const auto COLORMAP_TOOLTIP_FORMAT = QStringLiteral("x: %1\ny: %2\nvalue: %3");
35 36
36 37 /// Offset used to shift the tooltip of the mouse
37 const auto TOOLTIP_OFFSET = QPoint{20, 20};
38 const auto TOOLTIP_OFFSET = QPoint { 20, 20 };
38 39
39 40 /// Tooltip display rectangle (the tooltip is hidden when the mouse leaves this rectangle)
40 const auto TOOLTIP_RECT = QRect{10, 10, 10, 10};
41 const auto TOOLTIP_RECT = QRect { 10, 10, 10, 10 };
41 42
42 43 /// Timeout after which the tooltip is displayed
43 44 const auto TOOLTIP_TIMEOUT = 500;
44 45
45 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
46 void initPointTracerStyle(QCPItemTracer& tracer) noexcept
46 47 {
47 48 tracer.setInterpolating(false);
48 49 tracer.setStyle(QCPItemTracer::tsCircle);
@@ -52,16 +53,16 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
52 53 tracer.setSelectable(false);
53 54 }
54 55
55 QPixmap pixmap(const QString &iconPath) noexcept
56 QPixmap pixmap(const QString& iconPath) noexcept
56 57 {
57 return QIcon{iconPath}.pixmap(QSize{16, 16});
58 return QIcon { iconPath }.pixmap(QSize { 16, 16 });
58 59 }
59 60
60 void initClosePixmapStyle(QCPItemPixmap &pixmap) noexcept
61 void initClosePixmapStyle(QCPItemPixmap& pixmap) noexcept
61 62 {
62 63 // Icon
63 64 pixmap.setPixmap(
64 sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton).pixmap(QSize{16, 16}));
65 sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton).pixmap(QSize { 16, 16 }));
65 66
66 67 // Position
67 68 pixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
@@ -72,7 +73,7 void initClosePixmapStyle(QCPItemPixmap &pixmap) noexcept
72 73 pixmap.setSelectable(true);
73 74 }
74 75
75 void initXAxisPixmapStyle(QCPItemPixmap &itemPixmap) noexcept
76 void initXAxisPixmapStyle(QCPItemPixmap& itemPixmap) noexcept
76 77 {
77 78 // Icon
78 79 itemPixmap.setPixmap(pixmap(HIDE_AXIS_ICON_PATH));
@@ -86,7 +87,7 void initXAxisPixmapStyle(QCPItemPixmap &itemPixmap) noexcept
86 87 itemPixmap.setSelectable(true);
87 88 }
88 89
89 void initTitleTextStyle(QCPItemText &text) noexcept
90 void initTitleTextStyle(QCPItemText& text) noexcept
90 91 {
91 92 // Font and background styles
92 93 text.setColor(Qt::gray);
@@ -107,13 +108,14 void initTitleTextStyle(QCPItemText &text) noexcept
107 108 * @param xCoord calculates the x index if true, calculates y index if false
108 109 * @return the cell index
109 110 */
110 int colorMapCellIndex(const QCPColorMap &colormap, double coord, bool xCoord)
111 int colorMapCellIndex(const QCPColorMap& colormap, double coord, bool xCoord)
111 112 {
112 113 // Determines the axis of the colormap according to xCoord, and whether it is logarithmic or not
113 114 auto isLogarithmic = (xCoord ? colormap.keyAxis() : colormap.valueAxis())->scaleType()
114 == QCPAxis::stLogarithmic;
115 == QCPAxis::stLogarithmic;
115 116
116 if (isLogarithmic) {
117 if (isLogarithmic)
118 {
117 119 // For a logarithmic axis we can't use the conversion method of colormap, so we calculate
118 120 // the index manually based on the position of the coordinate on the axis
119 121
@@ -127,13 +129,16 int colorMapCellIndex(const QCPColorMap &colormap, double coord, bool xCoord)
127 129 // According to the coord position, calculates the closest index in the range
128 130 return std::round((std::log10(coord) - std::log10(range.lower)) / valueStep);
129 131 }
130 else {
132 else
133 {
131 134 // For a linear axis, we use the conversion method of colormap
132 135 int index;
133 if (xCoord) {
136 if (xCoord)
137 {
134 138 colormap.data()->coordToCell(coord, 0., &index, nullptr);
135 139 }
136 else {
140 else
141 {
137 142 colormap.data()->coordToCell(0., coord, nullptr, &index);
138 143 }
139 144
@@ -143,17 +148,18 int colorMapCellIndex(const QCPColorMap &colormap, double coord, bool xCoord)
143 148
144 149 } // namespace
145 150
146 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
147 explicit VisualizationGraphRenderingDelegatePrivate(VisualizationGraphWidget &graphWidget)
148 : m_Plot{graphWidget.plot()},
149 m_PointTracer{new QCPItemTracer{&m_Plot}},
150 m_TracerTimer{},
151 m_ClosePixmap{new QCPItemPixmap{&m_Plot}},
152 m_TitleText{new QCPItemText{&m_Plot}},
153 m_XAxisPixmap{new QCPItemPixmap{&m_Plot}},
154 m_ShowXAxis{true},
155 m_XAxisLabel{},
156 m_ColorScale{SqpColorScale{m_Plot}}
151 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate
152 {
153 explicit VisualizationGraphRenderingDelegatePrivate(VisualizationGraphWidget& graphWidget)
154 : m_Plot { graphWidget.plot() }
155 , m_PointTracer { new QCPItemTracer { &m_Plot } }
156 , m_TracerTimer {}
157 , m_ClosePixmap { new QCPItemPixmap { &m_Plot } }
158 , m_TitleText { new QCPItemText { &m_Plot } }
159 , m_XAxisPixmap { new QCPItemPixmap { &m_Plot } }
160 , m_ShowXAxis { true }
161 , m_XAxisLabel {}
162 , m_ColorScale { SqpColorScale { m_Plot } }
157 163 {
158 164 initPointTracerStyle(*m_PointTracer);
159 165
@@ -165,12 +171,13 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegateP
165 171 initClosePixmapStyle(*m_ClosePixmap);
166 172
167 173 // Connects pixmap selection to graph widget closing
168 QObject::connect(&m_Plot, &QCustomPlot::itemClick,
169 [&graphWidget, this](auto item, auto mouseEvent) {
170 if (item == m_ClosePixmap) {
171 graphWidget.close();
172 }
173 });
174 QObject::connect(
175 &m_Plot, &QCustomPlot::itemClick, [&graphWidget, this](auto item, auto mouseEvent) {
176 if (item == m_ClosePixmap)
177 {
178 graphWidget.close();
179 }
180 });
174 181
175 182 // Inits graph name in plot overlay
176 183 m_TitleText->setLayer(OVERLAY_LAYER);
@@ -183,7 +190,8 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegateP
183 190
184 191 // Connects pixmap selection to graph x-axis showing/hiding
185 192 QObject::connect(&m_Plot, &QCustomPlot::itemClick, [this](auto item, auto mouseEvent) {
186 if (m_XAxisPixmap == item) {
193 if (m_XAxisPixmap == item)
194 {
187 195 // Changes the selection state and refreshes the x-axis
188 196 m_ShowXAxis = !m_ShowXAxis;
189 197 this->updateXAxisState();
@@ -202,38 +210,40 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegateP
202 210 void updateXAxisState() noexcept
203 211 {
204 212 m_Plot.xAxis->setTickLabels(m_ShowXAxis);
205 m_Plot.xAxis->setLabel(m_ShowXAxis ? m_XAxisLabel : QString{});
213 m_Plot.xAxis->setLabel(m_ShowXAxis ? m_XAxisLabel : QString {});
206 214 }
207 215
208 QCustomPlot &m_Plot;
209 QCPItemTracer *m_PointTracer;
216 QCustomPlot& m_Plot;
217 QCPItemTracer* m_PointTracer;
210 218 QTimer m_TracerTimer;
211 QCPItemPixmap *m_ClosePixmap; /// Graph's close button
212 QCPItemText *m_TitleText; /// Graph's title
213 QCPItemPixmap *m_XAxisPixmap;
219 QCPItemPixmap* m_ClosePixmap; /// Graph's close button
220 QCPItemText* m_TitleText; /// Graph's title
221 QCPItemPixmap* m_XAxisPixmap;
214 222 bool m_ShowXAxis; /// X-axis properties are shown or hidden
215 223 QString m_XAxisLabel;
216 224 SqpColorScale m_ColorScale; /// Color scale used for some types of graphs (as spectrograms)
217 225 };
218 226
219 227 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(
220 VisualizationGraphWidget &graphWidget)
221 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(graphWidget)}
228 VisualizationGraphWidget& graphWidget)
229 : impl { spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(graphWidget) }
222 230 {
223 231 }
224 232
225 void VisualizationGraphRenderingDelegate::onMouseDoubleClick(QMouseEvent *event) noexcept
233 void VisualizationGraphRenderingDelegate::onMouseDoubleClick(QMouseEvent* event) noexcept
226 234 {
227 235 // Opens color scale editor if color scale is double clicked
228 auto colorScale = static_cast<QCPColorScale *>(impl->m_Plot.layoutElementAt(event->pos()));
229 if (impl->m_ColorScale.m_Scale == colorScale) {
230 if (ColorScaleEditor{impl->m_ColorScale}.exec() == QDialog::Accepted) {
236 auto colorScale = static_cast<QCPColorScale*>(impl->m_Plot.layoutElementAt(event->pos()));
237 if (impl->m_ColorScale.m_Scale == colorScale)
238 {
239 if (ColorScaleEditor { impl->m_ColorScale }.exec() == QDialog::Accepted)
240 {
231 241 impl->m_Plot.replot();
232 242 }
233 243 }
234 244 }
235 245
236 void VisualizationGraphRenderingDelegate::updateTooltip(QMouseEvent *event) noexcept
246 void VisualizationGraphRenderingDelegate::updateTooltip(QMouseEvent* event) noexcept
237 247 {
238 248 // Cancels pending refresh
239 249 impl->m_TracerTimer.disconnect();
@@ -243,17 +253,19 void VisualizationGraphRenderingDelegate::updateTooltip(QMouseEvent *event) noex
243 253 impl->m_PointTracer->setVisible(false);
244 254 impl->m_Plot.replot();
245 255
246 QString tooltip{};
256 QString tooltip {};
247 257
248 258 // Gets the graph under the mouse position
249 259 auto eventPos = event->pos();
250 if (auto graph = qobject_cast<QCPGraph *>(impl->m_Plot.plottableAt(eventPos))) {
260 if (auto graph = qobject_cast<QCPGraph*>(impl->m_Plot.plottableAt(eventPos)))
261 {
251 262 auto mouseKey = graph->keyAxis()->pixelToCoord(eventPos.x());
252 263 auto graphData = graph->data();
253 264
254 265 // Gets the closest data point to the mouse
255 266 auto graphDataIt = graphData->findBegin(mouseKey);
256 if (graphDataIt != graphData->constEnd()) {
267 if (graphDataIt != graphData->constEnd())
268 {
257 269 // Sets tooltip
258 270 auto key = formatValue(graphDataIt->key, *graph->keyAxis());
259 271 auto value = formatValue(graphDataIt->value, *graph->valueAxis());
@@ -268,7 +280,8 void VisualizationGraphRenderingDelegate::updateTooltip(QMouseEvent *event) noex
268 280 impl->m_Plot.replot();
269 281 }
270 282 }
271 else if (auto colorMap = qobject_cast<QCPColorMap *>(impl->m_Plot.plottableAt(eventPos))) {
283 else if (auto colorMap = qobject_cast<QCPColorMap*>(impl->m_Plot.plottableAt(eventPos)))
284 {
272 285 // Gets x and y coords
273 286 auto x = colorMap->keyAxis()->pixelToCoord(eventPos.x());
274 287 auto y = colorMap->valueAxis()->pixelToCoord(eventPos.y());
@@ -280,15 +293,16 void VisualizationGraphRenderingDelegate::updateTooltip(QMouseEvent *event) noex
280 293
281 294 // Sets tooltips
282 295 tooltip = COLORMAP_TOOLTIP_FORMAT.arg(formatValue(x, *colorMap->keyAxis()),
283 formatValue(y, *colorMap->valueAxis()),
284 formatValue(value, *colorMap->colorScale()->axis()));
296 formatValue(y, *colorMap->valueAxis()),
297 formatValue(value, *colorMap->colorScale()->axis()));
285 298 }
286 299
287 if (!tooltip.isEmpty()) {
300 if (!tooltip.isEmpty())
301 {
288 302 // Starts timer to show tooltip after timeout
289 303 auto showTooltip = [tooltip, eventPos, this]() {
290 304 QToolTip::showText(impl->m_Plot.mapToGlobal(eventPos) + TOOLTIP_OFFSET, tooltip,
291 &impl->m_Plot, TOOLTIP_RECT);
305 &impl->m_Plot, TOOLTIP_RECT);
292 306 };
293 307
294 308 QObject::connect(&impl->m_TracerTimer, &QTimer::timeout, showTooltip);
@@ -303,7 +317,7 void VisualizationGraphRenderingDelegate::onPlotUpdated() noexcept
303 317 impl->m_Plot.replot();
304 318 }
305 319
306 void VisualizationGraphRenderingDelegate::setAxesUnits(const Variable &variable) noexcept
320 void VisualizationGraphRenderingDelegate::setAxesUnits(Variable2& variable) noexcept
307 321 {
308 322
309 323 auto axisHelper = IAxisHelperFactory::create(variable);
@@ -318,8 +332,8 void VisualizationGraphRenderingDelegate::setAxesUnits(const Variable &variable)
318 332 impl->m_Plot.layer(AXES_LAYER)->replot();
319 333 }
320 334
321 void VisualizationGraphRenderingDelegate::setGraphProperties(const Variable &variable,
322 PlottablesMap &plottables) noexcept
335 void VisualizationGraphRenderingDelegate::setGraphProperties(
336 Variable2& variable, PlottablesMap& plottables) noexcept
323 337 {
324 338 // Axes' properties
325 339 auto axisHelper = IAxisHelperFactory::create(variable);
This diff has been collapsed as it changes many lines, (787 lines changed) Show them Hide them
@@ -16,21 +16,22
16 16 #include <Common/MimeTypesDef.h>
17 17 #include <Common/containers.h>
18 18 #include <Data/ArrayData.h>
19 #include <Data/DateTimeRangeHelper.h>
19 20 #include <Data/IDataSeries.h>
20 21 #include <Data/SpectrogramSeries.h>
21 22 #include <DragAndDrop/DragDropGuiController.h>
22 23 #include <Settings/SqpSettingsDefs.h>
23 24 #include <SqpApplication.h>
24 25 #include <Time/TimeController.h>
25 #include <Variable/Variable.h>
26 #include <Variable/Variable2.h>
26 27 #include <Variable/VariableController2.h>
27 #include <Data/DateTimeRangeHelper.h>
28 28
29 29 #include <unordered_map>
30 30
31 31 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
32 32
33 namespace {
33 namespace
34 {
34 35
35 36 /// Key pressed to enable drag&drop in all modes
36 37 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
@@ -58,21 +59,22 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:
58 59
59 60 } // namespace
60 61
61 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
62 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate
63 {
62 64
63 explicit VisualizationGraphWidgetPrivate(const QString &name)
64 : m_Name{name},
65 m_Flags{GraphFlag::EnableAll},
66 m_IsCalibration{false},
67 m_RenderingDelegate{nullptr}
65 explicit VisualizationGraphWidgetPrivate(const QString& name)
66 : m_Name { name }
67 , m_Flags { GraphFlag::EnableAll }
68 , m_IsCalibration { false }
69 , m_RenderingDelegate { nullptr }
68 70 {
69 71 m_plot = new QCustomPlot();
70 72 // Necessary for all platform since Qt::AA_EnableHighDpiScaling is enable.
71 73 m_plot->setPlottingHint(QCP::phFastPolylines, true);
72 74 }
73 75
74 void updateData(PlottablesMap &plottables, std::shared_ptr<Variable> variable,
75 const DateTimeRange &range)
76 void updateData(
77 PlottablesMap& plottables, std::shared_ptr<Variable2> variable, const DateTimeRange& range)
76 78 {
77 79 VisualizationGraphHelper::updateData(plottables, variable, range);
78 80
@@ -82,7 +84,7 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
82 84
83 85 QString m_Name;
84 86 // 1 variable -> n qcpplot
85 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
87 std::map<std::shared_ptr<Variable2>, PlottablesMap> m_VariableToPlotMultiMap;
86 88 GraphFlags m_Flags;
87 89 bool m_IsCalibration;
88 90 QCustomPlot* m_plot;
@@ -93,14 +95,14 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
93 95 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
94 96
95 97 QCPItemRect* m_DrawingZoomRect = nullptr;
96 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
98 QStack<QPair<QCPRange, QCPRange>> m_ZoomStack;
97 99
98 100 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
99 101 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
100 102
101 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
102 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
103 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
103 VisualizationSelectionZoneItem* m_DrawingZone = nullptr;
104 VisualizationSelectionZoneItem* m_HoveredZone = nullptr;
105 QVector<VisualizationSelectionZoneItem*> m_SelectionZones;
104 106
105 107 bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even
106 108
@@ -111,13 +113,13 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
111 113 m_lastMousePos = m_plot->mapFromParent(position);
112 114 m_lastXRange = m_plot->xAxis->range();
113 115 m_lastYRange = m_plot->yAxis->range();
114
115 116 }
116 117
117 inline bool isDrawingZoomRect(){return m_DrawingZoomRect!=nullptr;}
118 inline bool isDrawingZoomRect() { return m_DrawingZoomRect != nullptr; }
118 119 void updateZoomRect(const QPoint& newPos)
119 120 {
120 QPointF pos{m_plot->xAxis->pixelToCoord(newPos.x()), m_plot->yAxis->pixelToCoord(newPos.y())};
121 QPointF pos { m_plot->xAxis->pixelToCoord(newPos.x()),
122 m_plot->yAxis->pixelToCoord(newPos.y()) };
121 123 m_DrawingZoomRect->bottomRight->setCoords(pos);
122 124 m_plot->replot(QCustomPlot::rpQueuedReplot);
123 125 }
@@ -127,16 +129,17 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
127 129 auto axisX = m_plot->axisRect()->axis(QCPAxis::atBottom);
128 130 auto axisY = m_plot->axisRect()->axis(QCPAxis::atLeft);
129 131
130 auto newAxisXRange = QCPRange{m_DrawingZoomRect->topLeft->coords().x(),
131 m_DrawingZoomRect->bottomRight->coords().x()};
132 auto newAxisXRange = QCPRange { m_DrawingZoomRect->topLeft->coords().x(),
133 m_DrawingZoomRect->bottomRight->coords().x() };
132 134
133 auto newAxisYRange = QCPRange{m_DrawingZoomRect->topLeft->coords().y(),
134 m_DrawingZoomRect->bottomRight->coords().y()};
135 auto newAxisYRange = QCPRange { m_DrawingZoomRect->topLeft->coords().y(),
136 m_DrawingZoomRect->bottomRight->coords().y() };
135 137
136 138 removeDrawingRect();
137 139
138 140 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
139 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
141 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0))
142 {
140 143 m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
141 144 axisX->setRange(newAxisXRange);
142 145 axisY->setRange(newAxisYRange);
@@ -145,20 +148,20 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
145 148 }
146 149 }
147 150
148 inline bool isDrawingZoneRect(){return m_DrawingZone!=nullptr;}
151 inline bool isDrawingZoneRect() { return m_DrawingZone != nullptr; }
149 152 void updateZoneRect(const QPoint& newPos)
150 153 {
151 154 m_DrawingZone->setEnd(m_plot->xAxis->pixelToCoord(newPos.x()));
152 155 m_plot->replot(QCustomPlot::rpQueuedReplot);
153 156 }
154 157
155 void startDrawingRect(const QPoint &pos)
158 void startDrawingRect(const QPoint& pos)
156 159 {
157 160 removeDrawingRect();
158 161
159 162 auto axisPos = posToAxisPos(pos);
160 163
161 m_DrawingZoomRect = new QCPItemRect{m_plot};
164 m_DrawingZoomRect = new QCPItemRect { m_plot };
162 165 QPen p;
163 166 p.setWidth(2);
164 167 m_DrawingZoomRect->setPen(p);
@@ -169,39 +172,44 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
169 172
170 173 void removeDrawingRect()
171 174 {
172 if (m_DrawingZoomRect) {
175 if (m_DrawingZoomRect)
176 {
173 177 m_plot->removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
174 178 m_DrawingZoomRect = nullptr;
175 179 m_plot->replot(QCustomPlot::rpQueuedReplot);
176 180 }
177 181 }
178 182
179 void selectZone(const QPoint &pos)
183 void selectZone(const QPoint& pos)
180 184 {
181 185 auto zoneAtPos = selectionZoneAt(pos);
182 setSelectionZonesEditionEnabled(sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones);
186 setSelectionZonesEditionEnabled(
187 sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones);
183 188 }
184 189
185 void startDrawingZone(const QPoint &pos)
190 void startDrawingZone(const QPoint& pos)
186 191 {
187 192 endDrawingZone();
188 193
189 194 auto axisPos = posToAxisPos(pos);
190 195
191 m_DrawingZone = new VisualizationSelectionZoneItem{m_plot};
196 m_DrawingZone = new VisualizationSelectionZoneItem { m_plot };
192 197 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
193 198 m_DrawingZone->setEditionEnabled(false);
194 199 }
195 200
196 201 void endDrawingZone()
197 202 {
198 if (m_DrawingZone) {
203 if (m_DrawingZone)
204 {
199 205 auto drawingZoneRange = m_DrawingZone->range();
200 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
206 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0)
207 {
201 208 m_DrawingZone->setEditionEnabled(true);
202 209 addSelectionZone(m_DrawingZone);
203 210 }
204 else {
211 else
212 {
205 213 m_plot->removeItem(m_DrawingZone);
206 214 }
207 215
@@ -217,26 +225,29 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
217 225 * @TODO implement this, the difficulty is that selection zones have their own
218 226 * event handling code which seems to rely on QCP GUI event handling propagation
219 227 * which was a realy bad design choice.
220 */
228 */
221 229 }
222 230
223 231 void setSelectionZonesEditionEnabled(bool value)
224 232 {
225 for (auto s : m_SelectionZones) {
233 for (auto s : m_SelectionZones)
234 {
226 235 s->setEditionEnabled(value);
227 236 }
228 237 }
229 238
230 void addSelectionZone(VisualizationSelectionZoneItem *zone) { m_SelectionZones << zone; }
239 void addSelectionZone(VisualizationSelectionZoneItem* zone) { m_SelectionZones << zone; }
231 240
232 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos) const
241 VisualizationSelectionZoneItem* selectionZoneAt(const QPoint& pos) const
233 242 {
234 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
243 VisualizationSelectionZoneItem* selectionZoneItemUnderCursor = nullptr;
235 244 auto minDistanceToZone = -1;
236 for (auto zone : m_SelectionZones) {
245 for (auto zone : m_SelectionZones)
246 {
237 247 auto distanceToZone = zone->selectTest(pos, false);
238 248 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
239 && distanceToZone >= 0 && distanceToZone < m_plot->selectionTolerance()) {
249 && distanceToZone >= 0 && distanceToZone < m_plot->selectionTolerance())
250 {
240 251 selectionZoneItemUnderCursor = zone;
241 252 }
242 253 }
@@ -244,13 +255,15 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
244 255 return selectionZoneItemUnderCursor;
245 256 }
246 257
247 QVector<VisualizationSelectionZoneItem *> selectionZonesAt(const QPoint &pos,
248 const QCustomPlot &plot) const
258 QVector<VisualizationSelectionZoneItem*> selectionZonesAt(
259 const QPoint& pos, const QCustomPlot& plot) const
249 260 {
250 QVector<VisualizationSelectionZoneItem *> zones;
251 for (auto zone : m_SelectionZones) {
261 QVector<VisualizationSelectionZoneItem*> zones;
262 for (auto zone : m_SelectionZones)
263 {
252 264 auto distanceToZone = zone->selectTest(pos, false);
253 if (distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
265 if (distanceToZone >= 0 && distanceToZone < plot.selectionTolerance())
266 {
254 267 zones << zone;
255 268 }
256 269 }
@@ -258,50 +271,50 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
258 271 return zones;
259 272 }
260 273
261 void moveSelectionZoneOnTop(VisualizationSelectionZoneItem *zone, QCustomPlot &plot)
274 void moveSelectionZoneOnTop(VisualizationSelectionZoneItem* zone, QCustomPlot& plot)
262 275 {
263 if (!m_SelectionZones.isEmpty() && m_SelectionZones.last() != zone) {
276 if (!m_SelectionZones.isEmpty() && m_SelectionZones.last() != zone)
277 {
264 278 zone->moveToTop();
265 279 m_SelectionZones.removeAll(zone);
266 280 m_SelectionZones.append(zone);
267 281 }
268 282 }
269 283
270 QPointF posToAxisPos(const QPoint &pos) const
284 QPointF posToAxisPos(const QPoint& pos) const
271 285 {
272 286 auto axisX = m_plot->axisRect()->axis(QCPAxis::atBottom);
273 287 auto axisY = m_plot->axisRect()->axis(QCPAxis::atLeft);
274 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
288 return QPointF { axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y()) };
275 289 }
276 290
277 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
291 bool pointIsInAxisRect(const QPointF& axisPoint, QCustomPlot& plot) const
278 292 {
279 293 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
280 294 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
281 295 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
282 296 }
283 297
284 inline QCPRange _pixDistanceToRange(double pos1, double pos2, QCPAxis *axis)
298 inline QCPRange _pixDistanceToRange(double pos1, double pos2, QCPAxis* axis)
285 299 {
286 300 if (axis->scaleType() == QCPAxis::stLinear)
287 301 {
288 302 auto diff = axis->pixelToCoord(pos1) - axis->pixelToCoord(pos2);
289 return QCPRange{axis->range().lower + diff, axis->range().upper + diff};
303 return QCPRange { axis->range().lower + diff, axis->range().upper + diff };
290 304 }
291 305 else
292 306 {
293 307 auto diff = axis->pixelToCoord(pos1) / axis->pixelToCoord(pos2);
294 return QCPRange{axis->range().lower * diff, axis->range().upper * diff};
308 return QCPRange { axis->range().lower * diff, axis->range().upper * diff };
295 309 }
296 310 }
297 311
298 void setRange(const DateTimeRange &newRange, bool updateVar=true)
312 void setRange(const DateTimeRange& newRange, bool updateVar = true)
299 313 {
300 314 this->m_plot->xAxis->setRange(newRange.m_TStart, newRange.m_TEnd);
301 if(updateVar)
315 if (updateVar)
302 316 {
303 for (auto it = m_VariableToPlotMultiMap.begin(),
304 end = m_VariableToPlotMultiMap.end();
317 for (auto it = m_VariableToPlotMultiMap.begin(), end = m_VariableToPlotMultiMap.end();
305 318 it != end; it = m_VariableToPlotMultiMap.upper_bound(it->first))
306 319 {
307 320 sqpApp->variableController().asyncChangeRange(it->first, newRange);
@@ -310,18 +323,15 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
310 323 m_plot->replot(QCustomPlot::rpQueuedReplot);
311 324 }
312 325
313 void setRange(const QCPRange &newRange)
326 void setRange(const QCPRange& newRange)
314 327 {
315 auto graphRange = DateTimeRange{newRange.lower, newRange.upper};
328 auto graphRange = DateTimeRange { newRange.lower, newRange.upper };
316 329 setRange(graphRange);
317 330 }
318 331
319 void rescaleY()
320 {
321 m_plot->yAxis->rescale(true);
322 }
332 void rescaleY() { m_plot->yAxis->rescale(true); }
323 333
324 std::tuple<double,double> moveGraph(const QPoint& destination)
334 std::tuple<double, double> moveGraph(const QPoint& destination)
325 335 {
326 336 auto currentPos = m_plot->mapFromParent(destination);
327 337 auto xAxis = m_plot->axisRect()->rangeDragAxis(Qt::Horizontal);
@@ -329,37 +339,39 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
329 339 auto oldXRange = xAxis->range();
330 340 auto oldYRange = yAxis->range();
331 341 double dx = xAxis->pixelToCoord(m_lastMousePos.x()) - xAxis->pixelToCoord(currentPos.x());
332 xAxis->setRange(m_lastXRange.lower+dx, m_lastXRange.upper+dx);
333 if(yAxis->scaleType() == QCPAxis::stLinear)
342 xAxis->setRange(m_lastXRange.lower + dx, m_lastXRange.upper + dx);
343 if (yAxis->scaleType() == QCPAxis::stLinear)
334 344 {
335 double dy = yAxis->pixelToCoord(m_lastMousePos.y()) - yAxis->pixelToCoord(currentPos.y());
336 yAxis->setRange(m_lastYRange.lower+dy, m_lastYRange.upper+dy);
345 double dy
346 = yAxis->pixelToCoord(m_lastMousePos.y()) - yAxis->pixelToCoord(currentPos.y());
347 yAxis->setRange(m_lastYRange.lower + dy, m_lastYRange.upper + dy);
337 348 }
338 349 else
339 350 {
340 double dy = yAxis->pixelToCoord(m_lastMousePos.y()) / yAxis->pixelToCoord(currentPos.y());
341 yAxis->setRange(m_lastYRange.lower*dy, m_lastYRange.upper*dy);
351 double dy
352 = yAxis->pixelToCoord(m_lastMousePos.y()) / yAxis->pixelToCoord(currentPos.y());
353 yAxis->setRange(m_lastYRange.lower * dy, m_lastYRange.upper * dy);
342 354 }
343 355 auto newXRange = xAxis->range();
344 356 auto newYRange = yAxis->range();
345 357 setRange(xAxis->range());
346 //m_lastMousePos = currentPos;
347 return {newXRange.lower - oldXRange.lower, newYRange.lower - oldYRange.lower};
358 // m_lastMousePos = currentPos;
359 return { newXRange.lower - oldXRange.lower, newYRange.lower - oldYRange.lower };
348 360 }
349 361
350 362 void zoom(double factor, int center, Qt::Orientation orientation)
351 363 {
352 QCPAxis *axis = m_plot->axisRect()->rangeZoomAxis(orientation);
364 QCPAxis* axis = m_plot->axisRect()->rangeZoomAxis(orientation);
353 365 axis->scaleRange(factor, axis->pixelToCoord(center));
354 366 if (orientation == Qt::Horizontal)
355 367 setRange(axis->range());
356 368 m_plot->replot(QCustomPlot::rpQueuedReplot);
357 369 }
358 370
359 void transform(const DateTimeRangeTransformation &tranformation)
371 void transform(const DateTimeRangeTransformation& tranformation)
360 372 {
361 373 auto graphRange = m_plot->xAxis->range();
362 DateTimeRange range{graphRange.lower, graphRange.upper};
374 DateTimeRange range { graphRange.lower, graphRange.upper };
363 375 range = range.transform(tranformation);
364 376 setRange(range);
365 377 m_plot->replot(QCustomPlot::rpQueuedReplot);
@@ -369,8 +381,8 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
369 381 {
370 382 auto xAxis = m_plot->axisRect()->rangeDragAxis(Qt::Horizontal);
371 383 auto yAxis = m_plot->axisRect()->rangeDragAxis(Qt::Vertical);
372 xAxis->setRange(QCPRange(xAxis->range().lower+dx, xAxis->range().upper+dx));
373 yAxis->setRange(QCPRange(yAxis->range().lower+dy, yAxis->range().upper+dy));
384 xAxis->setRange(QCPRange(xAxis->range().lower + dx, xAxis->range().upper + dx));
385 yAxis->setRange(QCPRange(yAxis->range().lower + dy, yAxis->range().upper + dy));
374 386 setRange(xAxis->range());
375 387 m_plot->replot(QCustomPlot::rpQueuedReplot);
376 388 }
@@ -378,26 +390,30 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
378 390 void move(double factor, Qt::Orientation orientation)
379 391 {
380 392 auto oldRange = m_plot->xAxis->range();
381 QCPAxis *axis = m_plot->axisRect()->rangeDragAxis(orientation);
382 if (m_plot->xAxis->scaleType() == QCPAxis::stLinear) {
393 QCPAxis* axis = m_plot->axisRect()->rangeDragAxis(orientation);
394 if (m_plot->xAxis->scaleType() == QCPAxis::stLinear)
395 {
383 396 double rg = (axis->range().upper - axis->range().lower) * (factor / 10);
384 397 axis->setRange(axis->range().lower + (rg), axis->range().upper + (rg));
385 398 }
386 else if (m_plot->xAxis->scaleType() == QCPAxis::stLogarithmic) {
399 else if (m_plot->xAxis->scaleType() == QCPAxis::stLogarithmic)
400 {
387 401 int start = 0, stop = 0;
388 402 double diff = 0.;
389 if (factor > 0.0) {
403 if (factor > 0.0)
404 {
390 405 stop = m_plot->width() * factor / 10;
391 406 start = 2 * m_plot->width() * factor / 10;
392 407 }
393 if (factor < 0.0) {
408 if (factor < 0.0)
409 {
394 410 factor *= -1.0;
395 411 start = m_plot->width() * factor / 10;
396 412 stop = 2 * m_plot->width() * factor / 10;
397 413 }
398 414 diff = axis->pixelToCoord(start) / axis->pixelToCoord(stop);
399 415 axis->setRange(m_plot->axisRect()->rangeDragAxis(orientation)->range().lower * diff,
400 m_plot->axisRect()->rangeDragAxis(orientation)->range().upper * diff);
416 m_plot->axisRect()->rangeDragAxis(orientation)->range().upper * diff);
401 417 }
402 418 if (orientation == Qt::Horizontal)
403 419 setRange(axis->range());
@@ -405,10 +421,10 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
405 421 }
406 422 };
407 423
408 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
409 : VisualizationDragWidget{parent},
410 ui{new Ui::VisualizationGraphWidget},
411 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
424 VisualizationGraphWidget::VisualizationGraphWidget(const QString& name, QWidget* parent)
425 : VisualizationDragWidget { parent }
426 , ui { new Ui::VisualizationGraphWidget }
427 , impl { spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name) }
412 428 {
413 429 ui->setupUi(this);
414 430 this->layout()->addWidget(impl->m_plot);
@@ -430,7 +446,8 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget
430 446 impl->m_plot->setContextMenuPolicy(Qt::CustomContextMenu);
431 447 impl->m_plot->setParent(this);
432 448
433 connect(&sqpApp->variableController(), &VariableController2::variableDeleted, this, &VisualizationGraphWidget::variableDeleted);
449 connect(&sqpApp->variableController(), &VariableController2::variableDeleted, this,
450 &VisualizationGraphWidget::variableDeleted);
434 451 }
435 452
436 453
@@ -439,24 +456,26 VisualizationGraphWidget::~VisualizationGraphWidget()
439 456 delete ui;
440 457 }
441 458
442 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
459 VisualizationZoneWidget* VisualizationGraphWidget::parentZoneWidget() const noexcept
443 460 {
444 461 auto parent = parentWidget();
445 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
462 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget*>(parent))
463 {
446 464 parent = parent->parentWidget();
447 465 }
448 466
449 return qobject_cast<VisualizationZoneWidget *>(parent);
467 return qobject_cast<VisualizationZoneWidget*>(parent);
450 468 }
451 469
452 VisualizationWidget *VisualizationGraphWidget::parentVisualizationWidget() const
470 VisualizationWidget* VisualizationGraphWidget::parentVisualizationWidget() const
453 471 {
454 472 auto parent = parentWidget();
455 while (parent != nullptr && !qobject_cast<VisualizationWidget *>(parent)) {
473 while (parent != nullptr && !qobject_cast<VisualizationWidget*>(parent))
474 {
456 475 parent = parent->parentWidget();
457 476 }
458 477
459 return qobject_cast<VisualizationWidget *>(parent);
478 return qobject_cast<VisualizationWidget*>(parent);
460 479 }
461 480
462 481 void VisualizationGraphWidget::setFlags(GraphFlags flags)
@@ -464,7 +483,7 void VisualizationGraphWidget::setFlags(GraphFlags flags)
464 483 impl->m_Flags = std::move(flags);
465 484 }
466 485
467 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, DateTimeRange range)
486 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable2> variable, DateTimeRange range)
468 487 {
469 488 // Uses delegate to create the qcpplot components according to the variable
470 489 auto createdPlottables = VisualizationGraphHelper::create(variable, *impl->m_plot);
@@ -472,45 +491,46 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, D
472 491 // Sets graph properties
473 492 impl->m_RenderingDelegate->setGraphProperties(*variable, createdPlottables);
474 493
475 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
494 impl->m_VariableToPlotMultiMap.insert({ variable, std::move(createdPlottables) });
476 495
477 496 setGraphRange(range);
478 497 // If the variable already has its data loaded, load its units and its range in the graph
479 if (variable->dataSeries() != nullptr) {
498 if (variable->data() != nullptr)
499 {
480 500 impl->m_RenderingDelegate->setAxesUnits(*variable);
481 501 }
482 502 else
483 503 {
484 auto context = new QObject{this};
485 connect(variable.get(), &Variable::updated, context,
486 [this, variable, context, range](QUuid)
487 {
488 this->impl->m_RenderingDelegate->setAxesUnits(*variable);
489 this->impl->m_plot->replot(QCustomPlot::rpQueuedReplot);
490 delete context;
491 }
492 );
504 auto context = new QObject { this };
505 connect(
506 variable.get(), &Variable2::updated, context, [this, variable, context, range](QUuid) {
507 this->impl->m_RenderingDelegate->setAxesUnits(*variable);
508 this->impl->m_plot->replot(QCustomPlot::rpQueuedReplot);
509 delete context;
510 });
493 511 }
494 512 //@TODO this is bad! when variable is moved to another graph it still fires
495 513 // even if this has been deleted
496 connect(variable.get(), &Variable::updated, this, &VisualizationGraphWidget::variableUpdated);
514 connect(variable.get(), &Variable2::updated, this, &VisualizationGraphWidget::variableUpdated);
497 515 this->onUpdateVarDisplaying(variable, range); // My bullshit
498 516 emit variableAdded(variable);
499 517 }
500 518
501 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
519 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable2> variable) noexcept
502 520 {
503 521 // Each component associated to the variable :
504 522 // - is removed from qcpplot (which deletes it)
505 523 // - is no longer referenced in the map
506 524 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
507 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
525 if (variableIt != impl->m_VariableToPlotMultiMap.cend())
526 {
508 527 emit variableAboutToBeRemoved(variable);
509 528
510 auto &plottablesMap = variableIt->second;
529 auto& plottablesMap = variableIt->second;
511 530
512 531 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
513 plottableIt != plottableEnd;) {
532 plottableIt != plottableEnd;)
533 {
514 534 impl->m_plot->removePlottable(plottableIt->second);
515 535 plottableIt = plottablesMap.erase(plottableIt);
516 536 }
@@ -522,20 +542,22 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable
522 542 impl->m_plot->replot(QCustomPlot::rpQueuedReplot);
523 543 }
524 544
525 std::vector<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
545 std::vector<std::shared_ptr<Variable2>> VisualizationGraphWidget::variables() const
526 546 {
527 auto variables = std::vector<std::shared_ptr<Variable> >{};
547 auto variables = std::vector<std::shared_ptr<Variable2>> {};
528 548 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
529 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
549 it != std::cend(impl->m_VariableToPlotMultiMap); ++it)
550 {
530 551 variables.push_back(it->first);
531 552 }
532 553
533 554 return variables;
534 555 }
535 556
536 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
557 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable2> variable)
537 558 {
538 if (!variable) {
559 if (!variable)
560 {
539 561 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
540 562 return;
541 563 }
@@ -546,17 +568,17 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
546 568 DateTimeRange VisualizationGraphWidget::graphRange() const noexcept
547 569 {
548 570 auto graphRange = impl->m_plot->xAxis->range();
549 return DateTimeRange{graphRange.lower, graphRange.upper};
571 return DateTimeRange { graphRange.lower, graphRange.upper };
550 572 }
551 573
552 void VisualizationGraphWidget::setGraphRange(const DateTimeRange &range, bool updateVar, bool forward)
574 void VisualizationGraphWidget::setGraphRange(
575 const DateTimeRange& range, bool updateVar, bool forward)
553 576 {
554 577 impl->setRange(range, updateVar);
555 if(forward)
578 if (forward)
556 579 {
557 580 emit this->setrange_sig(this->graphRange(), true, false);
558 581 }
559
560 582 }
561 583
562 584 void VisualizationGraphWidget::setAutoRangeOnVariableInitialization(bool value)
@@ -567,16 +589,18 void VisualizationGraphWidget::setAutoRangeOnVariableInitialization(bool value)
567 589 QVector<DateTimeRange> VisualizationGraphWidget::selectionZoneRanges() const
568 590 {
569 591 QVector<DateTimeRange> ranges;
570 for (auto zone : impl->m_SelectionZones) {
592 for (auto zone : impl->m_SelectionZones)
593 {
571 594 ranges << zone->range();
572 595 }
573 596
574 597 return ranges;
575 598 }
576 599
577 void VisualizationGraphWidget::addSelectionZones(const QVector<DateTimeRange> &ranges)
600 void VisualizationGraphWidget::addSelectionZones(const QVector<DateTimeRange>& ranges)
578 601 {
579 for (const auto &range : ranges) {
602 for (const auto& range : ranges)
603 {
580 604 // note: ownership is transfered to QCustomPlot
581 605 auto zone = new VisualizationSelectionZoneItem(&plot());
582 606 zone->setRange(range.m_TStart, range.m_TEnd);
@@ -586,8 +610,8 void VisualizationGraphWidget::addSelectionZones(const QVector<DateTimeRange> &r
586 610 plot().replot(QCustomPlot::rpQueuedReplot);
587 611 }
588 612
589 VisualizationSelectionZoneItem *
590 VisualizationGraphWidget::addSelectionZone(const QString &name, const DateTimeRange &range)
613 VisualizationSelectionZoneItem* VisualizationGraphWidget::addSelectionZone(
614 const QString& name, const DateTimeRange& range)
591 615 {
592 616 // note: ownership is transfered to QCustomPlot
593 617 auto zone = new VisualizationSelectionZoneItem(&plot());
@@ -600,11 +624,12 VisualizationGraphWidget::addSelectionZone(const QString &name, const DateTimeRa
600 624 return zone;
601 625 }
602 626
603 void VisualizationGraphWidget::removeSelectionZone(VisualizationSelectionZoneItem *selectionZone)
627 void VisualizationGraphWidget::removeSelectionZone(VisualizationSelectionZoneItem* selectionZone)
604 628 {
605 629 parentVisualizationWidget()->selectionZoneManager().setSelected(selectionZone, false);
606 630
607 if (impl->m_HoveredZone == selectionZone) {
631 if (impl->m_HoveredZone == selectionZone)
632 {
608 633 impl->m_HoveredZone = nullptr;
609 634 setCursor(Qt::ArrowCursor);
610 635 }
@@ -626,66 +651,69 void VisualizationGraphWidget::undoZoom()
626 651 plot().replot(QCustomPlot::rpQueuedReplot);
627 652 }
628 653
629 void VisualizationGraphWidget::zoom(double factor, int center, Qt::Orientation orientation, bool forward)
654 void VisualizationGraphWidget::zoom(
655 double factor, int center, Qt::Orientation orientation, bool forward)
630 656 {
631 657 impl->zoom(factor, center, orientation);
632 if(forward && orientation==Qt::Horizontal)
658 if (forward && orientation == Qt::Horizontal)
633 659 emit this->setrange_sig(this->graphRange(), true, false);
634 660 }
635 661
636 662 void VisualizationGraphWidget::move(double factor, Qt::Orientation orientation, bool forward)
637 663 {
638 664 impl->move(factor, orientation);
639 if(forward)
665 if (forward)
640 666 emit this->setrange_sig(this->graphRange(), true, false);
641 667 }
642 668
643 669 void VisualizationGraphWidget::move(double dx, double dy, bool forward)
644 670 {
645 671 impl->move(dx, dy);
646 if(forward)
672 if (forward)
647 673 emit this->setrange_sig(this->graphRange(), true, false);
648 674 }
649 675
650 void VisualizationGraphWidget::transform(const DateTimeRangeTransformation &tranformation, bool forward)
676 void VisualizationGraphWidget::transform(
677 const DateTimeRangeTransformation& tranformation, bool forward)
651 678 {
652 679 impl->transform(tranformation);
653 if(forward)
680 if (forward)
654 681 emit this->setrange_sig(this->graphRange(), true, false);
655 682 }
656 683
657 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
684 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor* visitor)
658 685 {
659 if (visitor) {
686 if (visitor)
687 {
660 688 visitor->visit(this);
661 689 }
662 else {
690 else
691 {
663 692 qCCritical(LOG_VisualizationGraphWidget())
664 693 << tr("Can't visit widget : the visitor is null");
665 694 }
666 695 }
667 696
668 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
697 bool VisualizationGraphWidget::canDrop(Variable2& variable) const
669 698 {
670 auto isSpectrogram = [](const auto &variable) {
671 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
672 };
699 auto isSpectrogram
700 = [](auto& variable) { return variable.type() == DataSeriesType::SPECTROGRAM; };
673 701
674 702 // - A spectrogram series can't be dropped on graph with existing plottables
675 703 // - No data series can be dropped on graph with existing spectrogram series
676 704 return isSpectrogram(variable)
677 ? impl->m_VariableToPlotMultiMap.empty()
678 : std::none_of(
679 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
680 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
705 ? impl->m_VariableToPlotMultiMap.empty()
706 : std::none_of(impl->m_VariableToPlotMultiMap.cbegin(),
707 impl->m_VariableToPlotMultiMap.cend(),
708 [isSpectrogram](const auto& entry) { return isSpectrogram(*entry.first); });
681 709 }
682 710
683 bool VisualizationGraphWidget::contains(const Variable &variable) const
711 bool VisualizationGraphWidget::contains(Variable2& variable) const
684 712 {
685 713 // Finds the variable among the keys of the map
686 714 auto variablePtr = &variable;
687 715 auto findVariable
688 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
716 = [variablePtr](const auto& entry) { return variablePtr == entry.first.get(); };
689 717
690 718 auto end = impl->m_VariableToPlotMultiMap.cend();
691 719 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
@@ -697,20 +725,22 QString VisualizationGraphWidget::name() const
697 725 return impl->m_Name;
698 726 }
699 727
700 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
728 QMimeData* VisualizationGraphWidget::mimeData(const QPoint& position) const
701 729 {
702 730 auto mimeData = new QMimeData;
703 731
704 732 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position);
705 733 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
706 && selectionZoneItemUnderCursor) {
707 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
708 selectionZoneItemUnderCursor->range()));
709 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
710 selectionZoneItemUnderCursor->range()));
734 && selectionZoneItemUnderCursor)
735 {
736 mimeData->setData(MIME_TYPE_TIME_RANGE,
737 TimeController::mimeDataForTimeRange(selectionZoneItemUnderCursor->range()));
738 mimeData->setData(MIME_TYPE_SELECTION_ZONE,
739 TimeController::mimeDataForTimeRange(selectionZoneItemUnderCursor->range()));
711 740 }
712 else {
713 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
741 else
742 {
743 mimeData->setData(MIME_TYPE_GRAPH, QByteArray {});
714 744
715 745 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
716 746 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
@@ -719,21 +749,22 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
719 749 return mimeData;
720 750 }
721 751
722 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
752 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint& dragPosition)
723 753 {
724 754 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition);
725 755 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
726 && selectionZoneItemUnderCursor) {
756 && selectionZoneItemUnderCursor)
757 {
727 758
728 759 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
729 760 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
730 761
731 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
732 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
762 auto zoneSize = QSizeF { qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
763 qAbs(zoneBottomRight.y() - zoneTopLeft.y()) }
733 764 .toSize();
734 765
735 766 auto pixmap = QPixmap(zoneSize);
736 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
767 render(&pixmap, QPoint(), QRegion { QRect { zoneTopLeft.toPoint(), zoneSize } });
737 768
738 769 return pixmap;
739 770 }
@@ -748,10 +779,12 bool VisualizationGraphWidget::isDragAllowed() const
748 779
749 780 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
750 781 {
751 if (highlighted) {
782 if (highlighted)
783 {
752 784 plot().setBackground(QBrush(QColor("#BBD5EE")));
753 785 }
754 else {
786 else
787 {
755 788 plot().setBackground(QBrush(Qt::white));
756 789 }
757 790
@@ -807,49 +840,55 void VisualizationGraphWidget::removeHorizontalCursor()
807 840 plot().replot(QCustomPlot::rpQueuedReplot);
808 841 }
809 842
810 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
843 void VisualizationGraphWidget::closeEvent(QCloseEvent* event)
811 844 {
812 845 Q_UNUSED(event);
813 846
814 for (auto i : impl->m_SelectionZones) {
847 for (auto i : impl->m_SelectionZones)
848 {
815 849 parentVisualizationWidget()->selectionZoneManager().setSelected(i, false);
816 850 }
817 851
818 852 // Prevents that all variables will be removed from graph when it will be closed
819 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
853 for (auto& variableEntry : impl->m_VariableToPlotMultiMap)
854 {
820 855 emit variableAboutToBeRemoved(variableEntry.first);
821 856 }
822 857 }
823 858
824 void VisualizationGraphWidget::enterEvent(QEvent *event)
859 void VisualizationGraphWidget::enterEvent(QEvent* event)
825 860 {
826 861 Q_UNUSED(event);
827 862 impl->m_RenderingDelegate->showGraphOverlay(true);
828 863 }
829 864
830 void VisualizationGraphWidget::leaveEvent(QEvent *event)
865 void VisualizationGraphWidget::leaveEvent(QEvent* event)
831 866 {
832 867 Q_UNUSED(event);
833 868 impl->m_RenderingDelegate->showGraphOverlay(false);
834 869
835 if (auto parentZone = parentZoneWidget()) {
870 if (auto parentZone = parentZoneWidget())
871 {
836 872 parentZone->notifyMouseLeaveGraph(this);
837 873 }
838 else {
874 else
875 {
839 876 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
840 877 }
841 878
842 if (impl->m_HoveredZone) {
879 if (impl->m_HoveredZone)
880 {
843 881 impl->m_HoveredZone->setHovered(false);
844 882 impl->m_HoveredZone = nullptr;
845 883 }
846 884 }
847 885
848 void VisualizationGraphWidget::wheelEvent(QWheelEvent *event)
886 void VisualizationGraphWidget::wheelEvent(QWheelEvent* event)
849 887 {
850 888 double factor;
851 889 double wheelSteps = event->delta() / 120.0; // a single step delta is +/-120 usually
852 if (event->modifiers() == Qt::ControlModifier) {
890 if (event->modifiers() == Qt::ControlModifier)
891 {
853 892 if (event->orientation() == Qt::Vertical) // mRangeZoom.testFlag(Qt::Vertical))
854 893 {
855 894 setCursor(Qt::SizeVerCursor);
@@ -857,7 +896,8 void VisualizationGraphWidget::wheelEvent(QWheelEvent *event)
857 896 zoom(factor, event->pos().y(), Qt::Vertical);
858 897 }
859 898 }
860 else if (event->modifiers() == Qt::ShiftModifier) {
899 else if (event->modifiers() == Qt::ShiftModifier)
900 {
861 901 if (event->orientation() == Qt::Vertical) // mRangeZoom.testFlag(Qt::Vertical))
862 902 {
863 903 setCursor(Qt::SizeHorCursor);
@@ -865,17 +905,17 void VisualizationGraphWidget::wheelEvent(QWheelEvent *event)
865 905 zoom(factor, event->pos().x(), Qt::Horizontal);
866 906 }
867 907 }
868 else {
908 else
909 {
869 910 move(wheelSteps, Qt::Horizontal);
870 911 }
871 912 event->accept();
872 913 }
873 914
874 915
875
876 void VisualizationGraphWidget::mouseMoveEvent(QMouseEvent *event)
916 void VisualizationGraphWidget::mouseMoveEvent(QMouseEvent* event)
877 917 {
878 if(impl->isDrawingZoomRect())
918 if (impl->isDrawingZoomRect())
879 919 {
880 920 impl->updateZoomRect(event->pos());
881 921 }
@@ -885,45 +925,46 void VisualizationGraphWidget::mouseMoveEvent(QMouseEvent *event)
885 925 }
886 926 else if (event->buttons() == Qt::LeftButton)
887 927 {
888 if(sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::None)
928 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::None)
889 929 {
890 auto [dx,dy] = impl->moveGraph(event->pos());
930 auto [dx, dy] = impl->moveGraph(event->pos());
891 931 emit this->setrange_sig(this->graphRange(), true, false);
892 932 }
893 else if(sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones)
933 else if (sqpApp->plotsInteractionMode()
934 == SqpApplication::PlotsInteractionMode::SelectionZones)
894 935 {
895 936 auto posInPlot = this->impl->m_plot->mapFromParent(event->pos());
896 if(auto item = impl->m_plot->itemAt(posInPlot))
937 if (auto item = impl->m_plot->itemAt(posInPlot))
897 938 {
898 if(qobject_cast<VisualizationSelectionZoneItem*>(item))
939 if (qobject_cast<VisualizationSelectionZoneItem*>(item))
899 940 {
900 QMouseEvent e{QEvent::MouseMove, posInPlot, event->button(),event->buttons(),event->modifiers()};
941 QMouseEvent e { QEvent::MouseMove, posInPlot, event->button(), event->buttons(),
942 event->modifiers() };
901 943 sqpApp->sendEvent(this->impl->m_plot, &e);
902 944 this->impl->m_plot->replot(QCustomPlot::rpImmediateRefresh);
903 945 }
904 946 }
905
906 947 }
907 948 }
908 949 else
909 950 {
910 951 impl->m_RenderingDelegate->updateTooltip(event);
911 952 }
912 //event->accept();
953 // event->accept();
913 954 QWidget::mouseMoveEvent(event);
914 955 }
915 956
916 void VisualizationGraphWidget::mouseReleaseEvent(QMouseEvent *event)
957 void VisualizationGraphWidget::mouseReleaseEvent(QMouseEvent* event)
917 958 {
918 if(impl->isDrawingZoomRect())
959 if (impl->isDrawingZoomRect())
919 960 {
920 961 auto oldRange = this->graphRange();
921 962 impl->applyZoomRect();
922 963 auto newRange = this->graphRange();
923 if(auto tf = DateTimeRangeHelper::computeTransformation(oldRange,newRange))
964 if (auto tf = DateTimeRangeHelper::computeTransformation(oldRange, newRange))
924 965 emit this->transform_sig(tf.value(), false);
925 966 }
926 else if(impl->isDrawingZoneRect())
967 else if (impl->isDrawingZoneRect())
927 968 {
928 969 impl->endDrawingZone();
929 970 }
@@ -932,20 +973,21 void VisualizationGraphWidget::mouseReleaseEvent(QMouseEvent *event)
932 973 setCursor(Qt::ArrowCursor);
933 974 }
934 975 auto posInPlot = this->impl->m_plot->mapFromParent(event->pos());
935 if(auto item = impl->m_plot->itemAt(posInPlot))
976 if (auto item = impl->m_plot->itemAt(posInPlot))
936 977 {
937 if(qobject_cast<VisualizationSelectionZoneItem*>(item))
978 if (qobject_cast<VisualizationSelectionZoneItem*>(item))
938 979 {
939 QMouseEvent e{QEvent::MouseButtonRelease, posInPlot, event->button(), event->buttons(), event->modifiers()};
980 QMouseEvent e { QEvent::MouseButtonRelease, posInPlot, event->button(),
981 event->buttons(), event->modifiers() };
940 982 sqpApp->sendEvent(this->impl->m_plot, &e);
941 983 }
942 984 }
943 985 event->accept();
944 986 }
945 987
946 void VisualizationGraphWidget::mousePressEvent(QMouseEvent *event)
988 void VisualizationGraphWidget::mousePressEvent(QMouseEvent* event)
947 989 {
948 if (event->button()==Qt::RightButton)
990 if (event->button() == Qt::RightButton)
949 991 {
950 992 onGraphMenuRequested(event->pos());
951 993 }
@@ -954,15 +996,16 void VisualizationGraphWidget::mousePressEvent(QMouseEvent *event)
954 996 auto selectedZone = impl->selectionZoneAt(event->pos());
955 997 switch (sqpApp->plotsInteractionMode())
956 998 {
957 case SqpApplication::PlotsInteractionMode::DragAndDrop :
958 break;
959 case SqpApplication::PlotsInteractionMode::SelectionZones :
960 impl->setSelectionZonesEditionEnabled(true);
961 if ((event->modifiers() == Qt::ControlModifier) && (selectedZone != nullptr))
962 {
963 auto alreadySelectedZones = parentVisualizationWidget()->selectionZoneManager().selectedItems();
999 case SqpApplication::PlotsInteractionMode::DragAndDrop:
1000 break;
1001 case SqpApplication::PlotsInteractionMode::SelectionZones:
1002 impl->setSelectionZonesEditionEnabled(true);
1003 if ((event->modifiers() == Qt::ControlModifier) && (selectedZone != nullptr))
1004 {
1005 auto alreadySelectedZones
1006 = parentVisualizationWidget()->selectionZoneManager().selectedItems();
964 1007 selectedZone->setAssociatedEditedZones(alreadySelectedZones);
965 if(SciQLop::containers::contains(alreadySelectedZones, selectedZone))
1008 if (SciQLop::containers::contains(alreadySelectedZones, selectedZone))
966 1009 {
967 1010 alreadySelectedZones.removeOne(selectedZone);
968 1011 }
@@ -970,64 +1013,68 void VisualizationGraphWidget::mousePressEvent(QMouseEvent *event)
970 1013 {
971 1014 alreadySelectedZones.append(selectedZone);
972 1015 }
973 parentVisualizationWidget()->selectionZoneManager().select(alreadySelectedZones);
974 }
975 else
976 {
977 if (!selectedZone)
978 {
979 parentVisualizationWidget()->selectionZoneManager().clearSelection();
980 impl->startDrawingZone(event->pos());
1016 parentVisualizationWidget()->selectionZoneManager().select(
1017 alreadySelectedZones);
981 1018 }
982 1019 else
983 1020 {
984 parentVisualizationWidget()->selectionZoneManager().select({ selectedZone });
1021 if (!selectedZone)
1022 {
1023 parentVisualizationWidget()->selectionZoneManager().clearSelection();
1024 impl->startDrawingZone(event->pos());
1025 }
1026 else
1027 {
1028 parentVisualizationWidget()->selectionZoneManager().select(
1029 { selectedZone });
1030 }
985 1031 }
986 }
987 {
988 auto posInPlot = this->impl->m_plot->mapFromParent(event->pos());
989 if(auto item = impl->m_plot->itemAt(posInPlot))
990 1032 {
991 if(qobject_cast<VisualizationSelectionZoneItem*>(item))
1033 auto posInPlot = this->impl->m_plot->mapFromParent(event->pos());
1034 if (auto item = impl->m_plot->itemAt(posInPlot))
992 1035 {
993 QMouseEvent e{QEvent::MouseButtonPress, posInPlot, event->button(), event->buttons(), event->modifiers()};
994 sqpApp->sendEvent(this->impl->m_plot, &e);
1036 if (qobject_cast<VisualizationSelectionZoneItem*>(item))
1037 {
1038 QMouseEvent e { QEvent::MouseButtonPress, posInPlot, event->button(),
1039 event->buttons(), event->modifiers() };
1040 sqpApp->sendEvent(this->impl->m_plot, &e);
1041 }
995 1042 }
996 1043 }
997 }
998 break;
999 case SqpApplication::PlotsInteractionMode::ZoomBox :
1000 impl->startDrawingRect(event->pos());
1001 break;
1002 default:
1003 if(auto item = impl->m_plot->itemAt(event->pos()))
1004 {
1005 emit impl->m_plot->itemClick(item,event);
1006 if(qobject_cast<VisualizationSelectionZoneItem*>(item))
1044 break;
1045 case SqpApplication::PlotsInteractionMode::ZoomBox:
1046 impl->startDrawingRect(event->pos());
1047 break;
1048 default:
1049 if (auto item = impl->m_plot->itemAt(event->pos()))
1050 {
1051 emit impl->m_plot->itemClick(item, event);
1052 if (qobject_cast<VisualizationSelectionZoneItem*>(item))
1053 {
1054 setCursor(Qt::ClosedHandCursor);
1055 impl->enterPlotDrag(event->pos());
1056 }
1057 }
1058 else
1007 1059 {
1008 1060 setCursor(Qt::ClosedHandCursor);
1009 1061 impl->enterPlotDrag(event->pos());
1010 1062 }
1011 }
1012 else
1013 {
1014 setCursor(Qt::ClosedHandCursor);
1015 impl->enterPlotDrag(event->pos());
1016 }
1017 1063 }
1018 1064 }
1019 //event->accept();
1065 // event->accept();
1020 1066 QWidget::mousePressEvent(event);
1021 1067 }
1022 1068
1023 void VisualizationGraphWidget::mouseDoubleClickEvent(QMouseEvent *event)
1069 void VisualizationGraphWidget::mouseDoubleClickEvent(QMouseEvent* event)
1024 1070 {
1025 1071 impl->m_RenderingDelegate->onMouseDoubleClick(event);
1026 1072 }
1027 1073
1028 void VisualizationGraphWidget::keyReleaseEvent(QKeyEvent *event)
1074 void VisualizationGraphWidget::keyReleaseEvent(QKeyEvent* event)
1029 1075 {
1030 switch (event->key()) {
1076 switch (event->key())
1077 {
1031 1078 case Qt::Key_Control:
1032 1079 event->accept();
1033 1080 break;
@@ -1039,12 +1086,13 void VisualizationGraphWidget::keyReleaseEvent(QKeyEvent *event)
1039 1086 break;
1040 1087 }
1041 1088 setCursor(Qt::ArrowCursor);
1042 //event->accept();
1089 // event->accept();
1043 1090 }
1044 1091
1045 void VisualizationGraphWidget::keyPressEvent(QKeyEvent *event)
1092 void VisualizationGraphWidget::keyPressEvent(QKeyEvent* event)
1046 1093 {
1047 switch (event->key()) {
1094 switch (event->key())
1095 {
1048 1096 case Qt::Key_Control:
1049 1097 setCursor(Qt::CrossCursor);
1050 1098 break;
@@ -1055,34 +1103,42 void VisualizationGraphWidget::keyPressEvent(QKeyEvent *event)
1055 1103 impl->m_plot->replot(QCustomPlot::rpQueuedReplot);
1056 1104 break;
1057 1105 case Qt::Key_Left:
1058 if (event->modifiers() != Qt::ControlModifier) {
1106 if (event->modifiers() != Qt::ControlModifier)
1107 {
1059 1108 move(-0.1, Qt::Horizontal);
1060 1109 }
1061 else {
1110 else
1111 {
1062 1112 zoom(2, this->width() / 2, Qt::Horizontal);
1063 1113 }
1064 1114 break;
1065 1115 case Qt::Key_Right:
1066 if (event->modifiers() != Qt::ControlModifier) {
1116 if (event->modifiers() != Qt::ControlModifier)
1117 {
1067 1118 move(0.1, Qt::Horizontal);
1068 1119 }
1069 else {
1120 else
1121 {
1070 1122 zoom(0.5, this->width() / 2, Qt::Horizontal);
1071 1123 }
1072 1124 break;
1073 1125 case Qt::Key_Up:
1074 if (event->modifiers() != Qt::ControlModifier) {
1126 if (event->modifiers() != Qt::ControlModifier)
1127 {
1075 1128 move(0.1, Qt::Vertical);
1076 1129 }
1077 else {
1130 else
1131 {
1078 1132 zoom(0.5, this->height() / 2, Qt::Vertical);
1079 1133 }
1080 1134 break;
1081 1135 case Qt::Key_Down:
1082 if (event->modifiers() != Qt::ControlModifier) {
1136 if (event->modifiers() != Qt::ControlModifier)
1137 {
1083 1138 move(-0.1, Qt::Vertical);
1084 1139 }
1085 else {
1140 else
1141 {
1086 1142 zoom(2, this->height() / 2, Qt::Vertical);
1087 1143 }
1088 1144 break;
@@ -1092,26 +1148,29 void VisualizationGraphWidget::keyPressEvent(QKeyEvent *event)
1092 1148 }
1093 1149 }
1094 1150
1095 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
1151 QCustomPlot& VisualizationGraphWidget::plot() const noexcept
1096 1152 {
1097 1153 return *impl->m_plot;
1098 1154 }
1099 1155
1100 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
1156 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint& pos) noexcept
1101 1157 {
1102 QMenu graphMenu{};
1158 QMenu graphMenu {};
1103 1159
1104 1160 // Iterates on variables (unique keys)
1105 1161 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
1106 end = impl->m_VariableToPlotMultiMap.cend();
1107 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
1162 end = impl->m_VariableToPlotMultiMap.cend();
1163 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first))
1164 {
1108 1165 // 'Remove variable' action
1109 1166 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
1110 [this, var = it->first]() { removeVariable(var); });
1167 [this, var = it->first]() { removeVariable(var); });
1111 1168 }
1112 1169
1113 if (!impl->m_ZoomStack.isEmpty()) {
1114 if (!graphMenu.isEmpty()) {
1170 if (!impl->m_ZoomStack.isEmpty())
1171 {
1172 if (!graphMenu.isEmpty())
1173 {
1115 1174 graphMenu.addSeparator();
1116 1175 }
1117 1176
@@ -1120,49 +1179,58 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
1120 1179
1121 1180 // Selection Zone Actions
1122 1181 auto selectionZoneItem = impl->selectionZoneAt(pos);
1123 if (selectionZoneItem) {
1182 if (selectionZoneItem)
1183 {
1124 1184 auto selectedItems = parentVisualizationWidget()->selectionZoneManager().selectedItems();
1125 1185 selectedItems.removeAll(selectionZoneItem);
1126 1186 selectedItems.prepend(selectionZoneItem); // Put the current selection zone first
1127 1187
1128 1188 auto zoneActions = sqpApp->actionsGuiController().selectionZoneActions();
1129 if (!zoneActions.isEmpty() && !graphMenu.isEmpty()) {
1189 if (!zoneActions.isEmpty() && !graphMenu.isEmpty())
1190 {
1130 1191 graphMenu.addSeparator();
1131 1192 }
1132 1193
1133 QHash<QString, QMenu *> subMenus;
1194 QHash<QString, QMenu*> subMenus;
1134 1195 QHash<QString, bool> subMenusEnabled;
1135 QHash<QString, FilteringAction *> filteredMenu;
1196 QHash<QString, FilteringAction*> filteredMenu;
1136 1197
1137 for (auto zoneAction : zoneActions) {
1198 for (auto zoneAction : zoneActions)
1199 {
1138 1200
1139 1201 auto isEnabled = zoneAction->isEnabled(selectedItems);
1140 1202
1141 1203 auto menu = &graphMenu;
1142 1204 QString menuPath;
1143 for (auto subMenuName : zoneAction->subMenuList()) {
1205 for (auto subMenuName : zoneAction->subMenuList())
1206 {
1144 1207 menuPath += '/';
1145 1208 menuPath += subMenuName;
1146 1209
1147 if (!subMenus.contains(menuPath)) {
1210 if (!subMenus.contains(menuPath))
1211 {
1148 1212 menu = menu->addMenu(subMenuName);
1149 1213 subMenus[menuPath] = menu;
1150 1214 subMenusEnabled[menuPath] = isEnabled;
1151 1215 }
1152 else {
1216 else
1217 {
1153 1218 menu = subMenus.value(menuPath);
1154 if (isEnabled) {
1219 if (isEnabled)
1220 {
1155 1221 // The sub menu is enabled if at least one of its actions is enabled
1156 1222 subMenusEnabled[menuPath] = true;
1157 1223 }
1158 1224 }
1159 1225 }
1160 1226
1161 FilteringAction *filterAction = nullptr;
1162 if (sqpApp->actionsGuiController().isMenuFiltered(zoneAction->subMenuList())) {
1227 FilteringAction* filterAction = nullptr;
1228 if (sqpApp->actionsGuiController().isMenuFiltered(zoneAction->subMenuList()))
1229 {
1163 1230 filterAction = filteredMenu.value(menuPath);
1164 if (!filterAction) {
1165 filterAction = new FilteringAction{this};
1231 if (!filterAction)
1232 {
1233 filterAction = new FilteringAction { this };
1166 1234 filteredMenu[menuPath] = filterAction;
1167 1235 menu->addAction(filterAction);
1168 1236 }
@@ -1172,29 +1240,32 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
1172 1240 action->setEnabled(isEnabled);
1173 1241 action->setShortcut(zoneAction->displayedShortcut());
1174 1242 QObject::connect(action, &QAction::triggered,
1175 [zoneAction, selectedItems]() { zoneAction->execute(selectedItems); });
1243 [zoneAction, selectedItems]() { zoneAction->execute(selectedItems); });
1176 1244
1177 if (filterAction && zoneAction->isFilteringAllowed()) {
1245 if (filterAction && zoneAction->isFilteringAllowed())
1246 {
1178 1247 filterAction->addActionToFilter(action);
1179 1248 }
1180 1249 }
1181 1250
1182 for (auto it = subMenus.cbegin(); it != subMenus.cend(); ++it) {
1251 for (auto it = subMenus.cbegin(); it != subMenus.cend(); ++it)
1252 {
1183 1253 it.value()->setEnabled(subMenusEnabled[it.key()]);
1184 1254 }
1185 1255 }
1186 1256
1187 if (!graphMenu.isEmpty()) {
1257 if (!graphMenu.isEmpty())
1258 {
1188 1259 graphMenu.exec(QCursor::pos());
1189 1260 }
1190 1261 }
1191 1262
1192 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
1263 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent* event) noexcept
1193 1264 {
1194 1265 impl->m_RenderingDelegate->onMouseDoubleClick(event);
1195 1266 }
1196 1267
1197 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
1268 void VisualizationGraphWidget::onMouseMove(QMouseEvent* event) noexcept
1198 1269 {
1199 1270 // Handles plot rendering when mouse is moving
1200 1271 impl->m_RenderingDelegate->updateTooltip(event);
@@ -1202,19 +1273,24 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
1202 1273 auto axisPos = impl->posToAxisPos(event->pos());
1203 1274
1204 1275 // Zoom box and zone drawing
1205 if (impl->m_DrawingZoomRect) {
1276 if (impl->m_DrawingZoomRect)
1277 {
1206 1278 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
1207 1279 }
1208 else if (impl->m_DrawingZone) {
1280 else if (impl->m_DrawingZone)
1281 {
1209 1282 impl->m_DrawingZone->setEnd(axisPos.x());
1210 1283 }
1211 1284
1212 1285 // Cursor
1213 if (auto parentZone = parentZoneWidget()) {
1214 if (impl->pointIsInAxisRect(axisPos, plot())) {
1286 if (auto parentZone = parentZoneWidget())
1287 {
1288 if (impl->pointIsInAxisRect(axisPos, plot()))
1289 {
1215 1290 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
1216 1291 }
1217 else {
1292 else
1293 {
1218 1294 parentZone->notifyMouseLeaveGraph(this);
1219 1295 }
1220 1296 }
@@ -1222,15 +1298,18 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
1222 1298 // Search for the selection zone under the mouse
1223 1299 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos());
1224 1300 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
1225 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
1301 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones)
1302 {
1226 1303
1227 1304 // Sets the appropriate cursor shape
1228 1305 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
1229 1306 setCursor(cursorShape);
1230 1307
1231 1308 // Manages the hovered zone
1232 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
1233 if (impl->m_HoveredZone) {
1309 if (selectionZoneItemUnderCursor != impl->m_HoveredZone)
1310 {
1311 if (impl->m_HoveredZone)
1312 {
1234 1313 impl->m_HoveredZone->setHovered(false);
1235 1314 }
1236 1315 selectionZoneItemUnderCursor->setHovered(true);
@@ -1238,9 +1317,11 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
1238 1317 plot().replot(QCustomPlot::rpQueuedReplot);
1239 1318 }
1240 1319 }
1241 else {
1320 else
1321 {
1242 1322 // There is no zone under the mouse or the interaction mode is not "selection zones"
1243 if (impl->m_HoveredZone) {
1323 if (impl->m_HoveredZone)
1324 {
1244 1325 impl->m_HoveredZone->setHovered(false);
1245 1326 impl->m_HoveredZone = nullptr;
1246 1327 }
@@ -1252,34 +1333,38 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
1252 1333 VisualizationDragWidget::mouseMoveEvent(event);
1253 1334 }
1254 1335
1255 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
1336 void VisualizationGraphWidget::onMouseWheel(QWheelEvent* event) noexcept
1256 1337 {
1257 1338 // Processes event only if the wheel occurs on axis rect
1258 if (!dynamic_cast<QCPAxisRect *>(impl->m_plot->layoutElementAt(event->posF()))) {
1339 if (!dynamic_cast<QCPAxisRect*>(impl->m_plot->layoutElementAt(event->posF())))
1340 {
1259 1341 return;
1260 1342 }
1261 1343
1262 1344 auto value = event->angleDelta().x() + event->angleDelta().y();
1263 if (value != 0) {
1345 if (value != 0)
1346 {
1264 1347
1265 1348 auto direction = value > 0 ? 1.0 : -1.0;
1266 1349 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
1267 1350 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
1268 1351 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
1269 1352
1270 auto zoomOrientations = QFlags<Qt::Orientation>{};
1353 auto zoomOrientations = QFlags<Qt::Orientation> {};
1271 1354 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
1272 1355 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
1273 1356
1274 1357 impl->m_plot->axisRect()->setRangeZoom(zoomOrientations);
1275 1358
1276 if (!isZoomX && !isZoomY) {
1359 if (!isZoomX && !isZoomY)
1360 {
1277 1361 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
1278 1362 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
1279 1363
1280 1364 axis->setRange(axis->range() + diff);
1281 1365
1282 if (plot().noAntialiasingOnDrag()) {
1366 if (plot().noAntialiasingOnDrag())
1367 {
1283 1368 plot().setNotAntialiasedElements(QCP::aeAll);
1284 1369 }
1285 1370
@@ -1288,22 +1373,26 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
1288 1373 }
1289 1374 }
1290 1375
1291 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
1376 void VisualizationGraphWidget::onMousePress(QMouseEvent* event) noexcept
1292 1377 {
1293 1378 auto isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
1294 1379 auto isSelectionZoneMode
1295 1380 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
1296 1381 auto isLeftClick = event->buttons().testFlag(Qt::LeftButton);
1297 1382
1298 if (!isDragDropClick && isLeftClick) {
1299 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
1383 if (!isDragDropClick && isLeftClick)
1384 {
1385 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox)
1386 {
1300 1387 // Starts a zoom box
1301 1388 impl->startDrawingRect(event->pos());
1302 1389 }
1303 else if (isSelectionZoneMode && impl->m_DrawingZone == nullptr) {
1390 else if (isSelectionZoneMode && impl->m_DrawingZone == nullptr)
1391 {
1304 1392 // Starts a new selection zone
1305 1393 auto zoneAtPos = impl->selectionZoneAt(event->pos());
1306 if (!zoneAtPos) {
1394 if (!zoneAtPos)
1395 {
1307 1396 impl->startDrawingZone(event->pos());
1308 1397 }
1309 1398 }
@@ -1314,24 +1403,29 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
1314 1403 impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick);
1315 1404
1316 1405 // Selection / Deselection
1317 if (isSelectionZoneMode) {
1406 if (isSelectionZoneMode)
1407 {
1318 1408 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
1319 1409 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos());
1320 1410
1321 1411
1322 1412 if (selectionZoneItemUnderCursor && !selectionZoneItemUnderCursor->selected()
1323 && !isMultiSelectionClick) {
1413 && !isMultiSelectionClick)
1414 {
1324 1415 parentVisualizationWidget()->selectionZoneManager().select(
1325 {selectionZoneItemUnderCursor});
1416 { selectionZoneItemUnderCursor });
1326 1417 }
1327 else if (!selectionZoneItemUnderCursor && !isMultiSelectionClick && isLeftClick) {
1418 else if (!selectionZoneItemUnderCursor && !isMultiSelectionClick && isLeftClick)
1419 {
1328 1420 parentVisualizationWidget()->selectionZoneManager().clearSelection();
1329 1421 }
1330 else {
1422 else
1423 {
1331 1424 // No selection change
1332 1425 }
1333 1426
1334 if (selectionZoneItemUnderCursor && isLeftClick) {
1427 if (selectionZoneItemUnderCursor && isLeftClick)
1428 {
1335 1429 selectionZoneItemUnderCursor->setAssociatedEditedZones(
1336 1430 parentVisualizationWidget()->selectionZoneManager().selectedItems());
1337 1431 }
@@ -1342,23 +1436,25 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
1342 1436 VisualizationDragWidget::mousePressEvent(event);
1343 1437 }
1344 1438
1345 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
1439 void VisualizationGraphWidget::onMouseRelease(QMouseEvent* event) noexcept
1346 1440 {
1347 if (impl->m_DrawingZoomRect) {
1441 if (impl->m_DrawingZoomRect)
1442 {
1348 1443
1349 1444 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
1350 1445 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
1351 1446
1352 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
1353 impl->m_DrawingZoomRect->bottomRight->coords().x()};
1447 auto newAxisXRange = QCPRange { impl->m_DrawingZoomRect->topLeft->coords().x(),
1448 impl->m_DrawingZoomRect->bottomRight->coords().x() };
1354 1449
1355 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
1356 impl->m_DrawingZoomRect->bottomRight->coords().y()};
1450 auto newAxisYRange = QCPRange { impl->m_DrawingZoomRect->topLeft->coords().y(),
1451 impl->m_DrawingZoomRect->bottomRight->coords().y() };
1357 1452
1358 1453 impl->removeDrawingRect();
1359 1454
1360 1455 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
1361 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
1456 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0))
1457 {
1362 1458 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
1363 1459 axisX->setRange(newAxisXRange);
1364 1460 axisY->setRange(newAxisYRange);
@@ -1372,55 +1468,67 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
1372 1468 // Selection / Deselection
1373 1469 auto isSelectionZoneMode
1374 1470 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
1375 if (isSelectionZoneMode) {
1471 if (isSelectionZoneMode)
1472 {
1376 1473 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
1377 1474 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos());
1378 1475 if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton
1379 && !impl->m_HasMovedMouse) {
1476 && !impl->m_HasMovedMouse)
1477 {
1380 1478
1381 1479 auto zonesUnderCursor = impl->selectionZonesAt(event->pos(), plot());
1382 if (zonesUnderCursor.count() > 1) {
1480 if (zonesUnderCursor.count() > 1)
1481 {
1383 1482 // There are multiple zones under the mouse.
1384 1483 // Performs the selection with a selection dialog.
1385 VisualizationMultiZoneSelectionDialog dialog{this};
1484 VisualizationMultiZoneSelectionDialog dialog { this };
1386 1485 dialog.setZones(zonesUnderCursor);
1387 1486 dialog.move(mapToGlobal(event->pos() - QPoint(dialog.width() / 2, 20)));
1388 1487 dialog.activateWindow();
1389 1488 dialog.raise();
1390 if (dialog.exec() == QDialog::Accepted) {
1489 if (dialog.exec() == QDialog::Accepted)
1490 {
1391 1491 auto selection = dialog.selectedZones();
1392 1492
1393 if (!isMultiSelectionClick) {
1493 if (!isMultiSelectionClick)
1494 {
1394 1495 parentVisualizationWidget()->selectionZoneManager().clearSelection();
1395 1496 }
1396 1497
1397 for (auto it = selection.cbegin(); it != selection.cend(); ++it) {
1498 for (auto it = selection.cbegin(); it != selection.cend(); ++it)
1499 {
1398 1500 auto zone = it.key();
1399 1501 auto isSelected = it.value();
1400 parentVisualizationWidget()->selectionZoneManager().setSelected(zone,
1401 isSelected);
1502 parentVisualizationWidget()->selectionZoneManager().setSelected(
1503 zone, isSelected);
1402 1504
1403 if (isSelected) {
1505 if (isSelected)
1506 {
1404 1507 // Puts the zone on top of the stack so it can be moved or resized
1405 1508 impl->moveSelectionZoneOnTop(zone, plot());
1406 1509 }
1407 1510 }
1408 1511 }
1409 1512 }
1410 else {
1411 if (!isMultiSelectionClick) {
1513 else
1514 {
1515 if (!isMultiSelectionClick)
1516 {
1412 1517 parentVisualizationWidget()->selectionZoneManager().select(
1413 {selectionZoneItemUnderCursor});
1518 { selectionZoneItemUnderCursor });
1414 1519 impl->moveSelectionZoneOnTop(selectionZoneItemUnderCursor, plot());
1415 1520 }
1416 else {
1521 else
1522 {
1417 1523 parentVisualizationWidget()->selectionZoneManager().setSelected(
1418 selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected()
1419 || event->button() == Qt::RightButton);
1524 selectionZoneItemUnderCursor,
1525 !selectionZoneItemUnderCursor->selected()
1526 || event->button() == Qt::RightButton);
1420 1527 }
1421 1528 }
1422 1529 }
1423 else {
1530 else
1531 {
1424 1532 // No selection change
1425 1533 }
1426 1534 }
@@ -1429,39 +1537,44 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
1429 1537 void VisualizationGraphWidget::onDataCacheVariableUpdated()
1430 1538 {
1431 1539 auto graphRange = impl->m_plot->xAxis->range();
1432 auto dateTime = DateTimeRange{graphRange.lower, graphRange.upper};
1540 auto dateTime = DateTimeRange { graphRange.lower, graphRange.upper };
1433 1541
1434 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
1542 for (auto& variableEntry : impl->m_VariableToPlotMultiMap)
1543 {
1435 1544 auto variable = variableEntry.first;
1436 1545 qCDebug(LOG_VisualizationGraphWidget())
1437 1546 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
1438 1547 qCDebug(LOG_VisualizationGraphWidget())
1439 1548 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
1440 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
1549 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range()))
1550 {
1441 1551 impl->updateData(variableEntry.second, variable, variable->range());
1442 1552 }
1443 1553 }
1444 1554 }
1445 1555
1446 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
1447 const DateTimeRange &range)
1556 void VisualizationGraphWidget::onUpdateVarDisplaying(
1557 std::shared_ptr<Variable2> variable, const DateTimeRange& range)
1448 1558 {
1449 1559 auto it = impl->m_VariableToPlotMultiMap.find(variable);
1450 if (it != impl->m_VariableToPlotMultiMap.end()) {
1560 if (it != impl->m_VariableToPlotMultiMap.end())
1561 {
1451 1562 impl->updateData(it->second, variable, range);
1452 1563 }
1453 1564 }
1454 1565
1455 1566 void VisualizationGraphWidget::variableUpdated(QUuid id)
1456 1567 {
1457 for (auto &[var, plotables] : impl->m_VariableToPlotMultiMap) {
1458 if (var->ID() == id) {
1568 for (auto& [var, plotables] : impl->m_VariableToPlotMultiMap)
1569 {
1570 if (var->ID() == id)
1571 {
1459 1572 impl->updateData(plotables, var, this->graphRange());
1460 1573 }
1461 1574 }
1462 1575 }
1463 1576
1464 void VisualizationGraphWidget::variableDeleted(const std::shared_ptr<Variable> & variable)
1577 void VisualizationGraphWidget::variableDeleted(const std::shared_ptr<Variable2>& variable)
1465 1578 {
1466 1579 this->removeVariable(variable);
1467 1580 }
@@ -17,7 +17,8
17 17
18 18 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
19 19
20 namespace {
20 namespace
21 {
21 22
22 23 /**
23 24 * Applies a function to all zones of the tab represented by its layout
@@ -25,12 +26,15 namespace {
25 26 * @param fun the function to apply to each zone
26 27 */
27 28 template <typename Fun>
28 void processZones(QLayout &layout, Fun fun)
29 void processZones(QLayout& layout, Fun fun)
29 30 {
30 for (auto i = 0; i < layout.count(); ++i) {
31 if (auto item = layout.itemAt(i)) {
31 for (auto i = 0; i < layout.count(); ++i)
32 {
33 if (auto item = layout.itemAt(i))
34 {
32 35 if (auto visualizationZoneWidget
33 = qobject_cast<VisualizationZoneWidget *>(item->widget())) {
36 = qobject_cast<VisualizationZoneWidget*>(item->widget()))
37 {
34 38 fun(*visualizationZoneWidget);
35 39 }
36 40 }
@@ -39,15 +43,16 void processZones(QLayout &layout, Fun fun)
39 43
40 44 /// Generates a default name for a new zone, according to the number of zones already displayed in
41 45 /// the tab
42 QString defaultZoneName(QLayout &layout)
46 QString defaultZoneName(QLayout& layout)
43 47 {
44 48 QSet<QString> existingNames;
45 processZones(layout,
46 [&existingNames](auto &zoneWidget) { existingNames.insert(zoneWidget.name()); });
49 processZones(
50 layout, [&existingNames](auto& zoneWidget) { existingNames.insert(zoneWidget.name()); });
47 51
48 52 int zoneNum = 1;
49 53 QString name;
50 do {
54 do
55 {
51 56 name = QObject::tr("Zone ").append(QString::number(zoneNum));
52 57 ++zoneNum;
53 58 } while (existingNames.contains(name));
@@ -57,8 +62,9 QString defaultZoneName(QLayout &layout)
57 62
58 63 } // namespace
59 64
60 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
61 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
65 struct VisualizationTabWidget::VisualizationTabWidgetPrivate
66 {
67 explicit VisualizationTabWidgetPrivate(const QString& name) : m_Name { name } {}
62 68
63 69 QString m_Name;
64 70
@@ -66,18 +72,18 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
66 72 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
67 73 #endif
68 74
69 void dropGraph(int index, VisualizationTabWidget *tabWidget);
70 void dropZone(int index, VisualizationTabWidget *tabWidget);
71 void dropVariables(const std::vector<std::shared_ptr<Variable> > &variables, int index,
72 VisualizationTabWidget *tabWidget);
73 void dropProducts(const QVariantList &productsMetaData, int index,
74 VisualizationTabWidget *tabWidget);
75 void dropGraph(int index, VisualizationTabWidget* tabWidget);
76 void dropZone(int index, VisualizationTabWidget* tabWidget);
77 void dropVariables(const std::vector<std::shared_ptr<Variable2>>& variables, int index,
78 VisualizationTabWidget* tabWidget);
79 void dropProducts(
80 const QVariantList& productsMetaData, int index, VisualizationTabWidget* tabWidget);
75 81 };
76 82
77 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
78 : QWidget{parent},
79 ui{new Ui::VisualizationTabWidget},
80 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
83 VisualizationTabWidget::VisualizationTabWidget(const QString& name, QWidget* parent)
84 : QWidget { parent }
85 , ui { new Ui::VisualizationTabWidget }
86 , impl { spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name) }
81 87 {
82 88 ui->setupUi(this);
83 89
@@ -88,22 +94,22 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *par
88 94 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Zone, "Zone");
89 95 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
90 96 ui->dragDropContainer->layout()->setSpacing(0);
91 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
92 VisualizationDragDropContainer::DropBehavior::Inserted);
93 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
94 VisualizationDragDropContainer::DropBehavior::Inserted);
95 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
96 VisualizationDragDropContainer::DropBehavior::Inserted);
97 ui->dragDropContainer->setMimeType(MIME_TYPE_PRODUCT_LIST,
98 VisualizationDragDropContainer::DropBehavior::Inserted);
97 ui->dragDropContainer->setMimeType(
98 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
99 ui->dragDropContainer->setMimeType(
100 MIME_TYPE_ZONE, VisualizationDragDropContainer::DropBehavior::Inserted);
101 ui->dragDropContainer->setMimeType(
102 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::Inserted);
103 ui->dragDropContainer->setMimeType(
104 MIME_TYPE_PRODUCT_LIST, VisualizationDragDropContainer::DropBehavior::Inserted);
99 105
100 106 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
101 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
102 ui->dragDropContainer);
107 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(
108 mimeData, ui->dragDropContainer);
103 109 });
104 110
105 111 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
106 &VisualizationTabWidget::dropMimeData);
112 &VisualizationTabWidget::dropMimeData);
107 113
108 114 sqpApp->dragDropGuiController().addDragDropScrollArea(ui->scrollArea);
109 115
@@ -117,12 +123,12 VisualizationTabWidget::~VisualizationTabWidget()
117 123 delete ui;
118 124 }
119 125
120 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
126 void VisualizationTabWidget::addZone(VisualizationZoneWidget* zoneWidget)
121 127 {
122 128 ui->dragDropContainer->addDragWidget(zoneWidget);
123 129 }
124 130
125 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
131 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget* zoneWidget)
126 132 {
127 133 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
128 134 }
@@ -130,17 +136,18 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zone
130 136 QStringList VisualizationTabWidget::availableZoneWidgets() const
131 137 {
132 138 QStringList zones;
133 processZones(tabLayout(),
134 [&zones](VisualizationZoneWidget &zoneWidget) { zones << zoneWidget.name(); });
139 processZones(
140 tabLayout(), [&zones](VisualizationZoneWidget& zoneWidget) { zones << zoneWidget.name(); });
135 141
136 142 return zones;
137 143 }
138 144
139 VisualizationZoneWidget *VisualizationTabWidget::getZoneWithName(const QString &zoneName)
145 VisualizationZoneWidget* VisualizationTabWidget::getZoneWithName(const QString& zoneName)
140 146 {
141 VisualizationZoneWidget *result = nullptr;
142 processZones(tabLayout(), [&zoneName, &result](VisualizationZoneWidget &zoneWidget) {
143 if (!result && zoneWidget.name() == zoneName) {
147 VisualizationZoneWidget* result = nullptr;
148 processZones(tabLayout(), [&zoneName, &result](VisualizationZoneWidget& zoneWidget) {
149 if (!result && zoneWidget.name() == zoneName)
150 {
144 151 result = &zoneWidget;
145 152 }
146 153 });
@@ -148,13 +155,13 VisualizationZoneWidget *VisualizationTabWidget::getZoneWithName(const QString &
148 155 return result;
149 156 }
150 157
151 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
158 VisualizationZoneWidget* VisualizationTabWidget::createZone(std::shared_ptr<Variable2> variable)
152 159 {
153 return createZone({variable}, -1);
160 return createZone({ variable }, -1);
154 161 }
155 162
156 VisualizationZoneWidget *
157 VisualizationTabWidget::createZone(const std::vector<std::shared_ptr<Variable> > &variables, int index)
163 VisualizationZoneWidget* VisualizationTabWidget::createZone(
164 const std::vector<std::shared_ptr<Variable2>>& variables, int index)
158 165 {
159 166 auto zoneWidget = createEmptyZone(index);
160 167
@@ -164,40 +171,41 VisualizationTabWidget::createZone(const std::vector<std::shared_ptr<Variable> >
164 171 return zoneWidget;
165 172 }
166 173
167 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
174 VisualizationZoneWidget* VisualizationTabWidget::createEmptyZone(int index)
168 175 {
169 176 auto zoneWidget
170 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
177 = new VisualizationZoneWidget { defaultZoneName(*ui->dragDropContainer->layout()), this };
171 178 this->insertZone(index, zoneWidget);
172 179
173 180 return zoneWidget;
174 181 }
175 182
176 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
183 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor* visitor)
177 184 {
178 if (visitor) {
185 if (visitor)
186 {
179 187 visitor->visitEnter(this);
180 188
181 189 // Apply visitor to zone children: widgets different from zones are not visited (no action)
182 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
183 zoneWidget.accept(visitor);
184 });
190 processZones(tabLayout(),
191 [visitor](VisualizationZoneWidget& zoneWidget) { zoneWidget.accept(visitor); });
185 192
186 193 visitor->visitLeave(this);
187 194 }
188 else {
195 else
196 {
189 197 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
190 198 }
191 199 }
192 200
193 bool VisualizationTabWidget::canDrop(const Variable &variable) const
201 bool VisualizationTabWidget::canDrop(Variable2& variable) const
194 202 {
195 203 // A tab can always accomodate a variable
196 204 Q_UNUSED(variable);
197 205 return true;
198 206 }
199 207
200 bool VisualizationTabWidget::contains(const Variable &variable) const
208 bool VisualizationTabWidget::contains(Variable2& variable) const
201 209 {
202 210 Q_UNUSED(variable);
203 211 return false;
@@ -208,50 +216,56 QString VisualizationTabWidget::name() const
208 216 return impl->m_Name;
209 217 }
210 218
211 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
219 void VisualizationTabWidget::closeEvent(QCloseEvent* event)
212 220 {
213 221 // Closes zones in the tab
214 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
222 processZones(tabLayout(), [](VisualizationZoneWidget& zoneWidget) { zoneWidget.close(); });
215 223
216 224 QWidget::closeEvent(event);
217 225 }
218 226
219 QLayout &VisualizationTabWidget::tabLayout() const noexcept
227 QLayout& VisualizationTabWidget::tabLayout() const noexcept
220 228 {
221 229 return *ui->dragDropContainer->layout();
222 230 }
223 231
224 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
232 void VisualizationTabWidget::dropMimeData(int index, const QMimeData* mimeData)
225 233 {
226 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
234 if (mimeData->hasFormat(MIME_TYPE_GRAPH))
235 {
227 236 impl->dropGraph(index, this);
228 237 }
229 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
238 else if (mimeData->hasFormat(MIME_TYPE_ZONE))
239 {
230 240 impl->dropZone(index, this);
231 241 }
232 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
242 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST))
243 {
233 244 auto variables = sqpApp->variableController().variables(
234 Variable::variablesIDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
245 Variable2::IDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
235 246 impl->dropVariables(variables, index, this);
236 247 }
237 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
248 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST))
249 {
238 250 auto productsData = sqpApp->dataSourceController().productsDataForMimeData(
239 251 mimeData->data(MIME_TYPE_PRODUCT_LIST));
240 252 impl->dropProducts(productsData, index, this);
241 253 }
242 else {
254 else
255 {
243 256 qCWarning(LOG_VisualizationZoneWidget())
244 257 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
245 258 }
246 259 }
247 260
248 261 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
249 int index, VisualizationTabWidget *tabWidget)
262 int index, VisualizationTabWidget* tabWidget)
250 263 {
251 auto &helper = sqpApp->dragDropGuiController();
264 auto& helper = sqpApp->dragDropGuiController();
252 265
253 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
254 if (!graphWidget) {
266 auto graphWidget = qobject_cast<VisualizationGraphWidget*>(helper.getCurrentDragWidget());
267 if (!graphWidget)
268 {
255 269 qCWarning(LOG_VisualizationZoneWidget())
256 270 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
257 271 "found or invalid.");
@@ -260,8 +274,9 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
260 274 }
261 275
262 276 auto parentDragDropContainer
263 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
264 if (!parentDragDropContainer) {
277 = qobject_cast<VisualizationDragDropContainer*>(graphWidget->parentWidget());
278 if (!parentDragDropContainer)
279 {
265 280 qCWarning(LOG_VisualizationZoneWidget())
266 281 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
267 282 "the dropped graph is not found.");
@@ -271,9 +286,10 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
271 286
272 287 auto nbGraph = parentDragDropContainer->countDragWidget();
273 288
274 const auto &variables = graphWidget->variables();
289 const auto& variables = graphWidget->variables();
275 290
276 if (!variables.empty()) {
291 if (!variables.empty())
292 {
277 293 // Abort the requests for the variables (if any)
278 294 // Commented, because it's not sure if it's needed or not
279 295 // for (const auto& var : variables)
@@ -281,27 +297,32 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
281 297 // sqpApp->variableController().onAbortProgressRequested(var);
282 298 //}
283 299
284 if (nbGraph == 1) {
300 if (nbGraph == 1)
301 {
285 302 // This is the only graph in the previous zone, close the zone
286 303 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
287 304 }
288 else {
305 else
306 {
289 307 // Close the graph
290 308 helper.delayedCloseWidget(graphWidget);
291 309 }
292 310
293 311 auto zoneWidget = tabWidget->createZone(variables, index);
294 312 auto firstGraph = zoneWidget->firstGraph();
295 if (firstGraph) {
313 if (firstGraph)
314 {
296 315 firstGraph->addSelectionZones(graphWidget->selectionZoneRanges());
297 316 }
298 else {
317 else
318 {
299 319 qCWarning(LOG_VisualizationZoneWidget())
300 320 << tr("VisualizationTabWidget::dropGraph, no graph added in the widget.");
301 321 Q_ASSERT(false);
302 322 }
303 323 }
304 else {
324 else
325 {
305 326 // The graph is empty, create an empty zone and move the graph inside
306 327
307 328 auto parentZoneWidget = graphWidget->parentZoneWidget();
@@ -312,19 +333,21 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
312 333 zoneWidget->addGraph(graphWidget);
313 334
314 335 // Close the old zone if it was the only graph inside
315 if (nbGraph == 1) {
336 if (nbGraph == 1)
337 {
316 338 helper.delayedCloseWidget(parentZoneWidget);
317 339 }
318 340 }
319 341 }
320 342
321 343 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
322 int index, VisualizationTabWidget *tabWidget)
344 int index, VisualizationTabWidget* tabWidget)
323 345 {
324 auto &helper = sqpApp->dragDropGuiController();
346 auto& helper = sqpApp->dragDropGuiController();
325 347
326 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
327 if (!zoneWidget) {
348 auto zoneWidget = qobject_cast<VisualizationZoneWidget*>(helper.getCurrentDragWidget());
349 if (!zoneWidget)
350 {
328 351 qCWarning(LOG_VisualizationZoneWidget())
329 352 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
330 353 "found or invalid.");
@@ -333,8 +356,9 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
333 356 }
334 357
335 358 auto parentDragDropContainer
336 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
337 if (!parentDragDropContainer) {
359 = qobject_cast<VisualizationDragDropContainer*>(zoneWidget->parentWidget());
360 if (!parentDragDropContainer)
361 {
338 362 qCWarning(LOG_VisualizationZoneWidget())
339 363 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
340 364 "the dropped zone is not found.");
@@ -348,12 +372,13 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
348 372 }
349 373
350 374 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
351 const std::vector<std::shared_ptr<Variable> > &variables, int index,
352 VisualizationTabWidget *tabWidget)
375 const std::vector<std::shared_ptr<Variable2>>& variables, int index,
376 VisualizationTabWidget* tabWidget)
353 377 {
354 378 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
355 379 // compatible variable here
356 if (variables.size() > 1) {
380 if (variables.size() > 1)
381 {
357 382 qCWarning(LOG_VisualizationZoneWidget())
358 383 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
359 384 "aborted.");
@@ -364,26 +389,27 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
364 389 }
365 390
366 391 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropProducts(
367 const QVariantList &productsMetaData, int index, VisualizationTabWidget *tabWidget)
392 const QVariantList& productsMetaData, int index, VisualizationTabWidget* tabWidget)
368 393 {
369 394 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
370 395 // compatible variable here
371 if (productsMetaData.count() != 1) {
396 if (productsMetaData.count() != 1)
397 {
372 398 qCWarning(LOG_VisualizationZoneWidget())
373 399 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
374 400 "aborted.");
375 401 return;
376 402 }
377 403
378 auto context = new QObject{tabWidget};
404 auto context = new QObject { tabWidget };
379 405 connect(&sqpApp->variableController(), &VariableController2::variableAdded, context,
380 [this, index, tabWidget, context](auto variable) {
381 tabWidget->createZone({variable}, index);
382 delete context; // removes the connection
383 },
384 Qt::QueuedConnection);
406 [this, index, tabWidget, context](auto variable) {
407 tabWidget->createZone({ variable }, index);
408 delete context; // removes the connection
409 },
410 Qt::QueuedConnection);
385 411
386 412 auto productData = productsMetaData.first().toHash();
387 413 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
388 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
414 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
389 415 }
@@ -23,7 +23,8
23 23
24 24 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
25 25
26 struct VisualizationWidget::VisualizationWidgetPrivate {
26 struct VisualizationWidget::VisualizationWidgetPrivate
27 {
27 28 std::unique_ptr<VisualizationSelectionZoneManager> m_ZoneSelectionManager = nullptr;
28 29 VisualizationActionManager m_ActionManager;
29 30
@@ -33,20 +34,19 struct VisualizationWidget::VisualizationWidgetPrivate {
33 34 }
34 35 };
35 36
36 VisualizationWidget::VisualizationWidget(QWidget *parent)
37 : QWidget{parent},
38 ui{new Ui::VisualizationWidget},
39 impl{spimpl::make_unique_impl<VisualizationWidgetPrivate>()}
37 VisualizationWidget::VisualizationWidget(QWidget* parent)
38 : QWidget { parent }
39 , ui { new Ui::VisualizationWidget }
40 , impl { spimpl::make_unique_impl<VisualizationWidgetPrivate>() }
40 41 {
41 42 ui->setupUi(this);
42 43
43 auto addTabViewButton = new QToolButton{ui->tabWidget};
44 auto addTabViewButton = new QToolButton { ui->tabWidget };
44 45 addTabViewButton->setText(tr("Add View"));
45 46 addTabViewButton->setCursor(Qt::ArrowCursor);
46 47 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
47 48
48 49 auto enableMinimumCornerWidgetSize = [this](bool enable) {
49
50 50 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
51 51 auto width = enable ? tabViewCornerWidget->width() : 0;
52 52 auto height = enable ? tabViewCornerWidget->height() : 0;
@@ -57,29 +57,32 VisualizationWidget::VisualizationWidget(QWidget *parent)
57 57 };
58 58
59 59 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
60 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
61 ui->tabWidget};
60 auto widget
61 = new VisualizationTabWidget { QString { "View %1" }.arg(ui->tabWidget->count() + 1),
62 ui->tabWidget };
62 63 auto index = ui->tabWidget->addTab(widget, widget->name());
63 if (ui->tabWidget->count() > 0) {
64 if (ui->tabWidget->count() > 0)
65 {
64 66 enableMinimumCornerWidgetSize(false);
65 67 }
66 68 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
67 69 };
68 70
69 71 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
70 if (ui->tabWidget->count() == 1) {
72 if (ui->tabWidget->count() == 1)
73 {
71 74 enableMinimumCornerWidgetSize(true);
72 75 }
73 76
74 77 // Removes widget from tab and closes it
75 78 auto widget = ui->tabWidget->widget(index);
76 79 ui->tabWidget->removeTab(index);
77 if (widget) {
80 if (widget)
81 {
78 82 widget->close();
79 83 }
80 84
81 85 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
82
83 86 };
84 87
85 88 ui->tabWidget->setTabsClosable(true);
@@ -96,8 +99,10 VisualizationWidget::VisualizationWidget(QWidget *parent)
96 99 removeZoneAction->setShortcut(QKeySequence::Delete);
97 100 connect(removeZoneAction, &QAction::triggered, [this]() {
98 101 auto selection = impl->m_ZoneSelectionManager->selectedItems();
99 for (auto selectionZone : selection) {
100 if (auto graph = selectionZone->parentGraphWidget()) {
102 for (auto selectionZone : selection)
103 {
104 if (auto graph = selectionZone->parentGraphWidget())
105 {
101 106 graph->removeSelectionZone(selectionZone);
102 107 }
103 108 }
@@ -114,49 +119,54 VisualizationWidget::~VisualizationWidget()
114 119 delete ui;
115 120 }
116 121
117 VisualizationSelectionZoneManager &VisualizationWidget::selectionZoneManager() const
122 VisualizationSelectionZoneManager& VisualizationWidget::selectionZoneManager() const
118 123 {
119 124 return *impl->m_ZoneSelectionManager.get();
120 125 }
121 126
122 VisualizationTabWidget *VisualizationWidget::currentTabWidget() const
127 VisualizationTabWidget* VisualizationWidget::currentTabWidget() const
123 128 {
124 if (auto tab = qobject_cast<VisualizationTabWidget *>(ui->tabWidget->currentWidget())) {
129 if (auto tab = qobject_cast<VisualizationTabWidget*>(ui->tabWidget->currentWidget()))
130 {
125 131 return tab;
126 132 }
127 133
128 134 return nullptr;
129 135 }
130 136
131 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
137 void VisualizationWidget::accept(IVisualizationWidgetVisitor* visitor)
132 138 {
133 if (visitor) {
139 if (visitor)
140 {
134 141 visitor->visitEnter(this);
135 142
136 143 // Apply visitor for tab children
137 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
144 for (auto i = 0; i < ui->tabWidget->count(); ++i)
145 {
138 146 // Widgets different from tabs are not visited (no action)
139 147 if (auto visualizationTabWidget
140 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
148 = dynamic_cast<VisualizationTabWidget*>(ui->tabWidget->widget(i)))
149 {
141 150 visualizationTabWidget->accept(visitor);
142 151 }
143 152 }
144 153
145 154 visitor->visitLeave(this);
146 155 }
147 else {
156 else
157 {
148 158 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
149 159 }
150 160 }
151 161
152 bool VisualizationWidget::canDrop(const Variable &variable) const
162 bool VisualizationWidget::canDrop(Variable2& variable) const
153 163 {
154 164 // The main widget can never accomodate a variable
155 165 Q_UNUSED(variable);
156 166 return false;
157 167 }
158 168
159 bool VisualizationWidget::contains(const Variable &variable) const
169 bool VisualizationWidget::contains(Variable2& variable) const
160 170 {
161 171 Q_UNUSED(variable);
162 172 return false;
@@ -168,54 +178,60 QString VisualizationWidget::name() const
168 178 }
169 179
170 180 void VisualizationWidget::attachVariableMenu(
171 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
181 QMenu* menu, const QVector<std::shared_ptr<Variable2>>& variables) noexcept
172 182 {
173 183 // Menu is generated only if there is a single variable
174 if (variables.size() == 1) {
175 if (auto variable = variables.first()) {
184 if (variables.size() == 1)
185 {
186 if (auto variable = variables.first())
187 {
176 188 // Gets the containers of the variable
177 FindVariableOperation findVariableOperation{variable};
189 FindVariableOperation findVariableOperation { variable };
178 190 accept(&findVariableOperation);
179 191 auto variableContainers = findVariableOperation.result();
180 192
181 193 // Generates the actions that make it possible to visualize the variable
182 GenerateVariableMenuOperation generateVariableMenuOperation{
183 menu, variable, std::move(variableContainers)};
194 GenerateVariableMenuOperation generateVariableMenuOperation { menu, variable,
195 std::move(variableContainers) };
184 196 accept(&generateVariableMenuOperation);
185 197 }
186 else {
198 else
199 {
187 200 qCCritical(LOG_VisualizationWidget()) << tr(
188 201 "Can't generate the menu relative to the visualization: the variable is null");
189 202 }
190 203 }
191 else {
204 else
205 {
192 206 qCDebug(LOG_VisualizationWidget())
193 207 << tr("No generation of the menu related to the visualization: several variables are "
194 208 "selected");
195 209 }
196 210 }
197 211
198 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
212 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable2> variable) noexcept
199 213 {
200 214 // Calls the operation of removing all references to the variable in the visualization
201 auto removeVariableOperation = RemoveVariableOperation{variable};
215 auto removeVariableOperation = RemoveVariableOperation { variable };
202 216 accept(&removeVariableOperation);
203 217 }
204 218
205 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
206 const DateTimeRange &range) noexcept
219 void VisualizationWidget::onRangeChanged(
220 std::shared_ptr<Variable2> variable, const DateTimeRange& range) noexcept
207 221 {
208 222 // Calls the operation of rescaling all graph that contrains variable in the visualization
209 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
223 auto rescaleVariableOperation = RescaleAxeOperation { variable, range };
210 224 accept(&rescaleVariableOperation);
211 225 }
212 226
213 void VisualizationWidget::closeEvent(QCloseEvent *event)
227 void VisualizationWidget::closeEvent(QCloseEvent* event)
214 228 {
215 229 // Closes tabs in the widget
216 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
230 for (auto i = 0; i < ui->tabWidget->count(); ++i)
231 {
217 232 if (auto visualizationTabWidget
218 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
233 = dynamic_cast<VisualizationTabWidget*>(ui->tabWidget->widget(i)))
234 {
219 235 visualizationTabWidget->close();
220 236 }
221 237 }
This diff has been collapsed as it changes many lines, (553 lines changed) Show them Hide them
@@ -13,7 +13,7
13 13 #include <Data/DateTimeRangeHelper.h>
14 14 #include <DataSource/DataSourceController.h>
15 15 #include <Time/TimeController.h>
16 #include <Variable/Variable.h>
16 #include <Variable/Variable2.h>
17 17 #include <Variable/VariableController2.h>
18 18
19 19 #include <Visualization/operations/FindVariableOperation.h>
@@ -28,7 +28,8
28 28
29 29 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
30 30
31 namespace {
31 namespace
32 {
32 33
33 34 /**
34 35 * Applies a function to all graphs of the zone represented by its layout
@@ -36,12 +37,15 namespace {
36 37 * @param fun the function to apply to each graph
37 38 */
38 39 template <typename Fun>
39 void processGraphs(QLayout &layout, Fun fun)
40 void processGraphs(QLayout& layout, Fun fun)
40 41 {
41 for (auto i = 0; i < layout.count(); ++i) {
42 if (auto item = layout.itemAt(i)) {
42 for (auto i = 0; i < layout.count(); ++i)
43 {
44 if (auto item = layout.itemAt(i))
45 {
43 46 if (auto visualizationGraphWidget
44 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
47 = qobject_cast<VisualizationGraphWidget*>(item->widget()))
48 {
45 49 fun(*visualizationGraphWidget);
46 50 }
47 51 }
@@ -50,15 +54,16 void processGraphs(QLayout &layout, Fun fun)
50 54
51 55 /// Generates a default name for a new graph, according to the number of graphs already displayed in
52 56 /// the zone
53 QString defaultGraphName(QLayout &layout)
57 QString defaultGraphName(QLayout& layout)
54 58 {
55 59 QSet<QString> existingNames;
56 60 processGraphs(
57 layout, [&existingNames](auto &graphWidget) { existingNames.insert(graphWidget.name()); });
61 layout, [&existingNames](auto& graphWidget) { existingNames.insert(graphWidget.name()); });
58 62
59 63 int zoneNum = 1;
60 64 QString name;
61 do {
65 do
66 {
62 67 name = QObject::tr("Graph ").append(QString::number(zoneNum));
63 68 ++zoneNum;
64 69 } while (existingNames.contains(name));
@@ -68,65 +73,70 QString defaultGraphName(QLayout &layout)
68 73
69 74 } // namespace
70 75
71 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
76 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate
77 {
72 78
73 79 explicit VisualizationZoneWidgetPrivate()
74 : m_SynchronisationGroupId{QUuid::createUuid()},
75 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
80 : m_SynchronisationGroupId { QUuid::createUuid() }
81 , m_Synchronizer { std::make_unique<QCustomPlotSynchronizer>() }
76 82 {
77 83 }
78 84 QUuid m_SynchronisationGroupId;
79 85 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
80 86
81 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
82 void dropVariables(const std::vector<std::shared_ptr<Variable> > &variables, int index,
83 VisualizationZoneWidget *zoneWidget);
84 void dropProducts(const QVariantList &productsData, int index,
85 VisualizationZoneWidget *zoneWidget);
87 void dropGraph(int index, VisualizationZoneWidget* zoneWidget);
88 void dropVariables(const std::vector<std::shared_ptr<Variable2>>& variables, int index,
89 VisualizationZoneWidget* zoneWidget);
90 void dropProducts(
91 const QVariantList& productsData, int index, VisualizationZoneWidget* zoneWidget);
86 92 };
87 93
88 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
89 : VisualizationDragWidget{parent},
90 ui{new Ui::VisualizationZoneWidget},
91 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
94 VisualizationZoneWidget::VisualizationZoneWidget(const QString& name, QWidget* parent)
95 : VisualizationDragWidget { parent }
96 , ui { new Ui::VisualizationZoneWidget }
97 , impl { spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>() }
92 98 {
93 99 ui->setupUi(this);
94 100
95 101 ui->zoneNameLabel->setText(name);
96 102
97 103 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
98 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
99 VisualizationDragDropContainer::DropBehavior::Inserted);
104 ui->dragDropContainer->setMimeType(
105 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
100 106 ui->dragDropContainer->setMimeType(
101 107 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
102 108 ui->dragDropContainer->setMimeType(
103 109 MIME_TYPE_PRODUCT_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
104 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
105 VisualizationDragDropContainer::DropBehavior::Merged);
106 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
107 VisualizationDragDropContainer::DropBehavior::Forbidden);
108 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
109 VisualizationDragDropContainer::DropBehavior::Forbidden);
110 ui->dragDropContainer->setMimeType(
111 MIME_TYPE_TIME_RANGE, VisualizationDragDropContainer::DropBehavior::Merged);
112 ui->dragDropContainer->setMimeType(
113 MIME_TYPE_ZONE, VisualizationDragDropContainer::DropBehavior::Forbidden);
114 ui->dragDropContainer->setMimeType(
115 MIME_TYPE_SELECTION_ZONE, VisualizationDragDropContainer::DropBehavior::Forbidden);
110 116 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
111 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
112 ui->dragDropContainer);
117 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(
118 mimeData, ui->dragDropContainer);
113 119 });
114 120
115 121 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
116 if (!mimeData) {
122 if (!mimeData)
123 {
117 124 return false;
118 125 }
119 126
120 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
127 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST))
128 {
121 129 auto variables = sqpApp->variableController().variables(
122 Variable::variablesIDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
130 Variable2::IDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
123 131
124 if (variables.size() != 1) {
132 if (variables.size() != 1)
133 {
125 134 return false;
126 135 }
127 136 auto variable = variables.front();
128 137
129 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
138 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget*>(dragWidget))
139 {
130 140 return graphWidget->canDrop(*variable);
131 141 }
132 142 }
@@ -136,9 +146,9 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *p
136 146 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
137 147
138 148 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
139 &VisualizationZoneWidget::dropMimeData);
149 &VisualizationZoneWidget::dropMimeData);
140 150 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
141 &VisualizationZoneWidget::dropMimeDataOnGraph);
151 &VisualizationZoneWidget::dropMimeDataOnGraph);
142 152
143 153 // 'Close' options : widget is deleted when closed
144 154 setAttribute(Qt::WA_DeleteOnClose);
@@ -146,8 +156,8 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *p
146 156 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
147 157
148 158 // Synchronisation id
149 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
150 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
159 // QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
160 // Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
151 161 }
152 162
153 163 VisualizationZoneWidget::~VisualizationZoneWidget()
@@ -155,60 +165,55 VisualizationZoneWidget::~VisualizationZoneWidget()
155 165 delete ui;
156 166 }
157 167
158 void VisualizationZoneWidget::setZoneRange(const DateTimeRange &range)
168 void VisualizationZoneWidget::setZoneRange(const DateTimeRange& range)
159 169 {
160 if (auto graph = firstGraph()) {
170 if (auto graph = firstGraph())
171 {
161 172 graph->setGraphRange(range);
162 173 }
163 else {
174 else
175 {
164 176 qCWarning(LOG_VisualizationZoneWidget())
165 177 << tr("setZoneRange:Cannot set the range of an empty zone.");
166 178 }
167 179 }
168 180
169 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
181 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget* graphWidget)
170 182 {
171 183 // Synchronize new graph with others in the zone
172 // impl->m_Synchronizer->addGraph(*graphWidget);
173
174 // ui->dragDropContainer->addDragWidget(graphWidget);
175 insertGraph(0,graphWidget);
184 // impl->m_Synchronizer->addGraph(*graphWidget);
176 185
186 // ui->dragDropContainer->addDragWidget(graphWidget);
187 insertGraph(0, graphWidget);
177 188 }
178 189
179 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
190 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget* graphWidget)
180 191 {
181 192 DEPRECATE(
182 auto layout = ui->dragDropContainer->layout();
183 for(int i=0;i<layout->count();i++)
184 {
185 auto graph = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(i)->widget());
186 connect(graphWidget, &VisualizationGraphWidget::setrange_sig, graph, &VisualizationGraphWidget::setGraphRange);
187 connect(graph, &VisualizationGraphWidget::setrange_sig, graphWidget, &VisualizationGraphWidget::setGraphRange);
188 }
189 if(auto graph = firstGraph())
190 {
191 graphWidget->setGraphRange(graph->graphRange(), true);
192 }
193 )
193 auto layout = ui->dragDropContainer->layout(); for (int i = 0; i < layout->count(); i++) {
194 auto graph = qobject_cast<VisualizationGraphWidget*>(layout->itemAt(i)->widget());
195 connect(graphWidget, &VisualizationGraphWidget::setrange_sig, graph,
196 &VisualizationGraphWidget::setGraphRange);
197 connect(graph, &VisualizationGraphWidget::setrange_sig, graphWidget,
198 &VisualizationGraphWidget::setGraphRange);
199 } if (auto graph = firstGraph()) { graphWidget->setGraphRange(graph->graphRange(), true); })
194 200
195 201 // Synchronize new graph with others in the zone
196 202 impl->m_Synchronizer->addGraph(*graphWidget);
197 203
198 204 ui->dragDropContainer->insertDragWidget(index, graphWidget);
199
200 205 }
201 206
202 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
207 VisualizationGraphWidget* VisualizationZoneWidget::createGraph(std::shared_ptr<Variable2> variable)
203 208 {
204 209 return createGraph(variable, -1);
205 210 }
206 211
207 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
208 int index)
212 VisualizationGraphWidget* VisualizationZoneWidget::createGraph(
213 std::shared_ptr<Variable2> variable, int index)
209 214 {
210 215 auto graphWidget
211 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
216 = new VisualizationGraphWidget { defaultGraphName(*ui->dragDropContainer->layout()), this };
212 217
213 218
214 219 // Set graph properties
@@ -217,76 +222,79 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<V
217 222
218 223
219 224 // Lambda to synchronize zone widget
220 // auto synchronizeZoneWidget = [this, graphWidget](const DateTimeRange &graphRange,
221 // const DateTimeRange &oldGraphRange) {
222
223 // auto zoomType = DateTimeRangeHelper::getTransformationType(oldGraphRange, graphRange);
224 // auto frameLayout = ui->dragDropContainer->layout();
225 // for (auto i = 0; i < frameLayout->count(); ++i) {
226 // auto graphChild
227 // = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
228 // if (graphChild && (graphChild != graphWidget)) {
229
230 // auto graphChildRange = graphChild->graphRange();
231 // switch (zoomType) {
232 // case TransformationType::ZoomIn: {
233 // auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
234 // auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
235 // graphChildRange.m_TStart += deltaLeft;
236 // graphChildRange.m_TEnd -= deltaRight;
237 // break;
238 // }
239
240 // case TransformationType::ZoomOut: {
241 // auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
242 // auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
243 // graphChildRange.m_TStart -= deltaLeft;
244 // graphChildRange.m_TEnd += deltaRight;
245 // break;
246 // }
247 // case TransformationType::PanRight: {
248 // auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
249 // auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
250 // graphChildRange.m_TStart += deltaLeft;
251 // graphChildRange.m_TEnd += deltaRight;
252 // break;
253 // }
254 // case TransformationType::PanLeft: {
255 // auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
256 // auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
257 // graphChildRange.m_TStart -= deltaLeft;
258 // graphChildRange.m_TEnd -= deltaRight;
259 // break;
260 // }
261 // case TransformationType::Unknown: {
262 // break;
263 // }
264 // default:
265 // qCCritical(LOG_VisualizationZoneWidget())
266 // << tr("Impossible to synchronize: zoom type not take into account");
267 // // No action
268 // break;
269 // }
270 // graphChild->setFlags(GraphFlag::DisableAll);
271 // graphChild->setGraphRange(graphChildRange, true);
272 // graphChild->setFlags(GraphFlag::EnableAll);
273 // }
274 // }
275 // };
225 // auto synchronizeZoneWidget = [this, graphWidget](const DateTimeRange &graphRange,
226 // const DateTimeRange &oldGraphRange) {
227
228 // auto zoomType = DateTimeRangeHelper::getTransformationType(oldGraphRange, graphRange);
229 // auto frameLayout = ui->dragDropContainer->layout();
230 // for (auto i = 0; i < frameLayout->count(); ++i) {
231 // auto graphChild
232 // = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
233 // if (graphChild && (graphChild != graphWidget)) {
234
235 // auto graphChildRange = graphChild->graphRange();
236 // switch (zoomType) {
237 // case TransformationType::ZoomIn: {
238 // auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
239 // auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
240 // graphChildRange.m_TStart += deltaLeft;
241 // graphChildRange.m_TEnd -= deltaRight;
242 // break;
243 // }
244
245 // case TransformationType::ZoomOut: {
246 // auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
247 // auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
248 // graphChildRange.m_TStart -= deltaLeft;
249 // graphChildRange.m_TEnd += deltaRight;
250 // break;
251 // }
252 // case TransformationType::PanRight: {
253 // auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
254 // auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
255 // graphChildRange.m_TStart += deltaLeft;
256 // graphChildRange.m_TEnd += deltaRight;
257 // break;
258 // }
259 // case TransformationType::PanLeft: {
260 // auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
261 // auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
262 // graphChildRange.m_TStart -= deltaLeft;
263 // graphChildRange.m_TEnd -= deltaRight;
264 // break;
265 // }
266 // case TransformationType::Unknown: {
267 // break;
268 // }
269 // default:
270 // qCCritical(LOG_VisualizationZoneWidget())
271 // << tr("Impossible to synchronize: zoom type not take into
272 // account");
273 // // No action
274 // break;
275 // }
276 // graphChild->setFlags(GraphFlag::DisableAll);
277 // graphChild->setGraphRange(graphChildRange, true);
278 // graphChild->setFlags(GraphFlag::EnableAll);
279 // }
280 // }
281 // };
276 282
277 283 // connection for synchronization
278 //connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
284 // connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
279 285 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
280 &VisualizationZoneWidget::onVariableAdded);
286 &VisualizationZoneWidget::onVariableAdded);
281 287 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
282 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
288 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
283 289
284 auto range = DateTimeRange{};
285 if (auto firstGraph = this->firstGraph()) {
290 auto range = DateTimeRange {};
291 if (auto firstGraph = this->firstGraph())
292 {
286 293 // Case of a new graph in a existant zone
287 294 range = firstGraph->graphRange();
288 295 }
289 else {
296 else
297 {
290 298 // Case of a new graph as the first of the zone
291 299 range = variable->range();
292 300 }
@@ -299,28 +307,32 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<V
299 307 return graphWidget;
300 308 }
301 309
302 VisualizationGraphWidget *
303 VisualizationZoneWidget::createGraph(const std::vector<std::shared_ptr<Variable> > variables, int index)
310 VisualizationGraphWidget* VisualizationZoneWidget::createGraph(
311 const std::vector<std::shared_ptr<Variable2>> variables, int index)
304 312 {
305 if (variables.empty()) {
313 if (variables.empty())
314 {
306 315 return nullptr;
307 316 }
308 317
309 318 auto graphWidget = createGraph(variables.front(), index);
310 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
319 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt)
320 {
311 321 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
312 322 }
313 323
314 324 return graphWidget;
315 325 }
316 326
317 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
327 VisualizationGraphWidget* VisualizationZoneWidget::firstGraph() const
318 328 {
319 VisualizationGraphWidget *firstGraph = nullptr;
329 VisualizationGraphWidget* firstGraph = nullptr;
320 330 auto layout = ui->dragDropContainer->layout();
321 if (layout->count() > 0) {
331 if (layout->count() > 0)
332 {
322 333 if (auto visualizationGraphWidget
323 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
334 = qobject_cast<VisualizationGraphWidget*>(layout->itemAt(0)->widget()))
335 {
324 336 firstGraph = visualizationGraphWidget;
325 337 }
326 338 }
@@ -331,35 +343,36 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
331 343 void VisualizationZoneWidget::closeAllGraphs()
332 344 {
333 345 processGraphs(*ui->dragDropContainer->layout(),
334 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
346 [](VisualizationGraphWidget& graphWidget) { graphWidget.close(); });
335 347 }
336 348
337 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
349 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor* visitor)
338 350 {
339 if (visitor) {
351 if (visitor)
352 {
340 353 visitor->visitEnter(this);
341 354
342 355 // Apply visitor to graph children: widgets different from graphs are not visited (no
343 356 // action)
344 processGraphs(
345 *ui->dragDropContainer->layout(),
346 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
357 processGraphs(*ui->dragDropContainer->layout(),
358 [visitor](VisualizationGraphWidget& graphWidget) { graphWidget.accept(visitor); });
347 359
348 360 visitor->visitLeave(this);
349 361 }
350 else {
362 else
363 {
351 364 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
352 365 }
353 366 }
354 367
355 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
368 bool VisualizationZoneWidget::canDrop(Variable2& variable) const
356 369 {
357 370 // A tab can always accomodate a variable
358 371 Q_UNUSED(variable);
359 372 return true;
360 373 }
361 374
362 bool VisualizationZoneWidget::contains(const Variable &variable) const
375 bool VisualizationZoneWidget::contains(Variable2& variable) const
363 376 {
364 377 Q_UNUSED(variable);
365 378 return false;
@@ -370,14 +383,15 QString VisualizationZoneWidget::name() const
370 383 return ui->zoneNameLabel->text();
371 384 }
372 385
373 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
386 QMimeData* VisualizationZoneWidget::mimeData(const QPoint& position) const
374 387 {
375 388 Q_UNUSED(position);
376 389
377 390 auto mimeData = new QMimeData;
378 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
391 mimeData->setData(MIME_TYPE_ZONE, QByteArray {});
379 392
380 if (auto firstGraph = this->firstGraph()) {
393 if (auto firstGraph = this->firstGraph())
394 {
381 395 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
382 396 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
383 397 }
@@ -390,112 +404,117 bool VisualizationZoneWidget::isDragAllowed() const
390 404 return true;
391 405 }
392 406
393 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
394 const QPointF &plotPosition,
395 VisualizationGraphWidget *graphWidget)
407 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF& graphPosition,
408 const QPointF& plotPosition, VisualizationGraphWidget* graphWidget)
396 409 {
397 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
398 VisualizationGraphWidget &processedGraph) {
399
400 switch (sqpApp->plotsCursorMode()) {
401 case SqpApplication::PlotsCursorMode::Vertical:
402 processedGraph.removeHorizontalCursor();
403 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
404 break;
405 case SqpApplication::PlotsCursorMode::Temporal:
406 processedGraph.addVerticalCursor(plotPosition.x());
407 processedGraph.removeHorizontalCursor();
408 break;
409 case SqpApplication::PlotsCursorMode::Horizontal:
410 processedGraph.removeVerticalCursor();
411 if (&processedGraph == graphWidget) {
412 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
413 }
414 else {
410 processGraphs(*ui->dragDropContainer->layout(),
411 [&graphPosition, &plotPosition, &graphWidget](VisualizationGraphWidget& processedGraph) {
412 switch (sqpApp->plotsCursorMode())
413 {
414 case SqpApplication::PlotsCursorMode::Vertical:
415 415 processedGraph.removeHorizontalCursor();
416 }
417 break;
418 case SqpApplication::PlotsCursorMode::Cross:
419 if (&processedGraph == graphWidget) {
420 416 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
421 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
422 }
423 else {
417 break;
418 case SqpApplication::PlotsCursorMode::Temporal:
419 processedGraph.addVerticalCursor(plotPosition.x());
424 420 processedGraph.removeHorizontalCursor();
421 break;
422 case SqpApplication::PlotsCursorMode::Horizontal:
425 423 processedGraph.removeVerticalCursor();
426 }
427 break;
428 case SqpApplication::PlotsCursorMode::NoCursor:
429 processedGraph.removeHorizontalCursor();
430 processedGraph.removeVerticalCursor();
431 break;
432 }
433
434
435 });
424 if (&processedGraph == graphWidget)
425 {
426 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
427 }
428 else
429 {
430 processedGraph.removeHorizontalCursor();
431 }
432 break;
433 case SqpApplication::PlotsCursorMode::Cross:
434 if (&processedGraph == graphWidget)
435 {
436 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
437 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
438 }
439 else
440 {
441 processedGraph.removeHorizontalCursor();
442 processedGraph.removeVerticalCursor();
443 }
444 break;
445 case SqpApplication::PlotsCursorMode::NoCursor:
446 processedGraph.removeHorizontalCursor();
447 processedGraph.removeVerticalCursor();
448 break;
449 }
450 });
436 451 }
437 452
438 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
453 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget* graphWidget)
439 454 {
440 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
455 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget& processedGraph) {
441 456 processedGraph.removeHorizontalCursor();
442 457 processedGraph.removeVerticalCursor();
443 458 });
444 459 }
445 460
446 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
461 void VisualizationZoneWidget::closeEvent(QCloseEvent* event)
447 462 {
448 463 // Closes graphs in the zone
449 464 processGraphs(*ui->dragDropContainer->layout(),
450 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
465 [](VisualizationGraphWidget& graphWidget) { graphWidget.close(); });
451 466
452 467 // Delete synchronization group from variable controller
453 468 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
454 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
469 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
455 470
456 471 QWidget::closeEvent(event);
457 472 }
458 473
459 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
474 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable2> variable)
460 475 {
461 476 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
462 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
463 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
477 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable2>, variable),
478 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
464 479 }
465 480
466 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
481 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable2> variable)
467 482 {
468 483 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
469 Q_ARG(std::shared_ptr<Variable>, variable),
470 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
484 Q_ARG(std::shared_ptr<Variable2>, variable), Q_ARG(QUuid, impl->m_SynchronisationGroupId));
471 485 }
472 486
473 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
487 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData* mimeData)
474 488 {
475 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
489 if (mimeData->hasFormat(MIME_TYPE_GRAPH))
490 {
476 491 impl->dropGraph(index, this);
477 492 }
478 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
493 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST))
494 {
479 495 auto variables = sqpApp->variableController().variables(
480 Variable::variablesIDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
496 Variable2::IDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
481 497 impl->dropVariables(variables, index, this);
482 498 }
483 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
499 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST))
500 {
484 501 auto products = sqpApp->dataSourceController().productsDataForMimeData(
485 502 mimeData->data(MIME_TYPE_PRODUCT_LIST));
486 503 impl->dropProducts(products, index, this);
487 504 }
488 else {
505 else
506 {
489 507 qCWarning(LOG_VisualizationZoneWidget())
490 508 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
491 509 }
492 510 }
493 511
494 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
495 const QMimeData *mimeData)
512 void VisualizationZoneWidget::dropMimeDataOnGraph(
513 VisualizationDragWidget* dragWidget, const QMimeData* mimeData)
496 514 {
497 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
498 if (!graphWidget) {
515 auto graphWidget = qobject_cast<VisualizationGraphWidget*>(dragWidget);
516 if (!graphWidget)
517 {
499 518 qCWarning(LOG_VisualizationZoneWidget())
500 519 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
501 520 "drop aborted");
@@ -503,62 +522,66 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragW
503 522 return;
504 523 }
505 524
506 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
525 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST))
526 {
507 527 auto variables = sqpApp->variableController().variables(
508 Variable::variablesIDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
509 for (const auto &var : variables) {
528 Variable2::IDs(mimeData->data(MIME_TYPE_VARIABLE_LIST)));
529 for (const auto& var : variables)
530 {
510 531 graphWidget->addVariable(var, graphWidget->graphRange());
511 532 }
512 533 }
513 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
534 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST))
535 {
514 536 auto products = sqpApp->dataSourceController().productsDataForMimeData(
515 537 mimeData->data(MIME_TYPE_PRODUCT_LIST));
516 538
517 auto context = new QObject{this};
539 auto context = new QObject { this };
518 540 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
519 541 // BTW this is really dangerous, this assumes the next created variable will be this one...
520 542 connect(&sqpApp->variableController(), &VariableController2::variableAdded, context,
521 [this, graphWidget, context, range](auto variable) {
522 if(sqpApp->variableController().isReady(variable))
523 {
524 graphWidget->addVariable(variable, range);
525 delete context;
526 }
527 else
528 {
529 // -> this is pure insanity! this is a workaround to make a bad design work
530 QObject::connect(variable.get(), &Variable::updated,context,
531 [graphWidget, context, range, variable]()
532 {
533 graphWidget->addVariable(variable, range);
534 delete context;
535 });
536 }
537
538 },
539 Qt::QueuedConnection);
543 [this, graphWidget, context, range](auto variable) {
544 if (sqpApp->variableController().isReady(variable))
545 {
546 graphWidget->addVariable(variable, range);
547 delete context;
548 }
549 else
550 {
551 // -> this is pure insanity! this is a workaround to make a bad design work
552 QObject::connect(variable.get(), &Variable2::updated, context,
553 [graphWidget, context, range, variable]() {
554 graphWidget->addVariable(variable, range);
555 delete context;
556 });
557 }
558 },
559 Qt::QueuedConnection);
540 560
541 561 auto productData = products.first().toHash();
542 562 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
543 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
563 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
544 564 }
545 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
565 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE))
566 {
546 567 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
547 568 graphWidget->setGraphRange(range, true, true);
548 569 }
549 else {
570 else
571 {
550 572 qCWarning(LOG_VisualizationZoneWidget())
551 573 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
552 574 }
553 575 }
554 576
555 577 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
556 int index, VisualizationZoneWidget *zoneWidget)
578 int index, VisualizationZoneWidget* zoneWidget)
557 579 {
558 auto &helper = sqpApp->dragDropGuiController();
580 auto& helper = sqpApp->dragDropGuiController();
559 581
560 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
561 if (!graphWidget) {
582 auto graphWidget = qobject_cast<VisualizationGraphWidget*>(helper.getCurrentDragWidget());
583 if (!graphWidget)
584 {
562 585 qCWarning(LOG_VisualizationZoneWidget())
563 586 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
564 587 "found or invalid.");
@@ -567,8 +590,9 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
567 590 }
568 591
569 592 auto parentDragDropContainer
570 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
571 if (!parentDragDropContainer) {
593 = qobject_cast<VisualizationDragDropContainer*>(graphWidget->parentWidget());
594 if (!parentDragDropContainer)
595 {
572 596 qCWarning(LOG_VisualizationZoneWidget())
573 597 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
574 598 "the dropped graph is not found.");
@@ -576,9 +600,10 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
576 600 return;
577 601 }
578 602
579 const auto &variables = graphWidget->variables();
603 const auto& variables = graphWidget->variables();
580 604
581 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.empty()) {
605 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.empty())
606 {
582 607 // The drop didn't occur in the same zone
583 608
584 609 // Abort the requests for the variables (if any)
@@ -590,11 +615,13 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
590 615
591 616 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
592 617 auto nbGraph = parentDragDropContainer->countDragWidget();
593 if (nbGraph == 1) {
618 if (nbGraph == 1)
619 {
594 620 // This is the only graph in the previous zone, close the zone
595 621 helper.delayedCloseWidget(previousParentZoneWidget);
596 622 }
597 else {
623 else
624 {
598 625 // Close the graph
599 626 helper.delayedCloseWidget(graphWidget);
600 627 }
@@ -603,18 +630,22 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
603 630 auto newGraphWidget = zoneWidget->createGraph(variables, index);
604 631 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
605 632 }
606 else {
633 else
634 {
607 635 // The drop occurred in the same zone or the graph is empty
608 636 // Simple move of the graph, no variable operation associated
609 637 parentDragDropContainer->layout()->removeWidget(graphWidget);
610 638
611 if (variables.empty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
639 if (variables.empty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer)
640 {
612 641 // The graph is empty and dropped in a different zone.
613 642 // Take the range of the first graph in the zone (if existing).
614 643 auto layout = zoneWidget->ui->dragDropContainer->layout();
615 if (layout->count() > 0) {
644 if (layout->count() > 0)
645 {
616 646 if (auto visualizationGraphWidget
617 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
647 = qobject_cast<VisualizationGraphWidget*>(layout->itemAt(0)->widget()))
648 {
618 649 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
619 650 }
620 651 }
@@ -625,38 +656,40 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
625 656 }
626 657
627 658 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
628 const std::vector<std::shared_ptr<Variable> > &variables, int index,
629 VisualizationZoneWidget *zoneWidget)
659 const std::vector<std::shared_ptr<Variable2>>& variables, int index,
660 VisualizationZoneWidget* zoneWidget)
630 661 {
631 662 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
632 663 // compatible variable here
633 if (variables.size() > 1) {
664 if (variables.size() > 1)
665 {
634 666 return;
635 667 }
636 668 zoneWidget->createGraph(variables, index);
637 669 }
638 670
639 671 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProducts(
640 const QVariantList &productsData, int index, VisualizationZoneWidget *zoneWidget)
672 const QVariantList& productsData, int index, VisualizationZoneWidget* zoneWidget)
641 673 {
642 674 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
643 675 // compatible variable here
644 if (productsData.count() != 1) {
676 if (productsData.count() != 1)
677 {
645 678 qCWarning(LOG_VisualizationZoneWidget())
646 679 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
647 680 "aborted.");
648 681 return;
649 682 }
650 683
651 auto context = new QObject{zoneWidget};
684 auto context = new QObject { zoneWidget };
652 685 connect(&sqpApp->variableController(), &VariableController2::variableAdded, context,
653 [this, index, zoneWidget, context](auto variable) {
654 zoneWidget->createGraph(variable, index);
655 delete context; // removes the connection
656 },
657 Qt::QueuedConnection);
686 [this, index, zoneWidget, context](auto variable) {
687 zoneWidget->createGraph(variable, index);
688 delete context; // removes the connection
689 },
690 Qt::QueuedConnection);
658 691
659 692 auto productData = productsData.first().toHash();
660 693 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
661 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
694 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
662 695 }
@@ -5,68 +5,71
5 5 #include "Visualization/VisualizationWidget.h"
6 6 #include "Visualization/VisualizationZoneWidget.h"
7 7
8 #include <Variable/Variable.h>
8 #include <Variable/Variable2.h>
9 9
10 struct FindVariableOperation::FindVariableOperationPrivate {
11 explicit FindVariableOperationPrivate(std::shared_ptr<Variable> variable) : m_Variable{variable}
10 struct FindVariableOperation::FindVariableOperationPrivate
11 {
12 explicit FindVariableOperationPrivate(std::shared_ptr<Variable2> variable)
13 : m_Variable { variable }
12 14 {
13 15 }
14 16
15 void visit(IVisualizationWidget *widget)
17 void visit(IVisualizationWidget* widget)
16 18 {
17 if (m_Variable && widget && widget->contains(*m_Variable)) {
19 if (m_Variable && widget && widget->contains(*m_Variable))
20 {
18 21 m_Containers.insert(widget);
19 22 }
20 23 }
21 24
22 std::shared_ptr<Variable> m_Variable; ///< Variable to find
23 std::set<IVisualizationWidget *> m_Containers; ///< Containers found for the variable
25 std::shared_ptr<Variable2> m_Variable; ///< Variable to find
26 std::set<IVisualizationWidget*> m_Containers; ///< Containers found for the variable
24 27 };
25 28
26 FindVariableOperation::FindVariableOperation(std::shared_ptr<Variable> variable)
27 : impl{spimpl::make_unique_impl<FindVariableOperationPrivate>(variable)}
29 FindVariableOperation::FindVariableOperation(std::shared_ptr<Variable2> variable)
30 : impl { spimpl::make_unique_impl<FindVariableOperationPrivate>(variable) }
28 31 {
29 32 }
30 33
31 void FindVariableOperation::visitEnter(VisualizationWidget *widget)
34 void FindVariableOperation::visitEnter(VisualizationWidget* widget)
32 35 {
33 36 impl->visit(widget);
34 37 }
35 38
36 void FindVariableOperation::visitLeave(VisualizationWidget *widget)
39 void FindVariableOperation::visitLeave(VisualizationWidget* widget)
37 40 {
38 41 // Does nothing
39 42 Q_UNUSED(widget);
40 43 }
41 44
42 void FindVariableOperation::visitEnter(VisualizationTabWidget *tabWidget)
45 void FindVariableOperation::visitEnter(VisualizationTabWidget* tabWidget)
43 46 {
44 47 impl->visit(tabWidget);
45 48 }
46 49
47 void FindVariableOperation::visitLeave(VisualizationTabWidget *tabWidget)
50 void FindVariableOperation::visitLeave(VisualizationTabWidget* tabWidget)
48 51 {
49 52 // Does nothing
50 53 Q_UNUSED(tabWidget);
51 54 }
52 55
53 void FindVariableOperation::visitEnter(VisualizationZoneWidget *zoneWidget)
56 void FindVariableOperation::visitEnter(VisualizationZoneWidget* zoneWidget)
54 57 {
55 58 impl->visit(zoneWidget);
56 59 }
57 60
58 void FindVariableOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
61 void FindVariableOperation::visitLeave(VisualizationZoneWidget* zoneWidget)
59 62 {
60 63 // Does nothing
61 64 Q_UNUSED(zoneWidget);
62 65 }
63 66
64 void FindVariableOperation::visit(VisualizationGraphWidget *graphWidget)
67 void FindVariableOperation::visit(VisualizationGraphWidget* graphWidget)
65 68 {
66 69 impl->visit(graphWidget);
67 70 }
68 71
69 std::set<IVisualizationWidget *> FindVariableOperation::result() const noexcept
72 std::set<IVisualizationWidget*> FindVariableOperation::result() const noexcept
70 73 {
71 74 return impl->m_Containers;
72 75 }
@@ -5,21 +5,21
5 5 #include "Visualization/VisualizationTabWidget.h"
6 6 #include "Visualization/VisualizationZoneWidget.h"
7 7
8 #include <Variable/Variable.h>
8 #include <Variable/Variable2.h>
9 9
10 10 #include <QMenu>
11 11 #include <QStack>
12 12
13 13 Q_LOGGING_CATEGORY(LOG_GenerateVariableMenuOperation, "GenerateVariableMenuOperation")
14 14
15 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
16 explicit GenerateVariableMenuOperationPrivate(
17 QMenu *menu, std::shared_ptr<Variable> variable,
18 std::set<IVisualizationWidget *> variableContainers)
19 : m_Variable{variable},
20 m_VariableContainers{std::move(variableContainers)},
21 m_PlotMenuBuilder{menu},
22 m_UnplotMenuBuilder{menu}
15 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate
16 {
17 explicit GenerateVariableMenuOperationPrivate(QMenu* menu, std::shared_ptr<Variable2> variable,
18 std::set<IVisualizationWidget*> variableContainers)
19 : m_Variable { variable }
20 , m_VariableContainers { std::move(variableContainers) }
21 , m_PlotMenuBuilder { menu }
22 , m_UnplotMenuBuilder { menu }
23 23 {
24 24 }
25 25
@@ -27,11 +27,12 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
27 27 {
28 28 // Creates the root menu
29 29 if (auto plotMenu
30 = m_PlotMenuBuilder.addMenu(QObject::tr("Plot"), QIcon{":/icones/plot.png"})) {
31 plotMenu->setEnabled(m_Variable && m_Variable->dataSeries() != nullptr);
30 = m_PlotMenuBuilder.addMenu(QObject::tr("Plot"), QIcon { ":/icones/plot.png" }))
31 {
32 plotMenu->setEnabled(m_Variable && m_Variable->data() != nullptr);
32 33 }
33 34
34 m_UnplotMenuBuilder.addMenu(QObject::tr("Unplot"), QIcon{":/icones/unplot.png"});
35 m_UnplotMenuBuilder.addMenu(QObject::tr("Unplot"), QIcon { ":/icones/unplot.png" });
35 36 }
36 37
37 38 void visitRootLeave()
@@ -41,7 +42,7 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
41 42 m_UnplotMenuBuilder.closeMenu();
42 43 }
43 44
44 void visitNodeEnter(const IVisualizationWidget &container)
45 void visitNodeEnter(const IVisualizationWidget& container)
45 46 {
46 47 // Opens a new menu associated to the node
47 48 m_PlotMenuBuilder.addMenu(container.name());
@@ -49,10 +50,11 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
49 50 }
50 51
51 52 template <typename ActionFun>
52 void visitNodeLeavePlot(const IVisualizationWidget &container, const QString &actionName,
53 ActionFun actionFunction)
53 void visitNodeLeavePlot(
54 const IVisualizationWidget& container, const QString& actionName, ActionFun actionFunction)
54 55 {
55 if (isValidContainer(container)) {
56 if (isValidContainer(container))
57 {
56 58 m_PlotMenuBuilder.addSeparator();
57 59 m_PlotMenuBuilder.addAction(actionName, actionFunction);
58 60 }
@@ -68,46 +70,47 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
68 70 }
69 71
70 72 template <typename ActionFun>
71 void visitLeafPlot(const IVisualizationWidget &container, const QString &actionName,
72 ActionFun actionFunction)
73 void visitLeafPlot(
74 const IVisualizationWidget& container, const QString& actionName, ActionFun actionFunction)
73 75 {
74 if (isValidContainer(container)) {
76 if (isValidContainer(container))
77 {
75 78 m_PlotMenuBuilder.addAction(actionName, actionFunction);
76 79 }
77 80 }
78 81
79 82 template <typename ActionFun>
80 void visitLeafUnplot(IVisualizationWidget *container, const QString &actionName,
81 ActionFun actionFunction)
83 void visitLeafUnplot(
84 IVisualizationWidget* container, const QString& actionName, ActionFun actionFunction)
82 85 {
83 86 // If the container contains the variable, we generate 'unplot' action
84 if (m_VariableContainers.count(container) == 1) {
87 if (m_VariableContainers.count(container) == 1)
88 {
85 89 m_UnplotMenuBuilder.addAction(actionName, actionFunction);
86 90 }
87 91 }
88 92
89 bool isValidContainer(const IVisualizationWidget &container) const noexcept
93 bool isValidContainer(const IVisualizationWidget& container) const noexcept
90 94 {
91 95 // A container is valid if it can contain the variable and if the variable is not already
92 96 // contained in another container
93 97 return m_Variable && m_VariableContainers.size() == 0 && container.canDrop(*m_Variable);
94 98 }
95 99
96 std::shared_ptr<Variable> m_Variable;
97 std::set<IVisualizationWidget *> m_VariableContainers;
98 MenuBuilder m_PlotMenuBuilder; ///< Builder for the 'Plot' menu
100 std::shared_ptr<Variable2> m_Variable;
101 std::set<IVisualizationWidget*> m_VariableContainers;
102 MenuBuilder m_PlotMenuBuilder; ///< Builder for the 'Plot' menu
99 103 MenuBuilder m_UnplotMenuBuilder; ///< Builder for the 'Unplot' menu
100 104 };
101 105
102 GenerateVariableMenuOperation::GenerateVariableMenuOperation(
103 QMenu *menu, std::shared_ptr<Variable> variable,
104 std::set<IVisualizationWidget *> variableContainers)
105 : impl{spimpl::make_unique_impl<GenerateVariableMenuOperationPrivate>(
106 menu, variable, std::move(variableContainers))}
106 GenerateVariableMenuOperation::GenerateVariableMenuOperation(QMenu* menu,
107 std::shared_ptr<Variable2> variable, std::set<IVisualizationWidget*> variableContainers)
108 : impl { spimpl::make_unique_impl<GenerateVariableMenuOperationPrivate>(
109 menu, variable, std::move(variableContainers)) }
107 110 {
108 111 }
109 112
110 void GenerateVariableMenuOperation::visitEnter(VisualizationWidget *widget)
113 void GenerateVariableMenuOperation::visitEnter(VisualizationWidget* widget)
111 114 {
112 115 // VisualizationWidget is not intended to accommodate a variable
113 116 Q_UNUSED(widget)
@@ -116,7 +119,7 void GenerateVariableMenuOperation::visitEnter(VisualizationWidget *widget)
116 119 impl->visitRootEnter();
117 120 }
118 121
119 void GenerateVariableMenuOperation::visitLeave(VisualizationWidget *widget)
122 void GenerateVariableMenuOperation::visitLeave(VisualizationWidget* widget)
120 123 {
121 124 // VisualizationWidget is not intended to accommodate a variable
122 125 Q_UNUSED(widget)
@@ -125,58 +128,66 void GenerateVariableMenuOperation::visitLeave(VisualizationWidget *widget)
125 128 impl->visitRootLeave();
126 129 }
127 130
128 void GenerateVariableMenuOperation::visitEnter(VisualizationTabWidget *tabWidget)
131 void GenerateVariableMenuOperation::visitEnter(VisualizationTabWidget* tabWidget)
129 132 {
130 if (tabWidget) {
133 if (tabWidget)
134 {
131 135 // 'Plot' and 'Unplot' menus
132 136 impl->visitNodeEnter(*tabWidget);
133 137 }
134 else {
138 else
139 {
135 140 qCCritical(LOG_GenerateVariableMenuOperation(),
136 "Can't visit enter VisualizationTabWidget : the widget is null");
141 "Can't visit enter VisualizationTabWidget : the widget is null");
137 142 }
138 143 }
139 144
140 void GenerateVariableMenuOperation::visitLeave(VisualizationTabWidget *tabWidget)
145 void GenerateVariableMenuOperation::visitLeave(VisualizationTabWidget* tabWidget)
141 146 {
142 if (tabWidget) {
147 if (tabWidget)
148 {
143 149 // 'Plot' menu
144 150 impl->visitNodeLeavePlot(*tabWidget, QObject::tr("Open in a new zone"),
145 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, tabWidget ]() {
146 if (auto var = varW.lock()) {
147 tabWidget->createZone(var);
148 }
149 });
151 [varW = std::weak_ptr<Variable2> { impl->m_Variable }, tabWidget]() {
152 if (auto var = varW.lock())
153 {
154 tabWidget->createZone(var);
155 }
156 });
150 157
151 158 // 'Unplot' menu
152 159 impl->visitNodeLeaveUnplot();
153 160 }
154 else {
161 else
162 {
155 163 qCCritical(LOG_GenerateVariableMenuOperation(),
156 "Can't visit leave VisualizationTabWidget : the widget is null");
164 "Can't visit leave VisualizationTabWidget : the widget is null");
157 165 }
158 166 }
159 167
160 void GenerateVariableMenuOperation::visitEnter(VisualizationZoneWidget *zoneWidget)
168 void GenerateVariableMenuOperation::visitEnter(VisualizationZoneWidget* zoneWidget)
161 169 {
162 if (zoneWidget) {
170 if (zoneWidget)
171 {
163 172 // 'Plot' and 'Unplot' menus
164 173 impl->visitNodeEnter(*zoneWidget);
165 174 }
166 else {
175 else
176 {
167 177 qCCritical(LOG_GenerateVariableMenuOperation(),
168 "Can't visit enter VisualizationZoneWidget : the widget is null");
178 "Can't visit enter VisualizationZoneWidget : the widget is null");
169 179 }
170 180 }
171 181
172 void GenerateVariableMenuOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
182 void GenerateVariableMenuOperation::visitLeave(VisualizationZoneWidget* zoneWidget)
173 183 {
174 if (zoneWidget) {
184 if (zoneWidget)
185 {
175 186 // 'Plot' menu
176 impl->visitNodeLeavePlot(
177 *zoneWidget, QObject::tr("Open in a new graph"),
178 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, zoneWidget ]() {
179 if (auto var = varW.lock()) {
187 impl->visitNodeLeavePlot(*zoneWidget, QObject::tr("Open in a new graph"),
188 [varW = std::weak_ptr<Variable2> { impl->m_Variable }, zoneWidget]() {
189 if (auto var = varW.lock())
190 {
180 191 zoneWidget->createGraph(var);
181 192 }
182 193 });
@@ -184,33 +195,38 void GenerateVariableMenuOperation::visitLeave(VisualizationZoneWidget *zoneWidg
184 195 // 'Unplot' menu
185 196 impl->visitNodeLeaveUnplot();
186 197 }
187 else {
198 else
199 {
188 200 qCCritical(LOG_GenerateVariableMenuOperation(),
189 "Can't visit leave VisualizationZoneWidget : the widget is null");
201 "Can't visit leave VisualizationZoneWidget : the widget is null");
190 202 }
191 203 }
192 204
193 void GenerateVariableMenuOperation::visit(VisualizationGraphWidget *graphWidget)
205 void GenerateVariableMenuOperation::visit(VisualizationGraphWidget* graphWidget)
194 206 {
195 if (graphWidget) {
207 if (graphWidget)
208 {
196 209 // 'Plot' menu
197 210 impl->visitLeafPlot(*graphWidget, QObject::tr("Open in %1").arg(graphWidget->name()),
198 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
199 if (auto var = varW.lock()) {
200 graphWidget->addVariable(var, graphWidget->graphRange());
201 }
202 });
211 [varW = std::weak_ptr<Variable2> { impl->m_Variable }, graphWidget]() {
212 if (auto var = varW.lock())
213 {
214 graphWidget->addVariable(var, graphWidget->graphRange());
215 }
216 });
203 217
204 218 // 'Unplot' menu
205 219 impl->visitLeafUnplot(graphWidget, QObject::tr("Remove from %1").arg(graphWidget->name()),
206 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
207 if (auto var = varW.lock()) {
208 graphWidget->removeVariable(var);
209 }
210 });
220 [varW = std::weak_ptr<Variable2> { impl->m_Variable }, graphWidget]() {
221 if (auto var = varW.lock())
222 {
223 graphWidget->removeVariable(var);
224 }
225 });
211 226 }
212 else {
227 else
228 {
213 229 qCCritical(LOG_GenerateVariableMenuOperation(),
214 "Can't visit VisualizationGraphWidget : the widget is null");
230 "Can't visit VisualizationGraphWidget : the widget is null");
215 231 }
216 232 }
@@ -1,70 +1,74
1 1 #include "Visualization/operations/RemoveVariableOperation.h"
2 2 #include "Visualization/VisualizationGraphWidget.h"
3 3
4 #include <Variable/Variable.h>
4 #include <Variable/Variable2.h>
5 5
6 6 Q_LOGGING_CATEGORY(LOG_RemoveVariableOperation, "RemoveVariableOperation")
7 7
8 struct RemoveVariableOperation::RemoveVariableOperationPrivate {
9 explicit RemoveVariableOperationPrivate(std::shared_ptr<Variable> variable)
8 struct RemoveVariableOperation::RemoveVariableOperationPrivate
9 {
10 explicit RemoveVariableOperationPrivate(std::shared_ptr<Variable2> variable)
10 11 : m_Variable(variable)
11 12 {
12 13 }
13 14
14 std::shared_ptr<Variable> m_Variable;
15 std::shared_ptr<Variable2> m_Variable;
15 16 };
16 17
17 RemoveVariableOperation::RemoveVariableOperation(std::shared_ptr<Variable> variable)
18 : impl{spimpl::make_unique_impl<RemoveVariableOperationPrivate>(variable)}
18 RemoveVariableOperation::RemoveVariableOperation(std::shared_ptr<Variable2> variable)
19 : impl { spimpl::make_unique_impl<RemoveVariableOperationPrivate>(variable) }
19 20 {
20 21 }
21 22
22 void RemoveVariableOperation::visitEnter(VisualizationWidget *widget)
23 void RemoveVariableOperation::visitEnter(VisualizationWidget* widget)
23 24 {
24 25 // VisualizationWidget is not intended to contain a variable
25 26 Q_UNUSED(widget)
26 27 }
27 28
28 void RemoveVariableOperation::visitLeave(VisualizationWidget *widget)
29 void RemoveVariableOperation::visitLeave(VisualizationWidget* widget)
29 30 {
30 31 // VisualizationWidget is not intended to contain a variable
31 32 Q_UNUSED(widget)
32 33 }
33 34
34 void RemoveVariableOperation::visitEnter(VisualizationTabWidget *tabWidget)
35 void RemoveVariableOperation::visitEnter(VisualizationTabWidget* tabWidget)
35 36 {
36 37 // VisualizationTabWidget is not intended to contain a variable
37 38 Q_UNUSED(tabWidget)
38 39 }
39 40
40 void RemoveVariableOperation::visitLeave(VisualizationTabWidget *tabWidget)
41 void RemoveVariableOperation::visitLeave(VisualizationTabWidget* tabWidget)
41 42 {
42 43 // VisualizationTabWidget is not intended to contain a variable
43 44 Q_UNUSED(tabWidget)
44 45 }
45 46
46 void RemoveVariableOperation::visitEnter(VisualizationZoneWidget *zoneWidget)
47 void RemoveVariableOperation::visitEnter(VisualizationZoneWidget* zoneWidget)
47 48 {
48 49 // VisualizationZoneWidget is not intended to contain a variable
49 50 Q_UNUSED(zoneWidget)
50 51 }
51 52
52 void RemoveVariableOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
53 void RemoveVariableOperation::visitLeave(VisualizationZoneWidget* zoneWidget)
53 54 {
54 55 // VisualizationZoneWidget is not intended to contain a variable
55 56 Q_UNUSED(zoneWidget)
56 57 }
57 58
58 void RemoveVariableOperation::visit(VisualizationGraphWidget *graphWidget)
59 void RemoveVariableOperation::visit(VisualizationGraphWidget* graphWidget)
59 60 {
60 if (graphWidget) {
61 if (graphWidget)
62 {
61 63 // If the widget contains the variable, removes it
62 if (impl->m_Variable && graphWidget->contains(*impl->m_Variable)) {
64 if (impl->m_Variable && graphWidget->contains(*impl->m_Variable))
65 {
63 66 graphWidget->removeVariable(impl->m_Variable);
64 67 }
65 68 }
66 else {
69 else
70 {
67 71 qCCritical(LOG_RemoveVariableOperation(),
68 "Can't visit VisualizationGraphWidget : the widget is null");
72 "Can't visit VisualizationGraphWidget : the widget is null");
69 73 }
70 74 }
@@ -3,62 +3,67
3 3
4 4 Q_LOGGING_CATEGORY(LOG_RescaleAxeOperation, "RescaleAxeOperation")
5 5
6 struct RescaleAxeOperation::RescaleAxeOperationPrivate {
7 explicit RescaleAxeOperationPrivate(std::shared_ptr<Variable> variable, const DateTimeRange &range)
8 : m_Variable{variable}, m_Range{range}
6 struct RescaleAxeOperation::RescaleAxeOperationPrivate
7 {
8 explicit RescaleAxeOperationPrivate(
9 std::shared_ptr<Variable2> variable, const DateTimeRange& range)
10 : m_Variable { variable }, m_Range { range }
9 11 {
10 12 }
11 13
12 std::shared_ptr<Variable> m_Variable;
14 std::shared_ptr<Variable2> m_Variable;
13 15 DateTimeRange m_Range;
14 16 };
15 17
16 RescaleAxeOperation::RescaleAxeOperation(std::shared_ptr<Variable> variable, const DateTimeRange &range)
17 : impl{spimpl::make_unique_impl<RescaleAxeOperationPrivate>(variable, range)}
18 RescaleAxeOperation::RescaleAxeOperation(
19 std::shared_ptr<Variable2> variable, const DateTimeRange& range)
20 : impl { spimpl::make_unique_impl<RescaleAxeOperationPrivate>(variable, range) }
18 21 {
19 22 }
20 23
21 void RescaleAxeOperation::visitEnter(VisualizationWidget *widget)
24 void RescaleAxeOperation::visitEnter(VisualizationWidget* widget)
22 25 {
23 26 // VisualizationWidget is not intended to contain a variable
24 27 Q_UNUSED(widget)
25 28 }
26 29
27 void RescaleAxeOperation::visitLeave(VisualizationWidget *widget)
30 void RescaleAxeOperation::visitLeave(VisualizationWidget* widget)
28 31 {
29 32 // VisualizationWidget is not intended to contain a variable
30 33 Q_UNUSED(widget)
31 34 }
32 35
33 void RescaleAxeOperation::visitEnter(VisualizationTabWidget *tabWidget)
36 void RescaleAxeOperation::visitEnter(VisualizationTabWidget* tabWidget)
34 37 {
35 38 // VisualizationTabWidget is not intended to contain a variable
36 39 Q_UNUSED(tabWidget)
37 40 }
38 41
39 void RescaleAxeOperation::visitLeave(VisualizationTabWidget *tabWidget)
42 void RescaleAxeOperation::visitLeave(VisualizationTabWidget* tabWidget)
40 43 {
41 44 // VisualizationTabWidget is not intended to contain a variable
42 45 Q_UNUSED(tabWidget)
43 46 }
44 47
45 void RescaleAxeOperation::visitEnter(VisualizationZoneWidget *zoneWidget)
48 void RescaleAxeOperation::visitEnter(VisualizationZoneWidget* zoneWidget)
46 49 {
47 50 // VisualizationZoneWidget is not intended to contain a variable
48 51 Q_UNUSED(zoneWidget)
49 52 }
50 53
51 void RescaleAxeOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
54 void RescaleAxeOperation::visitLeave(VisualizationZoneWidget* zoneWidget)
52 55 {
53 56 // VisualizationZoneWidget is not intended to contain a variable
54 57 Q_UNUSED(zoneWidget)
55 58 }
56 59
57 void RescaleAxeOperation::visit(VisualizationGraphWidget *graphWidget)
60 void RescaleAxeOperation::visit(VisualizationGraphWidget* graphWidget)
58 61 {
59 if (graphWidget) {
62 if (graphWidget)
63 {
60 64 // If the widget contains the variable, rescale it
61 if (impl->m_Variable && graphWidget->contains(*impl->m_Variable)) {
65 if (impl->m_Variable && graphWidget->contains(*impl->m_Variable))
66 {
62 67 // During rescale, acquisition for the graph is disabled but synchronization is still
63 68 // enabled
64 69 graphWidget->setFlags(GraphFlag::EnableSynchronization);
@@ -66,8 +71,9 void RescaleAxeOperation::visit(VisualizationGraphWidget *graphWidget)
66 71 graphWidget->setFlags(GraphFlag::EnableAll);
67 72 }
68 73 }
69 else {
70 qCCritical(LOG_RescaleAxeOperation(),
71 "Can't visit VisualizationGraphWidget : the widget is null");
74 else
75 {
76 qCCritical(
77 LOG_RescaleAxeOperation(), "Can't visit VisualizationGraphWidget : the widget is null");
72 78 }
73 79 }
@@ -148,7 +148,7 void scroll_graph(T* w, int dx)
148 148
149 149 ALIAS_TEMPLATE_FUNCTION(isReady, static_cast<SqpApplication*>(qApp)->variableController().isReady)
150 150
151 void waitForVar(std::shared_ptr<Variable> var)
151 void waitForVar(std::shared_ptr<Variable2> var)
152 152 {
153 153 while (!isReady(var))
154 154 QCoreApplication::processEvents();
@@ -1,37 +1,36
1 #include <QtTest>
1 #include <QMainWindow>
2 2 #include <QObject>
3 #include <QString>
4 3 #include <QScreen>
5 #include <QMainWindow>
4 #include <QString>
6 5 #include <QWheelEvent>
6 #include <QtTest>
7 7
8 8 #include <qcustomplot.h>
9 9
10 #include <Common/cpp_utils.h>
10 11 #include <SqpApplication.h>
11 12 #include <Variable/VariableController2.h>
12 #include <Common/cpp_utils.h>
13 13
14 #include <Visualization/VisualizationZoneWidget.h>
15 #include <Visualization/VisualizationGraphWidget.h>
16 #include <TestProviders.h>
17 14 #include <GUITestUtils.h>
15 #include <TestProviders.h>
16 #include <Visualization/VisualizationGraphWidget.h>
17 #include <Visualization/VisualizationZoneWidget.h>
18 18
19 template <int GraphCount=2>
20 std::tuple< std::unique_ptr<VisualizationZoneWidget>,
21 std::vector<std::shared_ptr<Variable>>,
22 std::vector<VisualizationGraphWidget*>,
23 DateTimeRange>
19 template <int GraphCount = 2>
20 std::tuple<std::unique_ptr<VisualizationZoneWidget>, std::vector<std::shared_ptr<Variable2>>,
21 std::vector<VisualizationGraphWidget*>, DateTimeRange>
24 22 build_multi_graph_test()
25 23 {
26 24 auto w = std::make_unique<VisualizationZoneWidget>();
27 auto provider = std::make_shared<SimpleRange<10> >();
28 auto range = DateTimeRange::fromDateTime(QDate(2018, 8, 7), QTime(14, 00), QDate(2018, 8, 7),QTime(16, 00));
29 std::vector<std::shared_ptr<Variable>> variables;
25 auto provider = std::make_shared<SimpleRange<10>>();
26 auto range = DateTimeRange::fromDateTime(
27 QDate(2018, 8, 7), QTime(14, 00), QDate(2018, 8, 7), QTime(16, 00));
28 std::vector<std::shared_ptr<Variable2>> variables;
30 29 std::vector<VisualizationGraphWidget*> graphs;
31 for(auto i=0;i<GraphCount;i++)
30 for (auto i = 0; i < GraphCount; i++)
32 31 {
33 auto var = static_cast<SqpApplication *>(qApp)->variableController().createVariable(
34 QString("V%1").arg(i), {{"", "scalar"}}, provider, range);
32 auto var = static_cast<SqpApplication*>(qApp)->variableController().createVariable(
33 QString("V%1").arg(i), { { "", "scalar" } }, provider, range);
35 34 auto graph = new VisualizationGraphWidget();
36 35 graph->addVariable(var, range);
37 36 while (!isReady(var))
@@ -40,23 +39,25 build_multi_graph_test()
40 39 graphs.push_back(graph);
41 40 w->addGraph(graph);
42 41 }
43 return {std::move(w), variables, graphs, range};
42 return { std::move(w), variables, graphs, range };
44 43 }
45 44
46 45
47 class A_MultipleSyncGraphs : public QObject {
46 class A_MultipleSyncGraphs : public QObject
47 {
48 48 Q_OBJECT
49 49 public:
50 explicit A_MultipleSyncGraphs(QObject *parent = Q_NULLPTR) : QObject(parent) {}
50 explicit A_MultipleSyncGraphs(QObject* parent = Q_NULLPTR) : QObject(parent) {}
51 51
52 52 private slots:
53 53 void scrolls_left_with_mouse()
54 54 {
55 55 auto [w, variables, graphs, range] = build_multi_graph_test<3>();
56 auto var = variables.front();
56 auto var = variables.front();
57 57 auto graph = graphs.front();
58 58 QVERIFY(prepare_gui_test(w.get()));
59 for (auto i = 0; i < 100; i++) {
59 for (auto i = 0; i < 100; i++)
60 {
60 61 scroll_graph(graph, -200);
61 62 waitForVar(var);
62 63 }
@@ -65,18 +66,19 private slots:
65 66 /*
66 67 * Scrolling to the left implies going back in time
67 68 * Scroll only implies keeping the same delta T -> shit only transformation
68 */
69 */
69 70 QVERIFY(r.m_TEnd < range.m_TEnd);
70 QVERIFY(SciQLop::numeric::almost_equal<double>(r.delta(),range.delta(),1));
71 QVERIFY(SciQLop::numeric::almost_equal<double>(r.delta(), range.delta(), 1));
71 72 }
72 73
73 74 void scrolls_right_with_mouse()
74 75 {
75 76 auto [w, variables, graphs, range] = build_multi_graph_test<3>();
76 auto var = variables.front();
77 auto var = variables.front();
77 78 auto graph = graphs.front();
78 79 QVERIFY(prepare_gui_test(w.get()));
79 for (auto i = 0; i < 100; i++) {
80 for (auto i = 0; i < 100; i++)
81 {
80 82 scroll_graph(graph, 200);
81 83 waitForVar(var);
82 84 }
@@ -85,9 +87,9 private slots:
85 87 /*
86 88 * Scrolling to the right implies going forward in time
87 89 * Scroll only implies keeping the same delta T -> shit only transformation
88 */
90 */
89 91 QVERIFY(r.m_TEnd > range.m_TEnd);
90 QVERIFY(SciQLop::numeric::almost_equal<double>(r.delta(),range.delta(),1));
92 QVERIFY(SciQLop::numeric::almost_equal<double>(r.delta(), range.delta(), 1));
91 93 }
92 94 };
93 95
@@ -95,9 +97,9 private slots:
95 97 QT_BEGIN_NAMESPACE
96 98 QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS
97 99 QT_END_NAMESPACE
98 int main(int argc, char *argv[])
100 int main(int argc, char* argv[])
99 101 {
100 SqpApplication app{argc, argv};
102 SqpApplication app { argc, argv };
101 103 app.setAttribute(Qt::AA_Use96Dpi, true);
102 104 QTEST_DISABLE_KEYPAD_NAVIGATION;
103 105 QTEST_ADD_GPU_BLACKLIST_SUPPORT;
@@ -1,48 +1,52
1 #include <QtTest>
1 #include <QMainWindow>
2 2 #include <QObject>
3 #include <QString>
4 3 #include <QScreen>
5 #include <QMainWindow>
4 #include <QString>
6 5 #include <QWheelEvent>
6 #include <QtTest>
7 7
8 8 #include <qcustomplot.h>
9 9
10 #include <Common/cpp_utils.h>
10 11 #include <SqpApplication.h>
11 12 #include <Variable/VariableController2.h>
12 #include <Common/cpp_utils.h>
13 13
14 #include <Visualization/VisualizationGraphWidget.h>
15 #include <TestProviders.h>
16 14 #include <GUITestUtils.h>
17 #include <Variable/Variable.h>
15 #include <TestProviders.h>
16 #include <Variable/Variable2.h>
17 #include <Visualization/VisualizationGraphWidget.h>
18 18
19 std::tuple< std::unique_ptr<VisualizationGraphWidget>,
20 std::shared_ptr<Variable>,
21 DateTimeRange >
19 std::tuple<std::unique_ptr<VisualizationGraphWidget>, std::shared_ptr<Variable2>, DateTimeRange>
22 20 build_simple_graph_test()
23 21 {
24 22 auto w = std::make_unique<VisualizationGraphWidget>();
25 auto provider = std::make_shared<SimpleRange<10> >();
26 auto range = DateTimeRange::fromDateTime(QDate(2018, 8, 7), QTime(14, 00), QDate(2018, 8, 7),QTime(16, 00));
27 auto var = static_cast<SqpApplication *>(qApp)->variableController().createVariable("V1", {{"", "scalar"}}, provider, range);
28 while (!isReady(var)) QCoreApplication::processEvents();
23 auto provider = std::make_shared<SimpleRange<10>>();
24 auto range = DateTimeRange::fromDateTime(
25 QDate(2018, 8, 7), QTime(14, 00), QDate(2018, 8, 7), QTime(16, 00));
26 auto var = static_cast<SqpApplication*>(qApp)->variableController().createVariable(
27 "V1", { { "", "scalar" } }, provider, range);
28 while (!isReady(var))
29 QCoreApplication::processEvents();
29 30 w->addVariable(var, range);
30 while (!isReady(var)) QCoreApplication::processEvents();
31 return {std::move(w), var, range};
31 while (!isReady(var))
32 QCoreApplication::processEvents();
33 return { std::move(w), var, range };
32 34 }
33 35
34 36
35 class A_SimpleGraph : public QObject {
37 class A_SimpleGraph : public QObject
38 {
36 39 Q_OBJECT
37 40 public:
38 explicit A_SimpleGraph(QObject *parent = Q_NULLPTR) : QObject(parent) {}
41 explicit A_SimpleGraph(QObject* parent = Q_NULLPTR) : QObject(parent) {}
39 42
40 43 private slots:
41 44 void scrolls_left_with_mouse()
42 45 {
43 46 auto [w, var, range] = build_simple_graph_test();
44 47 QVERIFY(prepare_gui_test(w.get()));
45 for (auto i = 0; i < 100; i++) {
48 for (auto i = 0; i < 100; i++)
49 {
46 50 scroll_graph(w.get(), 200);
47 51 waitForVar(var);
48 52 }
@@ -50,16 +54,17 private slots:
50 54 /*
51 55 * Scrolling to the left implies going back in time
52 56 * Scroll only implies keeping the same delta T -> shit only transformation
53 */
57 */
54 58 QVERIFY(r.m_TEnd < range.m_TEnd);
55 QVERIFY(SciQLop::numeric::almost_equal<double>(r.delta(),range.delta(),1));
59 QVERIFY(SciQLop::numeric::almost_equal<double>(r.delta(), range.delta(), 1));
56 60 }
57 61
58 62 void scrolls_right_with_mouse()
59 63 {
60 64 auto [w, var, range] = build_simple_graph_test();
61 65 QVERIFY(prepare_gui_test(w.get()));
62 for (auto i = 0; i < 100; i++) {
66 for (auto i = 0; i < 100; i++)
67 {
63 68 scroll_graph(w.get(), -200);
64 69 waitForVar(var);
65 70 }
@@ -67,18 +72,18 private slots:
67 72 /*
68 73 * Scrolling to the right implies going forward in time
69 74 * Scroll only implies keeping the same delta T -> shit only transformation
70 */
75 */
71 76 QVERIFY(r.m_TEnd > range.m_TEnd);
72 QVERIFY(SciQLop::numeric::almost_equal<double>(r.delta(),range.delta(),1));
77 QVERIFY(SciQLop::numeric::almost_equal<double>(r.delta(), range.delta(), 1));
73 78 }
74 79 };
75 80
76 81 QT_BEGIN_NAMESPACE
77 82 QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS
78 83 QT_END_NAMESPACE
79 int main(int argc, char *argv[])
84 int main(int argc, char* argv[])
80 85 {
81 SqpApplication app{argc, argv};
86 SqpApplication app { argc, argv };
82 87 app.setAttribute(Qt::AA_Use96Dpi, true);
83 88 QTEST_DISABLE_KEYPAD_NAVIGATION;
84 89 QTEST_ADD_GPU_BLACKLIST_SUPPORT;
General Comments 0
You need to be logged in to leave comments. Login now