##// END OF EJS Templates
Merge pull request 189 from SCIQLOP-Initialisation develop...
leroux -
r448:f7cb609ac07f merge
parent child
Show More
@@ -0,0 +1,42
1 #ifndef SCIQLOP_RESCALEAXEOPERATION_H
2 #define SCIQLOP_RESCALEAXEOPERATION_H
3
4 #include "Visualization/IVisualizationWidgetVisitor.h"
5 #include <Data/SqpDateTime.h>
6
7 #include <Common/spimpl.h>
8
9 #include <QLoggingCategory>
10
11 #include <memory>
12
13 class Variable;
14
15 Q_DECLARE_LOGGING_CATEGORY(LOG_RescaleAxeOperation)
16
17 /**
18 * @brief The RescaleAxeOperation class defines an operation that traverses all of visualization
19 * widgets to remove a variable if they contain it
20 */
21 class RescaleAxeOperation : public IVisualizationWidgetVisitor {
22 public:
23 /**
24 * Ctor
25 * @param variable the variable to remove from widgets
26 */
27 explicit RescaleAxeOperation(std::shared_ptr<Variable> variable, const SqpDateTime &range);
28
29 void visitEnter(VisualizationWidget *widget) override final;
30 void visitLeave(VisualizationWidget *widget) override final;
31 void visitEnter(VisualizationTabWidget *tabWidget) override final;
32 void visitLeave(VisualizationTabWidget *tabWidget) override final;
33 void visitEnter(VisualizationZoneWidget *zoneWidget) override final;
34 void visitLeave(VisualizationZoneWidget *zoneWidget) override final;
35 void visit(VisualizationGraphWidget *graphWidget) override final;
36
37 private:
38 class RescaleAxeOperationPrivate;
39 spimpl::unique_impl_ptr<RescaleAxeOperationPrivate> impl;
40 };
41
42 #endif // SCIQLOP_RESCALEAXEOPERATION_H
@@ -0,0 +1,71
1 #include "Visualization/operations/RescaleAxeOperation.h"
2 #include "Visualization/VisualizationGraphWidget.h"
3
4 Q_LOGGING_CATEGORY(LOG_RescaleAxeOperation, "RescaleAxeOperation")
5
6 struct RescaleAxeOperation::RescaleAxeOperationPrivate {
7 explicit RescaleAxeOperationPrivate(std::shared_ptr<Variable> variable,
8 const SqpDateTime &range)
9 : m_Variable{variable}, m_Range{range}
10 {
11 }
12
13 std::shared_ptr<Variable> m_Variable;
14 SqpDateTime m_Range;
15 };
16
17 RescaleAxeOperation::RescaleAxeOperation(std::shared_ptr<Variable> variable,
18 const SqpDateTime &range)
19 : impl{spimpl::make_unique_impl<RescaleAxeOperationPrivate>(variable, range)}
20 {
21 }
22
23 void RescaleAxeOperation::visitEnter(VisualizationWidget *widget)
24 {
25 // VisualizationWidget is not intended to contain a variable
26 Q_UNUSED(widget)
27 }
28
29 void RescaleAxeOperation::visitLeave(VisualizationWidget *widget)
30 {
31 // VisualizationWidget is not intended to contain a variable
32 Q_UNUSED(widget)
33 }
34
35 void RescaleAxeOperation::visitEnter(VisualizationTabWidget *tabWidget)
36 {
37 // VisualizationTabWidget is not intended to contain a variable
38 Q_UNUSED(tabWidget)
39 }
40
41 void RescaleAxeOperation::visitLeave(VisualizationTabWidget *tabWidget)
42 {
43 // VisualizationTabWidget is not intended to contain a variable
44 Q_UNUSED(tabWidget)
45 }
46
47 void RescaleAxeOperation::visitEnter(VisualizationZoneWidget *zoneWidget)
48 {
49 // VisualizationZoneWidget is not intended to contain a variable
50 Q_UNUSED(zoneWidget)
51 }
52
53 void RescaleAxeOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
54 {
55 // VisualizationZoneWidget is not intended to contain a variable
56 Q_UNUSED(zoneWidget)
57 }
58
59 void RescaleAxeOperation::visit(VisualizationGraphWidget *graphWidget)
60 {
61 if (graphWidget) {
62 // If the widget contains the variable, rescale it
63 if (impl->m_Variable && graphWidget->contains(*impl->m_Variable)) {
64 graphWidget->setRange(impl->m_Variable, impl->m_Range);
65 }
66 }
67 else {
68 qCCritical(LOG_RescaleAxeOperation(),
69 "Can't visit VisualizationGraphWidget : the widget is null");
70 }
71 }
@@ -0,0 +1,3
1 Not Found
2
3 The requested URL /AMDA/data/WSRESULT/imf(0)-1343153090-1343153092-60.txt was not found on this server. No newline at end of file
@@ -1,265 +1,269
1 /*------------------------------------------------------------------------------
1 /*------------------------------------------------------------------------------
2 -- This file is a part of the SciQLop Software
2 -- This file is a part of the SciQLop Software
3 -- Copyright (C) 2017, Plasma Physics Laboratory - CNRS
3 -- Copyright (C) 2017, Plasma Physics Laboratory - CNRS
4 --
4 --
5 -- This program is free software; you can redistribute it and/or modify
5 -- This program is free software; you can redistribute it and/or modify
6 -- it under the terms of the GNU General Public License as published by
6 -- it under the terms of the GNU General Public License as published by
7 -- the Free Software Foundation; either version 2 of the License, or
7 -- the Free Software Foundation; either version 2 of the License, or
8 -- (at your option) any later version.
8 -- (at your option) any later version.
9 --
9 --
10 -- This program is distributed in the hope that it will be useful,
10 -- This program is distributed in the hope that it will be useful,
11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 -- GNU General Public License for more details.
13 -- GNU General Public License for more details.
14 --
14 --
15 -- You should have received a copy of the GNU General Public License
15 -- You should have received a copy of the GNU General Public License
16 -- along with this program; if not, write to the Free Software
16 -- along with this program; if not, write to the Free Software
17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 -------------------------------------------------------------------------------*/
18 -------------------------------------------------------------------------------*/
19 /*-- Author : Alexis Jeandet
19 /*-- Author : Alexis Jeandet
20 -- Mail : alexis.jeandet@member.fsf.org
20 -- Mail : alexis.jeandet@member.fsf.org
21 ----------------------------------------------------------------------------*/
21 ----------------------------------------------------------------------------*/
22 #include "MainWindow.h"
22 #include "MainWindow.h"
23 #include "ui_MainWindow.h"
23 #include "ui_MainWindow.h"
24
24
25 #include <DataSource/DataSourceController.h>
25 #include <DataSource/DataSourceController.h>
26 #include <DataSource/DataSourceWidget.h>
26 #include <DataSource/DataSourceWidget.h>
27 #include <SidePane/SqpSidePane.h>
27 #include <SidePane/SqpSidePane.h>
28 #include <SqpApplication.h>
28 #include <SqpApplication.h>
29 #include <Time/TimeController.h>
29 #include <Time/TimeController.h>
30 #include <TimeWidget/TimeWidget.h>
30 #include <TimeWidget/TimeWidget.h>
31 #include <Variable/Variable.h>
31 #include <Variable/Variable.h>
32 #include <Variable/VariableController.h>
32 #include <Variable/VariableController.h>
33 #include <Visualization/VisualizationController.h>
33 #include <Visualization/VisualizationController.h>
34
34
35 #include <QAction>
35 #include <QAction>
36 #include <QDate>
36 #include <QDate>
37 #include <QDateTime>
37 #include <QDateTime>
38 #include <QDir>
38 #include <QDir>
39 #include <QFileDialog>
39 #include <QFileDialog>
40 #include <QToolBar>
40 #include <QToolBar>
41 #include <QToolButton>
41 #include <QToolButton>
42 #include <memory.h>
42 #include <memory.h>
43
43
44 //#include <omp.h>
44 //#include <omp.h>
45 //#include <network/filedownloader.h>
45 //#include <network/filedownloader.h>
46 //#include <qlopdatabase.h>
46 //#include <qlopdatabase.h>
47 //#include <qlopsettings.h>
47 //#include <qlopsettings.h>
48 //#include <qlopgui.h>
48 //#include <qlopgui.h>
49 //#include <spacedata.h>
49 //#include <spacedata.h>
50 //#include "qlopcore.h"
50 //#include "qlopcore.h"
51 //#include "qlopcodecmanager.h"
51 //#include "qlopcodecmanager.h"
52 //#include "cdfcodec.h"
52 //#include "cdfcodec.h"
53 //#include "amdatxtcodec.h"
53 //#include "amdatxtcodec.h"
54 //#include <qlopplotmanager.h>
54 //#include <qlopplotmanager.h>
55
55
56 #include "iostream"
56 #include "iostream"
57
57
58 Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow")
58 Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow")
59
59
60 namespace {
60 namespace {
61 const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0;
61 const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0;
62 const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1;
62 const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1;
63 const auto VIEWPLITTERINDEX = 2;
63 const auto VIEWPLITTERINDEX = 2;
64 const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3;
64 const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3;
65 const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4;
65 const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4;
66 }
66 }
67
67
68 class MainWindow::MainWindowPrivate {
68 class MainWindow::MainWindowPrivate {
69 public:
69 public:
70 QSize m_LastOpenLeftInspectorSize;
70 QSize m_LastOpenLeftInspectorSize;
71 QSize m_LastOpenRightInspectorSize;
71 QSize m_LastOpenRightInspectorSize;
72 };
72 };
73
73
74 MainWindow::MainWindow(QWidget *parent)
74 MainWindow::MainWindow(QWidget *parent)
75 : QMainWindow{parent},
75 : QMainWindow{parent},
76 m_Ui{new Ui::MainWindow},
76 m_Ui{new Ui::MainWindow},
77 impl{spimpl::make_unique_impl<MainWindowPrivate>()}
77 impl{spimpl::make_unique_impl<MainWindowPrivate>()}
78 {
78 {
79 m_Ui->setupUi(this);
79 m_Ui->setupUi(this);
80
80
81 m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false);
81 m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false);
82 m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false);
82 m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false);
83
83
84
84
85 auto leftSidePane = m_Ui->leftInspectorSidePane->sidePane();
85 auto leftSidePane = m_Ui->leftInspectorSidePane->sidePane();
86 auto openLeftInspectorAction = new QAction{QIcon{
86 auto openLeftInspectorAction = new QAction{QIcon{
87 ":/icones/previous.png",
87 ":/icones/previous.png",
88 },
88 },
89 tr("Show/hide the left inspector"), this};
89 tr("Show/hide the left inspector"), this};
90
90
91
91
92 auto spacerLeftTop = new QWidget{};
92 auto spacerLeftTop = new QWidget{};
93 spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
93 spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
94
94
95 auto spacerLeftBottom = new QWidget{};
95 auto spacerLeftBottom = new QWidget{};
96 spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
96 spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
97
97
98 leftSidePane->addWidget(spacerLeftTop);
98 leftSidePane->addWidget(spacerLeftTop);
99 leftSidePane->addAction(openLeftInspectorAction);
99 leftSidePane->addAction(openLeftInspectorAction);
100 leftSidePane->addWidget(spacerLeftBottom);
100 leftSidePane->addWidget(spacerLeftBottom);
101
101
102
102
103 auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane();
103 auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane();
104 auto openRightInspectorAction = new QAction{QIcon{
104 auto openRightInspectorAction = new QAction{QIcon{
105 ":/icones/next.png",
105 ":/icones/next.png",
106 },
106 },
107 tr("Show/hide the right inspector"), this};
107 tr("Show/hide the right inspector"), this};
108
108
109 auto spacerRightTop = new QWidget{};
109 auto spacerRightTop = new QWidget{};
110 spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
110 spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
111
111
112 auto spacerRightBottom = new QWidget{};
112 auto spacerRightBottom = new QWidget{};
113 spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
113 spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
114
114
115 rightSidePane->addWidget(spacerRightTop);
115 rightSidePane->addWidget(spacerRightTop);
116 rightSidePane->addAction(openRightInspectorAction);
116 rightSidePane->addAction(openRightInspectorAction);
117 rightSidePane->addWidget(spacerRightBottom);
117 rightSidePane->addWidget(spacerRightBottom);
118
118
119 openLeftInspectorAction->setCheckable(true);
119 openLeftInspectorAction->setCheckable(true);
120 openRightInspectorAction->setCheckable(true);
120 openRightInspectorAction->setCheckable(true);
121
121
122 auto openInspector = [this](bool checked, bool right, auto action) {
122 auto openInspector = [this](bool checked, bool right, auto action) {
123
123
124 action->setIcon(QIcon{(checked xor right) ? ":/icones/next.png" : ":/icones/previous.png"});
124 action->setIcon(QIcon{(checked xor right) ? ":/icones/next.png" : ":/icones/previous.png"});
125
125
126 auto &lastInspectorSize
126 auto &lastInspectorSize
127 = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize;
127 = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize;
128
128
129 auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size()
129 auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size()
130 : m_Ui->leftMainInspectorWidget->size();
130 : m_Ui->leftMainInspectorWidget->size();
131
131
132 // Update of the last opened geometry
132 // Update of the last opened geometry
133 if (checked) {
133 if (checked) {
134 lastInspectorSize = nextInspectorSize;
134 lastInspectorSize = nextInspectorSize;
135 }
135 }
136
136
137 auto startSize = lastInspectorSize;
137 auto startSize = lastInspectorSize;
138 auto endSize = startSize;
138 auto endSize = startSize;
139 endSize.setWidth(0);
139 endSize.setWidth(0);
140
140
141 auto splitterInspectorIndex
141 auto splitterInspectorIndex
142 = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX;
142 = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX;
143
143
144 auto currentSizes = m_Ui->splitter->sizes();
144 auto currentSizes = m_Ui->splitter->sizes();
145 if (checked) {
145 if (checked) {
146 // adjust sizes individually here, e.g.
146 // adjust sizes individually here, e.g.
147 currentSizes[splitterInspectorIndex] -= lastInspectorSize.width();
147 currentSizes[splitterInspectorIndex] -= lastInspectorSize.width();
148 currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width();
148 currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width();
149 m_Ui->splitter->setSizes(currentSizes);
149 m_Ui->splitter->setSizes(currentSizes);
150 }
150 }
151 else {
151 else {
152 // adjust sizes individually here, e.g.
152 // adjust sizes individually here, e.g.
153 currentSizes[splitterInspectorIndex] += lastInspectorSize.width();
153 currentSizes[splitterInspectorIndex] += lastInspectorSize.width();
154 currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width();
154 currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width();
155 m_Ui->splitter->setSizes(currentSizes);
155 m_Ui->splitter->setSizes(currentSizes);
156 }
156 }
157
157
158 };
158 };
159
159
160
160
161 connect(openLeftInspectorAction, &QAction::triggered,
161 connect(openLeftInspectorAction, &QAction::triggered,
162 [openInspector, openLeftInspectorAction](bool checked) {
162 [openInspector, openLeftInspectorAction](bool checked) {
163 openInspector(checked, false, openLeftInspectorAction);
163 openInspector(checked, false, openLeftInspectorAction);
164 });
164 });
165 connect(openRightInspectorAction, &QAction::triggered,
165 connect(openRightInspectorAction, &QAction::triggered,
166 [openInspector, openRightInspectorAction](bool checked) {
166 [openInspector, openRightInspectorAction](bool checked) {
167 openInspector(checked, true, openRightInspectorAction);
167 openInspector(checked, true, openRightInspectorAction);
168 });
168 });
169
169
170 this->menuBar()->addAction(tr("File"));
170 this->menuBar()->addAction(tr("File"));
171 auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar"));
171 auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar"));
172
172
173 auto timeWidget = new TimeWidget{};
173 auto timeWidget = new TimeWidget{};
174 mainToolBar->addWidget(timeWidget);
174 mainToolBar->addWidget(timeWidget);
175
175
176 // Controllers / controllers connections
176 // Controllers / controllers connections
177 connect(&sqpApp->timeController(), SIGNAL(timeUpdated(SqpDateTime)),
177 connect(&sqpApp->timeController(), SIGNAL(timeUpdated(SqpDateTime)),
178 &sqpApp->variableController(), SLOT(onDateTimeOnSelection(SqpDateTime)));
178 &sqpApp->variableController(), SLOT(onDateTimeOnSelection(SqpDateTime)));
179
179
180 // Widgets / controllers connections
180 // Widgets / controllers connections
181
181
182 // DataSource
182 // DataSource
183 connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)),
183 connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)),
184 m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem *)));
184 m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem *)));
185
185
186 // Time
186 // Time
187 connect(timeWidget, SIGNAL(timeUpdated(SqpDateTime)), &sqpApp->timeController(),
187 connect(timeWidget, SIGNAL(timeUpdated(SqpDateTime)), &sqpApp->timeController(),
188 SLOT(onTimeToUpdate(SqpDateTime)));
188 SLOT(onTimeToUpdate(SqpDateTime)));
189
189
190 // Visualization
190 // Visualization
191 connect(&sqpApp->visualizationController(),
191 connect(&sqpApp->visualizationController(),
192 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), m_Ui->view,
192 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), m_Ui->view,
193 SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable>)));
193 SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable>)));
194
194
195 connect(&sqpApp->visualizationController(),
196 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpDateTime &)), m_Ui->view,
197 SLOT(onRangeChanged(std::shared_ptr<Variable>, const SqpDateTime &)));
198
195 // Widgets / widgets connections
199 // Widgets / widgets connections
196
200
197 // For the following connections, we use DirectConnection to allow each widget that can
201 // For the following connections, we use DirectConnection to allow each widget that can
198 // potentially attach a menu to the variable's menu to do so before this menu is displayed.
202 // potentially attach a menu to the variable's menu to do so before this menu is displayed.
199 // The order of connections is also important, since it determines the order in which each
203 // The order of connections is also important, since it determines the order in which each
200 // widget will attach its menu
204 // widget will attach its menu
201 connect(
205 connect(
202 m_Ui->variableInspectorWidget,
206 m_Ui->variableInspectorWidget,
203 SIGNAL(tableMenuAboutToBeDisplayed(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
207 SIGNAL(tableMenuAboutToBeDisplayed(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
204 m_Ui->view, SLOT(attachVariableMenu(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
208 m_Ui->view, SLOT(attachVariableMenu(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
205 Qt::DirectConnection);
209 Qt::DirectConnection);
206
210
207 /* QLopGUI::registerMenuBar(menuBar());
211 /* QLopGUI::registerMenuBar(menuBar());
208 this->setWindowIcon(QIcon(":/sciqlopLOGO.svg"));
212 this->setWindowIcon(QIcon(":/sciqlopLOGO.svg"));
209 this->m_progressWidget = new QWidget();
213 this->m_progressWidget = new QWidget();
210 this->m_progressLayout = new QVBoxLayout(this->m_progressWidget);
214 this->m_progressLayout = new QVBoxLayout(this->m_progressWidget);
211 this->m_progressWidget->setLayout(this->m_progressLayout);
215 this->m_progressWidget->setLayout(this->m_progressLayout);
212 this->m_progressWidget->setWindowModality(Qt::WindowModal);
216 this->m_progressWidget->setWindowModality(Qt::WindowModal);
213 m_progressThreadIds = (int*) malloc(OMP_THREADS*sizeof(int));
217 m_progressThreadIds = (int*) malloc(OMP_THREADS*sizeof(int));
214 for(int i=0;i<OMP_THREADS;i++)
218 for(int i=0;i<OMP_THREADS;i++)
215 {
219 {
216 this->m_progress.append(new QProgressBar(this->m_progressWidget));
220 this->m_progress.append(new QProgressBar(this->m_progressWidget));
217 this->m_progress.last()->setMinimum(0);
221 this->m_progress.last()->setMinimum(0);
218 this->m_progress.last()->setMaximum(100);
222 this->m_progress.last()->setMaximum(100);
219 this->m_progressLayout->addWidget(this->m_progress.last());
223 this->m_progressLayout->addWidget(this->m_progress.last());
220 this->m_progressWidget->hide();
224 this->m_progressWidget->hide();
221 this->m_progressThreadIds[i] = -1;
225 this->m_progressThreadIds[i] = -1;
222 }
226 }
223 this->m_progressWidget->setWindowTitle("Loading File");
227 this->m_progressWidget->setWindowTitle("Loading File");
224 const QList<QLopService*>ServicesToLoad=QList<QLopService*>()
228 const QList<QLopService*>ServicesToLoad=QList<QLopService*>()
225 << QLopCore::self()
229 << QLopCore::self()
226 << QLopPlotManager::self()
230 << QLopPlotManager::self()
227 << QLopCodecManager::self()
231 << QLopCodecManager::self()
228 << FileDownloader::self()
232 << FileDownloader::self()
229 << QLopDataBase::self()
233 << QLopDataBase::self()
230 << SpaceData::self();
234 << SpaceData::self();
231
235
232 CDFCodec::registerToManager();
236 CDFCodec::registerToManager();
233 AMDATXTCodec::registerToManager();
237 AMDATXTCodec::registerToManager();
234
238
235
239
236 for(int i=0;i<ServicesToLoad.count();i++)
240 for(int i=0;i<ServicesToLoad.count();i++)
237 {
241 {
238 qDebug()<<ServicesToLoad.at(i)->serviceName();
242 qDebug()<<ServicesToLoad.at(i)->serviceName();
239 ServicesToLoad.at(i)->initialize(); //must be called before getGUI
243 ServicesToLoad.at(i)->initialize(); //must be called before getGUI
240 QDockWidget* wdgt=ServicesToLoad.at(i)->getGUI();
244 QDockWidget* wdgt=ServicesToLoad.at(i)->getGUI();
241 if(wdgt)
245 if(wdgt)
242 {
246 {
243 wdgt->setAllowedAreas(Qt::AllDockWidgetAreas);
247 wdgt->setAllowedAreas(Qt::AllDockWidgetAreas);
244 this->addDockWidget(Qt::TopDockWidgetArea,wdgt);
248 this->addDockWidget(Qt::TopDockWidgetArea,wdgt);
245 }
249 }
246 PythonQt::self()->getMainModule().addObject(ServicesToLoad.at(i)->serviceName(),(QObject*)ServicesToLoad.at(i));
250 PythonQt::self()->getMainModule().addObject(ServicesToLoad.at(i)->serviceName(),(QObject*)ServicesToLoad.at(i));
247 }*/
251 }*/
248 }
252 }
249
253
250 MainWindow::~MainWindow()
254 MainWindow::~MainWindow()
251 {
255 {
252 }
256 }
253
257
254
258
255 void MainWindow::changeEvent(QEvent *e)
259 void MainWindow::changeEvent(QEvent *e)
256 {
260 {
257 QMainWindow::changeEvent(e);
261 QMainWindow::changeEvent(e);
258 switch (e->type()) {
262 switch (e->type()) {
259 case QEvent::LanguageChange:
263 case QEvent::LanguageChange:
260 m_Ui->retranslateUi(this);
264 m_Ui->retranslateUi(this);
261 break;
265 break;
262 default:
266 default:
263 break;
267 break;
264 }
268 }
265 }
269 }
@@ -1,59 +1,72
1 #ifndef SCIQLOP_IDATAPROVIDER_H
1 #ifndef SCIQLOP_IDATAPROVIDER_H
2 #define SCIQLOP_IDATAPROVIDER_H
2 #define SCIQLOP_IDATAPROVIDER_H
3
3
4 #include <memory>
4 #include <memory>
5
5
6 #include <QObject>
6 #include <QObject>
7 #include <QUuid>
7 #include <QUuid>
8
8
9 #include <Common/MetaTypes.h>
9 #include <Common/MetaTypes.h>
10
10
11 #include <Data/SqpDateTime.h>
11 #include <Data/SqpDateTime.h>
12
12
13 #include <functional>
14
13 class DataProviderParameters;
15 class DataProviderParameters;
14 class IDataSeries;
16 class IDataSeries;
15 class QNetworkReply;
17 class QNetworkReply;
16 class QNetworkRequest;
18 class QNetworkRequest;
17
19
18 /**
20 /**
19 * @brief The IDataProvider interface aims to declare a data provider.
21 * @brief The IDataProvider interface aims to declare a data provider.
20 *
22 *
21 * A data provider is an entity that generates data and returns it according to various parameters
23 * A data provider is an entity that generates data and returns it according to various parameters
22 * (time interval, product to retrieve the data, etc.)
24 * (time interval, product to retrieve the data, etc.)
23 *
25 *
24 * @sa IDataSeries
26 * @sa IDataSeries
25 */
27 */
26 class IDataProvider : public QObject {
28 class IDataProvider : public QObject {
27
29
28 Q_OBJECT
30 Q_OBJECT
29 public:
31 public:
30 virtual ~IDataProvider() noexcept = default;
32 virtual ~IDataProvider() noexcept = default;
31
33
32 /**
34 /**
33 * @brief requestDataLoading provide datas for the data identified by identifier and parameters
35 * @brief requestDataLoading provide datas for the data identified by identifier and parameters
34 */
36 */
35 virtual void requestDataLoading(QUuid identifier, const DataProviderParameters &parameters) = 0;
37 virtual void requestDataLoading(QUuid identifier, const DataProviderParameters &parameters) = 0;
36
38
39 /**
40 * @brief requestDataAborting stop data loading of the data identified by identifier
41 */
42 virtual void requestDataAborting(QUuid identifier) = 0;
43
37 signals:
44 signals:
38 /**
45 /**
39 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
46 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
40 * identified by identifier
47 * identified by identifier
41 */
48 */
42 void dataProvided(QUuid identifier, std::shared_ptr<IDataSeries> dateSerie,
49 void dataProvided(QUuid identifier, std::shared_ptr<IDataSeries> dateSerie,
43 const SqpDateTime &dateTime);
50 const SqpDateTime &dateTime);
44
51
52 /**
53 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
54 * identified by identifier
55 */
56 void dataProvidedProgress(QUuid identifier, double progress);
57
45
58
46 /**
59 /**
47 * @brief requestConstructed send a request for the data identified by identifier
60 * @brief requestConstructed send a request for the data identified by identifier
48 * @callback is the methode call by the reply of the request when it is finished.
61 * @callback is the methode call by the reply of the request when it is finished.
49 */
62 */
50 void requestConstructed(const QNetworkRequest &request, QUuid identifier,
63 void requestConstructed(const QNetworkRequest &request, QUuid identifier,
51 std::function<void(QNetworkReply *, QUuid)> callback);
64 std::function<void(QNetworkReply *, QUuid)> callback);
52 };
65 };
53
66
54 // Required for using shared_ptr in signals/slots
67 // Required for using shared_ptr in signals/slots
55 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
68 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
56 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
69 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
57 std::function<void(QNetworkReply *, QUuid)>)
70 std::function<void(QNetworkReply *, QUuid)>)
58
71
59 #endif // SCIQLOP_IDATAPROVIDER_H
72 #endif // SCIQLOP_IDATAPROVIDER_H
@@ -1,48 +1,50
1 #ifndef SCIQLOP_DATASOURCEITEMACTION_H
1 #ifndef SCIQLOP_DATASOURCEITEMACTION_H
2 #define SCIQLOP_DATASOURCEITEMACTION_H
2 #define SCIQLOP_DATASOURCEITEMACTION_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QObject>
7 #include <QObject>
8
8
9 #include <functional>
10
9 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceItemAction)
11 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceItemAction)
10
12
11 class DataSourceItem;
13 class DataSourceItem;
12
14
13 /**
15 /**
14 * @brief The DataSourceItemAction class represents an action on a data source item.
16 * @brief The DataSourceItemAction class represents an action on a data source item.
15 *
17 *
16 * An action is a function that will be executed when the slot execute() is called.
18 * An action is a function that will be executed when the slot execute() is called.
17 */
19 */
18 class DataSourceItemAction : public QObject {
20 class DataSourceItemAction : public QObject {
19
21
20 Q_OBJECT
22 Q_OBJECT
21
23
22 public:
24 public:
23 /// Signature of the function associated to the action
25 /// Signature of the function associated to the action
24 using ExecuteFunction = std::function<void(DataSourceItem &dataSourceItem)>;
26 using ExecuteFunction = std::function<void(DataSourceItem &dataSourceItem)>;
25
27
26 /**
28 /**
27 * Ctor
29 * Ctor
28 * @param name the name of the action
30 * @param name the name of the action
29 * @param fun the function that will be called when the action is executed
31 * @param fun the function that will be called when the action is executed
30 * @sa execute()
32 * @sa execute()
31 */
33 */
32 explicit DataSourceItemAction(const QString &name, ExecuteFunction fun);
34 explicit DataSourceItemAction(const QString &name, ExecuteFunction fun);
33
35
34 QString name() const noexcept;
36 QString name() const noexcept;
35
37
36 /// Sets the data source item concerned by the action
38 /// Sets the data source item concerned by the action
37 void setDataSourceItem(DataSourceItem *dataSourceItem) noexcept;
39 void setDataSourceItem(DataSourceItem *dataSourceItem) noexcept;
38
40
39 public slots:
41 public slots:
40 /// Executes the action
42 /// Executes the action
41 void execute();
43 void execute();
42
44
43 private:
45 private:
44 class DataSourceItemActionPrivate;
46 class DataSourceItemActionPrivate;
45 spimpl::unique_impl_ptr<DataSourceItemActionPrivate> impl;
47 spimpl::unique_impl_ptr<DataSourceItemActionPrivate> impl;
46 };
48 };
47
49
48 #endif // SCIQLOP_DATASOURCEITEMACTION_H
50 #endif // SCIQLOP_DATASOURCEITEMACTION_H
@@ -1,85 +1,95
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
3
3
4 #include <Data/SqpDateTime.h>
4 #include <Data/SqpDateTime.h>
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QObject>
7 #include <QObject>
8
8
9 #include <Common/spimpl.h>
9 #include <Common/spimpl.h>
10
10
11 class IDataProvider;
11 class IDataProvider;
12 class QItemSelectionModel;
12 class QItemSelectionModel;
13 class TimeController;
13 class TimeController;
14 class Variable;
14 class Variable;
15 class VariableModel;
15 class VariableModel;
16
16
17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
18
18
19 /**
19 /**
20 * @brief The VariableController class aims to handle the variables in SciQlop.
20 * @brief The VariableController class aims to handle the variables in SciQlop.
21 */
21 */
22 class VariableController : public QObject {
22 class VariableController : public QObject {
23 Q_OBJECT
23 Q_OBJECT
24 public:
24 public:
25 explicit VariableController(QObject *parent = 0);
25 explicit VariableController(QObject *parent = 0);
26 virtual ~VariableController();
26 virtual ~VariableController();
27
27
28 VariableModel *variableModel() noexcept;
28 VariableModel *variableModel() noexcept;
29 QItemSelectionModel *variableSelectionModel() noexcept;
29 QItemSelectionModel *variableSelectionModel() noexcept;
30
30
31 void setTimeController(TimeController *timeController) noexcept;
31 void setTimeController(TimeController *timeController) noexcept;
32
32
33 /**
33 /**
34 * Deletes from the controller the variable passed in parameter.
34 * Deletes from the controller the variable passed in parameter.
35 *
35 *
36 * Delete a variable includes:
36 * Delete a variable includes:
37 * - the deletion of the various references to the variable in SciQlop
37 * - the deletion of the various references to the variable in SciQlop
38 * - the deletion of the model variable
38 * - the deletion of the model variable
39 * - the deletion of the provider associated with the variable
39 * - the deletion of the provider associated with the variable
40 * - removing the cache associated with the variable
40 * - removing the cache associated with the variable
41 *
41 *
42 * @param variable the variable to delete from the controller.
42 * @param variable the variable to delete from the controller.
43 */
43 */
44 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
44 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
45
45
46 /**
46 /**
47 * Deletes from the controller the variables passed in parameter.
47 * Deletes from the controller the variables passed in parameter.
48 * @param variables the variables to delete from the controller.
48 * @param variables the variables to delete from the controller.
49 * @sa deleteVariable()
49 * @sa deleteVariable()
50 */
50 */
51 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
51 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
52
52
53 /**
54 * @brief abort the variable retrieve data progression
55 */
56 void abortProgress(std::shared_ptr<Variable> variable);
57
53 signals:
58 signals:
54 /// Signal emitted when a variable is about to be deleted from the controller
59 /// Signal emitted when a variable is about to be deleted from the controller
55 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
60 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
56
61
62 /// Signal emitted when a data acquisition is requested on a range for a variable
63 void rangeChanged(std::shared_ptr<Variable> variable, const SqpDateTime &range);
64
57 public slots:
65 public slots:
58 /// Request the data loading of the variable whithin dateTime
66 /// Request the data loading of the variable whithin dateTime
59 void onRequestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
67 void onRequestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
60 /**
68 /**
61 * Creates a new variable and adds it to the model
69 * Creates a new variable and adds it to the model
62 * @param name the name of the new variable
70 * @param name the name of the new variable
63 * @param metadata the metadata of the new variable
71 * @param metadata the metadata of the new variable
64 * @param provider the data provider for the new variable
72 * @param provider the data provider for the new variable
65 */
73 */
66 void createVariable(const QString &name, const QVariantHash &metadata,
74 void createVariable(const QString &name, const QVariantHash &metadata,
67 std::shared_ptr<IDataProvider> provider) noexcept;
75 std::shared_ptr<IDataProvider> provider) noexcept;
68
76
69 /// Update the temporal parameters of every selected variable to dateTime
77 /// Update the temporal parameters of every selected variable to dateTime
70 void onDateTimeOnSelection(const SqpDateTime &dateTime);
78 void onDateTimeOnSelection(const SqpDateTime &dateTime);
71
79
72
80
73 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
81 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
74
82
83 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
84
75 void initialize();
85 void initialize();
76 void finalize();
86 void finalize();
77
87
78 private:
88 private:
79 void waitForFinish();
89 void waitForFinish();
80
90
81 class VariableControllerPrivate;
91 class VariableControllerPrivate;
82 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
92 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
83 };
93 };
84
94
85 #endif // SCIQLOP_VARIABLECONTROLLER_H
95 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,71 +1,79
1 #ifndef SCIQLOP_VARIABLEMODEL_H
1 #ifndef SCIQLOP_VARIABLEMODEL_H
2 #define SCIQLOP_VARIABLEMODEL_H
2 #define SCIQLOP_VARIABLEMODEL_H
3
3
4
4
5 #include <Data/SqpDateTime.h>
5 #include <Data/SqpDateTime.h>
6
6
7 #include <QAbstractTableModel>
7 #include <QAbstractTableModel>
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9
9
10 #include <Common/MetaTypes.h>
10 #include <Common/MetaTypes.h>
11 #include <Common/spimpl.h>
11 #include <Common/spimpl.h>
12
12
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
14
14
15 enum VariableRoles { ProgressRole = Qt::UserRole };
15 enum VariableRoles { ProgressRole = Qt::UserRole };
16
16
17
17
18 class IDataSeries;
18 class IDataSeries;
19 class Variable;
19 class Variable;
20
20
21 /**
21 /**
22 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
22 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
23 */
23 */
24 class VariableModel : public QAbstractTableModel {
24 class VariableModel : public QAbstractTableModel {
25 Q_OBJECT
25 public:
26 public:
26 explicit VariableModel(QObject *parent = nullptr);
27 explicit VariableModel(QObject *parent = nullptr);
27
28
28 /**
29 /**
29 * Creates a new variable in the model
30 * Creates a new variable in the model
30 * @param name the name of the new variable
31 * @param name the name of the new variable
31 * @param dateTime the dateTime of the new variable
32 * @param dateTime the dateTime of the new variable
32 * @param metadata the metadata associated to the new variable
33 * @param metadata the metadata associated to the new variable
33 * @return the pointer to the new variable
34 * @return the pointer to the new variable
34 */
35 */
35 std::shared_ptr<Variable> createVariable(const QString &name, const SqpDateTime &dateTime,
36 std::shared_ptr<Variable> createVariable(const QString &name, const SqpDateTime &dateTime,
36 const QVariantHash &metadata) noexcept;
37 const QVariantHash &metadata) noexcept;
37
38
38 /**
39 /**
39 * Deletes a variable from the model, if it exists
40 * Deletes a variable from the model, if it exists
40 * @param variable the variable to delete
41 * @param variable the variable to delete
41 */
42 */
42 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
43 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
43
44
44
45
45 std::shared_ptr<Variable> variable(int index) const;
46 std::shared_ptr<Variable> variable(int index) const;
46
47
47 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
48 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
48
49
50
49 // /////////////////////////// //
51 // /////////////////////////// //
50 // QAbstractTableModel methods //
52 // QAbstractTableModel methods //
51 // /////////////////////////// //
53 // /////////////////////////// //
52
54
53 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
55 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
54 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
56 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
55 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
57 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
56 virtual QVariant headerData(int section, Qt::Orientation orientation,
58 virtual QVariant headerData(int section, Qt::Orientation orientation,
57 int role = Qt::DisplayRole) const override;
59 int role = Qt::DisplayRole) const override;
58
60
61
62 void abortProgress(const QModelIndex &index);
63
64 signals:
65 void abortProgessRequested(std::shared_ptr<Variable> variable);
66
59 private:
67 private:
60 class VariableModelPrivate;
68 class VariableModelPrivate;
61 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
69 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
62
70
63 private slots:
71 private slots:
64 /// Slot called when data of a variable has been updated
72 /// Slot called when data of a variable has been updated
65 void onVariableUpdated() noexcept;
73 void onVariableUpdated() noexcept;
66 };
74 };
67
75
68 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
76 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
69 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
77 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
70
78
71 #endif // SCIQLOP_VARIABLEMODEL_H
79 #endif // SCIQLOP_VARIABLEMODEL_H
@@ -1,44 +1,49
1 #ifndef SCIQLOP_VISUALIZATIONCONTROLLER_H
1 #ifndef SCIQLOP_VISUALIZATIONCONTROLLER_H
2 #define SCIQLOP_VISUALIZATIONCONTROLLER_H
2 #define SCIQLOP_VISUALIZATIONCONTROLLER_H
3
3
4 #include <Data/SqpDateTime.h>
5
4 #include <QLoggingCategory>
6 #include <QLoggingCategory>
5 #include <QObject>
7 #include <QObject>
6 #include <QUuid>
8 #include <QUuid>
7
9
8 #include <Common/spimpl.h>
10 #include <Common/spimpl.h>
9
11
10 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationController)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationController)
11
13
12 class DataSourceItem;
14 class DataSourceItem;
13 class Variable;
15 class Variable;
14
16
15 /**
17 /**
16 * @brief The VisualizationController class aims to make the link between SciQlop and its plugins.
18 * @brief The VisualizationController class aims to make the link between SciQlop and its plugins.
17 * This is the intermediate class that SciQlop has to use in the way to connect a data source.
19 * This is the intermediate class that SciQlop has to use in the way to connect a data source.
18 * Please first use register method to initialize a plugin specified by its metadata name (JSON
20 * Please first use register method to initialize a plugin specified by its metadata name (JSON
19 * plugin source) then others specifics method will be able to access it. You can load a data source
21 * plugin source) then others specifics method will be able to access it. You can load a data source
20 * driver plugin then create a data source.
22 * driver plugin then create a data source.
21 */
23 */
22 class VisualizationController : public QObject {
24 class VisualizationController : public QObject {
23 Q_OBJECT
25 Q_OBJECT
24 public:
26 public:
25 explicit VisualizationController(QObject *parent = 0);
27 explicit VisualizationController(QObject *parent = 0);
26 virtual ~VisualizationController();
28 virtual ~VisualizationController();
27
29
28 signals:
30 signals:
29 /// Signal emitted when a variable is about to be deleted from SciQlop
31 /// Signal emitted when a variable is about to be deleted from SciQlop
30 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
32 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
31
33
34 /// Signal emitted when a data acquisition is requested on a range for a variable
35 void rangeChanged(std::shared_ptr<Variable> variable, const SqpDateTime &range);
36
32 public slots:
37 public slots:
33 /// Manage init/end of the controller
38 /// Manage init/end of the controller
34 void initialize();
39 void initialize();
35 void finalize();
40 void finalize();
36
41
37 private:
42 private:
38 void waitForFinish();
43 void waitForFinish();
39
44
40 class VisualizationControllerPrivate;
45 class VisualizationControllerPrivate;
41 spimpl::unique_impl_ptr<VisualizationControllerPrivate> impl;
46 spimpl::unique_impl_ptr<VisualizationControllerPrivate> impl;
42 };
47 };
43
48
44 #endif // SCIQLOP_VISUALIZATIONCONTROLLER_H
49 #endif // SCIQLOP_VISUALIZATIONCONTROLLER_H
@@ -1,87 +1,133
1 #include "Network/NetworkController.h"
1 #include "Network/NetworkController.h"
2
2
3 #include <QMutex>
3 #include <QMutex>
4 #include <QNetworkAccessManager>
4 #include <QNetworkAccessManager>
5 #include <QNetworkReply>
5 #include <QNetworkReply>
6 #include <QNetworkRequest>
6 #include <QNetworkRequest>
7 #include <QReadWriteLock>
7 #include <QThread>
8 #include <QThread>
8
9
9 #include <unordered_map>
10 #include <unordered_map>
10
11
11 Q_LOGGING_CATEGORY(LOG_NetworkController, "NetworkController")
12 Q_LOGGING_CATEGORY(LOG_NetworkController, "NetworkController")
12
13
13 struct NetworkController::NetworkControllerPrivate {
14 struct NetworkController::NetworkControllerPrivate {
14 explicit NetworkControllerPrivate(NetworkController *parent) : m_WorkingMutex{} {}
15 explicit NetworkControllerPrivate(NetworkController *parent) : m_WorkingMutex{} {}
15 QMutex m_WorkingMutex;
16 QMutex m_WorkingMutex;
16
17
18 QReadWriteLock m_Lock;
17 std::unordered_map<QNetworkReply *, QUuid> m_NetworkReplyToVariableId;
19 std::unordered_map<QNetworkReply *, QUuid> m_NetworkReplyToVariableId;
18 std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
20 std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
21
22 void lockRead() { m_Lock.lockForRead(); }
23 void lockWrite() { m_Lock.lockForWrite(); }
24 void unlock() { m_Lock.unlock(); }
19 };
25 };
20
26
21 NetworkController::NetworkController(QObject *parent)
27 NetworkController::NetworkController(QObject *parent)
22 : QObject(parent), impl{spimpl::make_unique_impl<NetworkControllerPrivate>(this)}
28 : QObject(parent), impl{spimpl::make_unique_impl<NetworkControllerPrivate>(this)}
23 {
29 {
24 }
30 }
25
31
26 void NetworkController::onProcessRequested(const QNetworkRequest &request, QUuid identifier,
32 void NetworkController::onProcessRequested(const QNetworkRequest &request, QUuid identifier,
27 std::function<void(QNetworkReply *, QUuid)> callback)
33 std::function<void(QNetworkReply *, QUuid)> callback)
28 {
34 {
29 qCInfo(LOG_NetworkController()) << tr("NetworkController registered")
35 qCDebug(LOG_NetworkController()) << tr("NetworkController registered")
30 << QThread::currentThread();
36 << QThread::currentThread()->objectName();
31 auto reply = impl->m_AccessManager->get(request);
37 auto reply = impl->m_AccessManager->get(request);
32
38
33 // Store the couple reply id
39 // Store the couple reply id
40 impl->lockWrite();
34 impl->m_NetworkReplyToVariableId[reply] = identifier;
41 impl->m_NetworkReplyToVariableId[reply] = identifier;
42 impl->unlock();
35
43
36 auto onReplyFinished = [reply, this, identifier, callback]() {
44 auto onReplyFinished = [reply, this, identifier, callback]() {
37
45
38 qCInfo(LOG_NetworkController()) << tr("NetworkController onReplyFinished")
46 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished")
39 << QThread::currentThread();
47 << QThread::currentThread() << reply;
48 impl->lockRead();
40 auto it = impl->m_NetworkReplyToVariableId.find(reply);
49 auto it = impl->m_NetworkReplyToVariableId.find(reply);
50 impl->unlock();
41 if (it != impl->m_NetworkReplyToVariableId.cend()) {
51 if (it != impl->m_NetworkReplyToVariableId.cend()) {
52 impl->lockWrite();
53 impl->m_NetworkReplyToVariableId.erase(reply);
54 impl->unlock();
55 // Deletes reply
42 callback(reply, identifier);
56 callback(reply, identifier);
57 reply->deleteLater();
58
59 emit this->replyDownloadProgress(identifier, 0);
43 }
60 }
61
62 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished END")
63 << QThread::currentThread() << reply;
44 };
64 };
45
65
46 auto onReplyProgress = [reply, this](qint64 bytesRead, qint64 totalBytes) {
66 auto onReplyProgress = [reply, this](qint64 bytesRead, qint64 totalBytes) {
47
67
48 double progress = (bytesRead * 100.0) / totalBytes;
68 double progress = (bytesRead * 100.0) / totalBytes;
69 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress") << progress
70 << QThread::currentThread() << reply;
71 impl->lockRead();
49 auto it = impl->m_NetworkReplyToVariableId.find(reply);
72 auto it = impl->m_NetworkReplyToVariableId.find(reply);
73 impl->unlock();
50 if (it != impl->m_NetworkReplyToVariableId.cend()) {
74 if (it != impl->m_NetworkReplyToVariableId.cend()) {
51 emit this->replyDownloadProgress(it->second, progress);
75 emit this->replyDownloadProgress(it->second, progress);
52 }
76 }
77 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress END")
78 << QThread::currentThread() << reply;
53 };
79 };
54
80
55
81
56 connect(reply, &QNetworkReply::finished, this, onReplyFinished);
82 connect(reply, &QNetworkReply::finished, this, onReplyFinished);
57 connect(reply, &QNetworkReply::downloadProgress, this, onReplyProgress);
83 connect(reply, &QNetworkReply::downloadProgress, this, onReplyProgress);
84 qCDebug(LOG_NetworkController()) << tr("NetworkController registered END")
85 << QThread::currentThread()->objectName() << reply;
58 }
86 }
59
87
60 void NetworkController::initialize()
88 void NetworkController::initialize()
61 {
89 {
62 qCDebug(LOG_NetworkController()) << tr("NetworkController init") << QThread::currentThread();
90 qCDebug(LOG_NetworkController()) << tr("NetworkController init") << QThread::currentThread();
63 impl->m_WorkingMutex.lock();
91 impl->m_WorkingMutex.lock();
64 impl->m_AccessManager = std::make_unique<QNetworkAccessManager>();
92 impl->m_AccessManager = std::make_unique<QNetworkAccessManager>();
93
94
95 auto onReplyErrors = [this](QNetworkReply *reply, const QList<QSslError> &errors) {
96
97 qCCritical(LOG_NetworkController()) << tr("NetworkAcessManager errors: ") << errors;
98
99 };
100
101
102 connect(impl->m_AccessManager.get(), &QNetworkAccessManager::sslErrors, this, onReplyErrors);
103
65 qCDebug(LOG_NetworkController()) << tr("NetworkController init END");
104 qCDebug(LOG_NetworkController()) << tr("NetworkController init END");
66 }
105 }
67
106
68 void NetworkController::finalize()
107 void NetworkController::finalize()
69 {
108 {
70 impl->m_WorkingMutex.unlock();
109 impl->m_WorkingMutex.unlock();
71 }
110 }
72
111
73 void NetworkController::onReplyCanceled(QUuid identifier)
112 void NetworkController::onReplyCanceled(QUuid identifier)
74 {
113 {
75 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
114 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
115 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled")
116 << QThread::currentThread();
117
76
118
119 impl->lockRead();
77 auto end = impl->m_NetworkReplyToVariableId.cend();
120 auto end = impl->m_NetworkReplyToVariableId.cend();
78 auto it = std::find_if(impl->m_NetworkReplyToVariableId.cbegin(), end, findReply);
121 auto it = std::find_if(impl->m_NetworkReplyToVariableId.cbegin(), end, findReply);
122 impl->unlock();
79 if (it != end) {
123 if (it != end) {
80 it->first->abort();
124 it->first->abort();
81 }
125 }
126 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled END")
127 << QThread::currentThread();
82 }
128 }
83
129
84 void NetworkController::waitForFinish()
130 void NetworkController::waitForFinish()
85 {
131 {
86 QMutexLocker locker{&impl->m_WorkingMutex};
132 QMutexLocker locker{&impl->m_WorkingMutex};
87 }
133 }
@@ -1,90 +1,90
1 #include "Variable/Variable.h"
1 #include "Variable/Variable.h"
2
2
3 #include <Data/IDataSeries.h>
3 #include <Data/IDataSeries.h>
4 #include <Data/SqpDateTime.h>
4 #include <Data/SqpDateTime.h>
5
5
6 #include <QReadWriteLock>
6 #include <QReadWriteLock>
7 #include <QThread>
7 #include <QThread>
8
8
9 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
9 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
10
10
11 struct Variable::VariablePrivate {
11 struct Variable::VariablePrivate {
12 explicit VariablePrivate(const QString &name, const SqpDateTime &dateTime,
12 explicit VariablePrivate(const QString &name, const SqpDateTime &dateTime,
13 const QVariantHash &metadata)
13 const QVariantHash &metadata)
14 : m_Name{name}, m_DateTime{dateTime}, m_Metadata{metadata}, m_DataSeries{nullptr}
14 : m_Name{name}, m_DateTime{dateTime}, m_Metadata{metadata}, m_DataSeries{nullptr}
15 {
15 {
16 }
16 }
17
17
18 QString m_Name;
18 QString m_Name;
19
19
20 SqpDateTime m_DateTime; // The dateTime available in the view and loaded. not the cache.
20 SqpDateTime m_DateTime; // The dateTime available in the view and loaded. not the cache.
21 QVariantHash m_Metadata;
21 QVariantHash m_Metadata;
22 std::unique_ptr<IDataSeries> m_DataSeries;
22 std::unique_ptr<IDataSeries> m_DataSeries;
23 };
23 };
24
24
25 Variable::Variable(const QString &name, const SqpDateTime &dateTime, const QVariantHash &metadata)
25 Variable::Variable(const QString &name, const SqpDateTime &dateTime, const QVariantHash &metadata)
26 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
26 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
27 {
27 {
28 }
28 }
29
29
30 QString Variable::name() const noexcept
30 QString Variable::name() const noexcept
31 {
31 {
32 return impl->m_Name;
32 return impl->m_Name;
33 }
33 }
34
34
35 SqpDateTime Variable::dateTime() const noexcept
35 SqpDateTime Variable::dateTime() const noexcept
36 {
36 {
37 return impl->m_DateTime;
37 return impl->m_DateTime;
38 }
38 }
39
39
40 void Variable::setDateTime(const SqpDateTime &dateTime) noexcept
40 void Variable::setDateTime(const SqpDateTime &dateTime) noexcept
41 {
41 {
42 impl->m_DateTime = dateTime;
42 impl->m_DateTime = dateTime;
43 }
43 }
44
44
45 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
45 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
46 {
46 {
47 qCDebug(LOG_Variable()) << "Variable::setDataSeries" << QThread::currentThread()->objectName();
47 qCDebug(LOG_Variable()) << "Variable::setDataSeries" << QThread::currentThread()->objectName();
48 if (!dataSeries) {
48 if (!dataSeries) {
49 /// @todo ALX : log
49 /// @todo ALX : log
50 return;
50 return;
51 }
51 }
52
52
53 // Inits the data series of the variable
53 // Inits the data series of the variable
54 if (!impl->m_DataSeries) {
54 if (!impl->m_DataSeries) {
55 impl->m_DataSeries = dataSeries->clone();
55 impl->m_DataSeries = dataSeries->clone();
56 }
56 }
57 else {
57 else {
58 dataSeries->lockWrite();
58 dataSeries->lockWrite();
59 impl->m_DataSeries->lockWrite();
59 impl->m_DataSeries->lockWrite();
60 impl->m_DataSeries->merge(dataSeries.get());
60 impl->m_DataSeries->merge(dataSeries.get());
61 impl->m_DataSeries->unlock();
61 impl->m_DataSeries->unlock();
62 dataSeries->unlock();
62 dataSeries->unlock();
63 emit updated();
63 // emit updated();
64 }
64 }
65 }
65 }
66
66
67 IDataSeries *Variable::dataSeries() const noexcept
67 IDataSeries *Variable::dataSeries() const noexcept
68 {
68 {
69 return impl->m_DataSeries.get();
69 return impl->m_DataSeries.get();
70 }
70 }
71
71
72 QVariantHash Variable::metadata() const noexcept
72 QVariantHash Variable::metadata() const noexcept
73 {
73 {
74 return impl->m_Metadata;
74 return impl->m_Metadata;
75 }
75 }
76
76
77 bool Variable::contains(const SqpDateTime &dateTime) const noexcept
77 bool Variable::contains(const SqpDateTime &dateTime) const noexcept
78 {
78 {
79 return impl->m_DateTime.contains(dateTime);
79 return impl->m_DateTime.contains(dateTime);
80 }
80 }
81
81
82 bool Variable::intersect(const SqpDateTime &dateTime) const noexcept
82 bool Variable::intersect(const SqpDateTime &dateTime) const noexcept
83 {
83 {
84 return impl->m_DateTime.intersect(dateTime);
84 return impl->m_DateTime.intersect(dateTime);
85 }
85 }
86
86
87 bool Variable::isInside(const SqpDateTime &dateTime) const noexcept
87 bool Variable::isInside(const SqpDateTime &dateTime) const noexcept
88 {
88 {
89 return dateTime.contains(SqpDateTime{impl->m_DateTime.m_TStart, impl->m_DateTime.m_TEnd});
89 return dateTime.contains(SqpDateTime{impl->m_DateTime.m_TStart, impl->m_DateTime.m_TEnd});
90 }
90 }
@@ -1,212 +1,244
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableCacheController.h>
2 #include <Variable/VariableCacheController.h>
3 #include <Variable/VariableController.h>
3 #include <Variable/VariableController.h>
4 #include <Variable/VariableModel.h>
4 #include <Variable/VariableModel.h>
5
5
6 #include <Data/DataProviderParameters.h>
6 #include <Data/DataProviderParameters.h>
7 #include <Data/IDataProvider.h>
7 #include <Data/IDataProvider.h>
8 #include <Data/IDataSeries.h>
8 #include <Data/IDataSeries.h>
9 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
10
10
11 #include <QDateTime>
11 #include <QDateTime>
12 #include <QMutex>
12 #include <QMutex>
13 #include <QThread>
13 #include <QThread>
14 #include <QUuid>
14 #include <QUuid>
15 #include <QtCore/QItemSelectionModel>
15 #include <QtCore/QItemSelectionModel>
16
16
17 #include <unordered_map>
17 #include <unordered_map>
18
18
19 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
19 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
20
20
21 struct VariableController::VariableControllerPrivate {
21 struct VariableController::VariableControllerPrivate {
22 explicit VariableControllerPrivate(VariableController *parent)
22 explicit VariableControllerPrivate(VariableController *parent)
23 : m_WorkingMutex{},
23 : m_WorkingMutex{},
24 m_VariableModel{new VariableModel{parent}},
24 m_VariableModel{new VariableModel{parent}},
25 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
25 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
26 m_VariableCacheController{std::make_unique<VariableCacheController>()}
26 m_VariableCacheController{std::make_unique<VariableCacheController>()}
27 {
27 {
28 }
28 }
29
29
30 QMutex m_WorkingMutex;
30 QMutex m_WorkingMutex;
31 /// Variable model. The VariableController has the ownership
31 /// Variable model. The VariableController has the ownership
32 VariableModel *m_VariableModel;
32 VariableModel *m_VariableModel;
33 QItemSelectionModel *m_VariableSelectionModel;
33 QItemSelectionModel *m_VariableSelectionModel;
34
34
35
35
36 TimeController *m_TimeController{nullptr};
36 TimeController *m_TimeController{nullptr};
37 std::unique_ptr<VariableCacheController> m_VariableCacheController;
37 std::unique_ptr<VariableCacheController> m_VariableCacheController;
38
38
39 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
39 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
40 m_VariableToProviderMap;
40 m_VariableToProviderMap;
41 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifier;
41 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
42 };
42 };
43
43
44 VariableController::VariableController(QObject *parent)
44 VariableController::VariableController(QObject *parent)
45 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
45 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
46 {
46 {
47 qCDebug(LOG_VariableController()) << tr("VariableController construction")
47 qCDebug(LOG_VariableController()) << tr("VariableController construction")
48 << QThread::currentThread();
48 << QThread::currentThread();
49
50 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
51 &VariableController::onAbortProgressRequested);
49 }
52 }
50
53
51 VariableController::~VariableController()
54 VariableController::~VariableController()
52 {
55 {
53 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
56 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
54 << QThread::currentThread();
57 << QThread::currentThread();
55 this->waitForFinish();
58 this->waitForFinish();
56 }
59 }
57
60
58 VariableModel *VariableController::variableModel() noexcept
61 VariableModel *VariableController::variableModel() noexcept
59 {
62 {
60 return impl->m_VariableModel;
63 return impl->m_VariableModel;
61 }
64 }
62
65
63 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
66 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
64 {
67 {
65 return impl->m_VariableSelectionModel;
68 return impl->m_VariableSelectionModel;
66 }
69 }
67
70
68 void VariableController::setTimeController(TimeController *timeController) noexcept
71 void VariableController::setTimeController(TimeController *timeController) noexcept
69 {
72 {
70 impl->m_TimeController = timeController;
73 impl->m_TimeController = timeController;
71 }
74 }
72
75
73 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
76 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
74 {
77 {
75 if (!variable) {
78 if (!variable) {
76 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
79 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
77 return;
80 return;
78 }
81 }
79
82
80 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
83 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
81 // make some treatments before the deletion
84 // make some treatments before the deletion
82 emit variableAboutToBeDeleted(variable);
85 emit variableAboutToBeDeleted(variable);
83
86
87 // Deletes identifier
88 impl->m_VariableToIdentifierMap.erase(variable);
89
84 // Deletes provider
90 // Deletes provider
85 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
91 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
86 qCDebug(LOG_VariableController())
92 qCDebug(LOG_VariableController())
87 << tr("Number of providers deleted for variable %1: %2")
93 << tr("Number of providers deleted for variable %1: %2")
88 .arg(variable->name(), QString::number(nbProvidersDeleted));
94 .arg(variable->name(), QString::number(nbProvidersDeleted));
89
95
90 // Clears cache
96 // Clears cache
91 impl->m_VariableCacheController->clear(variable);
97 impl->m_VariableCacheController->clear(variable);
92
98
93 // Deletes from model
99 // Deletes from model
94 impl->m_VariableModel->deleteVariable(variable);
100 impl->m_VariableModel->deleteVariable(variable);
95 }
101 }
96
102
97 void VariableController::deleteVariables(
103 void VariableController::deleteVariables(
98 const QVector<std::shared_ptr<Variable> > &variables) noexcept
104 const QVector<std::shared_ptr<Variable> > &variables) noexcept
99 {
105 {
100 for (auto variable : qAsConst(variables)) {
106 for (auto variable : qAsConst(variables)) {
101 deleteVariable(variable);
107 deleteVariable(variable);
102 }
108 }
103 }
109 }
104
110
111 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
112 {
113 }
114
105 void VariableController::createVariable(const QString &name, const QVariantHash &metadata,
115 void VariableController::createVariable(const QString &name, const QVariantHash &metadata,
106 std::shared_ptr<IDataProvider> provider) noexcept
116 std::shared_ptr<IDataProvider> provider) noexcept
107 {
117 {
108
118
109 if (!impl->m_TimeController) {
119 if (!impl->m_TimeController) {
110 qCCritical(LOG_VariableController())
120 qCCritical(LOG_VariableController())
111 << tr("Impossible to create variable: The time controller is null");
121 << tr("Impossible to create variable: The time controller is null");
112 return;
122 return;
113 }
123 }
114
124
115 auto dateTime = impl->m_TimeController->dateTime();
125 auto dateTime = impl->m_TimeController->dateTime();
116
126
117 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime, metadata)) {
127 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime, metadata)) {
118 auto identifier = QUuid::createUuid();
128 auto identifier = QUuid::createUuid();
119
129
120 // store the provider
130 // store the provider
121 impl->m_VariableToProviderMap[newVariable] = provider;
131 impl->m_VariableToProviderMap[newVariable] = provider;
122 impl->m_VariableToIdentifier[newVariable] = identifier;
132 impl->m_VariableToIdentifierMap[newVariable] = identifier;
123
133
124 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
134 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
125 QUuid identifier, auto dataSeriesAcquired, auto dateTimeToPutInCache)
135 QUuid identifier, auto dataSeriesAcquired, auto dateTimeToPutInCache)
126 {
136 {
127 if (auto variable = varW.lock()) {
137 if (auto variable = varW.lock()) {
128 auto varIdentifier = impl->m_VariableToIdentifier.at(variable);
138 auto varIdentifier = impl->m_VariableToIdentifierMap.at(variable);
129 if (varIdentifier == identifier) {
139 if (varIdentifier == identifier) {
130 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
140 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
131 variable->setDataSeries(dataSeriesAcquired);
141 variable->setDataSeries(dataSeriesAcquired);
142 emit variable->updated();
132 }
143 }
133 }
144 }
134 };
145 };
135
146
136 connect(provider.get(), &IDataProvider::dataProvided, addDateTimeAcquired);
147 connect(provider.get(), &IDataProvider::dataProvided, addDateTimeAcquired);
148 connect(provider.get(), &IDataProvider::dataProvidedProgress, this,
149 &VariableController::onVariableRetrieveDataInProgress);
137 this->onRequestDataLoading(newVariable, dateTime);
150 this->onRequestDataLoading(newVariable, dateTime);
138 }
151 }
139 }
152 }
140
153
141 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
154 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
142 {
155 {
143 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
156 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
144 << QThread::currentThread()->objectName();
157 << QThread::currentThread()->objectName();
145 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
158 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
146
159
147 for (const auto &selectedRow : qAsConst(selectedRows)) {
160 for (const auto &selectedRow : qAsConst(selectedRows)) {
148 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
161 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
149 selectedVariable->setDateTime(dateTime);
162 selectedVariable->setDateTime(dateTime);
150 this->onRequestDataLoading(selectedVariable, dateTime);
163 this->onRequestDataLoading(selectedVariable, dateTime);
164
165 // notify that rescale operation has to be done
166 emit rangeChanged(selectedVariable, dateTime);
151 }
167 }
152 }
168 }
153 }
169 }
154
170
155 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
171 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
156 {
172 {
157 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
173 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
158
174
159 auto end = impl->m_VariableToIdentifier.cend();
175 auto end = impl->m_VariableToIdentifierMap.cend();
160 auto it = std::find_if(impl->m_VariableToIdentifier.cbegin(), end, findReply);
176 auto it = std::find_if(impl->m_VariableToIdentifierMap.cbegin(), end, findReply);
161 if (it != end) {
177 if (it != end) {
162 impl->m_VariableModel->setDataProgress(it->first, progress);
178 impl->m_VariableModel->setDataProgress(it->first, progress);
163 }
179 }
164 }
180 }
165
181
182 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
183 {
184 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
185 << QThread::currentThread()->objectName();
186
187 auto it = impl->m_VariableToIdentifierMap.find(variable);
188 if (it != impl->m_VariableToIdentifierMap.cend()) {
189 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
190 }
191 else {
192 qCWarning(LOG_VariableController())
193 << tr("Aborting progression of inexistant variable detected !!!")
194 << QThread::currentThread()->objectName();
195 }
196 }
197
166
198
167 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
199 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
168 const SqpDateTime &dateTime)
200 const SqpDateTime &dateTime)
169 {
201 {
170 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
202 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
171 << QThread::currentThread()->objectName();
203 << QThread::currentThread()->objectName();
172 // we want to load data of the variable for the dateTime.
204 // we want to load data of the variable for the dateTime.
173 // First we check if the cache contains some of them.
205 // First we check if the cache contains some of them.
174 // For the other, we ask the provider to give them.
206 // For the other, we ask the provider to give them.
175 if (variable) {
207 if (variable) {
176
208
177 auto dateTimeListNotInCache
209 auto dateTimeListNotInCache
178 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
210 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
179
211
180 if (!dateTimeListNotInCache.empty()) {
212 if (!dateTimeListNotInCache.empty()) {
181 // Ask the provider for each data on the dateTimeListNotInCache
213 // Ask the provider for each data on the dateTimeListNotInCache
182 auto identifier = impl->m_VariableToIdentifier.at(variable);
214 auto identifier = impl->m_VariableToIdentifierMap.at(variable);
183 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
215 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
184 identifier,
216 identifier,
185 DataProviderParameters{std::move(dateTimeListNotInCache), variable->metadata()});
217 DataProviderParameters{std::move(dateTimeListNotInCache), variable->metadata()});
186 }
218 }
187 else {
219 else {
188 emit variable->updated();
220 emit variable->updated();
189 }
221 }
190 }
222 }
191 else {
223 else {
192 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
224 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
193 }
225 }
194 }
226 }
195
227
196
228
197 void VariableController::initialize()
229 void VariableController::initialize()
198 {
230 {
199 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
231 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
200 impl->m_WorkingMutex.lock();
232 impl->m_WorkingMutex.lock();
201 qCDebug(LOG_VariableController()) << tr("VariableController init END");
233 qCDebug(LOG_VariableController()) << tr("VariableController init END");
202 }
234 }
203
235
204 void VariableController::finalize()
236 void VariableController::finalize()
205 {
237 {
206 impl->m_WorkingMutex.unlock();
238 impl->m_WorkingMutex.unlock();
207 }
239 }
208
240
209 void VariableController::waitForFinish()
241 void VariableController::waitForFinish()
210 {
242 {
211 QMutexLocker locker{&impl->m_WorkingMutex};
243 QMutexLocker locker{&impl->m_WorkingMutex};
212 }
244 }
@@ -1,235 +1,248
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableModel.h>
2 #include <Variable/VariableModel.h>
3
3
4 #include <Data/IDataSeries.h>
4 #include <Data/IDataSeries.h>
5
5
6 #include <QDateTime>
6 #include <QDateTime>
7 #include <QSize>
7 #include <QSize>
8 #include <unordered_map>
8 #include <unordered_map>
9
9
10 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
10 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
11
11
12 namespace {
12 namespace {
13
13
14 // Column indexes
14 // Column indexes
15 const auto NAME_COLUMN = 0;
15 const auto NAME_COLUMN = 0;
16 const auto TSTART_COLUMN = 1;
16 const auto TSTART_COLUMN = 1;
17 const auto TEND_COLUMN = 2;
17 const auto TEND_COLUMN = 2;
18 const auto NB_COLUMNS = 3;
18 const auto NB_COLUMNS = 3;
19
19
20 // Column properties
20 // Column properties
21 const auto DEFAULT_HEIGHT = 25;
21 const auto DEFAULT_HEIGHT = 25;
22 const auto DEFAULT_WIDTH = 100;
22 const auto DEFAULT_WIDTH = 100;
23
23
24 struct ColumnProperties {
24 struct ColumnProperties {
25 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
25 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
26 int height = DEFAULT_HEIGHT)
26 int height = DEFAULT_HEIGHT)
27 : m_Name{name}, m_Width{width}, m_Height{height}
27 : m_Name{name}, m_Width{width}, m_Height{height}
28 {
28 {
29 }
29 }
30
30
31 QString m_Name;
31 QString m_Name;
32 int m_Width;
32 int m_Width;
33 int m_Height;
33 int m_Height;
34 };
34 };
35
35
36 const auto COLUMN_PROPERTIES
36 const auto COLUMN_PROPERTIES
37 = QHash<int, ColumnProperties>{{NAME_COLUMN, {QObject::tr("Name")}},
37 = QHash<int, ColumnProperties>{{NAME_COLUMN, {QObject::tr("Name")}},
38 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
38 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
39 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}};
39 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}};
40
40
41 /// Format for datetimes
41 /// Format for datetimes
42 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
42 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
43
43
44
44
45 } // namespace
45 } // namespace
46
46
47 struct VariableModel::VariableModelPrivate {
47 struct VariableModel::VariableModelPrivate {
48 /// Variables created in SciQlop
48 /// Variables created in SciQlop
49 std::vector<std::shared_ptr<Variable> > m_Variables;
49 std::vector<std::shared_ptr<Variable> > m_Variables;
50 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
50 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
51
51
52
53 /// Return the row index of the variable. -1 if it's not found
52 /// Return the row index of the variable. -1 if it's not found
54 int indexOfVariable(Variable *variable) const noexcept;
53 int indexOfVariable(Variable *variable) const noexcept;
55 };
54 };
56
55
57 VariableModel::VariableModel(QObject *parent)
56 VariableModel::VariableModel(QObject *parent)
58 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
57 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
59 {
58 {
60 }
59 }
61
60
62 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
61 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
63 const SqpDateTime &dateTime,
62 const SqpDateTime &dateTime,
64 const QVariantHash &metadata) noexcept
63 const QVariantHash &metadata) noexcept
65 {
64 {
66 auto insertIndex = rowCount();
65 auto insertIndex = rowCount();
67 beginInsertRows({}, insertIndex, insertIndex);
66 beginInsertRows({}, insertIndex, insertIndex);
68
67
69 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
68 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
70
69
71 impl->m_Variables.push_back(variable);
70 impl->m_Variables.push_back(variable);
72 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
71 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
73
72
74 endInsertRows();
73 endInsertRows();
75
74
76 return variable;
75 return variable;
77 }
76 }
78
77
79 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
78 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
80 {
79 {
81 if (!variable) {
80 if (!variable) {
82 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
81 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
83 return;
82 return;
84 }
83 }
85
84
86 // Finds variable in the model
85 // Finds variable in the model
87 auto begin = impl->m_Variables.cbegin();
86 auto begin = impl->m_Variables.cbegin();
88 auto end = impl->m_Variables.cend();
87 auto end = impl->m_Variables.cend();
89 auto it = std::find(begin, end, variable);
88 auto it = std::find(begin, end, variable);
90 if (it != end) {
89 if (it != end) {
91 auto removeIndex = std::distance(begin, it);
90 auto removeIndex = std::distance(begin, it);
92
91
93 // Deletes variable
92 // Deletes variable
94 beginRemoveRows({}, removeIndex, removeIndex);
93 beginRemoveRows({}, removeIndex, removeIndex);
95 impl->m_Variables.erase(it);
94 impl->m_Variables.erase(it);
96 endRemoveRows();
95 endRemoveRows();
97 }
96 }
98 else {
97 else {
99 qCritical(LOG_VariableModel())
98 qCritical(LOG_VariableModel())
100 << tr("Can't delete variable %1 from the model: the variable is not in the model")
99 << tr("Can't delete variable %1 from the model: the variable is not in the model")
101 .arg(variable->name());
100 .arg(variable->name());
102 }
101 }
102
103 // Removes variable from progress map
104 impl->m_VariableToProgress.erase(variable);
103 }
105 }
104
106
105
107
106 std::shared_ptr<Variable> VariableModel::variable(int index) const
108 std::shared_ptr<Variable> VariableModel::variable(int index) const
107 {
109 {
108 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
110 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
109 }
111 }
110
112
111 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
113 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
112 {
114 {
113
115 if (progress > 0.0) {
114 impl->m_VariableToProgress[variable] = progress;
116 impl->m_VariableToProgress[variable] = progress;
117 }
118 else {
119 impl->m_VariableToProgress.erase(variable);
120 }
115 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
121 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
116
122
117 emit dataChanged(modelIndex, modelIndex);
123 emit dataChanged(modelIndex, modelIndex);
118 }
124 }
119
125
120 int VariableModel::columnCount(const QModelIndex &parent) const
126 int VariableModel::columnCount(const QModelIndex &parent) const
121 {
127 {
122 Q_UNUSED(parent);
128 Q_UNUSED(parent);
123
129
124 return NB_COLUMNS;
130 return NB_COLUMNS;
125 }
131 }
126
132
127 int VariableModel::rowCount(const QModelIndex &parent) const
133 int VariableModel::rowCount(const QModelIndex &parent) const
128 {
134 {
129 Q_UNUSED(parent);
135 Q_UNUSED(parent);
130
136
131 return impl->m_Variables.size();
137 return impl->m_Variables.size();
132 }
138 }
133
139
134 QVariant VariableModel::data(const QModelIndex &index, int role) const
140 QVariant VariableModel::data(const QModelIndex &index, int role) const
135 {
141 {
136 if (!index.isValid()) {
142 if (!index.isValid()) {
137 return QVariant{};
143 return QVariant{};
138 }
144 }
139
145
140 if (index.row() < 0 || index.row() >= rowCount()) {
146 if (index.row() < 0 || index.row() >= rowCount()) {
141 return QVariant{};
147 return QVariant{};
142 }
148 }
143
149
144 if (role == Qt::DisplayRole) {
150 if (role == Qt::DisplayRole) {
145 if (auto variable = impl->m_Variables.at(index.row()).get()) {
151 if (auto variable = impl->m_Variables.at(index.row()).get()) {
146 /// Lambda function that builds the variant to return for a time value
152 /// Lambda function that builds the variant to return for a time value
147 auto dateTimeVariant = [](double time) {
153 auto dateTimeVariant = [](double time) {
148 auto dateTime = QDateTime::fromMSecsSinceEpoch(time * 1000.);
154 auto dateTime = QDateTime::fromMSecsSinceEpoch(time * 1000.);
149 return dateTime.toString(DATETIME_FORMAT);
155 return dateTime.toString(DATETIME_FORMAT);
150 };
156 };
151
157
152 switch (index.column()) {
158 switch (index.column()) {
153 case NAME_COLUMN:
159 case NAME_COLUMN:
154 return variable->name();
160 return variable->name();
155 case TSTART_COLUMN:
161 case TSTART_COLUMN:
156 return dateTimeVariant(variable->dateTime().m_TStart);
162 return dateTimeVariant(variable->dateTime().m_TStart);
157 case TEND_COLUMN:
163 case TEND_COLUMN:
158 return dateTimeVariant(variable->dateTime().m_TEnd);
164 return dateTimeVariant(variable->dateTime().m_TEnd);
159 default:
165 default:
160 // No action
166 // No action
161 break;
167 break;
162 }
168 }
163
169
164 qWarning(LOG_VariableModel())
170 qWarning(LOG_VariableModel())
165 << tr("Can't get data (unknown column %1)").arg(index.column());
171 << tr("Can't get data (unknown column %1)").arg(index.column());
166 }
172 }
167 else {
173 else {
168 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
174 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
169 }
175 }
170 }
176 }
171 else if (role == VariableRoles::ProgressRole) {
177 else if (role == VariableRoles::ProgressRole) {
172 if (auto variable = impl->m_Variables.at(index.row())) {
178 if (auto variable = impl->m_Variables.at(index.row())) {
173
179
174 auto it = impl->m_VariableToProgress.find(variable);
180 auto it = impl->m_VariableToProgress.find(variable);
175 if (it != impl->m_VariableToProgress.cend()) {
181 if (it != impl->m_VariableToProgress.cend()) {
176 return it->second;
182 return it->second;
177 }
183 }
178 }
184 }
179 }
185 }
180
186
181 return QVariant{};
187 return QVariant{};
182 }
188 }
183
189
184 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
190 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
185 {
191 {
186 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
192 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
187 return QVariant{};
193 return QVariant{};
188 }
194 }
189
195
190 if (orientation == Qt::Horizontal) {
196 if (orientation == Qt::Horizontal) {
191 auto propertiesIt = COLUMN_PROPERTIES.find(section);
197 auto propertiesIt = COLUMN_PROPERTIES.find(section);
192 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
198 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
193 // Role is either DisplayRole or SizeHintRole
199 // Role is either DisplayRole or SizeHintRole
194 return (role == Qt::DisplayRole)
200 return (role == Qt::DisplayRole)
195 ? QVariant{propertiesIt->m_Name}
201 ? QVariant{propertiesIt->m_Name}
196 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
202 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
197 }
203 }
198 else {
204 else {
199 qWarning(LOG_VariableModel())
205 qWarning(LOG_VariableModel())
200 << tr("Can't get header data (unknown column %1)").arg(section);
206 << tr("Can't get header data (unknown column %1)").arg(section);
201 }
207 }
202 }
208 }
203
209
204 return QVariant{};
210 return QVariant{};
205 }
211 }
206
212
213 void VariableModel::abortProgress(const QModelIndex &index)
214 {
215 if (auto variable = impl->m_Variables.at(index.row())) {
216 emit abortProgessRequested(variable);
217 }
218 }
219
207 void VariableModel::onVariableUpdated() noexcept
220 void VariableModel::onVariableUpdated() noexcept
208 {
221 {
209 // Finds variable that has been updated in the model
222 // Finds variable that has been updated in the model
210 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
223 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
211 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
224 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
212
225
213 if (updatedVariableIndex > -1) {
226 if (updatedVariableIndex > -1) {
214 emit dataChanged(createIndex(updatedVariableIndex, 0),
227 emit dataChanged(createIndex(updatedVariableIndex, 0),
215 createIndex(updatedVariableIndex, columnCount() - 1));
228 createIndex(updatedVariableIndex, columnCount() - 1));
216 }
229 }
217 }
230 }
218 }
231 }
219
232
220 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
233 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
221 {
234 {
222 auto begin = std::cbegin(m_Variables);
235 auto begin = std::cbegin(m_Variables);
223 auto end = std::cend(m_Variables);
236 auto end = std::cend(m_Variables);
224 auto it
237 auto it
225 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
238 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
226
239
227 if (it != end) {
240 if (it != end) {
228 // Gets the index of the variable in the model: we assume here that views have the same
241 // Gets the index of the variable in the model: we assume here that views have the same
229 // order as the model
242 // order as the model
230 return std::distance(begin, it);
243 return std::distance(begin, it);
231 }
244 }
232 else {
245 else {
233 return -1;
246 return -1;
234 }
247 }
235 }
248 }
@@ -1,65 +1,82
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QWidget>
7 #include <QWidget>
8
8
9 #include <memory>
9 #include <memory>
10
10
11 #include <Common/spimpl.h>
11 #include <Common/spimpl.h>
12
12
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14
14
15 class QCPRange;
15 class QCPRange;
16 class SqpDateTime;
16 class SqpDateTime;
17 class Variable;
17 class Variable;
18
18
19 /**
20 * Possible types of zoom operation
21 */
22 enum class VisualizationGraphWidgetZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
23
19 namespace Ui {
24 namespace Ui {
20 class VisualizationGraphWidget;
25 class VisualizationGraphWidget;
21 } // namespace Ui
26 } // namespace Ui
22
27
23 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
28 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
24 Q_OBJECT
29 Q_OBJECT
25
30
26 public:
31 public:
27 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
32 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
28 virtual ~VisualizationGraphWidget();
33 virtual ~VisualizationGraphWidget();
29
34
35 void enableSynchronize(bool enable);
36
30 void addVariable(std::shared_ptr<Variable> variable);
37 void addVariable(std::shared_ptr<Variable> variable);
31 void addVariableUsingGraph(std::shared_ptr<Variable> variable);
38 void addVariableUsingGraph(std::shared_ptr<Variable> variable);
32 /// Removes a variable from the graph
39 /// Removes a variable from the graph
33 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
40 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
34
41
42 void setRange(std::shared_ptr<Variable> variable, const SqpDateTime &range);
43 SqpDateTime graphRange() const noexcept;
44 void setGraphRange(const SqpDateTime &range);
45
35 // IVisualizationWidget interface
46 // IVisualizationWidget interface
36 void accept(IVisualizationWidgetVisitor *visitor) override;
47 void accept(IVisualizationWidgetVisitor *visitor) override;
37 bool canDrop(const Variable &variable) const override;
48 bool canDrop(const Variable &variable) const override;
38 bool contains(const Variable &variable) const override;
49 bool contains(const Variable &variable) const override;
39 QString name() const override;
50 QString name() const override;
40
51
41 void updateDisplay(std::shared_ptr<Variable> variable);
42
52
43 signals:
53 signals:
44 void requestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
54 void requestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
55 void synchronize(const SqpDateTime &dateTime, const SqpDateTime &oldDateTime,
56 VisualizationGraphWidgetZoomType zoomType);
45
57
46
58
47 private:
59 private:
48 Ui::VisualizationGraphWidget *ui;
60 Ui::VisualizationGraphWidget *ui;
49
61
50 class VisualizationGraphWidgetPrivate;
62 class VisualizationGraphWidgetPrivate;
51 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
63 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
52
64
53 private slots:
65 private slots:
54 /// Slot called when right clicking on the graph (displays a menu)
66 /// Slot called when right clicking on the graph (displays a menu)
55 void onGraphMenuRequested(const QPoint &pos) noexcept;
67 void onGraphMenuRequested(const QPoint &pos) noexcept;
56
68
57 void onRangeChanged(const QCPRange &t1);
69 /// Rescale the X axe to range parameter
70 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
58
71
59 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
72 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
60 void onMouseWheel(QWheelEvent *event) noexcept;
73 void onMouseWheel(QWheelEvent *event) noexcept;
74 /// Slot called when a mouse press was made, to activate the calibration of a graph
75 void onMousePress(QMouseEvent *event) noexcept;
76 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
77 void onMouseRelease(QMouseEvent *event) noexcept;
61
78
62 void onDataCacheVariableUpdated();
79 void onDataCacheVariableUpdated();
63 };
80 };
64
81
65 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
82 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,48 +1,51
1 #ifndef SCIQLOP_VISUALIZATIONWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONWIDGET_H
2 #define SCIQLOP_VISUALIZATIONWIDGET_H
2 #define SCIQLOP_VISUALIZATIONWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5 #include <Data/SqpDateTime.h>
5
6
6 #include <QLoggingCategory>
7 #include <QLoggingCategory>
7 #include <QWidget>
8 #include <QWidget>
8
9
9 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationWidget)
10 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationWidget)
10
11
11 class QMenu;
12 class QMenu;
12 class Variable;
13 class Variable;
13 class VisualizationTabWidget;
14 class VisualizationTabWidget;
14
15
15 namespace Ui {
16 namespace Ui {
16 class VisualizationWidget;
17 class VisualizationWidget;
17 } // namespace Ui
18 } // namespace Ui
18
19
19 class VisualizationWidget : public QWidget, public IVisualizationWidget {
20 class VisualizationWidget : public QWidget, public IVisualizationWidget {
20 Q_OBJECT
21 Q_OBJECT
21
22
22 public:
23 public:
23 explicit VisualizationWidget(QWidget *parent = 0);
24 explicit VisualizationWidget(QWidget *parent = 0);
24 virtual ~VisualizationWidget();
25 virtual ~VisualizationWidget();
25
26
26 // IVisualizationWidget interface
27 // IVisualizationWidget interface
27 void accept(IVisualizationWidgetVisitor *visitor) override;
28 void accept(IVisualizationWidgetVisitor *visitor) override;
28 bool canDrop(const Variable &variable) const override;
29 bool canDrop(const Variable &variable) const override;
29 bool contains(const Variable &variable) const override;
30 bool contains(const Variable &variable) const override;
30 QString name() const override;
31 QString name() const override;
31
32
32 public slots:
33 public slots:
33 /**
34 /**
34 * Attaches to a menu the menu relative to the visualization of variables
35 * Attaches to a menu the menu relative to the visualization of variables
35 * @param menu the parent menu of the generated menu
36 * @param menu the parent menu of the generated menu
36 * @param variables the variables for which to generate the menu
37 * @param variables the variables for which to generate the menu
37 */
38 */
38 void attachVariableMenu(QMenu *menu,
39 void attachVariableMenu(QMenu *menu,
39 const QVector<std::shared_ptr<Variable> > &variables) noexcept;
40 const QVector<std::shared_ptr<Variable> > &variables) noexcept;
40
41
41 /// Slot called when a variable is about to be deleted from SciQlop
42 /// Slot called when a variable is about to be deleted from SciQlop
42 void onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept;
43 void onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept;
43
44
45 void onRangeChanged(std::shared_ptr<Variable> variable, const SqpDateTime &range) noexcept;
46
44 private:
47 private:
45 Ui::VisualizationWidget *ui;
48 Ui::VisualizationWidget *ui;
46 };
49 };
47
50
48 #endif // VISUALIZATIONWIDGET_H
51 #endif // VISUALIZATIONWIDGET_H
@@ -1,147 +1,151
1 #include "SqpApplication.h"
1 #include "SqpApplication.h"
2
2
3 #include <Data/IDataProvider.h>
3 #include <Data/IDataProvider.h>
4 #include <DataSource/DataSourceController.h>
4 #include <DataSource/DataSourceController.h>
5 #include <Network/NetworkController.h>
5 #include <Network/NetworkController.h>
6 #include <QThread>
6 #include <QThread>
7 #include <Time/TimeController.h>
7 #include <Time/TimeController.h>
8 #include <Variable/Variable.h>
8 #include <Variable/Variable.h>
9 #include <Variable/VariableController.h>
9 #include <Variable/VariableController.h>
10 #include <Visualization/VisualizationController.h>
10 #include <Visualization/VisualizationController.h>
11
11
12 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
12 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
13
13
14 class SqpApplication::SqpApplicationPrivate {
14 class SqpApplication::SqpApplicationPrivate {
15 public:
15 public:
16 SqpApplicationPrivate()
16 SqpApplicationPrivate()
17 : m_DataSourceController{std::make_unique<DataSourceController>()},
17 : m_DataSourceController{std::make_unique<DataSourceController>()},
18 m_NetworkController{std::make_unique<NetworkController>()},
18 m_NetworkController{std::make_unique<NetworkController>()},
19 m_TimeController{std::make_unique<TimeController>()},
19 m_TimeController{std::make_unique<TimeController>()},
20 m_VariableController{std::make_unique<VariableController>()},
20 m_VariableController{std::make_unique<VariableController>()},
21 m_VisualizationController{std::make_unique<VisualizationController>()}
21 m_VisualizationController{std::make_unique<VisualizationController>()}
22 {
22 {
23 // /////////////////////////////// //
23 // /////////////////////////////// //
24 // Connections between controllers //
24 // Connections between controllers //
25 // /////////////////////////////// //
25 // /////////////////////////////// //
26
26
27 // VariableController <-> DataSourceController
27 // VariableController <-> DataSourceController
28 connect(m_DataSourceController.get(),
28 connect(m_DataSourceController.get(),
29 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
29 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
30 std::shared_ptr<IDataProvider>)),
30 std::shared_ptr<IDataProvider>)),
31 m_VariableController.get(),
31 m_VariableController.get(),
32 SLOT(createVariable(const QString &, const QVariantHash &,
32 SLOT(createVariable(const QString &, const QVariantHash &,
33 std::shared_ptr<IDataProvider>)));
33 std::shared_ptr<IDataProvider>)));
34
34
35 // VariableController <-> VisualizationController
35 // VariableController <-> VisualizationController
36 connect(m_VariableController.get(),
36 connect(m_VariableController.get(),
37 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
37 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
38 m_VisualizationController.get(),
38 m_VisualizationController.get(),
39 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
39 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
40
40
41 connect(m_VariableController.get(),
42 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpDateTime &)),
43 m_VisualizationController.get(),
44 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpDateTime &)));
45
41
46
42 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
47 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
48 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
43 m_NetworkController->moveToThread(&m_NetworkControllerThread);
49 m_NetworkController->moveToThread(&m_NetworkControllerThread);
50 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
44 m_VariableController->moveToThread(&m_VariableControllerThread);
51 m_VariableController->moveToThread(&m_VariableControllerThread);
52 m_VariableControllerThread.setObjectName("VariableControllerThread");
45 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
53 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
54 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
46
55
47
56
48 // Additionnal init
57 // Additionnal init
49 m_VariableController->setTimeController(m_TimeController.get());
58 m_VariableController->setTimeController(m_TimeController.get());
50 }
59 }
51
60
52 virtual ~SqpApplicationPrivate()
61 virtual ~SqpApplicationPrivate()
53 {
62 {
54 qCInfo(LOG_SqpApplication()) << tr("SqpApplicationPrivate destruction");
63 qCInfo(LOG_SqpApplication()) << tr("SqpApplicationPrivate destruction");
55 m_DataSourceControllerThread.quit();
64 m_DataSourceControllerThread.quit();
56 m_DataSourceControllerThread.wait();
65 m_DataSourceControllerThread.wait();
57
66
58 m_NetworkControllerThread.quit();
67 m_NetworkControllerThread.quit();
59 m_NetworkControllerThread.wait();
68 m_NetworkControllerThread.wait();
60
69
61 m_VariableControllerThread.quit();
70 m_VariableControllerThread.quit();
62 m_VariableControllerThread.wait();
71 m_VariableControllerThread.wait();
63
72
64 m_VisualizationControllerThread.quit();
73 m_VisualizationControllerThread.quit();
65 m_VisualizationControllerThread.wait();
74 m_VisualizationControllerThread.wait();
66 }
75 }
67
76
68 std::unique_ptr<DataSourceController> m_DataSourceController;
77 std::unique_ptr<DataSourceController> m_DataSourceController;
69 std::unique_ptr<VariableController> m_VariableController;
78 std::unique_ptr<VariableController> m_VariableController;
70 std::unique_ptr<TimeController> m_TimeController;
79 std::unique_ptr<TimeController> m_TimeController;
71 std::unique_ptr<NetworkController> m_NetworkController;
80 std::unique_ptr<NetworkController> m_NetworkController;
72 std::unique_ptr<VisualizationController> m_VisualizationController;
81 std::unique_ptr<VisualizationController> m_VisualizationController;
73 QThread m_DataSourceControllerThread;
82 QThread m_DataSourceControllerThread;
74 QThread m_NetworkControllerThread;
83 QThread m_NetworkControllerThread;
75 QThread m_VariableControllerThread;
84 QThread m_VariableControllerThread;
76 QThread m_VisualizationControllerThread;
85 QThread m_VisualizationControllerThread;
77 };
86 };
78
87
79
88
80 SqpApplication::SqpApplication(int &argc, char **argv)
89 SqpApplication::SqpApplication(int &argc, char **argv)
81 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
90 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
82 {
91 {
83 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
92 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
84
93
85 connect(&impl->m_DataSourceControllerThread, &QThread::started,
94 connect(&impl->m_DataSourceControllerThread, &QThread::started,
86 impl->m_DataSourceController.get(), &DataSourceController::initialize);
95 impl->m_DataSourceController.get(), &DataSourceController::initialize);
87 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
96 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
88 impl->m_DataSourceController.get(), &DataSourceController::finalize);
97 impl->m_DataSourceController.get(), &DataSourceController::finalize);
89
98
90 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
99 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
91 &NetworkController::initialize);
100 &NetworkController::initialize);
92 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
101 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
93 &NetworkController::finalize);
102 &NetworkController::finalize);
94
103
95 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
104 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
96 &VariableController::initialize);
105 &VariableController::initialize);
97 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
106 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
98 &VariableController::finalize);
107 &VariableController::finalize);
99
108
100 connect(&impl->m_VisualizationControllerThread, &QThread::started,
109 connect(&impl->m_VisualizationControllerThread, &QThread::started,
101 impl->m_VisualizationController.get(), &VisualizationController::initialize);
110 impl->m_VisualizationController.get(), &VisualizationController::initialize);
102 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
111 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
103 impl->m_VisualizationController.get(), &VisualizationController::finalize);
112 impl->m_VisualizationController.get(), &VisualizationController::finalize);
104
113
105 impl->m_DataSourceControllerThread.start();
114 impl->m_DataSourceControllerThread.start();
106 impl->m_NetworkControllerThread.start();
115 impl->m_NetworkControllerThread.start();
107 impl->m_VariableControllerThread.start();
116 impl->m_VariableControllerThread.start();
108 impl->m_VisualizationControllerThread.start();
117 impl->m_VisualizationControllerThread.start();
109
110 // Core connections:
111 // NetworkController <-> VariableController
112 connect(&sqpApp->networkController(), &NetworkController::replyDownloadProgress,
113 &sqpApp->variableController(), &VariableController::onVariableRetrieveDataInProgress);
114 }
118 }
115
119
116 SqpApplication::~SqpApplication()
120 SqpApplication::~SqpApplication()
117 {
121 {
118 }
122 }
119
123
120 void SqpApplication::initialize()
124 void SqpApplication::initialize()
121 {
125 {
122 }
126 }
123
127
124 DataSourceController &SqpApplication::dataSourceController() noexcept
128 DataSourceController &SqpApplication::dataSourceController() noexcept
125 {
129 {
126 return *impl->m_DataSourceController;
130 return *impl->m_DataSourceController;
127 }
131 }
128
132
129 NetworkController &SqpApplication::networkController() noexcept
133 NetworkController &SqpApplication::networkController() noexcept
130 {
134 {
131 return *impl->m_NetworkController;
135 return *impl->m_NetworkController;
132 }
136 }
133
137
134 TimeController &SqpApplication::timeController() noexcept
138 TimeController &SqpApplication::timeController() noexcept
135 {
139 {
136 return *impl->m_TimeController;
140 return *impl->m_TimeController;
137 }
141 }
138
142
139 VariableController &SqpApplication::variableController() noexcept
143 VariableController &SqpApplication::variableController() noexcept
140 {
144 {
141 return *impl->m_VariableController;
145 return *impl->m_VariableController;
142 }
146 }
143
147
144 VisualizationController &SqpApplication::visualizationController() noexcept
148 VisualizationController &SqpApplication::visualizationController() noexcept
145 {
149 {
146 return *impl->m_VisualizationController;
150 return *impl->m_VisualizationController;
147 }
151 }
@@ -1,140 +1,199
1 #include <Variable/VariableController.h>
1 #include <Variable/VariableController.h>
2 #include <Variable/VariableInspectorWidget.h>
2 #include <Variable/VariableInspectorWidget.h>
3 #include <Variable/VariableMenuHeaderWidget.h>
3 #include <Variable/VariableMenuHeaderWidget.h>
4 #include <Variable/VariableModel.h>
4 #include <Variable/VariableModel.h>
5
5
6 #include <ui_VariableInspectorWidget.h>
6 #include <ui_VariableInspectorWidget.h>
7
7
8 #include <QMouseEvent>
8 #include <QSortFilterProxyModel>
9 #include <QSortFilterProxyModel>
9 #include <QStyledItemDelegate>
10 #include <QStyledItemDelegate>
10 #include <QWidgetAction>
11 #include <QWidgetAction>
11
12
12 #include <SqpApplication.h>
13 #include <SqpApplication.h>
13
14
14 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
15 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
15
16
16
17
17 class QProgressBarItemDelegate : public QStyledItemDelegate {
18 class QProgressBarItemDelegate : public QStyledItemDelegate {
18
19
19 public:
20 public:
20 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
21 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
21
22
22 void paint(QPainter *painter, const QStyleOptionViewItem &option,
23 void paint(QPainter *painter, const QStyleOptionViewItem &option,
23 const QModelIndex &index) const
24 const QModelIndex &index) const
24 {
25 {
25 auto data = index.data(Qt::DisplayRole);
26 auto data = index.data(Qt::DisplayRole);
26 auto progressData = index.data(VariableRoles::ProgressRole);
27 auto progressData = index.data(VariableRoles::ProgressRole);
27 if (data.isValid() && progressData.isValid()) {
28 if (data.isValid() && progressData.isValid()) {
28 auto name = data.value<QString>();
29 auto name = data.value<QString>();
29 auto progress = progressData.value<double>();
30 auto progress = progressData.value<double>();
30 if (progress >= 0) {
31 if (progress > 0) {
32 auto cancelButtonWidth = 20;
31 auto progressBarOption = QStyleOptionProgressBar{};
33 auto progressBarOption = QStyleOptionProgressBar{};
32 progressBarOption.rect = option.rect;
34 auto progressRect = option.rect;
35 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
36 progressBarOption.rect = progressRect;
33 progressBarOption.minimum = 0;
37 progressBarOption.minimum = 0;
34 progressBarOption.maximum = 100;
38 progressBarOption.maximum = 100;
35 progressBarOption.progress = progress;
39 progressBarOption.progress = progress;
36 progressBarOption.text
40 progressBarOption.text
37 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
41 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
38 progressBarOption.textVisible = true;
42 progressBarOption.textVisible = true;
39 progressBarOption.textAlignment = Qt::AlignCenter;
43 progressBarOption.textAlignment = Qt::AlignCenter;
40
44
45
41 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
46 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
42 painter);
47 painter);
48
49 // Cancel button
50 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
51 option.rect.height());
52 auto buttonOption = QStyleOptionButton{};
53 buttonOption.rect = buttonRect;
54 buttonOption.text = "X";
55
56 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
57 }
58 else {
59 QStyledItemDelegate::paint(painter, option, index);
43 }
60 }
44 }
61 }
45 else {
62 else {
46 QStyledItemDelegate::paint(painter, option, index);
63 QStyledItemDelegate::paint(painter, option, index);
47 }
64 }
48 }
65 }
66
67 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
68 const QModelIndex &index)
69 {
70 if (event->type() == QEvent::MouseButtonRelease) {
71 auto data = index.data(Qt::DisplayRole);
72 auto progressData = index.data(VariableRoles::ProgressRole);
73 if (data.isValid() && progressData.isValid()) {
74 auto cancelButtonWidth = 20;
75 auto progressRect = option.rect;
76 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
77 // Cancel button
78 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
79 option.rect.height());
80
81 auto e = (QMouseEvent *)event;
82 auto clickX = e->x();
83 auto clickY = e->y();
84
85 auto x = buttonRect.left(); // the X coordinate
86 auto y = buttonRect.top(); // the Y coordinate
87 auto w = buttonRect.width(); // button width
88 auto h = buttonRect.height(); // button height
89
90 if (clickX > x && clickX < x + w) {
91 if (clickY > y && clickY < y + h) {
92 auto variableModel = sqpApp->variableController().variableModel();
93 variableModel->abortProgress(index);
94 }
95 }
96 else {
97 QStyledItemDelegate::editorEvent(event, model, option, index);
98 }
99 }
100 else {
101 QStyledItemDelegate::editorEvent(event, model, option, index);
102 }
103 }
104 else {
105 QStyledItemDelegate::editorEvent(event, model, option, index);
106 }
107 }
49 };
108 };
50
109
51 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
110 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
52 : QWidget{parent},
111 : QWidget{parent},
53 ui{new Ui::VariableInspectorWidget},
112 ui{new Ui::VariableInspectorWidget},
54 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
113 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
55 {
114 {
56 ui->setupUi(this);
115 ui->setupUi(this);
57
116
58 // Sets model for table
117 // Sets model for table
59 // auto sortFilterModel = new QSortFilterProxyModel{this};
118 // auto sortFilterModel = new QSortFilterProxyModel{this};
60 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
119 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
61
120
62 auto variableModel = sqpApp->variableController().variableModel();
121 auto variableModel = sqpApp->variableController().variableModel();
63 ui->tableView->setModel(variableModel);
122 ui->tableView->setModel(variableModel);
64
123
65 // Adds extra signal/slot between view and model, so the view can be updated instantly when
124 // Adds extra signal/slot between view and model, so the view can be updated instantly when
66 // there is a change of data in the model
125 // there is a change of data in the model
67 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
126 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
68 SLOT(refresh()));
127 SLOT(refresh()));
69
128
70 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
129 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
71 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
130 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
72
131
73 // Fixes column sizes
132 // Fixes column sizes
74 auto model = ui->tableView->model();
133 auto model = ui->tableView->model();
75 const auto count = model->columnCount();
134 const auto count = model->columnCount();
76 for (auto i = 0; i < count; ++i) {
135 for (auto i = 0; i < count; ++i) {
77 ui->tableView->setColumnWidth(
136 ui->tableView->setColumnWidth(
78 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
137 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
79 }
138 }
80
139
81 // Sets selection options
140 // Sets selection options
82 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
141 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
83 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
142 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
84
143
85 // Connection to show a menu when right clicking on the tree
144 // Connection to show a menu when right clicking on the tree
86 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
145 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
87 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
146 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
88 &VariableInspectorWidget::onTableMenuRequested);
147 &VariableInspectorWidget::onTableMenuRequested);
89 }
148 }
90
149
91 VariableInspectorWidget::~VariableInspectorWidget()
150 VariableInspectorWidget::~VariableInspectorWidget()
92 {
151 {
93 delete ui;
152 delete ui;
94 }
153 }
95
154
96 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
155 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
97 {
156 {
98 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
157 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
99
158
100 // Gets the model to retrieve the underlying selected variables
159 // Gets the model to retrieve the underlying selected variables
101 auto model = sqpApp->variableController().variableModel();
160 auto model = sqpApp->variableController().variableModel();
102 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
161 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
103 for (const auto &selectedRow : qAsConst(selectedRows)) {
162 for (const auto &selectedRow : qAsConst(selectedRows)) {
104 if (auto selectedVariable = model->variable(selectedRow.row())) {
163 if (auto selectedVariable = model->variable(selectedRow.row())) {
105 selectedVariables.push_back(selectedVariable);
164 selectedVariables.push_back(selectedVariable);
106 }
165 }
107 }
166 }
108
167
109 QMenu tableMenu{};
168 QMenu tableMenu{};
110
169
111 // Emits a signal so that potential receivers can populate the menu before displaying it
170 // Emits a signal so that potential receivers can populate the menu before displaying it
112 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
171 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
113
172
114 // Adds menu-specific actions
173 // Adds menu-specific actions
115 if (!selectedVariables.isEmpty()) {
174 if (!selectedVariables.isEmpty()) {
116 // 'Delete' action
175 // 'Delete' action
117 auto deleteFun = [&selectedVariables]() {
176 auto deleteFun = [&selectedVariables]() {
118 sqpApp->variableController().deleteVariables(selectedVariables);
177 sqpApp->variableController().deleteVariables(selectedVariables);
119 };
178 };
120
179
121 tableMenu.addSeparator();
180 tableMenu.addSeparator();
122 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
181 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
123 }
182 }
124
183
125 if (!tableMenu.isEmpty()) {
184 if (!tableMenu.isEmpty()) {
126 // Generates menu header (inserted before first action)
185 // Generates menu header (inserted before first action)
127 auto firstAction = tableMenu.actions().first();
186 auto firstAction = tableMenu.actions().first();
128 auto headerAction = new QWidgetAction{&tableMenu};
187 auto headerAction = new QWidgetAction{&tableMenu};
129 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
188 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
130 tableMenu.insertAction(firstAction, headerAction);
189 tableMenu.insertAction(firstAction, headerAction);
131
190
132 // Displays menu
191 // Displays menu
133 tableMenu.exec(mapToGlobal(pos));
192 tableMenu.exec(mapToGlobal(pos));
134 }
193 }
135 }
194 }
136
195
137 void VariableInspectorWidget::refresh() noexcept
196 void VariableInspectorWidget::refresh() noexcept
138 {
197 {
139 ui->tableView->viewport()->update();
198 ui->tableView->viewport()->update();
140 }
199 }
@@ -1,160 +1,159
1 #include "Visualization/VisualizationGraphHelper.h"
1 #include "Visualization/VisualizationGraphHelper.h"
2 #include "Visualization/qcustomplot.h"
2 #include "Visualization/qcustomplot.h"
3
3
4 #include <Data/ScalarSeries.h>
4 #include <Data/ScalarSeries.h>
5
5
6 #include <Variable/Variable.h>
6 #include <Variable/Variable.h>
7
7
8 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
8 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
9
9
10 namespace {
10 namespace {
11
11
12 class SqpDataContainer : public QCPGraphDataContainer {
12 class SqpDataContainer : public QCPGraphDataContainer {
13 public:
13 public:
14 void appendGraphDataUnsorted(const QCPGraphData &data) { mData.append(data); }
14 void appendGraphDataUnsorted(const QCPGraphData &data) { mData.append(data); }
15 };
15 };
16
16
17
17
18 /// Format for datetimes on a axis
18 /// Format for datetimes on a axis
19 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
19 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
20
20
21 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
21 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
22 /// non-time data
22 /// non-time data
23 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
23 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
24 {
24 {
25 if (isTimeAxis) {
25 if (isTimeAxis) {
26 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
26 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
27 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
27 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
28
28
29 return dateTicker;
29 return dateTicker;
30 }
30 }
31 else {
31 else {
32 // default ticker
32 // default ticker
33 return QSharedPointer<QCPAxisTicker>::create();
33 return QSharedPointer<QCPAxisTicker>::create();
34 }
34 }
35 }
35 }
36
36
37 void updateScalarData(QCPAbstractPlottable *component, ScalarSeries &scalarSeries,
37 void updateScalarData(QCPAbstractPlottable *component, ScalarSeries &scalarSeries,
38 const SqpDateTime &dateTime)
38 const SqpDateTime &dateTime)
39 {
39 {
40 qCDebug(LOG_VisualizationGraphHelper()) << "TORM: updateScalarData"
40 qCDebug(LOG_VisualizationGraphHelper()) << "TORM: updateScalarData"
41 << QThread::currentThread()->objectName();
41 << QThread::currentThread()->objectName();
42 if (auto qcpGraph = dynamic_cast<QCPGraph *>(component)) {
42 if (auto qcpGraph = dynamic_cast<QCPGraph *>(component)) {
43 // Clean the graph
43 // Clean the graph
44 // NAIVE approch
44 // NAIVE approch
45 scalarSeries.lockRead();
45 scalarSeries.lockRead();
46 {
46 {
47 const auto xData = scalarSeries.xAxisData()->data();
47 const auto xData = scalarSeries.xAxisData()->data();
48 const auto valuesData = scalarSeries.valuesData()->data();
48 const auto valuesData = scalarSeries.valuesData()->data();
49 const auto count = xData.count();
49 const auto count = xData.count();
50 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points in cache"
50 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points in cache"
51 << xData.count();
51 << xData.count();
52
52
53 auto dataContainer = qcpGraph->data();
53 auto dataContainer = qcpGraph->data();
54 dataContainer->clear();
54 dataContainer->clear();
55 auto sqpDataContainer = QSharedPointer<SqpDataContainer>::create();
55 auto sqpDataContainer = QSharedPointer<SqpDataContainer>::create();
56 qcpGraph->setData(sqpDataContainer);
56 qcpGraph->setData(sqpDataContainer);
57
57
58 for (auto i = 0; i < count; ++i) {
58 for (auto i = 0; i < count; ++i) {
59 const auto x = xData[i];
59 const auto x = xData[i];
60 if (x >= dateTime.m_TStart && x <= dateTime.m_TEnd) {
60 if (x >= dateTime.m_TStart && x <= dateTime.m_TEnd) {
61 sqpDataContainer->appendGraphDataUnsorted(QCPGraphData(x, valuesData[i]));
61 sqpDataContainer->appendGraphDataUnsorted(QCPGraphData(x, valuesData[i]));
62 }
62 }
63 }
63 }
64 sqpDataContainer->sort();
64 sqpDataContainer->sort();
65 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points displayed"
65 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points displayed"
66 << sqpDataContainer->size();
66 << sqpDataContainer->size();
67 }
67 }
68 scalarSeries.unlock();
68 scalarSeries.unlock();
69
69
70
70
71 // Display all data
71 // Display all data
72 component->rescaleAxes();
73 component->parentPlot()->replot();
72 component->parentPlot()->replot();
74 }
73 }
75 else {
74 else {
76 /// @todo DEBUG
75 /// @todo DEBUG
77 }
76 }
78 }
77 }
79
78
80 QCPAbstractPlottable *createScalarSeriesComponent(ScalarSeries &scalarSeries, QCustomPlot &plot,
79 QCPAbstractPlottable *createScalarSeriesComponent(ScalarSeries &scalarSeries, QCustomPlot &plot,
81 const SqpDateTime &dateTime)
80 const SqpDateTime &dateTime)
82 {
81 {
83 auto component = plot.addGraph();
82 auto component = plot.addGraph();
84
83
85 if (component) {
84 if (component) {
86 // // Graph data
85 // // Graph data
87 component->setData(scalarSeries.xAxisData()->data(), scalarSeries.valuesData()->data(),
86 component->setData(scalarSeries.xAxisData()->data(), scalarSeries.valuesData()->data(),
88 true);
87 true);
89
88
90 updateScalarData(component, scalarSeries, dateTime);
89 updateScalarData(component, scalarSeries, dateTime);
91
90
92 // Axes properties
91 // Axes properties
93 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
92 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
94 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
93 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
95
94
96 auto setAxisProperties = [](auto axis, const auto &unit) {
95 auto setAxisProperties = [](auto axis, const auto &unit) {
97 // label (unit name)
96 // label (unit name)
98 axis->setLabel(unit.m_Name);
97 axis->setLabel(unit.m_Name);
99
98
100 // ticker (depending on the type of unit)
99 // ticker (depending on the type of unit)
101 axis->setTicker(axisTicker(unit.m_TimeUnit));
100 axis->setTicker(axisTicker(unit.m_TimeUnit));
102 };
101 };
103 setAxisProperties(plot.xAxis, scalarSeries.xAxisUnit());
102 setAxisProperties(plot.xAxis, scalarSeries.xAxisUnit());
104 setAxisProperties(plot.yAxis, scalarSeries.valuesUnit());
103 setAxisProperties(plot.yAxis, scalarSeries.valuesUnit());
105
104
106 // Display all data
105 // Display all data
107 component->rescaleAxes();
106 component->rescaleAxes();
108 plot.replot();
107 plot.replot();
109 }
108 }
110 else {
109 else {
111 qCDebug(LOG_VisualizationGraphHelper())
110 qCDebug(LOG_VisualizationGraphHelper())
112 << QObject::tr("Can't create graph for the scalar series");
111 << QObject::tr("Can't create graph for the scalar series");
113 }
112 }
114
113
115 return component;
114 return component;
116 }
115 }
117
116
118 } // namespace
117 } // namespace
119
118
120 QVector<QCPAbstractPlottable *> VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
119 QVector<QCPAbstractPlottable *> VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
121 QCustomPlot &plot) noexcept
120 QCustomPlot &plot) noexcept
122 {
121 {
123 auto result = QVector<QCPAbstractPlottable *>{};
122 auto result = QVector<QCPAbstractPlottable *>{};
124
123
125 if (variable) {
124 if (variable) {
126 // Gets the data series of the variable to call the creation of the right components
125 // Gets the data series of the variable to call the creation of the right components
127 // according to its type
126 // according to its type
128 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(variable->dataSeries())) {
127 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(variable->dataSeries())) {
129 result.append(createScalarSeriesComponent(*scalarSeries, plot, variable->dateTime()));
128 result.append(createScalarSeriesComponent(*scalarSeries, plot, variable->dateTime()));
130 }
129 }
131 else {
130 else {
132 qCDebug(LOG_VisualizationGraphHelper())
131 qCDebug(LOG_VisualizationGraphHelper())
133 << QObject::tr("Can't create graph plottables : unmanaged data series type");
132 << QObject::tr("Can't create graph plottables : unmanaged data series type");
134 }
133 }
135 }
134 }
136 else {
135 else {
137 qCDebug(LOG_VisualizationGraphHelper())
136 qCDebug(LOG_VisualizationGraphHelper())
138 << QObject::tr("Can't create graph plottables : the variable is null");
137 << QObject::tr("Can't create graph plottables : the variable is null");
139 }
138 }
140
139
141 return result;
140 return result;
142 }
141 }
143
142
144 void VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *> plotableVect,
143 void VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *> plotableVect,
145 IDataSeries *dataSeries, const SqpDateTime &dateTime)
144 IDataSeries *dataSeries, const SqpDateTime &dateTime)
146 {
145 {
147 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(dataSeries)) {
146 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(dataSeries)) {
148 if (plotableVect.size() == 1) {
147 if (plotableVect.size() == 1) {
149 updateScalarData(plotableVect.at(0), *scalarSeries, dateTime);
148 updateScalarData(plotableVect.at(0), *scalarSeries, dateTime);
150 }
149 }
151 else {
150 else {
152 qCCritical(LOG_VisualizationGraphHelper()) << QObject::tr(
151 qCCritical(LOG_VisualizationGraphHelper()) << QObject::tr(
153 "Can't update Data of a scalarSeries because there is not only one component "
152 "Can't update Data of a scalarSeries because there is not only one component "
154 "associated");
153 "associated");
155 }
154 }
156 }
155 }
157 else {
156 else {
158 /// @todo DEBUG
157 /// @todo DEBUG
159 }
158 }
160 }
159 }
@@ -1,285 +1,401
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationGraphHelper.h"
3 #include "Visualization/VisualizationGraphHelper.h"
4 #include "ui_VisualizationGraphWidget.h"
4 #include "ui_VisualizationGraphWidget.h"
5
5
6 #include <Data/ArrayData.h>
6 #include <Data/ArrayData.h>
7 #include <Data/IDataSeries.h>
7 #include <Data/IDataSeries.h>
8 #include <SqpApplication.h>
8 #include <SqpApplication.h>
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
11
11
12 #include <unordered_map>
12 #include <unordered_map>
13
13
14 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
14 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
15
15
16 namespace {
16 namespace {
17
17
18 /// Key pressed to enable zoom on horizontal axis
18 /// Key pressed to enable zoom on horizontal axis
19 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
19 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
20
20
21 /// Key pressed to enable zoom on vertical axis
21 /// Key pressed to enable zoom on vertical axis
22 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
22 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
23
23
24 } // namespace
24 } // namespace
25
25
26 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
26 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
27
27
28 explicit VisualizationGraphWidgetPrivate() : m_DoSynchronize{true}, m_IsCalibration{false} {}
29
30
31 // Return the operation when range changed
32 VisualizationGraphWidgetZoomType getZoomType(const QCPRange &t1, const QCPRange &t2);
33
28 // 1 variable -> n qcpplot
34 // 1 variable -> n qcpplot
29 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
35 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
36
37 bool m_DoSynchronize;
38 bool m_IsCalibration;
30 };
39 };
31
40
32 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
41 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
33 : QWidget{parent},
42 : QWidget{parent},
34 ui{new Ui::VisualizationGraphWidget},
43 ui{new Ui::VisualizationGraphWidget},
35 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
44 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
36 {
45 {
37 ui->setupUi(this);
46 ui->setupUi(this);
38
47
39 ui->graphNameLabel->setText(name);
48 ui->graphNameLabel->setText(name);
40
49
41 // 'Close' options : widget is deleted when closed
50 // 'Close' options : widget is deleted when closed
42 setAttribute(Qt::WA_DeleteOnClose);
51 setAttribute(Qt::WA_DeleteOnClose);
43 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
52 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
44 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
53 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
45
54
46 // Set qcpplot properties :
55 // Set qcpplot properties :
47 // - Drag (on x-axis) and zoom are enabled
56 // - Drag (on x-axis) and zoom are enabled
48 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
57 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
49 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
58 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
50 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
59 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
60 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
61 connect(ui->widget, &QCustomPlot::mouseRelease, this,
62 &VisualizationGraphWidget::onMouseRelease);
51 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
63 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
52 connect(ui->widget->xAxis,
64 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
53 static_cast<void (QCPAxis::*)(const QCPRange &)>(&QCPAxis::rangeChanged), this,
65 &QCPAxis::rangeChanged),
54 &VisualizationGraphWidget::onRangeChanged);
66 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
55
67
56 // Activates menu when right clicking on the graph
68 // Activates menu when right clicking on the graph
57 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
69 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
58 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
70 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
59 &VisualizationGraphWidget::onGraphMenuRequested);
71 &VisualizationGraphWidget::onGraphMenuRequested);
60
72
61 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
73 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
62 &VariableController::onRequestDataLoading);
74 &VariableController::onRequestDataLoading);
63 }
75 }
64
76
65
77
66 VisualizationGraphWidget::~VisualizationGraphWidget()
78 VisualizationGraphWidget::~VisualizationGraphWidget()
67 {
79 {
68 delete ui;
80 delete ui;
69 }
81 }
70
82
83 void VisualizationGraphWidget::enableSynchronize(bool enable)
84 {
85 impl->m_DoSynchronize = enable;
86 }
87
71 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
88 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
72 {
89 {
73 // Uses delegate to create the qcpplot components according to the variable
90 // Uses delegate to create the qcpplot components according to the variable
74 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
91 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
75
92
76 for (auto createdPlottable : qAsConst(createdPlottables)) {
93 for (auto createdPlottable : qAsConst(createdPlottables)) {
77 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
94 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
78 }
95 }
79
96
80 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
97 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
81 }
98 }
82 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
99 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
83 {
100 {
84
101
85 // when adding a variable, we need to set its time range to the current graph range
102 // when adding a variable, we need to set its time range to the current graph range
86 auto grapheRange = ui->widget->xAxis->range();
103 auto grapheRange = ui->widget->xAxis->range();
87 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
104 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
88 variable->setDateTime(dateTime);
105 variable->setDateTime(dateTime);
89
106
90 auto variableDateTimeWithTolerance = dateTime;
107 auto variableDateTimeWithTolerance = dateTime;
91
108
92 // add 10% tolerance for each side
109 // add 20% tolerance for each side
93 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
110 auto tolerance = 0.2 * (dateTime.m_TEnd - dateTime.m_TStart);
94 variableDateTimeWithTolerance.m_TStart -= tolerance;
111 variableDateTimeWithTolerance.m_TStart -= tolerance;
95 variableDateTimeWithTolerance.m_TEnd += tolerance;
112 variableDateTimeWithTolerance.m_TEnd += tolerance;
96
113
97 // Uses delegate to create the qcpplot components according to the variable
114 // Uses delegate to create the qcpplot components according to the variable
98 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
115 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
99
116
100 for (auto createdPlottable : qAsConst(createdPlottables)) {
117 for (auto createdPlottable : qAsConst(createdPlottables)) {
101 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
118 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
102 }
119 }
103
120
104 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
121 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
105
122
106 // CHangement detected, we need to ask controller to request data loading
123 // CHangement detected, we need to ask controller to request data loading
107 emit requestDataLoading(variable, variableDateTimeWithTolerance);
124 emit requestDataLoading(variable, variableDateTimeWithTolerance);
108 }
125 }
109
126
110 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
127 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
111 {
128 {
112 // Each component associated to the variable :
129 // Each component associated to the variable :
113 // - is removed from qcpplot (which deletes it)
130 // - is removed from qcpplot (which deletes it)
114 // - is no longer referenced in the map
131 // - is no longer referenced in the map
115 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
132 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
116 for (auto it = componentsIt.first; it != componentsIt.second;) {
133 for (auto it = componentsIt.first; it != componentsIt.second;) {
117 ui->widget->removePlottable(it->second);
134 ui->widget->removePlottable(it->second);
118 it = impl->m_VariableToPlotMultiMap.erase(it);
135 it = impl->m_VariableToPlotMultiMap.erase(it);
119 }
136 }
120
137
121 // Updates graph
138 // Updates graph
122 ui->widget->replot();
139 ui->widget->replot();
123 }
140 }
124
141
142 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable,
143 const SqpDateTime &range)
144 {
145 // Note: in case of different axes that depends on variable, we could start with a code like
146 // that:
147 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
148 // for (auto it = componentsIt.first; it != componentsIt.second;) {
149 // }
150 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
151 ui->widget->replot();
152 }
153
154 SqpDateTime VisualizationGraphWidget::graphRange() const noexcept
155 {
156 auto grapheRange = ui->widget->xAxis->range();
157 return SqpDateTime{grapheRange.lower, grapheRange.upper};
158 }
159
160 void VisualizationGraphWidget::setGraphRange(const SqpDateTime &range)
161 {
162 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
163 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
164 ui->widget->replot();
165 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
166 }
167
125 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
168 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
126 {
169 {
127 if (visitor) {
170 if (visitor) {
128 visitor->visit(this);
171 visitor->visit(this);
129 }
172 }
130 else {
173 else {
131 qCCritical(LOG_VisualizationGraphWidget())
174 qCCritical(LOG_VisualizationGraphWidget())
132 << tr("Can't visit widget : the visitor is null");
175 << tr("Can't visit widget : the visitor is null");
133 }
176 }
134 }
177 }
135
178
136 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
179 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
137 {
180 {
138 /// @todo : for the moment, a graph can always accomodate a variable
181 /// @todo : for the moment, a graph can always accomodate a variable
139 Q_UNUSED(variable);
182 Q_UNUSED(variable);
140 return true;
183 return true;
141 }
184 }
142
185
143 bool VisualizationGraphWidget::contains(const Variable &variable) const
186 bool VisualizationGraphWidget::contains(const Variable &variable) const
144 {
187 {
145 // Finds the variable among the keys of the map
188 // Finds the variable among the keys of the map
146 auto variablePtr = &variable;
189 auto variablePtr = &variable;
147 auto findVariable
190 auto findVariable
148 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
191 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
149
192
150 auto end = impl->m_VariableToPlotMultiMap.cend();
193 auto end = impl->m_VariableToPlotMultiMap.cend();
151 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
194 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
152 return it != end;
195 return it != end;
153 }
196 }
154
197
155 QString VisualizationGraphWidget::name() const
198 QString VisualizationGraphWidget::name() const
156 {
199 {
157 return ui->graphNameLabel->text();
200 return ui->graphNameLabel->text();
158 }
201 }
159
202
160 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
203 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
161 {
204 {
162 QMenu graphMenu{};
205 QMenu graphMenu{};
163
206
164 // Iterates on variables (unique keys)
207 // Iterates on variables (unique keys)
165 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
208 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
166 end = impl->m_VariableToPlotMultiMap.cend();
209 end = impl->m_VariableToPlotMultiMap.cend();
167 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
210 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
168 // 'Remove variable' action
211 // 'Remove variable' action
169 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
212 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
170 [ this, var = it->first ]() { removeVariable(var); });
213 [ this, var = it->first ]() { removeVariable(var); });
171 }
214 }
172
215
173 if (!graphMenu.isEmpty()) {
216 if (!graphMenu.isEmpty()) {
174 graphMenu.exec(mapToGlobal(pos));
217 graphMenu.exec(mapToGlobal(pos));
175 }
218 }
176 }
219 }
177
220
178 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1)
221 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
179 {
222 {
180 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
223 qCInfo(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
181 << QThread::currentThread()->objectName();
224 << QThread::currentThread()->objectName();
225
226 auto dateTimeRange = SqpDateTime{t1.lower, t1.upper};
182
227
228 auto zoomType = impl->getZoomType(t1, t2);
183 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
229 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
184 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
230 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
185
231
186 auto variable = it->first;
232 auto variable = it->first;
187 auto dateTime = SqpDateTime{t1.lower, t1.upper};
233 auto currentDateTime = dateTimeRange;
188
234
189 if (!variable->contains(dateTime)) {
235 auto toleranceFactor = 0.2;
190
236 auto tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
191 auto variableDateTimeWithTolerance = dateTime;
237 auto variableDateTimeWithTolerance = currentDateTime;
192 if (!variable->isInside(dateTime)) {
238 variableDateTimeWithTolerance.m_TStart -= tolerance;
239 variableDateTimeWithTolerance.m_TEnd += tolerance;
240
241 qCDebug(LOG_VisualizationGraphWidget()) << "r" << currentDateTime;
242 qCDebug(LOG_VisualizationGraphWidget()) << "t" << variableDateTimeWithTolerance;
243 qCDebug(LOG_VisualizationGraphWidget()) << "v" << variable->dateTime();
244 // If new range with tol is upper than variable datetime parameters. we need to request new
245 // data
246 if (!variable->contains(variableDateTimeWithTolerance)) {
247
248 auto variableDateTimeWithTolerance = currentDateTime;
249 if (!variable->isInside(currentDateTime)) {
193 auto variableDateTime = variable->dateTime();
250 auto variableDateTime = variable->dateTime();
194 if (variableDateTime.m_TStart < dateTime.m_TStart) {
251 if (variable->contains(variableDateTimeWithTolerance)) {
195 qCDebug(LOG_VisualizationGraphWidget()) << tr("TDetection pan to right:");
252 qCDebug(LOG_VisualizationGraphWidget())
253 << tr("TORM: Detection zoom in that need request:");
254 // add 10% tolerance for each side
255 tolerance
256 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
257 variableDateTimeWithTolerance.m_TStart -= tolerance;
258 variableDateTimeWithTolerance.m_TEnd += tolerance;
259 }
260 else if (variableDateTime.m_TStart < currentDateTime.m_TStart) {
261 qCInfo(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to right:");
196
262
197 auto diffEndToKeepDelta = dateTime.m_TEnd - variableDateTime.m_TEnd;
263 auto diffEndToKeepDelta = currentDateTime.m_TEnd - variableDateTime.m_TEnd;
198 dateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
264 currentDateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
199 // Tolerance have to be added to the right
265 // Tolerance have to be added to the right
200 // add 10% tolerance for right (end) side
266 // add tolerance for right (end) side
201 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
267 tolerance
268 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
202 variableDateTimeWithTolerance.m_TEnd += tolerance;
269 variableDateTimeWithTolerance.m_TEnd += tolerance;
203 }
270 }
204 else if (variableDateTime.m_TEnd > dateTime.m_TEnd) {
271 else if (variableDateTime.m_TEnd > currentDateTime.m_TEnd) {
205 qCDebug(LOG_VisualizationGraphWidget()) << tr("Detection pan to left: ");
272 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to left: ");
206 auto diffStartToKeepDelta = variableDateTime.m_TStart - dateTime.m_TStart;
273 auto diffStartToKeepDelta
207 dateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
274 = variableDateTime.m_TStart - currentDateTime.m_TStart;
275 currentDateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
208 // Tolerance have to be added to the left
276 // Tolerance have to be added to the left
209 // add 10% tolerance for left (start) side
277 // add tolerance for left (start) side
210 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
278 tolerance
279 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
211 variableDateTimeWithTolerance.m_TStart -= tolerance;
280 variableDateTimeWithTolerance.m_TStart -= tolerance;
212 }
281 }
213 else {
282 else {
214 qCWarning(LOG_VisualizationGraphWidget())
283 qCCritical(LOG_VisualizationGraphWidget())
215 << tr("Detection anormal zoom detection: ");
284 << tr("Detection anormal zoom detection: ");
216 }
285 }
217 }
286 }
218 else {
287 else {
219 qCDebug(LOG_VisualizationGraphWidget()) << tr("Detection zoom out: ");
288 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection zoom out: ");
220 // add 10% tolerance for each side
289 // add 10% tolerance for each side
221 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
290 tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
222 variableDateTimeWithTolerance.m_TStart -= tolerance;
291 variableDateTimeWithTolerance.m_TStart -= tolerance;
223 variableDateTimeWithTolerance.m_TEnd += tolerance;
292 variableDateTimeWithTolerance.m_TEnd += tolerance;
293 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
294 }
295 if (!variable->contains(dateTimeRange)) {
296 qCDebug(LOG_VisualizationGraphWidget())
297 << "TORM: Modif on variable datetime detected" << currentDateTime;
298 variable->setDateTime(currentDateTime);
224 }
299 }
225 variable->setDateTime(dateTime);
226
300
301 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Request data detection: ");
227 // CHangement detected, we need to ask controller to request data loading
302 // CHangement detected, we need to ask controller to request data loading
228 emit requestDataLoading(variable, variableDateTimeWithTolerance);
303 emit requestDataLoading(variable, variableDateTimeWithTolerance);
229 }
304 }
230 else {
305 else {
231 qCDebug(LOG_VisualizationGraphWidget()) << tr("Detection zoom in: ");
306 qCInfo(LOG_VisualizationGraphWidget())
307 << tr("TORM: Detection zoom in that doesn't need request: ");
308 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
232 }
309 }
233 }
310 }
311
312 if (impl->m_DoSynchronize && !impl->m_IsCalibration) {
313 auto oldDateTime = SqpDateTime{t2.lower, t2.upper};
314 qCDebug(LOG_VisualizationGraphWidget())
315 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
316 << QThread::currentThread()->objectName();
317 emit synchronize(dateTimeRange, oldDateTime, zoomType);
318 }
234 }
319 }
235
320
236 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
321 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
237 {
322 {
238 auto zoomOrientations = QFlags<Qt::Orientation>{};
323 auto zoomOrientations = QFlags<Qt::Orientation>{};
239
324
240 // Lambda that enables a zoom orientation if the key modifier related to this orientation
325 // Lambda that enables a zoom orientation if the key modifier related to this orientation
241 // has
326 // has
242 // been pressed
327 // been pressed
243 auto enableOrientation
328 auto enableOrientation
244 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
329 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
245 auto orientationEnabled = event->modifiers().testFlag(modifier);
330 auto orientationEnabled = event->modifiers().testFlag(modifier);
246 zoomOrientations.setFlag(orientation, orientationEnabled);
331 zoomOrientations.setFlag(orientation, orientationEnabled);
247 };
332 };
248 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
333 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
249 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
334 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
250
335
251 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
336 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
252 }
337 }
253
338
339 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
340 {
341 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
342 }
343
344 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
345 {
346 impl->m_IsCalibration = false;
347 }
348
254 void VisualizationGraphWidget::onDataCacheVariableUpdated()
349 void VisualizationGraphWidget::onDataCacheVariableUpdated()
255 {
350 {
256 // NOTE:
351 // NOTE:
257 // We don't want to call the method for each component of a variable unitarily, but for
352 // We don't want to call the method for each component of a variable unitarily, but for
258 // all
353 // all
259 // its components at once (eg its three components in the case of a vector).
354 // its components at once (eg its three components in the case of a vector).
260
355
261 // The unordered_multimap does not do this easily, so the question is whether to:
356 // The unordered_multimap does not do this easily, so the question is whether to:
262 // - use an ordered_multimap and the algos of std to group the values by key
357 // - use an ordered_multimap and the algos of std to group the values by key
263 // - use a map (unique keys) and store as values directly the list of components
358 // - use a map (unique keys) and store as values directly the list of components
264
359
360 auto grapheRange = ui->widget->xAxis->range();
361 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
362
265 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
363 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
266 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
364 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
267 auto variable = it->first;
365 auto variable = it->first;
268 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
366 qCDebug(LOG_VisualizationGraphWidget())
269 variable->dataSeries(), variable->dateTime());
367 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S"
368 << variable->dateTime();
369 qCDebug(LOG_VisualizationGraphWidget())
370 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
371 if (dateTime.contains(variable->dateTime()) || dateTime.intersect(variable->dateTime())) {
372
373 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
374 variable->dataSeries(), variable->dateTime());
375 }
270 }
376 }
271 }
377 }
272
378
273 void VisualizationGraphWidget::updateDisplay(std::shared_ptr<Variable> variable)
379 VisualizationGraphWidgetZoomType
380 VisualizationGraphWidget::VisualizationGraphWidgetPrivate::getZoomType(const QCPRange &t1,
381 const QCPRange &t2)
274 {
382 {
275 auto abstractPlotableItPair = impl->m_VariableToPlotMultiMap.equal_range(variable);
383 // t1.lower <= t2.lower && t2.upper <= t1.upper
276
384 auto zoomType = VisualizationGraphWidgetZoomType::Unknown;
277 auto abstractPlotableVect = QVector<QCPAbstractPlottable *>{};
385 if (t1.lower <= t2.lower && t2.upper <= t1.upper) {
278
386 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
279 for (auto it = abstractPlotableItPair.first; it != abstractPlotableItPair.second; ++it) {
280 abstractPlotableVect.push_back(it->second);
281 }
387 }
282
388 else if (t1.lower > t2.lower && t1.upper > t2.upper) {
283 VisualizationGraphHelper::updateData(abstractPlotableVect, variable->dataSeries(),
389 zoomType = VisualizationGraphWidgetZoomType::PanRight;
284 variable->dateTime());
390 }
391 else if (t1.lower < t2.lower && t1.upper < t2.upper) {
392 zoomType = VisualizationGraphWidgetZoomType::PanLeft;
393 }
394 else if (t1.lower > t2.lower && t2.upper > t1.upper) {
395 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
396 }
397 else {
398 qCCritical(LOG_VisualizationGraphWidget()) << "getZoomType: Unknown type detected";
399 }
400 return zoomType;
285 }
401 }
@@ -1,143 +1,152
1 #include "Visualization/VisualizationWidget.h"
1 #include "Visualization/VisualizationWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationGraphWidget.h"
3 #include "Visualization/VisualizationGraphWidget.h"
4 #include "Visualization/VisualizationTabWidget.h"
4 #include "Visualization/VisualizationTabWidget.h"
5 #include "Visualization/VisualizationZoneWidget.h"
5 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/operations/GenerateVariableMenuOperation.h"
6 #include "Visualization/operations/GenerateVariableMenuOperation.h"
7 #include "Visualization/operations/RemoveVariableOperation.h"
7 #include "Visualization/operations/RemoveVariableOperation.h"
8 #include "Visualization/operations/RescaleAxeOperation.h"
8 #include "Visualization/qcustomplot.h"
9 #include "Visualization/qcustomplot.h"
9
10
10 #include "ui_VisualizationWidget.h"
11 #include "ui_VisualizationWidget.h"
11
12
12 #include <QToolButton>
13 #include <QToolButton>
13
14
14 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
15 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
15
16
16 VisualizationWidget::VisualizationWidget(QWidget *parent)
17 VisualizationWidget::VisualizationWidget(QWidget *parent)
17 : QWidget{parent}, ui{new Ui::VisualizationWidget}
18 : QWidget{parent}, ui{new Ui::VisualizationWidget}
18 {
19 {
19 ui->setupUi(this);
20 ui->setupUi(this);
20
21
21 auto addTabViewButton = new QToolButton{ui->tabWidget};
22 auto addTabViewButton = new QToolButton{ui->tabWidget};
22 addTabViewButton->setText(tr("Add View"));
23 addTabViewButton->setText(tr("Add View"));
23 addTabViewButton->setCursor(Qt::ArrowCursor);
24 addTabViewButton->setCursor(Qt::ArrowCursor);
24 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
25 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
25
26
26 auto enableMinimumCornerWidgetSize = [this](bool enable) {
27 auto enableMinimumCornerWidgetSize = [this](bool enable) {
27
28
28 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
29 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
29 auto width = enable ? tabViewCornerWidget->width() : 0;
30 auto width = enable ? tabViewCornerWidget->width() : 0;
30 auto height = enable ? tabViewCornerWidget->height() : 0;
31 auto height = enable ? tabViewCornerWidget->height() : 0;
31 tabViewCornerWidget->setMinimumHeight(height);
32 tabViewCornerWidget->setMinimumHeight(height);
32 tabViewCornerWidget->setMinimumWidth(width);
33 tabViewCornerWidget->setMinimumWidth(width);
33 ui->tabWidget->setMinimumHeight(height);
34 ui->tabWidget->setMinimumHeight(height);
34 ui->tabWidget->setMinimumWidth(width);
35 ui->tabWidget->setMinimumWidth(width);
35 };
36 };
36
37
37 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
38 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
38 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
39 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
39 ui->tabWidget};
40 ui->tabWidget};
40 auto index = ui->tabWidget->addTab(widget, widget->name());
41 auto index = ui->tabWidget->addTab(widget, widget->name());
41 if (ui->tabWidget->count() > 0) {
42 if (ui->tabWidget->count() > 0) {
42 enableMinimumCornerWidgetSize(false);
43 enableMinimumCornerWidgetSize(false);
43 }
44 }
44 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
45 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
45 };
46 };
46
47
47 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
48 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
48 if (ui->tabWidget->count() == 1) {
49 if (ui->tabWidget->count() == 1) {
49 enableMinimumCornerWidgetSize(true);
50 enableMinimumCornerWidgetSize(true);
50 }
51 }
51
52
52 // Removes widget from tab and closes it
53 // Removes widget from tab and closes it
53 auto widget = ui->tabWidget->widget(index);
54 auto widget = ui->tabWidget->widget(index);
54 ui->tabWidget->removeTab(index);
55 ui->tabWidget->removeTab(index);
55 if (widget) {
56 if (widget) {
56 widget->close();
57 widget->close();
57 }
58 }
58
59
59 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
60 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
60
61
61 };
62 };
62
63
63 ui->tabWidget->setTabsClosable(true);
64 ui->tabWidget->setTabsClosable(true);
64
65
65 connect(addTabViewButton, &QToolButton::clicked, addTabView);
66 connect(addTabViewButton, &QToolButton::clicked, addTabView);
66 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
67 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
67
68
68 // Adds default tab
69 // Adds default tab
69 addTabView();
70 addTabView();
70 }
71 }
71
72
72 VisualizationWidget::~VisualizationWidget()
73 VisualizationWidget::~VisualizationWidget()
73 {
74 {
74 delete ui;
75 delete ui;
75 }
76 }
76
77
77 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
78 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
78 {
79 {
79 if (visitor) {
80 if (visitor) {
80 visitor->visitEnter(this);
81 visitor->visitEnter(this);
81
82
82 // Apply visitor for tab children
83 // Apply visitor for tab children
83 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
84 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
84 // Widgets different from tabs are not visited (no action)
85 // Widgets different from tabs are not visited (no action)
85 if (auto visualizationTabWidget
86 if (auto visualizationTabWidget
86 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
87 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
87 visualizationTabWidget->accept(visitor);
88 visualizationTabWidget->accept(visitor);
88 }
89 }
89 }
90 }
90
91
91 visitor->visitLeave(this);
92 visitor->visitLeave(this);
92 }
93 }
93 else {
94 else {
94 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
95 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
95 }
96 }
96 }
97 }
97
98
98 bool VisualizationWidget::canDrop(const Variable &variable) const
99 bool VisualizationWidget::canDrop(const Variable &variable) const
99 {
100 {
100 // The main widget can never accomodate a variable
101 // The main widget can never accomodate a variable
101 Q_UNUSED(variable);
102 Q_UNUSED(variable);
102 return false;
103 return false;
103 }
104 }
104
105
105 bool VisualizationWidget::contains(const Variable &variable) const
106 bool VisualizationWidget::contains(const Variable &variable) const
106 {
107 {
107 Q_UNUSED(variable);
108 Q_UNUSED(variable);
108 return false;
109 return false;
109 }
110 }
110
111
111 QString VisualizationWidget::name() const
112 QString VisualizationWidget::name() const
112 {
113 {
113 return QStringLiteral("MainView");
114 return QStringLiteral("MainView");
114 }
115 }
115
116
116 void VisualizationWidget::attachVariableMenu(
117 void VisualizationWidget::attachVariableMenu(
117 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
118 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
118 {
119 {
119 // Menu is generated only if there is a single variable
120 // Menu is generated only if there is a single variable
120 if (variables.size() == 1) {
121 if (variables.size() == 1) {
121 if (auto variable = variables.first()) {
122 if (auto variable = variables.first()) {
122 // Generates the actions that make it possible to visualize the variable
123 // Generates the actions that make it possible to visualize the variable
123 auto generateVariableMenuOperation = GenerateVariableMenuOperation{menu, variable};
124 auto generateVariableMenuOperation = GenerateVariableMenuOperation{menu, variable};
124 accept(&generateVariableMenuOperation);
125 accept(&generateVariableMenuOperation);
125 }
126 }
126 else {
127 else {
127 qCCritical(LOG_VisualizationWidget()) << tr(
128 qCCritical(LOG_VisualizationWidget()) << tr(
128 "Can't generate the menu relative to the visualization: the variable is null");
129 "Can't generate the menu relative to the visualization: the variable is null");
129 }
130 }
130 }
131 }
131 else {
132 else {
132 qCDebug(LOG_VisualizationWidget())
133 qCDebug(LOG_VisualizationWidget())
133 << tr("No generation of the menu related to the visualization: several variables are "
134 << tr("No generation of the menu related to the visualization: several variables are "
134 "selected");
135 "selected");
135 }
136 }
136 }
137 }
137
138
138 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
139 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
139 {
140 {
140 // Calls the operation of removing all references to the variable in the visualization
141 // Calls the operation of removing all references to the variable in the visualization
141 auto removeVariableOperation = RemoveVariableOperation{variable};
142 auto removeVariableOperation = RemoveVariableOperation{variable};
142 accept(&removeVariableOperation);
143 accept(&removeVariableOperation);
143 }
144 }
145
146 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
147 const SqpDateTime &range) noexcept
148 {
149 // Calls the operation of rescaling all graph that contrains variable in the visualization
150 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
151 accept(&rescaleVariableOperation);
152 }
@@ -1,111 +1,200
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
3 #include "Data/SqpDateTime.h"
4
2 #include "Visualization/IVisualizationWidgetVisitor.h"
5 #include "Visualization/IVisualizationWidgetVisitor.h"
6 #include "Visualization/VisualizationGraphWidget.h"
3 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
4
8
5 #include "Visualization/VisualizationGraphWidget.h"
6
9
7 #include <SqpApplication.h>
10 #include <SqpApplication.h>
8
11
9 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
12 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
10
13
11 namespace {
14 namespace {
12
15
13 /// Minimum height for graph added in zones (in pixels)
16 /// Minimum height for graph added in zones (in pixels)
14 const auto GRAPH_MINIMUM_HEIGHT = 300;
17 const auto GRAPH_MINIMUM_HEIGHT = 300;
15
18
16 /// Generates a default name for a new graph, according to the number of graphs already displayed in
19 /// Generates a default name for a new graph, according to the number of graphs already displayed in
17 /// the zone
20 /// the zone
18 QString defaultGraphName(const QLayout &layout)
21 QString defaultGraphName(const QLayout &layout)
19 {
22 {
20 auto count = 0;
23 auto count = 0;
21 for (auto i = 0; i < layout.count(); ++i) {
24 for (auto i = 0; i < layout.count(); ++i) {
22 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
25 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
23 count++;
26 count++;
24 }
27 }
25 }
28 }
26
29
27 return QObject::tr("Graph %1").arg(count + 1);
30 return QObject::tr("Graph %1").arg(count + 1);
28 }
31 }
29
32
30 } // namespace
33 } // namespace
31
34
32 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
35 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
33 : QWidget{parent}, ui{new Ui::VisualizationZoneWidget}
36 : QWidget{parent}, ui{new Ui::VisualizationZoneWidget}
34 {
37 {
35 ui->setupUi(this);
38 ui->setupUi(this);
36
39
37 ui->zoneNameLabel->setText(name);
40 ui->zoneNameLabel->setText(name);
38
41
39 // 'Close' options : widget is deleted when closed
42 // 'Close' options : widget is deleted when closed
40 setAttribute(Qt::WA_DeleteOnClose);
43 setAttribute(Qt::WA_DeleteOnClose);
41 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
44 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
42 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
45 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
43 }
46 }
44
47
45 VisualizationZoneWidget::~VisualizationZoneWidget()
48 VisualizationZoneWidget::~VisualizationZoneWidget()
46 {
49 {
47 delete ui;
50 delete ui;
48 }
51 }
49
52
50 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
53 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
51 {
54 {
52 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
55 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
53 }
56 }
54
57
55 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
58 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
56 {
59 {
57 auto graphWidget = new VisualizationGraphWidget{
60 auto graphWidget = new VisualizationGraphWidget{
58 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
61 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
59
62
63
60 // Set graph properties
64 // Set graph properties
61 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
65 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
62 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
66 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
63
67
64 this->addGraph(graphWidget);
68 this->addGraph(graphWidget);
65
69
66 graphWidget->addVariable(variable);
70 graphWidget->addVariable(variable);
67
71
72 // Lambda to synchronize zone widget
73 auto synchronizeZoneWidget = [this, graphWidget](const SqpDateTime &dateTime,
74 const SqpDateTime &oldDateTime,
75 VisualizationGraphWidgetZoomType zoomType) {
76 auto frameLayout = ui->visualizationZoneFrame->layout();
77 for (auto i = 0; i < frameLayout->count(); ++i) {
78 auto graphChild
79 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
80 if (graphChild && (graphChild != graphWidget)) {
81
82 auto graphChildRange = graphChild->graphRange();
83 switch (zoomType) {
84 case VisualizationGraphWidgetZoomType::ZoomIn: {
85 auto deltaLeft = dateTime.m_TStart - oldDateTime.m_TStart;
86 auto deltaRight = oldDateTime.m_TEnd - dateTime.m_TEnd;
87 graphChildRange.m_TStart += deltaLeft;
88 graphChildRange.m_TEnd -= deltaRight;
89 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
90 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
91 << deltaLeft;
92 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
93 << deltaRight;
94 qCCritical(LOG_VisualizationZoneWidget())
95 << tr("TORM: dt") << dateTime.m_TEnd - dateTime.m_TStart;
96
97 break;
98 }
99
100 case VisualizationGraphWidgetZoomType::ZoomOut: {
101 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
102 auto deltaLeft = oldDateTime.m_TStart - dateTime.m_TStart;
103 auto deltaRight = dateTime.m_TEnd - oldDateTime.m_TEnd;
104 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
105 << deltaLeft;
106 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
107 << deltaRight;
108 qCCritical(LOG_VisualizationZoneWidget())
109 << tr("TORM: dt") << dateTime.m_TEnd - dateTime.m_TStart;
110 graphChildRange.m_TStart -= deltaLeft;
111 graphChildRange.m_TEnd += deltaRight;
112 break;
113 }
114 case VisualizationGraphWidgetZoomType::PanRight: {
115 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
116 auto deltaRight = dateTime.m_TEnd - oldDateTime.m_TEnd;
117 graphChildRange.m_TStart += deltaRight;
118 graphChildRange.m_TEnd += deltaRight;
119 qCCritical(LOG_VisualizationZoneWidget())
120 << tr("TORM: dt") << dateTime.m_TEnd - dateTime.m_TStart;
121 break;
122 }
123 case VisualizationGraphWidgetZoomType::PanLeft: {
124 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
125 auto deltaLeft = oldDateTime.m_TStart - dateTime.m_TStart;
126 graphChildRange.m_TStart -= deltaLeft;
127 graphChildRange.m_TEnd -= deltaLeft;
128 break;
129 }
130 case VisualizationGraphWidgetZoomType::Unknown: {
131 qCCritical(LOG_VisualizationZoneWidget())
132 << tr("Impossible to synchronize: zoom type unknown");
133 break;
134 }
135 default:
136 qCCritical(LOG_VisualizationZoneWidget())
137 << tr("Impossible to synchronize: zoom type not take into account");
138 // No action
139 break;
140 }
141 graphChild->enableSynchronize(false);
142 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
143 << graphChild->graphRange();
144 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
145 << graphChildRange;
146 qCCritical(LOG_VisualizationZoneWidget())
147 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
148 graphChild->setGraphRange(graphChildRange);
149 graphChild->enableSynchronize(true);
150 }
151 }
152 };
153
154 // connection for synchronization
155 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
156
68 return graphWidget;
157 return graphWidget;
69 }
158 }
70
159
71 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
160 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
72 {
161 {
73 if (visitor) {
162 if (visitor) {
74 visitor->visitEnter(this);
163 visitor->visitEnter(this);
75
164
76 // Apply visitor to graph children
165 // Apply visitor to graph children
77 auto layout = ui->visualizationZoneFrame->layout();
166 auto layout = ui->visualizationZoneFrame->layout();
78 for (auto i = 0; i < layout->count(); ++i) {
167 for (auto i = 0; i < layout->count(); ++i) {
79 if (auto item = layout->itemAt(i)) {
168 if (auto item = layout->itemAt(i)) {
80 // Widgets different from graphs are not visited (no action)
169 // Widgets different from graphs are not visited (no action)
81 if (auto visualizationGraphWidget
170 if (auto visualizationGraphWidget
82 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
171 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
83 visualizationGraphWidget->accept(visitor);
172 visualizationGraphWidget->accept(visitor);
84 }
173 }
85 }
174 }
86 }
175 }
87
176
88 visitor->visitLeave(this);
177 visitor->visitLeave(this);
89 }
178 }
90 else {
179 else {
91 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
180 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
92 }
181 }
93 }
182 }
94
183
95 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
184 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
96 {
185 {
97 // A tab can always accomodate a variable
186 // A tab can always accomodate a variable
98 Q_UNUSED(variable);
187 Q_UNUSED(variable);
99 return true;
188 return true;
100 }
189 }
101
190
102 bool VisualizationZoneWidget::contains(const Variable &variable) const
191 bool VisualizationZoneWidget::contains(const Variable &variable) const
103 {
192 {
104 Q_UNUSED(variable);
193 Q_UNUSED(variable);
105 return false;
194 return false;
106 }
195 }
107
196
108 QString VisualizationZoneWidget::name() const
197 QString VisualizationZoneWidget::name() const
109 {
198 {
110 return ui->zoneNameLabel->text();
199 return ui->zoneNameLabel->text();
111 }
200 }
@@ -1,28 +1,30
1 #ifndef SCIQLOP_AMDAPROVIDER_H
1 #ifndef SCIQLOP_AMDAPROVIDER_H
2 #define SCIQLOP_AMDAPROVIDER_H
2 #define SCIQLOP_AMDAPROVIDER_H
3
3
4 #include "AmdaGlobal.h"
4 #include "AmdaGlobal.h"
5
5
6 #include <Data/IDataProvider.h>
6 #include <Data/IDataProvider.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9
9
10
10
11 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
11 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
12
12
13 class QNetworkReply;
13 class QNetworkReply;
14
14
15 /**
15 /**
16 * @brief The AmdaProvider class is an example of how a data provider can generate data
16 * @brief The AmdaProvider class is an example of how a data provider can generate data
17 */
17 */
18 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
18 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
19 public:
19 public:
20 explicit AmdaProvider();
20 explicit AmdaProvider();
21
21
22 void requestDataLoading(QUuid token, const DataProviderParameters &parameters) override;
22 void requestDataLoading(QUuid token, const DataProviderParameters &parameters) override;
23
23
24 void requestDataAborting(QUuid identifier) override;
25
24 private:
26 private:
25 void retrieveData(QUuid token, const SqpDateTime &dateTime, const QVariantHash &data);
27 void retrieveData(QUuid token, const SqpDateTime &dateTime, const QVariantHash &data);
26 };
28 };
27
29
28 #endif // SCIQLOP_AMDAPROVIDER_H
30 #endif // SCIQLOP_AMDAPROVIDER_H
@@ -1,129 +1,148
1 #include "AmdaProvider.h"
1 #include "AmdaProvider.h"
2 #include "AmdaDefs.h"
2 #include "AmdaDefs.h"
3 #include "AmdaResultParser.h"
3 #include "AmdaResultParser.h"
4
4
5 #include <Data/DataProviderParameters.h>
5 #include <Data/DataProviderParameters.h>
6 #include <Network/NetworkController.h>
6 #include <Network/NetworkController.h>
7 #include <SqpApplication.h>
7 #include <SqpApplication.h>
8 #include <Variable/Variable.h>
8 #include <Variable/Variable.h>
9
9
10 #include <QNetworkAccessManager>
10 #include <QNetworkAccessManager>
11 #include <QNetworkReply>
11 #include <QNetworkReply>
12 #include <QTemporaryFile>
12 #include <QTemporaryFile>
13 #include <QThread>
13 #include <QThread>
14
14
15 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
15 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
16
16
17 namespace {
17 namespace {
18
18
19 /// URL format for a request on AMDA server. The parameters are as follows:
19 /// URL format for a request on AMDA server. The parameters are as follows:
20 /// - %1: start date
20 /// - %1: start date
21 /// - %2: end date
21 /// - %2: end date
22 /// - %3: parameter id
22 /// - %3: parameter id
23 const auto AMDA_URL_FORMAT = QStringLiteral(
23 const auto AMDA_URL_FORMAT = QStringLiteral(
24 "http://amda.irap.omp.eu/php/rest/"
24 "http://amda.irap.omp.eu/php/rest/"
25 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&sampling=60&outputFormat=ASCII&"
25 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&sampling=60&outputFormat=ASCII&"
26 "timeFormat=ISO8601&gzip=0");
26 "timeFormat=ISO8601&gzip=0");
27
27
28 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
28 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
29 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:ss");
29 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
30
30
31 /// Formats a time to a date that can be passed in URL
31 /// Formats a time to a date that can be passed in URL
32 QString dateFormat(double sqpDateTime) noexcept
32 QString dateFormat(double sqpDateTime) noexcept
33 {
33 {
34 auto dateTime = QDateTime::fromMSecsSinceEpoch(sqpDateTime * 1000.);
34 auto dateTime = QDateTime::fromMSecsSinceEpoch(sqpDateTime * 1000.);
35 return dateTime.toString(AMDA_TIME_FORMAT);
35 return dateTime.toString(AMDA_TIME_FORMAT);
36 }
36 }
37
37
38 } // namespace
38 } // namespace
39
39
40 AmdaProvider::AmdaProvider()
40 AmdaProvider::AmdaProvider()
41 {
41 {
42 qCDebug(LOG_NetworkController()) << tr("AmdaProvider::AmdaProvider")
42 qCDebug(LOG_NetworkController()) << tr("AmdaProvider::AmdaProvider")
43 << QThread::currentThread();
43 << QThread::currentThread();
44 if (auto app = sqpApp) {
44 if (auto app = sqpApp) {
45 auto &networkController = app->networkController();
45 auto &networkController = app->networkController();
46 connect(this, SIGNAL(requestConstructed(QNetworkRequest, QUuid,
46 connect(this, SIGNAL(requestConstructed(QNetworkRequest, QUuid,
47 std::function<void(QNetworkReply *, QUuid)>)),
47 std::function<void(QNetworkReply *, QUuid)>)),
48 &networkController,
48 &networkController,
49 SLOT(onProcessRequested(QNetworkRequest, QUuid,
49 SLOT(onProcessRequested(QNetworkRequest, QUuid,
50 std::function<void(QNetworkReply *, QUuid)>)));
50 std::function<void(QNetworkReply *, QUuid)>)));
51
52
53 connect(&sqpApp->networkController(), SIGNAL(replyDownloadProgress(QUuid, double)), this,
54 SIGNAL(dataProvidedProgress(QUuid, double)));
51 }
55 }
52 }
56 }
53
57
54 void AmdaProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
58 void AmdaProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
55 {
59 {
56 // NOTE: Try to use multithread if possible
60 // NOTE: Try to use multithread if possible
57 const auto times = parameters.m_Times;
61 const auto times = parameters.m_Times;
58 const auto data = parameters.m_Data;
62 const auto data = parameters.m_Data;
59 for (const auto &dateTime : qAsConst(times)) {
63 for (const auto &dateTime : qAsConst(times)) {
60 retrieveData(token, dateTime, data);
64 retrieveData(token, dateTime, data);
61 }
65 }
62 }
66 }
63
67
68 void AmdaProvider::requestDataAborting(QUuid identifier)
69 {
70 if (auto app = sqpApp) {
71 auto &networkController = app->networkController();
72 networkController.onReplyCanceled(identifier);
73 }
74 }
75
64 void AmdaProvider::retrieveData(QUuid token, const SqpDateTime &dateTime, const QVariantHash &data)
76 void AmdaProvider::retrieveData(QUuid token, const SqpDateTime &dateTime, const QVariantHash &data)
65 {
77 {
66 // Retrieves product ID from data: if the value is invalid, no request is made
78 // Retrieves product ID from data: if the value is invalid, no request is made
67 auto productId = data.value(AMDA_XML_ID_KEY).toString();
79 auto productId = data.value(AMDA_XML_ID_KEY).toString();
68 if (productId.isNull()) {
80 if (productId.isNull()) {
69 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
81 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
70 return;
82 return;
71 }
83 }
84 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData") << dateTime;
72
85
73 // /////////// //
86 // /////////// //
74 // Creates URL //
87 // Creates URL //
75 // /////////// //
88 // /////////// //
76
89
77 auto startDate = dateFormat(dateTime.m_TStart);
90 auto startDate = dateFormat(dateTime.m_TStart);
78 auto endDate = dateFormat(dateTime.m_TEnd);
91 auto endDate = dateFormat(dateTime.m_TEnd);
79
92
80 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
93 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
81
94 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData url:") << url;
82 auto tempFile = std::make_shared<QTemporaryFile>();
95 auto tempFile = std::make_shared<QTemporaryFile>();
83
96
84 // LAMBDA
97 // LAMBDA
85 auto httpDownloadFinished
98 auto httpDownloadFinished
86 = [this, dateTime, tempFile, token](QNetworkReply *reply, QUuid dataId) noexcept {
99 = [this, dateTime, tempFile, token](QNetworkReply *reply, QUuid dataId) noexcept {
87 Q_UNUSED(dataId);
100 Q_UNUSED(dataId);
88
101
89 if (tempFile) {
102 // Don't do anything if the reply was abort
90 auto replyReadAll = reply->readAll();
103 if (reply->error() != QNetworkReply::OperationCanceledError) {
91 if (!replyReadAll.isEmpty()) {
104
92 tempFile->write(replyReadAll);
105 if (tempFile) {
93 }
106 auto replyReadAll = reply->readAll();
94 tempFile->close();
107 if (!replyReadAll.isEmpty()) {
95
108 tempFile->write(replyReadAll);
96 // Parse results file
109 }
97 if (auto dataSeries = AmdaResultParser::readTxt(tempFile->fileName())) {
110 tempFile->close();
98 emit dataProvided(token, dataSeries, dateTime);
111
99 }
112 // Parse results file
100 else {
113 if (auto dataSeries = AmdaResultParser::readTxt(tempFile->fileName())) {
101 /// @todo ALX : debug
114 emit dataProvided(token, dataSeries, dateTime);
115 }
116 else {
117 /// @todo ALX : debug
118 }
102 }
119 }
103 }
120 }
104
121
105 // Deletes reply
106 reply->deleteLater();
107 reply = nullptr;
108 };
122 };
109 auto httpFinishedLambda = [this, httpDownloadFinished, tempFile](QNetworkReply *reply,
123 auto httpFinishedLambda
110 QUuid dataId) noexcept {
124 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
111
125
112 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
126 // Don't do anything if the reply was abort
113 // Deletes old reply
127 if (reply->error() != QNetworkReply::OperationCanceledError) {
114 reply->deleteLater();
128 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
115
129
116 // Executes request for downloading file //
117
130
118 // Creates destination file
131 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData downloadFileUrl:")
119 if (tempFile->open()) {
132 << downloadFileUrl;
120 // Executes request
133 // Executes request for downloading file //
121 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId, httpDownloadFinished);
134
122 }
135 // Creates destination file
123 };
136 if (tempFile->open()) {
137 // Executes request
138 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId,
139 httpDownloadFinished);
140 }
141 }
142 };
124
143
125 // //////////////// //
144 // //////////////// //
126 // Executes request //
145 // Executes request //
127 // //////////////// //
146 // //////////////// //
128 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
147 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
129 }
148 }
@@ -1,134 +1,145
1 #include "AmdaResultParser.h"
1 #include "AmdaResultParser.h"
2
2
3 #include <Data/ScalarSeries.h>
3 #include <Data/ScalarSeries.h>
4
4
5 #include <QDateTime>
5 #include <QDateTime>
6 #include <QFile>
6 #include <QFile>
7 #include <QRegularExpression>
7 #include <QRegularExpression>
8
8
9 #include <cmath>
9 #include <cmath>
10
10
11 Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser")
11 Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser")
12
12
13 namespace {
13 namespace {
14
14
15 /// Message in result file when the file was not found on server
16 const auto FILE_NOT_FOUND_MESSAGE = QStringLiteral("Not Found");
17
15 /// Format for dates in result files
18 /// Format for dates in result files
16 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
19 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
17
20
18 /// Separator between values in a result line
21 /// Separator between values in a result line
19 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
22 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
20
23
21 /// Regex to find unit in a line. Examples of valid lines:
24 /// Regex to find unit in a line. Examples of valid lines:
22 /// ... - Units : nT - ...
25 /// ... - Units : nT - ...
23 /// ... -Units:nT- ...
26 /// ... -Units:nT- ...
24 /// ... -Units: mΒ²- ...
27 /// ... -Units: mΒ²- ...
25 /// ... - Units : m/s - ...
28 /// ... - Units : m/s - ...
26 const auto UNIT_REGEX = QRegularExpression{QStringLiteral("-\\s*Units\\s*:\\s*(.+?)\\s*-")};
29 const auto UNIT_REGEX = QRegularExpression{QStringLiteral("-\\s*Units\\s*:\\s*(.+?)\\s*-")};
27
30
28 /// Converts a string date to a double date
31 /// Converts a string date to a double date
29 /// @return a double that represents the date in seconds, NaN if the string date can't be converted
32 /// @return a double that represents the date in seconds, NaN if the string date can't be converted
30 double doubleDate(const QString &stringDate) noexcept
33 double doubleDate(const QString &stringDate) noexcept
31 {
34 {
32 auto dateTime = QDateTime::fromString(stringDate, DATE_FORMAT);
35 auto dateTime = QDateTime::fromString(stringDate, DATE_FORMAT);
33 return dateTime.isValid() ? (dateTime.toMSecsSinceEpoch() / 1000.)
36 return dateTime.isValid() ? (dateTime.toMSecsSinceEpoch() / 1000.)
34 : std::numeric_limits<double>::quiet_NaN();
37 : std::numeric_limits<double>::quiet_NaN();
35 }
38 }
36
39
37 /**
40 /**
38 * Reads stream to retrieve x-axis unit
41 * Reads stream to retrieve x-axis unit
39 * @param stream the stream to read
42 * @param stream the stream to read
40 * @return the unit that has been read in the stream, a default unit (time unit with no label) if an
43 * @return the unit that has been read in the stream, a default unit (time unit with no label) if an
41 * error occured during reading
44 * error occured during reading
42 */
45 */
43 Unit readXAxisUnit(QTextStream &stream)
46 Unit readXAxisUnit(QTextStream &stream)
44 {
47 {
45 QString line{};
48 QString line{};
46
49
47 if (stream.readLineInto(&line)) {
50 if (stream.readLineInto(&line)) {
48 auto match = UNIT_REGEX.match(line);
51 auto match = UNIT_REGEX.match(line);
49 if (match.hasMatch()) {
52 if (match.hasMatch()) {
50 return Unit{match.captured(1), true};
53 return Unit{match.captured(1), true};
51 }
54 }
52 else {
55 else {
53 qCWarning(LOG_AmdaResultParser())
56 qCWarning(LOG_AmdaResultParser())
54 << QObject::tr("Can't read unit: invalid line %1").arg(line);
57 << QObject::tr("Can't read unit: invalid line %1").arg(line);
55 }
58 }
56 }
59 }
57 else {
60 else {
58 qCWarning(LOG_AmdaResultParser()) << QObject::tr("Can't read unit: end of file");
61 qCWarning(LOG_AmdaResultParser()) << QObject::tr("Can't read unit: end of file");
59 }
62 }
60
63
61 // Error cases
64 // Error cases
62 return Unit{{}, true};
65 return Unit{{}, true};
63 }
66 }
64
67
65 /**
68 /**
66 * Reads stream to retrieve results
69 * Reads stream to retrieve results
67 * @param stream the stream to read
70 * @param stream the stream to read
68 * @return the pair of vectors x-axis data/values data that has been read in the stream
71 * @return the pair of vectors x-axis data/values data that has been read in the stream
69 */
72 */
70 QPair<QVector<double>, QVector<double> > readResults(QTextStream &stream)
73 QPair<QVector<double>, QVector<double> > readResults(QTextStream &stream)
71 {
74 {
72 auto xData = QVector<double>{};
75 auto xData = QVector<double>{};
73 auto valuesData = QVector<double>{};
76 auto valuesData = QVector<double>{};
74
77
75 QString line{};
78 QString line{};
76 while (stream.readLineInto(&line)) {
79 while (stream.readLineInto(&line)) {
77 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
80 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
78 if (lineData.size() == 2) {
81 if (lineData.size() == 2) {
79 // X : the data is converted from date to double (in secs)
82 // X : the data is converted from date to double (in secs)
80 auto x = doubleDate(lineData.at(0));
83 auto x = doubleDate(lineData.at(0));
81
84
82 // Value
85 // Value
83 bool valueOk;
86 bool valueOk;
84 auto value = lineData.at(1).toDouble(&valueOk);
87 auto value = lineData.at(1).toDouble(&valueOk);
85
88
86 // Adds result only if x and value are valid
89 // Adds result only if x and value are valid
87 if (!std::isnan(x) && !std::isnan(value) && valueOk) {
90 if (!std::isnan(x) && !std::isnan(value) && valueOk) {
88 xData.push_back(x);
91 xData.push_back(x);
89 valuesData.push_back(value);
92 valuesData.push_back(value);
90 }
93 }
91 else {
94 else {
92 qCWarning(LOG_AmdaResultParser())
95 qCWarning(LOG_AmdaResultParser())
93 << QObject::tr(
96 << QObject::tr(
94 "Can't retrieve results from line %1: x and/or value are invalid")
97 "Can't retrieve results from line %1: x and/or value are invalid")
95 .arg(line);
98 .arg(line);
96 }
99 }
97 }
100 }
98 else {
101 else {
99 qCWarning(LOG_AmdaResultParser())
102 qCWarning(LOG_AmdaResultParser())
100 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
103 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
101 }
104 }
102 }
105 }
103
106
104 return qMakePair(std::move(xData), std::move(valuesData));
107 return qMakePair(std::move(xData), std::move(valuesData));
105 }
108 }
106
109
107 } // namespace
110 } // namespace
108
111
109 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath) noexcept
112 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath) noexcept
110 {
113 {
111 QFile file{filePath};
114 QFile file{filePath};
112
115
113 if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
116 if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
114 qCCritical(LOG_AmdaResultParser())
117 qCCritical(LOG_AmdaResultParser())
115 << QObject::tr("Can't retrieve AMDA data from file %1: %2")
118 << QObject::tr("Can't retrieve AMDA data from file %1: %2")
116 .arg(filePath, file.errorString());
119 .arg(filePath, file.errorString());
117 return nullptr;
120 return nullptr;
118 }
121 }
119
122
120 QTextStream stream{&file};
123 QTextStream stream{&file};
121
124
122 // Ignore first two lines (comments lines)
125 // Checks if the file was found on the server
123 stream.readLine();
126 auto firstLine = stream.readLine();
127 if (firstLine.compare(FILE_NOT_FOUND_MESSAGE) == 0) {
128 qCCritical(LOG_AmdaResultParser())
129 << QObject::tr("Can't retrieve AMDA data from file %1: file was not found on server")
130 .arg(filePath);
131 return nullptr;
132 }
133
134 // Ignore comments lines
124 stream.readLine();
135 stream.readLine();
125
136
126 // Reads x-axis unit
137 // Reads x-axis unit
127 auto xAxisUnit = readXAxisUnit(stream);
138 auto xAxisUnit = readXAxisUnit(stream);
128
139
129 // Reads results
140 // Reads results
130 auto results = readResults(stream);
141 auto results = readResults(stream);
131
142
132 return std::make_shared<ScalarSeries>(std::move(results.first), std::move(results.second),
143 return std::make_shared<ScalarSeries>(std::move(results.first), std::move(results.second),
133 xAxisUnit, Unit{});
144 xAxisUnit, Unit{});
134 }
145 }
@@ -1,179 +1,182
1 #include "AmdaResultParser.h"
1 #include "AmdaResultParser.h"
2
2
3 #include <Data/ScalarSeries.h>
3 #include <Data/ScalarSeries.h>
4
4
5 #include <QObject>
5 #include <QObject>
6 #include <QtTest>
6 #include <QtTest>
7
7
8 namespace {
8 namespace {
9
9
10 /// Path for the tests
10 /// Path for the tests
11 const auto TESTS_RESOURCES_PATH
11 const auto TESTS_RESOURCES_PATH
12 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaResultParser"}.absoluteFilePath();
12 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaResultParser"}.absoluteFilePath();
13
13
14 QString inputFilePath(const QString &inputFileName)
14 QString inputFilePath(const QString &inputFileName)
15 {
15 {
16 return QFileInfo{TESTS_RESOURCES_PATH, inputFileName}.absoluteFilePath();
16 return QFileInfo{TESTS_RESOURCES_PATH, inputFileName}.absoluteFilePath();
17 }
17 }
18
18
19 struct ExpectedResults {
19 struct ExpectedResults {
20 explicit ExpectedResults() = default;
20 explicit ExpectedResults() = default;
21
21
22 /// Ctor with QVector<QDateTime> as x-axis data. Datetimes are converted to doubles
22 /// Ctor with QVector<QDateTime> as x-axis data. Datetimes are converted to doubles
23 explicit ExpectedResults(Unit xAxisUnit, Unit valuesUnit, const QVector<QDateTime> &xAxisData,
23 explicit ExpectedResults(Unit xAxisUnit, Unit valuesUnit, const QVector<QDateTime> &xAxisData,
24 QVector<double> valuesData)
24 QVector<double> valuesData)
25 : m_ParsingOK{true},
25 : m_ParsingOK{true},
26 m_XAxisUnit{xAxisUnit},
26 m_XAxisUnit{xAxisUnit},
27 m_ValuesUnit{valuesUnit},
27 m_ValuesUnit{valuesUnit},
28 m_XAxisData{},
28 m_XAxisData{},
29 m_ValuesData{std::move(valuesData)}
29 m_ValuesData{std::move(valuesData)}
30 {
30 {
31 // Converts QVector<QDateTime> to QVector<double>
31 // Converts QVector<QDateTime> to QVector<double>
32 std::transform(xAxisData.cbegin(), xAxisData.cend(), std::back_inserter(m_XAxisData),
32 std::transform(xAxisData.cbegin(), xAxisData.cend(), std::back_inserter(m_XAxisData),
33 [](const auto &dateTime) { return dateTime.toMSecsSinceEpoch() / 1000.; });
33 [](const auto &dateTime) { return dateTime.toMSecsSinceEpoch() / 1000.; });
34 }
34 }
35
35
36 /**
36 /**
37 * Validates a DataSeries compared to the expected results
37 * Validates a DataSeries compared to the expected results
38 * @param results the DataSeries to validate
38 * @param results the DataSeries to validate
39 */
39 */
40 void validate(std::shared_ptr<IDataSeries> results)
40 void validate(std::shared_ptr<IDataSeries> results)
41 {
41 {
42 if (m_ParsingOK) {
42 if (m_ParsingOK) {
43 auto scalarSeries = dynamic_cast<ScalarSeries *>(results.get());
43 auto scalarSeries = dynamic_cast<ScalarSeries *>(results.get());
44 QVERIFY(scalarSeries != nullptr);
44 QVERIFY(scalarSeries != nullptr);
45
45
46 // Checks units
46 // Checks units
47 QVERIFY(scalarSeries->xAxisUnit() == m_XAxisUnit);
47 QVERIFY(scalarSeries->xAxisUnit() == m_XAxisUnit);
48 QVERIFY(scalarSeries->valuesUnit() == m_ValuesUnit);
48 QVERIFY(scalarSeries->valuesUnit() == m_ValuesUnit);
49
49
50 // Checks values
50 // Checks values
51 QVERIFY(scalarSeries->xAxisData()->data() == m_XAxisData);
51 QVERIFY(scalarSeries->xAxisData()->data() == m_XAxisData);
52 QVERIFY(scalarSeries->valuesData()->data() == m_ValuesData);
52 QVERIFY(scalarSeries->valuesData()->data() == m_ValuesData);
53 }
53 }
54 else {
54 else {
55 QVERIFY(results == nullptr);
55 QVERIFY(results == nullptr);
56 }
56 }
57 }
57 }
58
58
59 // Parsing was successfully completed
59 // Parsing was successfully completed
60 bool m_ParsingOK{false};
60 bool m_ParsingOK{false};
61 // Expected x-axis unit
61 // Expected x-axis unit
62 Unit m_XAxisUnit{};
62 Unit m_XAxisUnit{};
63 // Expected values unit
63 // Expected values unit
64 Unit m_ValuesUnit{};
64 Unit m_ValuesUnit{};
65 // Expected x-axis data
65 // Expected x-axis data
66 QVector<double> m_XAxisData{};
66 QVector<double> m_XAxisData{};
67 // Expected values data
67 // Expected values data
68 QVector<double> m_ValuesData{};
68 QVector<double> m_ValuesData{};
69 };
69 };
70
70
71 } // namespace
71 } // namespace
72
72
73 Q_DECLARE_METATYPE(ExpectedResults)
73 Q_DECLARE_METATYPE(ExpectedResults)
74
74
75 class TestAmdaResultParser : public QObject {
75 class TestAmdaResultParser : public QObject {
76 Q_OBJECT
76 Q_OBJECT
77 private slots:
77 private slots:
78 /// Input test data
78 /// Input test data
79 /// @sa testTxtJson()
79 /// @sa testTxtJson()
80 void testReadTxt_data();
80 void testReadTxt_data();
81
81
82 /// Tests parsing of a TXT file
82 /// Tests parsing of a TXT file
83 void testReadTxt();
83 void testReadTxt();
84 };
84 };
85
85
86 void TestAmdaResultParser::testReadTxt_data()
86 void TestAmdaResultParser::testReadTxt_data()
87 {
87 {
88 // ////////////// //
88 // ////////////// //
89 // Test structure //
89 // Test structure //
90 // ////////////// //
90 // ////////////// //
91
91
92 // Name of TXT file to read
92 // Name of TXT file to read
93 QTest::addColumn<QString>("inputFileName");
93 QTest::addColumn<QString>("inputFileName");
94 // Expected results
94 // Expected results
95 QTest::addColumn<ExpectedResults>("expectedResults");
95 QTest::addColumn<ExpectedResults>("expectedResults");
96
96
97 // ////////// //
97 // ////////// //
98 // Test cases //
98 // Test cases //
99 // ////////// //
99 // ////////// //
100
100
101 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
101 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
102 return QDateTime{{year, month, day}, {hours, minutes, seconds}};
102 return QDateTime{{year, month, day}, {hours, minutes, seconds}};
103 };
103 };
104
104
105 // Valid file
105 // Valid file
106 QTest::newRow("Valid file")
106 QTest::newRow("Valid file")
107 << QStringLiteral("ValidScalar1.txt")
107 << QStringLiteral("ValidScalar1.txt")
108 << ExpectedResults{
108 << ExpectedResults{
109 Unit{QStringLiteral("nT"), true}, Unit{},
109 Unit{QStringLiteral("nT"), true}, Unit{},
110 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
110 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
111 dateTime(2013, 9, 23, 9, 2, 30), dateTime(2013, 9, 23, 9, 3, 30),
111 dateTime(2013, 9, 23, 9, 2, 30), dateTime(2013, 9, 23, 9, 3, 30),
112 dateTime(2013, 9, 23, 9, 4, 30), dateTime(2013, 9, 23, 9, 5, 30),
112 dateTime(2013, 9, 23, 9, 4, 30), dateTime(2013, 9, 23, 9, 5, 30),
113 dateTime(2013, 9, 23, 9, 6, 30), dateTime(2013, 9, 23, 9, 7, 30),
113 dateTime(2013, 9, 23, 9, 6, 30), dateTime(2013, 9, 23, 9, 7, 30),
114 dateTime(2013, 9, 23, 9, 8, 30), dateTime(2013, 9, 23, 9, 9, 30)},
114 dateTime(2013, 9, 23, 9, 8, 30), dateTime(2013, 9, 23, 9, 9, 30)},
115 QVector<double>{-2.83950, -2.71850, -2.52150, -2.57633, -2.58050, -2.48325, -2.63025,
115 QVector<double>{-2.83950, -2.71850, -2.52150, -2.57633, -2.58050, -2.48325, -2.63025,
116 -2.55800, -2.43250, -2.42200}};
116 -2.55800, -2.43250, -2.42200}};
117
117
118 // Valid files but with some invalid lines (wrong unit, wrong values, etc.)
118 // Valid files but with some invalid lines (wrong unit, wrong values, etc.)
119 QTest::newRow("No unit file") << QStringLiteral("NoUnit.txt")
119 QTest::newRow("No unit file") << QStringLiteral("NoUnit.txt")
120 << ExpectedResults{Unit{QStringLiteral(""), true}, Unit{},
120 << ExpectedResults{Unit{QStringLiteral(""), true}, Unit{},
121 QVector<QDateTime>{}, QVector<double>{}};
121 QVector<QDateTime>{}, QVector<double>{}};
122 QTest::newRow("Wrong unit file")
122 QTest::newRow("Wrong unit file")
123 << QStringLiteral("WrongUnit.txt")
123 << QStringLiteral("WrongUnit.txt")
124 << ExpectedResults{Unit{QStringLiteral(""), true}, Unit{},
124 << ExpectedResults{Unit{QStringLiteral(""), true}, Unit{},
125 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30),
125 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30),
126 dateTime(2013, 9, 23, 9, 1, 30),
126 dateTime(2013, 9, 23, 9, 1, 30),
127 dateTime(2013, 9, 23, 9, 2, 30)},
127 dateTime(2013, 9, 23, 9, 2, 30)},
128 QVector<double>{-2.83950, -2.71850, -2.52150}};
128 QVector<double>{-2.83950, -2.71850, -2.52150}};
129
129
130 QTest::newRow("Wrong results file (date of first line is invalid")
130 QTest::newRow("Wrong results file (date of first line is invalid")
131 << QStringLiteral("WrongDate.txt")
131 << QStringLiteral("WrongDate.txt")
132 << ExpectedResults{
132 << ExpectedResults{
133 Unit{QStringLiteral("nT"), true}, Unit{},
133 Unit{QStringLiteral("nT"), true}, Unit{},
134 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
134 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
135 QVector<double>{-2.71850, -2.52150}};
135 QVector<double>{-2.71850, -2.52150}};
136
136
137 QTest::newRow("Wrong results file (too many values for first line")
137 QTest::newRow("Wrong results file (too many values for first line")
138 << QStringLiteral("TooManyValues.txt")
138 << QStringLiteral("TooManyValues.txt")
139 << ExpectedResults{
139 << ExpectedResults{
140 Unit{QStringLiteral("nT"), true}, Unit{},
140 Unit{QStringLiteral("nT"), true}, Unit{},
141 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
141 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
142 QVector<double>{-2.71850, -2.52150}};
142 QVector<double>{-2.71850, -2.52150}};
143
143
144 QTest::newRow("Wrong results file (value of first line is invalid")
144 QTest::newRow("Wrong results file (value of first line is invalid")
145 << QStringLiteral("WrongValue.txt")
145 << QStringLiteral("WrongValue.txt")
146 << ExpectedResults{
146 << ExpectedResults{
147 Unit{QStringLiteral("nT"), true}, Unit{},
147 Unit{QStringLiteral("nT"), true}, Unit{},
148 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
148 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
149 QVector<double>{-2.71850, -2.52150}};
149 QVector<double>{-2.71850, -2.52150}};
150
150
151 QTest::newRow("Wrong results file (value of first line is NaN")
151 QTest::newRow("Wrong results file (value of first line is NaN")
152 << QStringLiteral("NaNValue.txt")
152 << QStringLiteral("NaNValue.txt")
153 << ExpectedResults{
153 << ExpectedResults{
154 Unit{QStringLiteral("nT"), true}, Unit{},
154 Unit{QStringLiteral("nT"), true}, Unit{},
155 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
155 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
156 QVector<double>{-2.71850, -2.52150}};
156 QVector<double>{-2.71850, -2.52150}};
157
157
158 // Invalid file
158 // Invalid files
159 QTest::newRow("Invalid file (unexisting file)") << QStringLiteral("UnexistingFile.txt")
159 QTest::newRow("Invalid file (unexisting file)") << QStringLiteral("UnexistingFile.txt")
160 << ExpectedResults{};
160 << ExpectedResults{};
161
162 QTest::newRow("Invalid file (file not found on server)") << QStringLiteral("FileNotFound.txt")
163 << ExpectedResults{};
161 }
164 }
162
165
163 void TestAmdaResultParser::testReadTxt()
166 void TestAmdaResultParser::testReadTxt()
164 {
167 {
165 QFETCH(QString, inputFileName);
168 QFETCH(QString, inputFileName);
166 QFETCH(ExpectedResults, expectedResults);
169 QFETCH(ExpectedResults, expectedResults);
167
170
168 // Parses file
171 // Parses file
169 auto filePath = inputFilePath(inputFileName);
172 auto filePath = inputFilePath(inputFileName);
170 auto results = AmdaResultParser::readTxt(filePath);
173 auto results = AmdaResultParser::readTxt(filePath);
171
174
172 // ///////////////// //
175 // ///////////////// //
173 // Validates results //
176 // Validates results //
174 // ///////////////// //
177 // ///////////////// //
175 expectedResults.validate(results);
178 expectedResults.validate(results);
176 }
179 }
177
180
178 QTEST_MAIN(TestAmdaResultParser)
181 QTEST_MAIN(TestAmdaResultParser)
179 #include "TestAmdaResultParser.moc"
182 #include "TestAmdaResultParser.moc"
@@ -1,25 +1,33
1 #ifndef SCIQLOP_COSINUSPROVIDER_H
1 #ifndef SCIQLOP_COSINUSPROVIDER_H
2 #define SCIQLOP_COSINUSPROVIDER_H
2 #define SCIQLOP_COSINUSPROVIDER_H
3
3
4 #include "MockPluginGlobal.h"
4 #include "MockPluginGlobal.h"
5
5
6 #include <Data/IDataProvider.h>
6 #include <Data/IDataProvider.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QUuid>
9
10
11 #include <QHash>
10 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
11
13
12 /**
14 /**
13 * @brief The CosinusProvider class is an example of how a data provider can generate data
15 * @brief The CosinusProvider class is an example of how a data provider can generate data
14 */
16 */
15 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
17 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
16 public:
18 public:
19 /// @sa IDataProvider::requestDataLoading(). The current impl isn't thread safe.
17 void requestDataLoading(QUuid token, const DataProviderParameters &parameters) override;
20 void requestDataLoading(QUuid token, const DataProviderParameters &parameters) override;
18
21
19
22
23 /// @sa IDataProvider::requestDataAborting(). The current impl isn't thread safe.
24 void requestDataAborting(QUuid identifier) override;
25
26
20 private:
27 private:
21 /// @sa IDataProvider::retrieveData()
28 std::shared_ptr<IDataSeries> retrieveData(QUuid token, const SqpDateTime &dateTime);
22 std::shared_ptr<IDataSeries> retrieveData(const SqpDateTime &dateTime) const;
29
30 QHash<QUuid, bool> m_VariableToEnableProvider;
23 };
31 };
24
32
25 #endif // SCIQLOP_COSINUSPROVIDER_H
33 #endif // SCIQLOP_COSINUSPROVIDER_H
@@ -1,48 +1,95
1 #include "CosinusProvider.h"
1 #include "CosinusProvider.h"
2
2
3 #include <Data/DataProviderParameters.h>
3 #include <Data/DataProviderParameters.h>
4 #include <Data/ScalarSeries.h>
4 #include <Data/ScalarSeries.h>
5
5
6 #include <cmath>
6 #include <cmath>
7
7
8 #include <QDateTime>
8 #include <QDateTime>
9 #include <QFuture>
9 #include <QThread>
10 #include <QThread>
11 #include <QtConcurrent/QtConcurrent>
10
12
11 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
13 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
12
14
13 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(const SqpDateTime &dateTime) const
15 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(QUuid token, const SqpDateTime &dateTime)
14 {
16 {
17 // TODO: Add Mutex
15 auto dataIndex = 0;
18 auto dataIndex = 0;
16
19
17 // Gets the timerange from the parameters
20 // Gets the timerange from the parameters
18 double freq = 100.0;
21 double freq = 100.0;
19 double start = dateTime.m_TStart * freq; // 100 htz
22 double start = dateTime.m_TStart * freq; // 100 htz
20 double end = dateTime.m_TEnd * freq; // 100 htz
23 double end = dateTime.m_TEnd * freq; // 100 htz
21
24
22 // We assure that timerange is valid
25 // We assure that timerange is valid
23 if (end < start) {
26 if (end < start) {
24 std::swap(start, end);
27 std::swap(start, end);
25 }
28 }
26
29
27 // Generates scalar series containing cosinus values (one value per second)
30 // Generates scalar series containing cosinus values (one value per second)
28 auto scalarSeries
31 auto scalarSeries
29 = std::make_shared<ScalarSeries>(end - start, Unit{QStringLiteral("t"), true}, Unit{});
32 = std::make_shared<ScalarSeries>(end - start, Unit{QStringLiteral("t"), true}, Unit{});
30
33
34
35 int progress = 0;
36 auto progressEnd = end - start;
31 for (auto time = start; time < end; ++time, ++dataIndex) {
37 for (auto time = start; time < end; ++time, ++dataIndex) {
32 const auto timeOnFreq = time / freq;
38 auto it = m_VariableToEnableProvider.find(token);
33 scalarSeries->setData(dataIndex, timeOnFreq, std::cos(timeOnFreq));
39 if (it != m_VariableToEnableProvider.end() && it.value()) {
40 const auto timeOnFreq = time / freq;
41 scalarSeries->setData(dataIndex, timeOnFreq, std::cos(timeOnFreq));
42
43 // progression
44 int currentProgress = (time - start) * 100.0 / progressEnd;
45 if (currentProgress != progress) {
46 progress = currentProgress;
47
48 emit dataProvidedProgress(token, progress);
49 }
50 }
51 else {
52 if (!it.value()) {
53 qCDebug(LOG_CosinusProvider())
54 << "CosinusProvider::retrieveData: ARRET De l'acquisition detectΓ©"
55 << end - time;
56 }
57 }
34 }
58 }
59 emit dataProvidedProgress(token, 0.0);
60
61
35 return scalarSeries;
62 return scalarSeries;
36 }
63 }
37
64
38 void CosinusProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
65 void CosinusProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
39 {
66 {
67 // TODO: Add Mutex
68 m_VariableToEnableProvider[token] = true;
40 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataLoading"
69 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataLoading"
41 << QThread::currentThread()->objectName();
70 << QThread::currentThread()->objectName();
42 // NOTE: Try to use multithread if possible
71 // NOTE: Try to use multithread if possible
43 const auto times = parameters.m_Times;
72 const auto times = parameters.m_Times;
73
44 for (const auto &dateTime : qAsConst(times)) {
74 for (const auto &dateTime : qAsConst(times)) {
45 auto scalarSeries = this->retrieveData(dateTime);
75 if (m_VariableToEnableProvider[token]) {
46 emit dataProvided(token, scalarSeries, dateTime);
76 auto scalarSeries = this->retrieveData(token, dateTime);
77 emit dataProvided(token, scalarSeries, dateTime);
78 }
79 }
80 }
81
82 void CosinusProvider::requestDataAborting(QUuid identifier)
83 {
84 // TODO: Add Mutex
85 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << identifier
86 << QThread::currentThread()->objectName();
87 auto it = m_VariableToEnableProvider.find(identifier);
88 if (it != m_VariableToEnableProvider.end()) {
89 it.value() = false;
90 }
91 else {
92 qCWarning(LOG_CosinusProvider())
93 << tr("Aborting progression of inexistant identifier detected !!!");
47 }
94 }
48 }
95 }
General Comments 0
You need to be logged in to leave comments. Login now