##// END OF EJS Templates
Switched to new TS impl but quite broken!...
jeandet -
r1420:3c3e24550401
parent child
Show More
@@ -13,9 +13,15 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 if(BUILD_PLUGINS)
16 17 target_link_libraries(sciqlopapp mockplugin)
17 18 target_link_libraries(sciqlopapp amdaplugin)
18 19 endif()
20 endif()
21
22 if(NOT BUILD_PLUGINS)
23 add_definitions(-DSQP_NO_PLUGINS)
24 endif()
19 25
20 26 target_link_libraries(sciqlopapp
21 27 Qt5::Core
@@ -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,7 +25,8 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:
@@ -40,8 +42,8 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 49 Ui::VariableInspectorWidget *ui;
@@ -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,15 +20,16 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:
@@ -12,7 +12,7 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 18 QString formatValue(double value, const QCPAxis &axis);
@@ -20,7 +20,8 QString formatValue(double value, const QCPAxis &axis);
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
@@ -36,9 +37,10 struct IAxisHelper {
36 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,12 +13,13 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
@@ -26,9 +27,10 struct IPlottablesHelper {
26 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 static void updateData(PlottablesMap& plottables, std::shared_ptr<Variable2> variable,
36 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,10 +9,11 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
@@ -26,11 +27,11 public:
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,17 +18,19 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 enum GraphFlag
33 {
32 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
@@ -41,7 +43,8 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;
@@ -60,16 +63,16 public:
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 77 void setGraphRange(const DateTimeRange &range, bool updateVar=false, bool forward=false);
75 78 void setAutoRangeOnVariableInitialization(bool value);
@@ -80,7 +83,8 public:
80 83 /// Adds new selection zones in the graph
81 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 89 void removeSelectionZone(VisualizationSelectionZoneItem *selectionZone);
86 90
@@ -94,8 +98,8 public:
94 98
95 99 // IVisualizationWidget interface
96 100 void accept(IVisualizationWidgetVisitor *visitor) override;
97 bool canDrop(const Variable &variable) const override;
98 bool contains(const Variable &variable) const 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
@@ -118,12 +122,12 public:
118 122
119 123 signals:
120 124 void synchronize(const DateTimeRange &range, const DateTimeRange &oldRange);
121 void changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange &range);
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 133 void zoom_sig(double factor, int center, Qt::Orientation orientation, bool forward=true);
@@ -172,10 +176,10 private slots:
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,11 +14,13 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:
@@ -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,8 +55,8 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.
@@ -65,8 +67,8 public:
65 67
66 68 // IVisualizationWidget interface
67 69 void accept(IVisualizationWidgetVisitor *visitor) override;
68 bool canDrop(const Variable &variable) const override;
69 bool contains(const Variable &variable) const 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:
@@ -12,15 +12,17
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:
@@ -34,8 +36,8 public:
34 36
35 37 // IVisualizationWidget interface
36 38 void accept(IVisualizationWidgetVisitor *visitor) override;
37 bool canDrop(const Variable &variable) const override;
38 bool contains(const Variable &variable) const 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,13 +46,13 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 58 void closeEvent(QCloseEvent *event) override;
@@ -14,14 +14,16
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:
@@ -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,8 +64,8 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 71 VisualizationGraphWidget *firstGraph() const;
@@ -73,8 +75,8 public:
73 75
74 76 // IVisualizationWidget interface
75 77 void accept(IVisualizationWidgetVisitor *visitor) override;
76 bool canDrop(const Variable &variable) const override;
77 bool contains(const Variable &variable) const 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
@@ -95,9 +97,9 private:
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 104 void dropMimeData(int index, const QMimeData *mimeData);
103 105 void dropMimeDataOnGraph(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
@@ -8,20 +8,21
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 27 void visitEnter(VisualizationWidget *widget) override final;
27 28 void visitLeave(VisualizationWidget *widget) override final;
@@ -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,7 +30,7 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 explicit GenerateVariableMenuOperation(QMenu* menu, std::shared_ptr<Variable2> variable,
33 34 std::set<IVisualizationWidget *> variableContainers);
34 35
35 36 void visitEnter(VisualizationWidget *widget) override final;
@@ -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,13 +17,14 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 explicit RemoveVariableOperation(std::shared_ptr<Variable2> variable);
27 28
28 29 void visitEnter(VisualizationWidget *widget) override final;
29 30 void visitLeave(VisualizationWidget *widget) override final;
@@ -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,13 +18,14 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 explicit RescaleAxeOperation(std::shared_ptr<Variable2> variable, const DateTimeRange& range);
28 29
29 30 void visitEnter(VisualizationWidget *widget) override final;
30 31 void visitLeave(VisualizationWidget *widget) override final;
@@ -23,7 +23,8
23 23 Q_LOGGING_CATEGORY(LOG_DragDropGuiController, "DragDropGuiController")
24 24
25 25
26 struct DragDropGuiController::DragDropGuiControllerPrivate {
26 struct DragDropGuiController::DragDropGuiControllerPrivate
27 {
27 28
28 29 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
29 30 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
@@ -42,9 +43,9 struct DragDropGuiController::DragDropGuiControllerPrivate {
42 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 51 auto layout = new QVBoxLayout{m_PlaceHolder.get()};
@@ -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
71 {
72 if (m_CurrentDragWidget)
70 73 {
71 if (m_CurrentDragWidget) {
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");
@@ -117,16 +121,17 void DragDropGuiController::resetDragAndDrop()
117 121
118 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;
@@ -142,8 +147,8 QWidget &DragDropGuiController::placeHolder() const
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();
@@ -194,12 +200,14 QUrl DragDropGuiController::imageTemporaryUrl(const QImage &image) const
194 200
195 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
@@ -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
@@ -234,7 +243,8 void DragDropGuiController::doCloseWidgets()
234 243 bool DragDropGuiController::checkMimeDataForVisualization(
235 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) {
276 if (parent)
277 {
263 278 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
264 279
265 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,20 +19,23
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 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 40 auto progressBarOption = QStyleOptionProgressBar{};
38 41 auto progressRect = option.rect;
@@ -47,8 +50,8 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,
@@ -59,11 +62,13 public:
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 }
@@ -71,10 +76,12 public:
71 76 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
72 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);
@@ -91,22 +98,27 public:
91 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) {
101 if (clickX > x && clickX < x + w)
102 {
103 if (clickY > y && clickY < y + h)
104 {
96 105 //auto& variableModel = sqpApp->variableModel();
97 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
@@ -116,9 +128,9 public:
116 128 };
117 129
118 130 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
119 : QWidget{parent},
120 ui{new Ui::VariableInspectorWidget},
121 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
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());
@@ -149,7 +159,8 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
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 }
@@ -172,9 +183,11 VariableInspectorWidget::~VariableInspectorWidget()
172 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 }
@@ -185,25 +198,27 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
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)]()
210 auto duplicateFun = [varW = std::weak_ptr<Variable2>(selectedVariable)]() {
211 if (auto var = varW.lock())
196 212 {
197 if (auto var = varW.lock()) {
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 ]()
219 auto renameFun = [varW = std::weak_ptr<Variable2>(selectedVariable), this]() {
220 if (auto var = varW.lock())
205 221 {
206 if (auto var = varW.lock()) {
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());
@@ -212,7 +227,8 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
212 227 [](const auto &variable) { return variable->name(); });
213 228
214 229 RenameVariableDialog dialog{var->name(), forbiddenNames, this};
215 if (dialog.exec() == QDialog::Accepted) {
230 if (dialog.exec() == QDialog::Accepted)
231 {
216 232 var->setName(dialog.name());
217 233 }
218 234 }
@@ -230,11 +246,13 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
230 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 253 auto headerAction = new QWidgetAction{&tableMenu};
237 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
254 headerAction->setDefaultWidget(
255 new VariableMenuHeaderWidget { selectedVariables, &tableMenu });
238 256 tableMenu.insertAction(firstAction, headerAction);
239 257
240 258 // Displays menu
@@ -1,12 +1,12
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)
9 const QVector<std::shared_ptr<Variable2>>& variables, QWidget* parent)
10 10 : QWidget{parent}, ui{new Ui::VariableMenuHeaderWidget}
11 11 {
12 12 ui->setupUi(this);
@@ -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,29 +49,31 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,
52 void setAxisProperties(QCPAxis& axis, const std::string& unit, bool isTime,
49 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 {
75 struct AxisSetter
76 {
71 77 static void setProperties(QCustomPlot &, SqpColorScale &)
72 78 {
73 79 // Default implementation does nothing
@@ -87,8 +93,10 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> > {
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 {
92 100 static void setProperties(QCustomPlot &, SqpColorScale &)
93 101 {
94 102 // Nothing to do
@@ -96,15 +104,9 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>:
96 104
97 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,7 +115,8 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> > {
118 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
119 {
117 120 static void setProperties(QCustomPlot &plot, SqpColorScale &colorScale)
118 121 {
119 122 // Displays color scale in plot
@@ -124,7 +127,8 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries
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
@@ -134,17 +138,11 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries
134 138
135 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,8 +151,9 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 158 void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
160 159 {
@@ -163,16 +162,18 struct AxisHelper : public IAxisHelper {
163 162
164 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
@@ -180,30 +181,33 struct AxisHelper : public IAxisHelper {
180 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
195 {
196 switch (variable.type())
192 197 {
193 switch (variable.type()) {
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,19 +6,21
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 struct PlottablesSetter
23 {
22 24 static void setProperties(PlottablesMap &)
23 25 {
24 26 // Default implementation does nothing
@@ -33,25 +35,27 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 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 {
38 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) {
57 if (graphIt != end)
58 {
55 59 graphIt->second->setPen(QPen{colors.at(i)});
56 60 }
57 61 }
@@ -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> > {
71 typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
72 {
68 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,7 +108,8 struct PlottablesSetter<T,
98 108 * @tparam T the data series' type
99 109 */
100 110 template <typename T>
101 struct PlottablesHelper : public IPlottablesHelper {
111 struct PlottablesHelper : public IPlottablesHelper
112 {
102 113 void setProperties(PlottablesMap &plottables) override
103 114 {
104 115 PlottablesSetter<T>::setProperties(plottables);
@@ -107,16 +118,16 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
122 {
123 switch (variable.type())
112 124 {
113 switch (variable.type()) {
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;
@@ -2,17 +2,19
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 19 void appendGraphData(const QCPGraphData &data) { mData.append(data); }
18 20 };
@@ -24,13 +26,9 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 struct PlottablesCreator
29 30 {
30 qCCritical(LOG_DataSeries())
31 << QObject::tr("Can't create plottables: unmanaged data series type");
32 return {};
33 }
31 static PlottablesMap createPlottables(QCustomPlot&) { return {}; }
34 32 };
35 33
36 34 PlottablesMap createGraphs(QCustomPlot &plot, int nbGraphs)
@@ -38,7 +36,8 PlottablesMap createGraphs(QCustomPlot &plot, int nbGraphs)
38 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 42 result.insert({i, graph});
44 43 }
@@ -53,7 +52,8 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> > {
55 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>>
56 {
57 57 static PlottablesMap createPlottables(QCustomPlot &plot) { return createGraphs(plot, 1); }
58 58 };
59 59
@@ -62,7 +62,8 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> > {
65 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<VectorTimeSerie, T>::value>>
66 {
66 67 static PlottablesMap createPlottables(QCustomPlot &plot) { return createGraphs(plot, 3); }
67 68 };
68 69
@@ -72,7 +73,8 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 typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
77 {
76 78 static PlottablesMap createPlottables(QCustomPlot &plot)
77 79 {
78 80 PlottablesMap result{};
@@ -91,7 +93,8 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 {
96 struct PlottablesUpdater
97 {
95 98 static void setPlotYAxisRange(T &, const DateTimeRange &, QCustomPlot &)
96 99 {
97 100 qCCritical(LOG_VisualizationGraphHelper())
@@ -111,61 +114,120 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 struct PlottablesUpdater<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>>
118 {
117 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 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);
148 }
149 }
150
151 if (!plottables.empty())
152 {
153 auto plot = plottables.begin()->second->parentPlot();
145 154
146 dataContainers.insert({plottable.first, dataContainer});
155 if (rescaleAxes)
156 {
157 plot->rescaleAxes();
147 158 }
148 159 }
149 dataSeries.lockRead();
160 }
161 };
162
150 163
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)));
164 template <typename T>
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)
168 {
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 });
160 177 }
178
179 plot.yAxis->setRange(QCPRange { minValue, maxValue });
161 180 }
162 181
163 dataSeries.unlock();
182 static void updatePlottables(
183 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
184 {
164 185
165 if (!plottables.empty()) {
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 }
220 }
221 graph->setData(dataContainer);
222 }
223 }
224
225 if (!plottables.empty())
226 {
166 227 auto plot = plottables.begin()->second->parentPlot();
167 228
168 if (rescaleAxes) {
229 if (rescaleAxes)
230 {
169 231 plot->rescaleAxes();
170 232 }
171 233 }
@@ -178,87 +240,97 struct PlottablesUpdater<T,
178 240 */
179 241 template <typename T>
180 242 struct PlottablesUpdater<T,
181 typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
243 typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
244 {
182 245 static void setPlotYAxisRange(T &dataSeries, const DateTimeRange &xAxisRange, QCustomPlot &plot)
183 246 {
184 double min, max;
185 std::tie(min, max) = dataSeries.yBounds();
247 // TODO
248 // double min, max;
249 // std::tie(min, max) = dataSeries.yBounds();
186 250
187 if (!std::isnan(min) && !std::isnan(max)) {
188 plot.yAxis->setRange(QCPRange{min, max});
189 }
251 // if (!std::isnan(min) && !std::isnan(max))
252 // {
253 // plot.yAxis->setRange(QCPRange { min, max });
254 // }
190 255 }
191 256
192 static void updatePlottables(T &dataSeries, PlottablesMap &plottables, const DateTimeRange &range,
193 bool rescaleAxes)
257 static void updatePlottables(
258 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
194 259 {
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
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);
240 }
241 }
242 }
243
244 // Rescales axes
245 auto plot = colormap->parentPlot();
246
247 if (rescaleAxes) {
248 plot->rescaleAxes();
249 }
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 // }
250 321 }
251 322 };
252 323
253 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 330 virtual PlottablesMap create(QCustomPlot &plot) const = 0;
259 331 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;
332 virtual void update(
333 PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes = false) const = 0;
262 334 };
263 335
264 336 /**
@@ -266,20 +338,24 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 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
352 {
353 if (m_DataSeries)
278 354 {
279 if (m_DataSeries) {
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";
@@ -288,73 +364,79 struct PlottablesHelper : public IPlottablesHelper {
288 364
289 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
384 {
385 switch (variable->type())
306 386 {
307 switch (variable->type()) {
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
408 {
409 if (variable)
329 410 {
330 if (variable) {
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 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
425 {
426 if (variable)
344 427 {
345 if (variable) {
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");
@@ -113,7 +114,8 int colorMapCellIndex(const QCPColorMap &colormap, double coord, bool xCoord)
113 114 auto isLogarithmic = (xCoord ? colormap.keyAxis() : colormap.valueAxis())->scaleType()
114 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 {
151 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate
152 {
147 153 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}}
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,9 +171,10 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) {
174 QObject::connect(
175 &m_Plot, &QCustomPlot::itemClick, [&graphWidget, this](auto item, auto mouseEvent) {
176 if (item == m_ClosePixmap)
177 {
171 178 graphWidget.close();
172 179 }
173 180 });
@@ -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();
@@ -226,8 +234,10 void VisualizationGraphRenderingDelegate::onMouseDoubleClick(QMouseEvent *event)
226 234 {
227 235 // Opens color scale editor if color scale is double clicked
228 236 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) {
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 }
@@ -247,13 +257,15 void VisualizationGraphRenderingDelegate::updateTooltip(QMouseEvent *event) noex
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());
@@ -284,7 +297,8 void VisualizationGraphRenderingDelegate::updateTooltip(QMouseEvent *event) noex
284 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,
@@ -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);
@@ -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 65 explicit VisualizationGraphWidgetPrivate(const QString &name)
64 : m_Name{name},
65 m_Flags{GraphFlag::EnableAll},
66 m_IsCalibration{false},
67 m_RenderingDelegate{nullptr}
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;
@@ -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 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 }
@@ -136,7 +138,8 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
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);
@@ -169,7 +172,8 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);
@@ -179,7 +183,8 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
179 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 190 void startDrawingZone(const QPoint &pos)
@@ -195,13 +200,16 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
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
@@ -222,7 +230,8 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
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 }
@@ -233,10 +242,12 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
233 242 {
234 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 261 QVector<VisualizationSelectionZoneItem *> zones;
251 for (auto zone : m_SelectionZones) {
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 }
@@ -260,7 +273,8 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
260 273
261 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);
@@ -300,8 +314,7 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
300 314 this->m_plot->xAxis->setRange(newRange.m_TStart, newRange.m_TEnd);
301 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);
@@ -316,10 +329,7 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
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 334 std::tuple<double,double> moveGraph(const QPoint& destination)
325 335 {
@@ -332,12 +342,14 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
332 342 xAxis->setRange(m_lastXRange.lower+dx, m_lastXRange.upper+dx);
333 343 if(yAxis->scaleType() == QCPAxis::stLinear)
334 344 {
335 double dy = yAxis->pixelToCoord(m_lastMousePos.y()) - yAxis->pixelToCoord(currentPos.y());
345 double dy
346 = yAxis->pixelToCoord(m_lastMousePos.y()) - yAxis->pixelToCoord(currentPos.y());
336 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());
351 double dy
352 = yAxis->pixelToCoord(m_lastMousePos.y()) / yAxis->pixelToCoord(currentPos.y());
341 353 yAxis->setRange(m_lastYRange.lower*dy, m_lastYRange.upper*dy);
342 354 }
343 355 auto newXRange = xAxis->range();
@@ -379,18 +391,22 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
379 391 {
380 392 auto oldRange = m_plot->xAxis->range();
381 393 QCPAxis *axis = m_plot->axisRect()->rangeDragAxis(orientation);
382 if (m_plot->xAxis->scaleType() == QCPAxis::stLinear) {
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;
@@ -406,9 +422,9 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
406 422 };
407 423
408 424 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
409 : VisualizationDragWidget{parent},
410 ui{new Ui::VisualizationGraphWidget},
411 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
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
@@ -442,7 +459,8 VisualizationGraphWidget::~VisualizationGraphWidget()
442 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
@@ -452,7 +470,8 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noex
452 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
@@ -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);
@@ -476,41 +495,42 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, D
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 504 auto context = new QObject{this};
485 connect(variable.get(), &Variable::updated, context,
486 [this, variable, context, range](QUuid)
487 {
505 connect(
506 variable.get(), &Variable2::updated, context, [this, variable, context, range](QUuid) {
488 507 this->impl->m_RenderingDelegate->setAxesUnits(*variable);
489 508 this->impl->m_plot->replot(QCustomPlot::rpQueuedReplot);
490 509 delete context;
491 }
492 );
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 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)
558 {
559 if (!variable)
537 560 {
538 if (!variable) {
539 561 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
540 562 return;
541 563 }
@@ -549,14 +571,14 DateTimeRange VisualizationGraphWidget::graphRange() const noexcept
549 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 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,7 +589,8 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
@@ -576,7 +599,8 QVector<DateTimeRange> VisualizationGraphWidget::selectionZoneRanges() const
576 599
577 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());
@@ -604,7 +628,8 void VisualizationGraphWidget::removeSelectionZone(VisualizationSelectionZoneIte
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,7 +651,8 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 658 if(forward && orientation==Qt::Horizontal)
@@ -647,7 +673,8 void VisualizationGraphWidget::move(double dx, double dy, bool 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 680 if(forward)
@@ -656,31 +683,32 void VisualizationGraphWidget::transform(const DateTimeRangeTransformation &tran
656 683
657 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 705 ? impl->m_VariableToPlotMultiMap.empty()
678 : std::none_of(
679 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
706 : std::none_of(impl->m_VariableToPlotMultiMap.cbegin(),
707 impl->m_VariableToPlotMultiMap.cend(),
680 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;
@@ -703,13 +731,15 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
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 {
741 else
742 {
713 743 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
714 744
715 745 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
@@ -723,7 +753,8 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();
@@ -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
@@ -811,12 +844,14 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 }
@@ -832,14 +867,17 void VisualizationGraphWidget::leaveEvent(QEvent *event)
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 }
@@ -849,7 +887,8 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,14 +905,14 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 916 void VisualizationGraphWidget::mouseMoveEvent(QMouseEvent *event)
877 917 {
878 918 if(impl->isDrawingZoomRect())
@@ -890,19 +930,20 void VisualizationGraphWidget::mouseMoveEvent(QMouseEvent *event)
890 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 937 if(auto item = impl->m_plot->itemAt(posInPlot))
897 938 {
898 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
@@ -936,7 +977,8 void VisualizationGraphWidget::mouseReleaseEvent(QMouseEvent *event)
936 977 {
937 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 }
@@ -960,7 +1002,8 void VisualizationGraphWidget::mousePressEvent(QMouseEvent *event)
960 1002 impl->setSelectionZonesEditionEnabled(true);
961 1003 if ((event->modifiers() == Qt::ControlModifier) && (selectedZone != nullptr))
962 1004 {
963 auto alreadySelectedZones = parentVisualizationWidget()->selectionZoneManager().selectedItems();
1005 auto alreadySelectedZones
1006 = parentVisualizationWidget()->selectionZoneManager().selectedItems();
964 1007 selectedZone->setAssociatedEditedZones(alreadySelectedZones);
965 1008 if(SciQLop::containers::contains(alreadySelectedZones, selectedZone))
966 1009 {
@@ -970,7 +1013,8 void VisualizationGraphWidget::mousePressEvent(QMouseEvent *event)
970 1013 {
971 1014 alreadySelectedZones.append(selectedZone);
972 1015 }
973 parentVisualizationWidget()->selectionZoneManager().select(alreadySelectedZones);
1016 parentVisualizationWidget()->selectionZoneManager().select(
1017 alreadySelectedZones);
974 1018 }
975 1019 else
976 1020 {
@@ -981,7 +1025,8 void VisualizationGraphWidget::mousePressEvent(QMouseEvent *event)
981 1025 }
982 1026 else
983 1027 {
984 parentVisualizationWidget()->selectionZoneManager().select({ selectedZone });
1028 parentVisualizationWidget()->selectionZoneManager().select(
1029 { selectedZone });
985 1030 }
986 1031 }
987 1032 {
@@ -990,7 +1035,8 void VisualizationGraphWidget::mousePressEvent(QMouseEvent *event)
990 1035 {
991 1036 if(qobject_cast<VisualizationSelectionZoneItem*>(item))
992 1037 {
993 QMouseEvent e{QEvent::MouseButtonPress, posInPlot, event->button(), event->buttons(), event->modifiers()};
1038 QMouseEvent e { QEvent::MouseButtonPress, posInPlot, event->button(),
1039 event->buttons(), event->modifiers() };
994 1040 sqpApp->sendEvent(this->impl->m_plot, &e);
995 1041 }
996 1042 }
@@ -1027,7 +1073,8 void VisualizationGraphWidget::mouseDoubleClickEvent(QMouseEvent *event)
1027 1073
1028 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;
@@ -1044,7 +1091,8 void VisualizationGraphWidget::keyReleaseEvent(QKeyEvent *event)
1044 1091
1045 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;
@@ -1104,14 +1160,17 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
1104 1160 // Iterates on variables (unique keys)
1105 1161 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
1106 1162 end = impl->m_VariableToPlotMultiMap.cend();
1107 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
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 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,13 +1179,15 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
@@ -1134,24 +1195,29 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
1134 1195 QHash<QString, bool> subMenusEnabled;
1135 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 }
@@ -1159,9 +1225,11 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
1159 1225 }
1160 1226
1161 1227 FilteringAction *filterAction = nullptr;
1162 if (sqpApp->actionsGuiController().isMenuFiltered(zoneAction->subMenuList())) {
1228 if (sqpApp->actionsGuiController().isMenuFiltered(zoneAction->subMenuList()))
1229 {
1163 1230 filterAction = filteredMenu.value(menuPath);
1164 if (!filterAction) {
1231 if (!filterAction)
1232 {
1165 1233 filterAction = new FilteringAction{this};
1166 1234 filteredMenu[menuPath] = filterAction;
1167 1235 menu->addAction(filterAction);
@@ -1174,17 +1242,20 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
1174 1242 QObject::connect(action, &QAction::triggered,
1175 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 }
@@ -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 }
@@ -1255,12 +1336,14 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
1255 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);
@@ -1273,13 +1356,15 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
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
@@ -1295,15 +1380,19 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
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 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 }
@@ -1344,7 +1438,8 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
1344 1438
1345 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);
@@ -1358,7 +1453,8 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
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,14 +1468,17 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 1484 VisualizationMultiZoneSelectionDialog dialog{this};
@@ -1387,40 +1486,49 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
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 1518 {selectionZoneItemUnderCursor});
1414 1519 impl->moveSelectionZoneOnTop(selectionZoneItemUnderCursor, plot());
1415 1520 }
1416 else {
1521 else
1522 {
1417 1523 parentVisualizationWidget()->selectionZoneManager().setSelected(
1418 selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected()
1524 selectionZoneItemUnderCursor,
1525 !selectionZoneItemUnderCursor->selected()
1419 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 }
@@ -1431,37 +1539,42 void VisualizationGraphWidget::onDataCacheVariableUpdated()
1431 1539 auto graphRange = impl->m_plot->xAxis->range();
1432 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
@@ -27,10 +28,13 namespace {
27 28 template <typename Fun>
28 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 }
@@ -42,12 +46,13 void processZones(QLayout &layout, Fun fun)
42 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,7 +62,8 QString defaultZoneName(QLayout &layout)
57 62
58 63 } // namespace
59 64
60 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
65 struct VisualizationTabWidget::VisualizationTabWidgetPrivate
66 {
61 67 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
62 68
63 69 QString m_Name;
@@ -68,16 +74,16 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
68 74
69 75 void dropGraph(int index, VisualizationTabWidget *tabWidget);
70 76 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,
77 void dropVariables(const std::vector<std::shared_ptr<Variable2>>& variables, int index,
74 78 VisualizationTabWidget *tabWidget);
79 void dropProducts(
80 const QVariantList& productsMetaData, int index, VisualizationTabWidget* tabWidget);
75 81 };
76 82
77 83 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
78 : QWidget{parent},
79 ui{new Ui::VisualizationTabWidget},
80 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
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,18 +94,18 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,
@@ -130,8 +136,8 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 }
@@ -140,7 +146,8 VisualizationZoneWidget *VisualizationTabWidget::getZoneWithName(const QString &
140 146 {
141 147 VisualizationZoneWidget *result = nullptr;
142 148 processZones(tabLayout(), [&zoneName, &result](VisualizationZoneWidget &zoneWidget) {
143 if (!result && zoneWidget.name() == zoneName) {
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 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
@@ -175,29 +182,30 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
175 182
176 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;
@@ -223,23 +231,28 QLayout &VisualizationTabWidget::tabLayout() const noexcept
223 231
224 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 }
@@ -251,7 +264,8 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
251 264 auto &helper = sqpApp->dragDropGuiController();
252 265
253 266 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
254 if (!graphWidget) {
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.");
@@ -261,7 +275,8 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
261 275
262 276 auto parentDragDropContainer
263 277 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
264 if (!parentDragDropContainer) {
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.");
@@ -273,7 +288,8 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
273 288
274 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,7 +333,8 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 }
@@ -324,7 +346,8 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
324 346 auto &helper = sqpApp->dragDropGuiController();
325 347
326 348 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
327 if (!zoneWidget) {
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.");
@@ -334,7 +357,8 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
334 357
335 358 auto parentDragDropContainer
336 359 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
337 if (!parentDragDropContainer) {
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,
375 const std::vector<std::shared_ptr<Variable2>>& variables, int index,
352 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.");
@@ -368,7 +393,8 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropProducts(
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.");
@@ -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
@@ -34,9 +35,9 struct VisualizationWidget::VisualizationWidgetPrivate {
34 35 };
35 36
36 37 VisualizationWidget::VisualizationWidget(QWidget *parent)
37 : QWidget{parent},
38 ui{new Ui::VisualizationWidget},
39 impl{spimpl::make_unique_impl<VisualizationWidgetPrivate>()}
38 : QWidget { parent }
39 , ui { new Ui::VisualizationWidget }
40 , impl { spimpl::make_unique_impl<VisualizationWidgetPrivate>() }
40 41 {
41 42 ui->setupUi(this);
42 43
@@ -46,7 +47,6 VisualizationWidget::VisualizationWidget(QWidget *parent)
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),
60 auto widget
61 = new VisualizationTabWidget { QString { "View %1" }.arg(ui->tabWidget->count() + 1),
61 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 }
@@ -121,7 +126,8 VisualizationSelectionZoneManager &VisualizationWidget::selectionZoneManager() c
121 126
122 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
@@ -130,33 +136,37 VisualizationTabWidget *VisualizationWidget::currentTabWidget() const
130 136
131 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,42 +178,46 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 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 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 223 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
@@ -213,9 +227,11 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
213 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 }
@@ -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
@@ -38,10 +39,13 namespace {
38 39 template <typename Fun>
39 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 }
@@ -58,7 +62,8 QString defaultGraphName(QLayout &layout)
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 87 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,
88 void dropVariables(const std::vector<std::shared_ptr<Variable2>>& variables, int index,
85 89 VisualizationZoneWidget *zoneWidget);
90 void dropProducts(
91 const QVariantList& productsData, int index, VisualizationZoneWidget* zoneWidget);
86 92 };
87 93
88 94 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
89 : VisualizationDragWidget{parent},
90 ui{new Ui::VisualizationZoneWidget},
91 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
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 }
@@ -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()
@@ -157,10 +167,12 VisualizationZoneWidget::~VisualizationZoneWidget()
157 167
158 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 }
@@ -173,39 +185,32 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
173 185
174 186 // ui->dragDropContainer->addDragWidget(graphWidget);
175 187 insertGraph(0,graphWidget);
176
177 188 }
178 189
179 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 {
193 auto layout = ui->dragDropContainer->layout(); for (int i = 0; i < layout->count(); i++) {
185 194 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 )
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 216 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
@@ -263,7 +268,8 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<V
263 268 // }
264 269 // default:
265 270 // qCCritical(LOG_VisualizationZoneWidget())
266 // << tr("Impossible to synchronize: zoom type not take into account");
271 // << tr("Impossible to synchronize: zoom type not take into
272 // account");
267 273 // // No action
268 274 // break;
269 275 // }
@@ -282,11 +288,13 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<V
282 288 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
283 289
284 290 auto range = DateTimeRange{};
285 if (auto firstGraph = this->firstGraph()) {
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,15 +307,17 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)
312 {
313 if (variables.empty())
304 314 {
305 if (variables.empty()) {
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
@@ -318,9 +328,11 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
318 328 {
319 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 }
@@ -336,30 +348,31 void VisualizationZoneWidget::closeAllGraphs()
336 348
337 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(),
357 processGraphs(*ui->dragDropContainer->layout(),
346 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;
@@ -377,7 +390,8 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
377 390 auto mimeData = new QMimeData;
378 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 }
@@ -391,13 +405,12 bool VisualizationZoneWidget::isDragAllowed() const
391 405 }
392 406
393 407 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
394 const QPointF &plotPosition,
395 VisualizationGraphWidget *graphWidget)
408 const QPointF& plotPosition, VisualizationGraphWidget* graphWidget)
409 {
410 processGraphs(*ui->dragDropContainer->layout(),
411 [&graphPosition, &plotPosition, &graphWidget](VisualizationGraphWidget& processedGraph) {
412 switch (sqpApp->plotsCursorMode())
396 413 {
397 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
398 VisualizationGraphWidget &processedGraph) {
399
400 switch (sqpApp->plotsCursorMode()) {
401 414 case SqpApplication::PlotsCursorMode::Vertical:
402 415 processedGraph.removeHorizontalCursor();
403 416 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
@@ -408,19 +421,23 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPositio
408 421 break;
409 422 case SqpApplication::PlotsCursorMode::Horizontal:
410 423 processedGraph.removeVerticalCursor();
411 if (&processedGraph == graphWidget) {
424 if (&processedGraph == graphWidget)
425 {
412 426 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
413 427 }
414 else {
428 else
429 {
415 430 processedGraph.removeHorizontalCursor();
416 431 }
417 432 break;
418 433 case SqpApplication::PlotsCursorMode::Cross:
419 if (&processedGraph == graphWidget) {
434 if (&processedGraph == graphWidget)
435 {
420 436 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
421 437 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
422 438 }
423 else {
439 else
440 {
424 441 processedGraph.removeHorizontalCursor();
425 442 processedGraph.removeVerticalCursor();
426 443 }
@@ -430,8 +447,6 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPositio
430 447 processedGraph.removeVerticalCursor();
431 448 break;
432 449 }
433
434
435 450 });
436 451 }
437 452
@@ -456,46 +471,50 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
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),
477 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable2>, variable),
463 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 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 515 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
498 if (!graphWidget) {
516 if (!graphWidget)
517 {
499 518 qCWarning(LOG_VisualizationZoneWidget())
500 519 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
501 520 "drop aborted");
@@ -503,14 +522,17 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
@@ -527,14 +549,12 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragW
527 549 else
528 550 {
529 551 // -> 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 {
552 QObject::connect(variable.get(), &Variable2::updated, context,
553 [graphWidget, context, range, variable]() {
533 554 graphWidget->addVariable(variable, range);
534 555 delete context;
535 556 });
536 557 }
537
538 558 },
539 559 Qt::QueuedConnection);
540 560
@@ -542,11 +562,13 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragW
542 562 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
543 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 }
@@ -558,7 +580,8 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
558 580 auto &helper = sqpApp->dragDropGuiController();
559 581
560 582 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
561 if (!graphWidget) {
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.");
@@ -568,7 +591,8 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
568 591
569 592 auto parentDragDropContainer
570 593 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
571 if (!parentDragDropContainer) {
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.");
@@ -578,7 +602,8 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
578 602
579 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,12 +656,13 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,
659 const std::vector<std::shared_ptr<Variable2>>& variables, int index,
629 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);
@@ -641,7 +673,8 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProducts(
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.");
@@ -5,25 +5,28
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 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
25 std::shared_ptr<Variable2> m_Variable; ///< Variable to find
23 26 std::set<IVisualizationWidget *> m_Containers; ///< Containers found for the variable
24 27 };
25 28
26 FindVariableOperation::FindVariableOperation(std::shared_ptr<Variable> variable)
29 FindVariableOperation::FindVariableOperation(std::shared_ptr<Variable2> variable)
27 30 : impl{spimpl::make_unique_impl<FindVariableOperationPrivate>(variable)}
28 31 {
29 32 }
@@ -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,
15 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate
16 {
17 explicit GenerateVariableMenuOperationPrivate(QMenu* menu, std::shared_ptr<Variable2> variable,
18 18 std::set<IVisualizationWidget *> variableContainers)
19 : m_Variable{variable},
20 m_VariableContainers{std::move(variableContainers)},
21 m_PlotMenuBuilder{menu},
22 m_UnplotMenuBuilder{menu}
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,8 +27,9 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 35 m_UnplotMenuBuilder.addMenu(QObject::tr("Unplot"), QIcon{":/icones/unplot.png"});
@@ -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)
55 {
56 if (isValidContainer(container))
54 57 {
55 if (isValidContainer(container)) {
56 58 m_PlotMenuBuilder.addSeparator();
57 59 m_PlotMenuBuilder.addAction(actionName, actionFunction);
58 60 }
@@ -68,20 +70,22 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)
75 {
76 if (isValidContainer(container))
73 77 {
74 if (isValidContainer(container)) {
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 }
@@ -93,15 +97,14 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
93 97 return m_Variable && m_VariableContainers.size() == 0 && container.canDrop(*m_Variable);
94 98 }
95 99
96 std::shared_ptr<Variable> m_Variable;
100 std::shared_ptr<Variable2> m_Variable;
97 101 std::set<IVisualizationWidget *> m_VariableContainers;
98 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)
106 GenerateVariableMenuOperation::GenerateVariableMenuOperation(QMenu* menu,
107 std::shared_ptr<Variable2> variable, std::set<IVisualizationWidget*> variableContainers)
105 108 : impl{spimpl::make_unique_impl<GenerateVariableMenuOperationPrivate>(
106 109 menu, variable, std::move(variableContainers))}
107 110 {
@@ -127,11 +130,13 void GenerateVariableMenuOperation::visitLeave(VisualizationWidget *widget)
127 130
128 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 141 "Can't visit enter VisualizationTabWidget : the widget is null");
137 142 }
@@ -139,11 +144,13 void GenerateVariableMenuOperation::visitEnter(VisualizationTabWidget *tabWidget
139 144
140 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()) {
151 [varW = std::weak_ptr<Variable2> { impl->m_Variable }, tabWidget]() {
152 if (auto var = varW.lock())
153 {
147 154 tabWidget->createZone(var);
148 155 }
149 156 });
@@ -151,7 +158,8 void GenerateVariableMenuOperation::visitLeave(VisualizationTabWidget *tabWidget
151 158 // 'Unplot' menu
152 159 impl->visitNodeLeaveUnplot();
153 160 }
154 else {
161 else
162 {
155 163 qCCritical(LOG_GenerateVariableMenuOperation(),
156 164 "Can't visit leave VisualizationTabWidget : the widget is null");
157 165 }
@@ -159,11 +167,13 void GenerateVariableMenuOperation::visitLeave(VisualizationTabWidget *tabWidget
159 167
160 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 178 "Can't visit enter VisualizationZoneWidget : the widget is null");
169 179 }
@@ -171,12 +181,13 void GenerateVariableMenuOperation::visitEnter(VisualizationZoneWidget *zoneWidg
171 181
172 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,7 +195,8 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 201 "Can't visit leave VisualizationZoneWidget : the widget is null");
190 202 }
@@ -192,24 +204,28 void GenerateVariableMenuOperation::visitLeave(VisualizationZoneWidget *zoneWidg
192 204
193 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()) {
211 [varW = std::weak_ptr<Variable2> { impl->m_Variable }, graphWidget]() {
212 if (auto var = varW.lock())
213 {
200 214 graphWidget->addVariable(var, graphWidget->graphRange());
201 215 }
202 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()) {
220 [varW = std::weak_ptr<Variable2> { impl->m_Variable }, graphWidget]() {
221 if (auto var = varW.lock())
222 {
208 223 graphWidget->removeVariable(var);
209 224 }
210 225 });
211 226 }
212 else {
227 else
228 {
213 229 qCCritical(LOG_GenerateVariableMenuOperation(),
214 230 "Can't visit VisualizationGraphWidget : the widget is null");
215 231 }
@@ -1,20 +1,21
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 RemoveVariableOperation::RemoveVariableOperation(std::shared_ptr<Variable2> variable)
18 19 : impl{spimpl::make_unique_impl<RemoveVariableOperationPrivate>(variable)}
19 20 {
20 21 }
@@ -57,13 +58,16 void RemoveVariableOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
57 58
58 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 72 "Can't visit VisualizationGraphWidget : the widget is null");
69 73 }
@@ -3,17 +3,20
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)
6 struct RescaleAxeOperation::RescaleAxeOperationPrivate
7 {
8 explicit RescaleAxeOperationPrivate(
9 std::shared_ptr<Variable2> variable, const DateTimeRange& range)
8 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)
18 RescaleAxeOperation::RescaleAxeOperation(
19 std::shared_ptr<Variable2> variable, const DateTimeRange& range)
17 20 : impl{spimpl::make_unique_impl<RescaleAxeOperationPrivate>(variable, range)}
18 21 {
19 22 }
@@ -56,9 +59,11 void RescaleAxeOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
56 59
57 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,32 +1,31
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 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>
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 25 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;
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 30 for(auto i=0;i<GraphCount;i++)
32 31 {
@@ -44,7 +43,8 build_multi_graph_test()
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 50 explicit A_MultipleSyncGraphs(QObject *parent = Q_NULLPTR) : QObject(parent) {}
@@ -56,7 +56,8 private slots:
56 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 }
@@ -76,7 +77,8 private slots:
76 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 }
@@ -1,38 +1,41
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 23 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();
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 while (!isReady(var))
32 QCoreApplication::processEvents();
31 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 41 explicit A_SimpleGraph(QObject *parent = Q_NULLPTR) : QObject(parent) {}
@@ -42,7 +45,8 private slots:
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 }
@@ -59,7 +63,8 private slots:
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 }
General Comments 0
You need to be logged in to leave comments. Login now