##// END OF EJS Templates
Initialisation of the graph range at creation in a new graphe, or inside...
perrinel -
r518:5673fc6ded12
parent child
Show More
@@ -1,38 +1,40
1 1 #ifndef SCIQLOP_VISUALIZATIONGRAPHHELPER_H
2 2 #define SCIQLOP_VISUALIZATIONGRAPHHELPER_H
3 3
4 4 #include <Data/SqpRange.h>
5 5
6 6 #include <QLoggingCategory>
7 7 #include <QVector>
8 8
9 9 #include <memory>
10 10
11 11 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphHelper)
12 12
13 13 class IDataSeries;
14 14 class QCPAbstractPlottable;
15 15 class QCustomPlot;
16 16 class Variable;
17 17
18 18 /**
19 19 * @brief The VisualizationGraphHelper class aims to create the QCustomPlot components relative to a
20 20 * variable, depending on the data series of this variable
21 21 */
22 22 struct VisualizationGraphHelper {
23 23 /**
24 24 * Creates (if possible) the QCustomPlot components relative to the variable passed in
25 25 * parameter, and adds these to the plot passed in parameter.
26 26 * @param variable the variable for which to create the components
27 27 * @param plot the plot in which to add the created components. It takes ownership of these
28 28 * components.
29 29 * @return the list of the components created
30 30 */
31 31 static QVector<QCPAbstractPlottable *> create(std::shared_ptr<Variable> variable,
32 32 QCustomPlot &plot) noexcept;
33 static QVector<QCPAbstractPlottable *> createV2(std::shared_ptr<Variable> variable,
34 QCustomPlot &plot) noexcept;
33 35
34 36 static void updateData(QVector<QCPAbstractPlottable *> plotableVect,
35 37 std::shared_ptr<IDataSeries> dataSeries, const SqpRange &dateTime);
36 38 };
37 39
38 40 #endif // SCIQLOP_VISUALIZATIONGRAPHHELPER_H
@@ -1,83 +1,84
1 1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5
6 6 #include <QLoggingCategory>
7 7 #include <QWidget>
8 8
9 9 #include <memory>
10 10
11 11 #include <Common/spimpl.h>
12 12
13 13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14 14
15 15 class QCPRange;
16 16 class SqpRange;
17 17 class Variable;
18 18
19 19 namespace Ui {
20 20 class VisualizationGraphWidget;
21 21 } // namespace Ui
22 22
23 23 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
24 24 Q_OBJECT
25 25
26 26 public:
27 27 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
28 28 virtual ~VisualizationGraphWidget();
29 29
30 30 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
31 31 void enableAcquisition(bool enable);
32 32
33 void addVariable(std::shared_ptr<Variable> variable);
34 void addVariableUsingGraph(std::shared_ptr<Variable> variable);
33 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
34
35 35 /// Removes a variable from the graph
36 36 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
37 37
38 38 void setRange(std::shared_ptr<Variable> variable, const SqpRange &range);
39 void setYRange(const SqpRange &range);
39 40 SqpRange graphRange() const noexcept;
40 41 void setGraphRange(const SqpRange &range);
41 42
42 43 // IVisualizationWidget interface
43 44 void accept(IVisualizationWidgetVisitor *visitor) override;
44 45 bool canDrop(const Variable &variable) const override;
45 46 bool contains(const Variable &variable) const override;
46 47 QString name() const override;
47 48
48 49
49 50 signals:
50 51 void synchronize(const SqpRange &range, const SqpRange &oldRange);
51 52 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
52 53 const SqpRange &oldRange, bool synchronise);
53 54
54 55
55 56 void variableAdded(std::shared_ptr<Variable> var);
56 57
57 58
58 59 private:
59 60 Ui::VisualizationGraphWidget *ui;
60 61
61 62 class VisualizationGraphWidgetPrivate;
62 63 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
63 64
64 65 private slots:
65 66 /// Slot called when right clicking on the graph (displays a menu)
66 67 void onGraphMenuRequested(const QPoint &pos) noexcept;
67 68
68 69 /// Rescale the X axe to range parameter
69 70 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
70 71
71 72 /// Slot called when a mouse move was made
72 73 void onMouseMove(QMouseEvent *event) noexcept;
73 74 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
74 75 void onMouseWheel(QWheelEvent *event) noexcept;
75 76 /// Slot called when a mouse press was made, to activate the calibration of a graph
76 77 void onMousePress(QMouseEvent *event) noexcept;
77 78 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
78 79 void onMouseRelease(QMouseEvent *event) noexcept;
79 80
80 81 void onDataCacheVariableUpdated();
81 82 };
82 83
83 84 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,163 +1,210
1 1 #include "Visualization/VisualizationGraphHelper.h"
2 2 #include "Visualization/qcustomplot.h"
3 3
4 4 #include <Data/ScalarSeries.h>
5 5
6 6 #include <Variable/Variable.h>
7 7
8 8 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
9 9
10 10 namespace {
11 11
12 12 class SqpDataContainer : public QCPGraphDataContainer {
13 13 public:
14 14 void appendGraphData(const QCPGraphData &data) { mData.append(data); }
15 15 };
16 16
17 17
18 18 /// Format for datetimes on a axis
19 19 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
20 20
21 21 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
22 22 /// non-time data
23 23 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
24 24 {
25 25 if (isTimeAxis) {
26 26 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
27 27 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
28 28 dateTicker->setDateTimeSpec(Qt::UTC);
29 29
30 30 return dateTicker;
31 31 }
32 32 else {
33 33 // default ticker
34 34 return QSharedPointer<QCPAxisTicker>::create();
35 35 }
36 36 }
37 37
38 38 void updateScalarData(QCPAbstractPlottable *component, std::shared_ptr<ScalarSeries> scalarSeries,
39 39 const SqpRange &dateTime)
40 40 {
41 41 qCDebug(LOG_VisualizationGraphHelper()) << "TORM: updateScalarData"
42 42 << QThread::currentThread()->objectName();
43 43 if (auto qcpGraph = dynamic_cast<QCPGraph *>(component)) {
44 44 scalarSeries->lockRead();
45 45 {
46 46 const auto &xData = scalarSeries->xAxisData()->cdata();
47 47 const auto &valuesData = scalarSeries->valuesData()->cdata();
48 48
49 49 auto xDataBegin = xData.cbegin();
50 50 auto xDataEnd = xData.cend();
51 51
52 52 qCInfo(LOG_VisualizationGraphHelper()) << "TODEBUG: Current points in cache"
53 53 << xData.count();
54 54
55 55 auto sqpDataContainer = QSharedPointer<SqpDataContainer>::create();
56 56 qcpGraph->setData(sqpDataContainer);
57 57
58 58 auto lowerIt = std::lower_bound(xDataBegin, xDataEnd, dateTime.m_TStart);
59 59 auto upperIt = std::upper_bound(xDataBegin, xDataEnd, dateTime.m_TEnd);
60 60 auto distance = std::distance(xDataBegin, lowerIt);
61 61
62 62 auto valuesDataIt = valuesData.cbegin() + distance;
63 63 for (auto xAxisDataIt = lowerIt; xAxisDataIt != upperIt;
64 64 ++xAxisDataIt, ++valuesDataIt) {
65 65 sqpDataContainer->appendGraphData(QCPGraphData(*xAxisDataIt, *valuesDataIt));
66 66 }
67 67
68 68 qCInfo(LOG_VisualizationGraphHelper()) << "TODEBUG: Current points displayed"
69 69 << sqpDataContainer->size();
70 70 }
71 71 scalarSeries->unlock();
72 72
73 73
74 74 // Display all data
75 75 component->parentPlot()->replot();
76 76 }
77 77 else {
78 78 /// @todo DEBUG
79 79 }
80 80 }
81 81
82 QCPAbstractPlottable *createScalarSeriesComponentV2(std::shared_ptr<ScalarSeries> scalarSeries,
83 QCustomPlot &plot)
84 {
85 auto component = plot.addGraph();
86
87 if (component) {
88 // Axes properties
89 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
90 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
91
92 auto setAxisProperties = [](auto axis, const auto &unit) {
93 // label (unit name)
94 axis->setLabel(unit.m_Name);
95
96 // ticker (depending on the type of unit)
97 axis->setTicker(axisTicker(unit.m_TimeUnit));
98 };
99 setAxisProperties(plot.xAxis, scalarSeries->xAxisUnit());
100 setAxisProperties(plot.yAxis, scalarSeries->valuesUnit());
101 }
102 return component;
103 }
104
82 105 QCPAbstractPlottable *createScalarSeriesComponent(std::shared_ptr<ScalarSeries> scalarSeries,
83 106 QCustomPlot &plot, const SqpRange &dateTime)
84 107 {
85 108 auto component = plot.addGraph();
86 109
87 110 if (component) {
88 111 // // Graph data
89 112 component->setData(scalarSeries->xAxisData()->data(), scalarSeries->valuesData()->data(),
90 113 true);
91 114
92 115 updateScalarData(component, scalarSeries, dateTime);
93 116
94 117 // Axes properties
95 118 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
96 119 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
97 120
98 121 auto setAxisProperties = [](auto axis, const auto &unit) {
99 122 // label (unit name)
100 123 axis->setLabel(unit.m_Name);
101 124
102 125 // ticker (depending on the type of unit)
103 126 axis->setTicker(axisTicker(unit.m_TimeUnit));
104 127 };
105 128 setAxisProperties(plot.xAxis, scalarSeries->xAxisUnit());
106 129 setAxisProperties(plot.yAxis, scalarSeries->valuesUnit());
107 130
108 131 // Display all data
109 132 component->rescaleAxes();
110 133 plot.replot();
111 134 }
112 135 else {
113 136 qCDebug(LOG_VisualizationGraphHelper())
114 137 << QObject::tr("Can't create graph for the scalar series");
115 138 }
116 139
117 140 return component;
118 141 }
119 142
120 143 } // namespace
121 144
145 QVector<QCPAbstractPlottable *>
146 VisualizationGraphHelper::createV2(std::shared_ptr<Variable> variable, QCustomPlot &plot) noexcept
147 {
148 auto result = QVector<QCPAbstractPlottable *>{};
149
150 if (variable) {
151 // Gets the data series of the variable to call the creation of the right components
152 // according to its type
153 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(variable->dataSeries())) {
154 result.append(createScalarSeriesComponentV2(scalarSeries, plot));
155 }
156 else {
157 qCDebug(LOG_VisualizationGraphHelper())
158 << QObject::tr("Can't create graph plottables : unmanaged data series type");
159 }
160 }
161 else {
162 qCDebug(LOG_VisualizationGraphHelper())
163 << QObject::tr("Can't create graph plottables : the variable is null");
164 }
165
166 return result;
167 }
168
122 169 QVector<QCPAbstractPlottable *> VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
123 170 QCustomPlot &plot) noexcept
124 171 {
125 172 auto result = QVector<QCPAbstractPlottable *>{};
126 173
127 174 if (variable) {
128 175 // Gets the data series of the variable to call the creation of the right components
129 176 // according to its type
130 177 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(variable->dataSeries())) {
131 178 result.append(createScalarSeriesComponent(scalarSeries, plot, variable->range()));
132 179 }
133 180 else {
134 181 qCDebug(LOG_VisualizationGraphHelper())
135 182 << QObject::tr("Can't create graph plottables : unmanaged data series type");
136 183 }
137 184 }
138 185 else {
139 186 qCDebug(LOG_VisualizationGraphHelper())
140 187 << QObject::tr("Can't create graph plottables : the variable is null");
141 188 }
142 189
143 190 return result;
144 191 }
145 192
146 193 void VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *> plotableVect,
147 194 std::shared_ptr<IDataSeries> dataSeries,
148 195 const SqpRange &dateTime)
149 196 {
150 197 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
151 198 if (plotableVect.size() == 1) {
152 199 updateScalarData(plotableVect.at(0), scalarSeries, dateTime);
153 200 }
154 201 else {
155 202 qCCritical(LOG_VisualizationGraphHelper()) << QObject::tr(
156 203 "Can't update Data of a scalarSeries because there is not only one component "
157 204 "associated");
158 205 }
159 206 }
160 207 else {
161 208 /// @todo DEBUG
162 209 }
163 210 }
@@ -1,307 +1,307
1 1 #include "Visualization/VisualizationGraphWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "Visualization/VisualizationGraphHelper.h"
4 4 #include "Visualization/VisualizationGraphRenderingDelegate.h"
5 5 #include "ui_VisualizationGraphWidget.h"
6 6
7 7 #include <Data/ArrayData.h>
8 8 #include <Data/IDataSeries.h>
9 9 #include <Settings/SqpSettingsDefs.h>
10 10 #include <SqpApplication.h>
11 11 #include <Variable/Variable.h>
12 12 #include <Variable/VariableController.h>
13 13
14 14 #include <unordered_map>
15 15
16 16 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
17 17
18 18 namespace {
19 19
20 20 /// Key pressed to enable zoom on horizontal axis
21 21 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
22 22
23 23 /// Key pressed to enable zoom on vertical axis
24 24 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
25 25
26 26 } // namespace
27 27
28 28 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
29 29
30 30 explicit VisualizationGraphWidgetPrivate()
31 31 : m_DoAcquisition{true}, m_IsCalibration{false}, m_RenderingDelegate{nullptr}
32 32 {
33 33 }
34 34
35 35 // 1 variable -> n qcpplot
36 36 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
37 37 bool m_DoAcquisition;
38 38 bool m_IsCalibration;
39 39 QCPItemTracer *m_TextTracer;
40 40 /// Delegate used to attach rendering features to the plot
41 41 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
42 42 };
43 43
44 44 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
45 45 : QWidget{parent},
46 46 ui{new Ui::VisualizationGraphWidget},
47 47 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
48 48 {
49 49 ui->setupUi(this);
50 50
51 51 // The delegate must be initialized after the ui as it uses the plot
52 52 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*ui->widget);
53 53
54 54 ui->graphNameLabel->setText(name);
55 55
56 56 // 'Close' options : widget is deleted when closed
57 57 setAttribute(Qt::WA_DeleteOnClose);
58 58 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
59 59 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
60 60
61 61 // Set qcpplot properties :
62 62 // - Drag (on x-axis) and zoom are enabled
63 63 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
64 64 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
65 65 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
66 66
67 67 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
68 68 connect(ui->widget, &QCustomPlot::mouseRelease, this,
69 69 &VisualizationGraphWidget::onMouseRelease);
70 70 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
71 71 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
72 72 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
73 73 &QCPAxis::rangeChanged),
74 74 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
75 75
76 76 // Activates menu when right clicking on the graph
77 77 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
78 78 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
79 79 &VisualizationGraphWidget::onGraphMenuRequested);
80 80
81 81 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
82 82 &VariableController::onRequestDataLoading);
83 83 }
84 84
85 85
86 86 VisualizationGraphWidget::~VisualizationGraphWidget()
87 87 {
88 88 delete ui;
89 89 }
90 90
91 91 void VisualizationGraphWidget::enableAcquisition(bool enable)
92 92 {
93 93 impl->m_DoAcquisition = enable;
94 94 }
95 95
96 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
96 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
97 97 {
98 auto calibrationState = impl->m_IsCalibration;
99 impl->m_IsCalibration = true;
100 98 // Uses delegate to create the qcpplot components according to the variable
101 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
102 impl->m_IsCalibration = calibrationState;
99 auto createdPlottables = VisualizationGraphHelper::createV2(variable, *ui->widget);
103 100
104 101 for (auto createdPlottable : qAsConst(createdPlottables)) {
105 102 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
106 103 }
107 104
108 105 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
109 106
110 emit variableAdded(variable);
111 }
112 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
113 {
114 // Uses delegate to create the qcpplot components according to the variable
115 this->addVariable(variable);
107 auto varRange = variable->range();
116 108
117 // Request range for the variable
118 auto graphRange = ui->widget->xAxis->range();
109 this->enableAcquisition(false);
110 this->setGraphRange(range);
111 this->enableAcquisition(true);
119 112
120 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable,
121 SqpRange{graphRange.lower, graphRange.upper}, variable->range(), false);
113 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, varRange,
114 false);
115
116 emit variableAdded(variable);
122 117 }
123 118
124 119 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
125 120 {
126 121 // Each component associated to the variable :
127 122 // - is removed from qcpplot (which deletes it)
128 123 // - is no longer referenced in the map
129 124 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
130 125 for (auto it = componentsIt.first; it != componentsIt.second;) {
131 126 ui->widget->removePlottable(it->second);
132 127 it = impl->m_VariableToPlotMultiMap.erase(it);
133 128 }
134 129
135 130 // Updates graph
136 131 ui->widget->replot();
137 132 }
138 133
139 134 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable, const SqpRange &range)
140 135 {
141 136 // Note: in case of different axes that depends on variable, we could start with a code like
142 137 // that:
143 138 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
144 139 // for (auto it = componentsIt.first; it != componentsIt.second;) {
145 140 // }
146 141 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
147 142 ui->widget->replot();
148 143 }
149 144
145 void VisualizationGraphWidget::setYRange(const SqpRange &range)
146 {
147 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
148 }
149
150 150 SqpRange VisualizationGraphWidget::graphRange() const noexcept
151 151 {
152 152 auto graphRange = ui->widget->xAxis->range();
153 153 return SqpRange{graphRange.lower, graphRange.upper};
154 154 }
155 155
156 156 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
157 157 {
158 158 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
159 159 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
160 160 ui->widget->replot();
161 161 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
162 162 }
163 163
164 164 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
165 165 {
166 166 if (visitor) {
167 167 visitor->visit(this);
168 168 }
169 169 else {
170 170 qCCritical(LOG_VisualizationGraphWidget())
171 171 << tr("Can't visit widget : the visitor is null");
172 172 }
173 173 }
174 174
175 175 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
176 176 {
177 177 /// @todo : for the moment, a graph can always accomodate a variable
178 178 Q_UNUSED(variable);
179 179 return true;
180 180 }
181 181
182 182 bool VisualizationGraphWidget::contains(const Variable &variable) const
183 183 {
184 184 // Finds the variable among the keys of the map
185 185 auto variablePtr = &variable;
186 186 auto findVariable
187 187 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
188 188
189 189 auto end = impl->m_VariableToPlotMultiMap.cend();
190 190 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
191 191 return it != end;
192 192 }
193 193
194 194 QString VisualizationGraphWidget::name() const
195 195 {
196 196 return ui->graphNameLabel->text();
197 197 }
198 198
199 199 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
200 200 {
201 201 QMenu graphMenu{};
202 202
203 203 // Iterates on variables (unique keys)
204 204 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
205 205 end = impl->m_VariableToPlotMultiMap.cend();
206 206 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
207 207 // 'Remove variable' action
208 208 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
209 209 [ this, var = it->first ]() { removeVariable(var); });
210 210 }
211 211
212 212 if (!graphMenu.isEmpty()) {
213 213 graphMenu.exec(mapToGlobal(pos));
214 214 }
215 215 }
216 216
217 217 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
218 218 {
219 219 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
220 220 << QThread::currentThread()->objectName() << "DoAcqui"
221 221 << impl->m_DoAcquisition;
222 222
223 223 auto graphRange = SqpRange{t1.lower, t1.upper};
224 224 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
225 225
226 226 if (impl->m_DoAcquisition) {
227 227 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
228 228
229 229 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
230 230 end = impl->m_VariableToPlotMultiMap.end();
231 231 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
232 232 variableUnderGraphVector.push_back(it->first);
233 233 }
234 234 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange, oldGraphRange,
235 235 !impl->m_IsCalibration);
236 236
237 237 if (!impl->m_IsCalibration) {
238 238 qCDebug(LOG_VisualizationGraphWidget())
239 239 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
240 240 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
241 241 emit synchronize(graphRange, oldGraphRange);
242 242 }
243 243 }
244 244 }
245 245
246 246 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
247 247 {
248 248 // Handles plot rendering when mouse is moving
249 249 impl->m_RenderingDelegate->onMouseMove(event);
250 250 }
251 251
252 252 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
253 253 {
254 254 auto zoomOrientations = QFlags<Qt::Orientation>{};
255 255
256 256 // Lambda that enables a zoom orientation if the key modifier related to this orientation
257 257 // has
258 258 // been pressed
259 259 auto enableOrientation
260 260 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
261 261 auto orientationEnabled = event->modifiers().testFlag(modifier);
262 262 zoomOrientations.setFlag(orientation, orientationEnabled);
263 263 };
264 264 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
265 265 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
266 266
267 267 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
268 268 }
269 269
270 270 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
271 271 {
272 272 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
273 273 }
274 274
275 275 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
276 276 {
277 277 impl->m_IsCalibration = false;
278 278 }
279 279
280 280 void VisualizationGraphWidget::onDataCacheVariableUpdated()
281 281 {
282 282 // NOTE:
283 283 // We don't want to call the method for each component of a variable unitarily, but for
284 284 // all
285 285 // its components at once (eg its three components in the case of a vector).
286 286
287 287 // The unordered_multimap does not do this easily, so the question is whether to:
288 288 // - use an ordered_multimap and the algos of std to group the values by key
289 289 // - use a map (unique keys) and store as values directly the list of components
290 290
291 291 auto graphRange = ui->widget->xAxis->range();
292 292 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
293 293
294 294 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
295 295 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
296 296 auto variable = it->first;
297 297 qCDebug(LOG_VisualizationGraphWidget())
298 298 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
299 299 qCDebug(LOG_VisualizationGraphWidget())
300 300 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
301 301 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
302 302
303 303 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
304 304 variable->dataSeries(), variable->range());
305 305 }
306 306 }
307 307 }
@@ -1,225 +1,244
1 1 #include "Visualization/VisualizationZoneWidget.h"
2 2
3 3
4 4 #include "Visualization/IVisualizationWidgetVisitor.h"
5 5 #include "Visualization/VisualizationGraphWidget.h"
6 6 #include "ui_VisualizationZoneWidget.h"
7 7
8 8 #include <Data/SqpRange.h>
9 #include <Variable/Variable.h>
9 10 #include <Variable/VariableController.h>
10 11
11 12 #include <QUuid>
12 13 #include <SqpApplication.h>
13 14
14 15 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
15 16
16 17 namespace {
17 18
18 19 /// Minimum height for graph added in zones (in pixels)
19 20 const auto GRAPH_MINIMUM_HEIGHT = 300;
20 21
21 22 /// Generates a default name for a new graph, according to the number of graphs already displayed in
22 23 /// the zone
23 24 QString defaultGraphName(const QLayout &layout)
24 25 {
25 26 auto count = 0;
26 27 for (auto i = 0; i < layout.count(); ++i) {
27 28 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
28 29 count++;
29 30 }
30 31 }
31 32
32 33 return QObject::tr("Graph %1").arg(count + 1);
33 34 }
34 35
35 36 } // namespace
36 37
37 38 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
38 39
39 40 explicit VisualizationZoneWidgetPrivate() : m_SynchronisationGroupId{QUuid::createUuid()} {}
40 41 QUuid m_SynchronisationGroupId;
41 42 };
42 43
43 44 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
44 45 : QWidget{parent},
45 46 ui{new Ui::VisualizationZoneWidget},
46 47 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
47 48 {
48 49 ui->setupUi(this);
49 50
50 51 ui->zoneNameLabel->setText(name);
51 52
52 53 // 'Close' options : widget is deleted when closed
53 54 setAttribute(Qt::WA_DeleteOnClose);
54 55 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
55 56 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
56 57
57 58 // Synchronisation id
58 59 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
59 60 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
60 61 }
61 62
62 63 VisualizationZoneWidget::~VisualizationZoneWidget()
63 64 {
64 65 delete ui;
65 66 }
66 67
67 68 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
68 69 {
69 70 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
70 71 }
71 72
72 73 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
73 74 {
74 75 auto graphWidget = new VisualizationGraphWidget{
75 76 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
76 77
77 78
78 79 // Set graph properties
79 80 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
80 81 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
81 82
82 83
83 84 // Lambda to synchronize zone widget
84 85 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
85 86 const SqpRange &oldGraphRange) {
86 87
87 88 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
88 89 auto frameLayout = ui->visualizationZoneFrame->layout();
89 90 for (auto i = 0; i < frameLayout->count(); ++i) {
90 91 auto graphChild
91 92 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
92 93 if (graphChild && (graphChild != graphWidget)) {
93 94
94 95 auto graphChildRange = graphChild->graphRange();
95 96 switch (zoomType) {
96 97 case AcquisitionZoomType::ZoomIn: {
97 98 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
98 99 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
99 100 graphChildRange.m_TStart += deltaLeft;
100 101 graphChildRange.m_TEnd -= deltaRight;
101 102 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
102 103 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
103 104 << deltaLeft;
104 105 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
105 106 << deltaRight;
106 107 qCCritical(LOG_VisualizationZoneWidget())
107 108 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
108 109
109 110 break;
110 111 }
111 112
112 113 case AcquisitionZoomType::ZoomOut: {
113 114 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
114 115 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
115 116 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
116 117 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
117 118 << deltaLeft;
118 119 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
119 120 << deltaRight;
120 121 qCCritical(LOG_VisualizationZoneWidget())
121 122 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
122 123 graphChildRange.m_TStart -= deltaLeft;
123 124 graphChildRange.m_TEnd += deltaRight;
124 125 break;
125 126 }
126 127 case AcquisitionZoomType::PanRight: {
127 128 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
128 129 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
129 130 graphChildRange.m_TStart += deltaRight;
130 131 graphChildRange.m_TEnd += deltaRight;
131 132 qCCritical(LOG_VisualizationZoneWidget())
132 133 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
133 134 break;
134 135 }
135 136 case AcquisitionZoomType::PanLeft: {
136 137 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
137 138 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
138 139 graphChildRange.m_TStart -= deltaLeft;
139 140 graphChildRange.m_TEnd -= deltaLeft;
140 141 break;
141 142 }
142 143 case AcquisitionZoomType::Unknown: {
143 144 qCCritical(LOG_VisualizationZoneWidget())
144 145 << tr("Impossible to synchronize: zoom type unknown");
145 146 break;
146 147 }
147 148 default:
148 149 qCCritical(LOG_VisualizationZoneWidget())
149 150 << tr("Impossible to synchronize: zoom type not take into account");
150 151 // No action
151 152 break;
152 153 }
153 154 graphChild->enableAcquisition(false);
154 155 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
155 156 << graphChild->graphRange();
156 157 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
157 158 << graphChildRange;
158 159 qCCritical(LOG_VisualizationZoneWidget())
159 160 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
160 161 graphChild->setGraphRange(graphChildRange);
161 162 graphChild->enableAcquisition(true);
162 163 }
163 164 }
164 165 };
165 166
166 167 // connection for synchronization
167 168 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
168 169 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
169 170 &VisualizationZoneWidget::onVariableAdded);
170 171
172 auto range = SqpRange{};
173
174 // Apply visitor to graph children
175 auto layout = ui->visualizationZoneFrame->layout();
176 if (layout->count() > 0) {
177 // Case of a new graph in a existant zone
178 if (auto visualizationGraphWidget
179 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
180 range = visualizationGraphWidget->graphRange();
181 }
182 }
183 else {
184 // Case of a new graph as the first of the zone
185 range = variable->range();
186 }
187
171 188 this->addGraph(graphWidget);
172 189
173 graphWidget->addVariable(variable);
190 graphWidget->addVariable(variable, range);
191 // TODO: get y using variable range
192 graphWidget->setYRange(SqpRange{-10, 10});
174 193
175 194 return graphWidget;
176 195 }
177 196
178 197 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
179 198 {
180 199 if (visitor) {
181 200 visitor->visitEnter(this);
182 201
183 202 // Apply visitor to graph children
184 203 auto layout = ui->visualizationZoneFrame->layout();
185 204 for (auto i = 0; i < layout->count(); ++i) {
186 205 if (auto item = layout->itemAt(i)) {
187 206 // Widgets different from graphs are not visited (no action)
188 207 if (auto visualizationGraphWidget
189 208 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
190 209 visualizationGraphWidget->accept(visitor);
191 210 }
192 211 }
193 212 }
194 213
195 214 visitor->visitLeave(this);
196 215 }
197 216 else {
198 217 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
199 218 }
200 219 }
201 220
202 221 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
203 222 {
204 223 // A tab can always accomodate a variable
205 224 Q_UNUSED(variable);
206 225 return true;
207 226 }
208 227
209 228 bool VisualizationZoneWidget::contains(const Variable &variable) const
210 229 {
211 230 Q_UNUSED(variable);
212 231 return false;
213 232 }
214 233
215 234 QString VisualizationZoneWidget::name() const
216 235 {
217 236 return ui->zoneNameLabel->text();
218 237 }
219 238
220 239 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
221 240 {
222 241 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
223 242 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
224 243 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
225 244 }
@@ -1,200 +1,201
1 1 #include "Visualization/operations/GenerateVariableMenuOperation.h"
2 2 #include "Visualization/operations/MenuBuilder.h"
3 3
4 4 #include "Visualization/VisualizationGraphWidget.h"
5 5 #include "Visualization/VisualizationTabWidget.h"
6 6 #include "Visualization/VisualizationZoneWidget.h"
7 7
8 8 #include <Variable/Variable.h>
9 9
10 10 #include <QMenu>
11 11 #include <QStack>
12 12
13 13 Q_LOGGING_CATEGORY(LOG_GenerateVariableMenuOperation, "GenerateVariableMenuOperation")
14 14
15 15 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
16 16 explicit GenerateVariableMenuOperationPrivate(QMenu *menu, std::shared_ptr<Variable> variable)
17 17 : m_Variable{variable}, m_PlotMenuBuilder{menu}, m_UnplotMenuBuilder{menu}
18 18 {
19 19 }
20 20
21 21 void visitRootEnter()
22 22 {
23 23 // Creates the root menu
24 24 if (auto plotMenu
25 25 = m_PlotMenuBuilder.addMenu(QObject::tr("Plot"), QIcon{":/icones/plot.png"})) {
26 26 plotMenu->setEnabled(m_Variable && m_Variable->dataSeries() != nullptr);
27 27 }
28 28
29 29 m_UnplotMenuBuilder.addMenu(QObject::tr("Unplot"), QIcon{":/icones/unplot.png"});
30 30 }
31 31
32 32 void visitRootLeave()
33 33 {
34 34 // Closes the root menu
35 35 m_PlotMenuBuilder.closeMenu();
36 36 m_UnplotMenuBuilder.closeMenu();
37 37 }
38 38
39 39 void visitNodeEnter(const IVisualizationWidget &container)
40 40 {
41 41 // Opens a new menu associated to the node
42 42 m_PlotMenuBuilder.addMenu(container.name());
43 43 m_UnplotMenuBuilder.addMenu(container.name());
44 44 }
45 45
46 46 template <typename ActionFun>
47 47 void visitNodeLeavePlot(const IVisualizationWidget &container, const QString &actionName,
48 48 ActionFun actionFunction)
49 49 {
50 50 if (m_Variable && container.canDrop(*m_Variable)) {
51 51 m_PlotMenuBuilder.addSeparator();
52 52 m_PlotMenuBuilder.addAction(actionName, actionFunction);
53 53 }
54 54
55 55 // Closes the menu associated to the node
56 56 m_PlotMenuBuilder.closeMenu();
57 57 }
58 58
59 59 void visitNodeLeaveUnplot()
60 60 {
61 61 // Closes the menu associated to the node
62 62 m_UnplotMenuBuilder.closeMenu();
63 63 }
64 64
65 65 template <typename ActionFun>
66 66 void visitLeafPlot(const IVisualizationWidget &container, const QString &actionName,
67 67 ActionFun actionFunction)
68 68 {
69 69 if (m_Variable && container.canDrop(*m_Variable)) {
70 70 m_PlotMenuBuilder.addAction(actionName, actionFunction);
71 71 }
72 72 }
73 73
74 74 template <typename ActionFun>
75 75 void visitLeafUnplot(const IVisualizationWidget &container, const QString &actionName,
76 76 ActionFun actionFunction)
77 77 {
78 78 if (m_Variable && container.contains(*m_Variable)) {
79 79 m_UnplotMenuBuilder.addAction(actionName, actionFunction);
80 80 }
81 81 }
82 82
83 83 std::shared_ptr<Variable> m_Variable;
84 84 MenuBuilder m_PlotMenuBuilder; ///< Builder for the 'Plot' menu
85 85 MenuBuilder m_UnplotMenuBuilder; ///< Builder for the 'Unplot' menu
86 86 };
87 87
88 88 GenerateVariableMenuOperation::GenerateVariableMenuOperation(QMenu *menu,
89 89 std::shared_ptr<Variable> variable)
90 90 : impl{spimpl::make_unique_impl<GenerateVariableMenuOperationPrivate>(menu, variable)}
91 91 {
92 92 }
93 93
94 94 void GenerateVariableMenuOperation::visitEnter(VisualizationWidget *widget)
95 95 {
96 96 // VisualizationWidget is not intended to accommodate a variable
97 97 Q_UNUSED(widget)
98 98
99 99 // 'Plot' and 'Unplot' menus
100 100 impl->visitRootEnter();
101 101 }
102 102
103 103 void GenerateVariableMenuOperation::visitLeave(VisualizationWidget *widget)
104 104 {
105 105 // VisualizationWidget is not intended to accommodate a variable
106 106 Q_UNUSED(widget)
107 107
108 108 // 'Plot' and 'Unplot' menus
109 109 impl->visitRootLeave();
110 110 }
111 111
112 112 void GenerateVariableMenuOperation::visitEnter(VisualizationTabWidget *tabWidget)
113 113 {
114 114 if (tabWidget) {
115 115 // 'Plot' and 'Unplot' menus
116 116 impl->visitNodeEnter(*tabWidget);
117 117 }
118 118 else {
119 119 qCCritical(LOG_GenerateVariableMenuOperation(),
120 120 "Can't visit enter VisualizationTabWidget : the widget is null");
121 121 }
122 122 }
123 123
124 124 void GenerateVariableMenuOperation::visitLeave(VisualizationTabWidget *tabWidget)
125 125 {
126 126 if (tabWidget) {
127 127 // 'Plot' menu
128 128 impl->visitNodeLeavePlot(*tabWidget, QObject::tr("Open in a new zone"),
129 129 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, tabWidget ]() {
130 130 if (auto var = varW.lock()) {
131 131 tabWidget->createZone(var);
132 132 }
133 133 });
134 134
135 135 // 'Unplot' menu
136 136 impl->visitNodeLeaveUnplot();
137 137 }
138 138 else {
139 139 qCCritical(LOG_GenerateVariableMenuOperation(),
140 140 "Can't visit leave VisualizationTabWidget : the widget is null");
141 141 }
142 142 }
143 143
144 144 void GenerateVariableMenuOperation::visitEnter(VisualizationZoneWidget *zoneWidget)
145 145 {
146 146 if (zoneWidget) {
147 147 // 'Plot' and 'Unplot' menus
148 148 impl->visitNodeEnter(*zoneWidget);
149 149 }
150 150 else {
151 151 qCCritical(LOG_GenerateVariableMenuOperation(),
152 152 "Can't visit enter VisualizationZoneWidget : the widget is null");
153 153 }
154 154 }
155 155
156 156 void GenerateVariableMenuOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
157 157 {
158 qCCritical(LOG_GenerateVariableMenuOperation(), "Open in a new graph DETECTED !!");
158 159 if (zoneWidget) {
159 160 // 'Plot' menu
160 161 impl->visitNodeLeavePlot(
161 162 *zoneWidget, QObject::tr("Open in a new graph"),
162 163 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, zoneWidget ]() {
163 164 if (auto var = varW.lock()) {
164 165 zoneWidget->createGraph(var);
165 166 }
166 167 });
167 168
168 169 // 'Unplot' menu
169 170 impl->visitNodeLeaveUnplot();
170 171 }
171 172 else {
172 173 qCCritical(LOG_GenerateVariableMenuOperation(),
173 174 "Can't visit leave VisualizationZoneWidget : the widget is null");
174 175 }
175 176 }
176 177
177 178 void GenerateVariableMenuOperation::visit(VisualizationGraphWidget *graphWidget)
178 179 {
179 180 if (graphWidget) {
180 181 // 'Plot' menu
181 182 impl->visitLeafPlot(*graphWidget, QObject::tr("Open in %1").arg(graphWidget->name()),
182 183 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
183 184 if (auto var = varW.lock()) {
184 graphWidget->addVariableUsingGraph(var);
185 graphWidget->addVariable(var, graphWidget->graphRange());
185 186 }
186 187 });
187 188
188 189 // 'Unplot' menu
189 190 impl->visitLeafUnplot(*graphWidget, QObject::tr("Remove from %1").arg(graphWidget->name()),
190 191 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
191 192 if (auto var = varW.lock()) {
192 193 graphWidget->removeVariable(var);
193 194 }
194 195 });
195 196 }
196 197 else {
197 198 qCCritical(LOG_GenerateVariableMenuOperation(),
198 199 "Can't visit VisualizationGraphWidget : the widget is null");
199 200 }
200 201 }
@@ -1,103 +1,103
1 1 #include "CosinusProvider.h"
2 2
3 3 #include <Data/DataProviderParameters.h>
4 4 #include <Data/ScalarSeries.h>
5 5
6 6 #include <cmath>
7 7
8 8 #include <QFuture>
9 9 #include <QThread>
10 10 #include <QtConcurrent/QtConcurrent>
11 11
12 12 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
13 13
14 14 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(QUuid acqIdentifier,
15 15 const SqpRange &dataRangeRequested)
16 16 {
17 17 // TODO: Add Mutex
18 18 auto dataIndex = 0;
19 19
20 20 // Gets the timerange from the parameters
21 21 double freq = 100.0;
22 22 double start = std::ceil(dataRangeRequested.m_TStart * freq); // 100 htz
23 23 double end = std::floor(dataRangeRequested.m_TEnd * freq); // 100 htz
24 24
25 25 // We assure that timerange is valid
26 26 if (end < start) {
27 27 std::swap(start, end);
28 28 }
29 29
30 30 // Generates scalar series containing cosinus values (one value per second)
31 31 auto dataCount = end - start;
32 32
33 33 auto xAxisData = QVector<double>{};
34 34 xAxisData.resize(dataCount);
35 35
36 36 auto valuesData = QVector<double>{};
37 37 valuesData.resize(dataCount);
38 38
39 39 int progress = 0;
40 40 auto progressEnd = dataCount;
41 41 for (auto time = start; time < end; ++time, ++dataIndex) {
42 42 auto it = m_VariableToEnableProvider.find(acqIdentifier);
43 43 if (it != m_VariableToEnableProvider.end() && it.value()) {
44 44 const auto timeOnFreq = time / freq;
45 45
46 46 xAxisData.replace(dataIndex, timeOnFreq);
47 47 valuesData.replace(dataIndex, std::cos(timeOnFreq));
48 48
49 49 // progression
50 50 int currentProgress = (time - start) * 100.0 / progressEnd;
51 51 if (currentProgress != progress) {
52 52 progress = currentProgress;
53 53
54 54 emit dataProvidedProgress(acqIdentifier, progress);
55 55 }
56 56 }
57 57 else {
58 58 if (!it.value()) {
59 59 qCDebug(LOG_CosinusProvider())
60 60 << "CosinusProvider::retrieveData: ARRET De l'acquisition detectΓ©"
61 61 << end - time;
62 62 }
63 63 }
64 64 }
65 65 emit dataProvidedProgress(acqIdentifier, 0.0);
66 66
67 67 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
68 68 Unit{QStringLiteral("t"), true}, Unit{});
69 69 }
70 70
71 71 void CosinusProvider::requestDataLoading(QUuid acqIdentifier,
72 72 const DataProviderParameters &parameters)
73 73 {
74 74 // TODO: Add Mutex
75 75 m_VariableToEnableProvider[acqIdentifier] = true;
76 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataLoading"
76 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::requestDataLoading"
77 77 << QThread::currentThread()->objectName();
78 78 // NOTE: Try to use multithread if possible
79 79 const auto times = parameters.m_Times;
80 80
81 81 for (const auto &dateTime : qAsConst(times)) {
82 82 if (m_VariableToEnableProvider[acqIdentifier]) {
83 83 auto scalarSeries = this->retrieveData(acqIdentifier, dateTime);
84 qCCritical(LOG_CosinusProvider()) << "CosinusProvider::dataProvided";
84 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::dataProvided";
85 85 emit dataProvided(acqIdentifier, scalarSeries, dateTime);
86 86 }
87 87 }
88 88 }
89 89
90 90 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
91 91 {
92 92 // TODO: Add Mutex
93 93 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << acqIdentifier
94 94 << QThread::currentThread()->objectName();
95 95 auto it = m_VariableToEnableProvider.find(acqIdentifier);
96 96 if (it != m_VariableToEnableProvider.end()) {
97 97 it.value() = false;
98 98 }
99 99 else {
100 100 qCWarning(LOG_CosinusProvider())
101 101 << tr("Aborting progression of inexistant identifier detected !!!");
102 102 }
103 103 }
General Comments 1
Under Review
author

Auto status change to "Under Review"

You need to be logged in to leave comments. Login now