##// END OF EJS Templates
Merge branch 'feature/DownloadWhenTolIsOutsideCache' into develop
perrinel -
r405:632636b095ab 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, removes 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 }
@@ -1,265 +1,269
1 1 /*------------------------------------------------------------------------------
2 2 -- This file is a part of the SciQLop Software
3 3 -- Copyright (C) 2017, Plasma Physics Laboratory - CNRS
4 4 --
5 5 -- This program is free software; you can redistribute it and/or modify
6 6 -- it under the terms of the GNU General Public License as published by
7 7 -- the Free Software Foundation; either version 2 of the License, or
8 8 -- (at your option) any later version.
9 9 --
10 10 -- This program is distributed in the hope that it will be useful,
11 11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 -- GNU General Public License for more details.
14 14 --
15 15 -- You should have received a copy of the GNU General Public License
16 16 -- along with this program; if not, write to the Free Software
17 17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 18 -------------------------------------------------------------------------------*/
19 19 /*-- Author : Alexis Jeandet
20 20 -- Mail : alexis.jeandet@member.fsf.org
21 21 ----------------------------------------------------------------------------*/
22 22 #include "MainWindow.h"
23 23 #include "ui_MainWindow.h"
24 24
25 25 #include <DataSource/DataSourceController.h>
26 26 #include <DataSource/DataSourceWidget.h>
27 27 #include <SidePane/SqpSidePane.h>
28 28 #include <SqpApplication.h>
29 29 #include <Time/TimeController.h>
30 30 #include <TimeWidget/TimeWidget.h>
31 31 #include <Variable/Variable.h>
32 32 #include <Variable/VariableController.h>
33 33 #include <Visualization/VisualizationController.h>
34 34
35 35 #include <QAction>
36 36 #include <QDate>
37 37 #include <QDateTime>
38 38 #include <QDir>
39 39 #include <QFileDialog>
40 40 #include <QToolBar>
41 41 #include <QToolButton>
42 42 #include <memory.h>
43 43
44 44 //#include <omp.h>
45 45 //#include <network/filedownloader.h>
46 46 //#include <qlopdatabase.h>
47 47 //#include <qlopsettings.h>
48 48 //#include <qlopgui.h>
49 49 //#include <spacedata.h>
50 50 //#include "qlopcore.h"
51 51 //#include "qlopcodecmanager.h"
52 52 //#include "cdfcodec.h"
53 53 //#include "amdatxtcodec.h"
54 54 //#include <qlopplotmanager.h>
55 55
56 56 #include "iostream"
57 57
58 58 Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow")
59 59
60 60 namespace {
61 61 const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0;
62 62 const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1;
63 63 const auto VIEWPLITTERINDEX = 2;
64 64 const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3;
65 65 const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4;
66 66 }
67 67
68 68 class MainWindow::MainWindowPrivate {
69 69 public:
70 70 QSize m_LastOpenLeftInspectorSize;
71 71 QSize m_LastOpenRightInspectorSize;
72 72 };
73 73
74 74 MainWindow::MainWindow(QWidget *parent)
75 75 : QMainWindow{parent},
76 76 m_Ui{new Ui::MainWindow},
77 77 impl{spimpl::make_unique_impl<MainWindowPrivate>()}
78 78 {
79 79 m_Ui->setupUi(this);
80 80
81 81 m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false);
82 82 m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false);
83 83
84 84
85 85 auto leftSidePane = m_Ui->leftInspectorSidePane->sidePane();
86 86 auto openLeftInspectorAction = new QAction{QIcon{
87 87 ":/icones/previous.png",
88 88 },
89 89 tr("Show/hide the left inspector"), this};
90 90
91 91
92 92 auto spacerLeftTop = new QWidget{};
93 93 spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
94 94
95 95 auto spacerLeftBottom = new QWidget{};
96 96 spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
97 97
98 98 leftSidePane->addWidget(spacerLeftTop);
99 99 leftSidePane->addAction(openLeftInspectorAction);
100 100 leftSidePane->addWidget(spacerLeftBottom);
101 101
102 102
103 103 auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane();
104 104 auto openRightInspectorAction = new QAction{QIcon{
105 105 ":/icones/next.png",
106 106 },
107 107 tr("Show/hide the right inspector"), this};
108 108
109 109 auto spacerRightTop = new QWidget{};
110 110 spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
111 111
112 112 auto spacerRightBottom = new QWidget{};
113 113 spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
114 114
115 115 rightSidePane->addWidget(spacerRightTop);
116 116 rightSidePane->addAction(openRightInspectorAction);
117 117 rightSidePane->addWidget(spacerRightBottom);
118 118
119 119 openLeftInspectorAction->setCheckable(true);
120 120 openRightInspectorAction->setCheckable(true);
121 121
122 122 auto openInspector = [this](bool checked, bool right, auto action) {
123 123
124 124 action->setIcon(QIcon{(checked xor right) ? ":/icones/next.png" : ":/icones/previous.png"});
125 125
126 126 auto &lastInspectorSize
127 127 = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize;
128 128
129 129 auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size()
130 130 : m_Ui->leftMainInspectorWidget->size();
131 131
132 132 // Update of the last opened geometry
133 133 if (checked) {
134 134 lastInspectorSize = nextInspectorSize;
135 135 }
136 136
137 137 auto startSize = lastInspectorSize;
138 138 auto endSize = startSize;
139 139 endSize.setWidth(0);
140 140
141 141 auto splitterInspectorIndex
142 142 = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX;
143 143
144 144 auto currentSizes = m_Ui->splitter->sizes();
145 145 if (checked) {
146 146 // adjust sizes individually here, e.g.
147 147 currentSizes[splitterInspectorIndex] -= lastInspectorSize.width();
148 148 currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width();
149 149 m_Ui->splitter->setSizes(currentSizes);
150 150 }
151 151 else {
152 152 // adjust sizes individually here, e.g.
153 153 currentSizes[splitterInspectorIndex] += lastInspectorSize.width();
154 154 currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width();
155 155 m_Ui->splitter->setSizes(currentSizes);
156 156 }
157 157
158 158 };
159 159
160 160
161 161 connect(openLeftInspectorAction, &QAction::triggered,
162 162 [openInspector, openLeftInspectorAction](bool checked) {
163 163 openInspector(checked, false, openLeftInspectorAction);
164 164 });
165 165 connect(openRightInspectorAction, &QAction::triggered,
166 166 [openInspector, openRightInspectorAction](bool checked) {
167 167 openInspector(checked, true, openRightInspectorAction);
168 168 });
169 169
170 170 this->menuBar()->addAction(tr("File"));
171 171 auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar"));
172 172
173 173 auto timeWidget = new TimeWidget{};
174 174 mainToolBar->addWidget(timeWidget);
175 175
176 176 // Controllers / controllers connections
177 177 connect(&sqpApp->timeController(), SIGNAL(timeUpdated(SqpDateTime)),
178 178 &sqpApp->variableController(), SLOT(onDateTimeOnSelection(SqpDateTime)));
179 179
180 180 // Widgets / controllers connections
181 181
182 182 // DataSource
183 183 connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)),
184 184 m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem *)));
185 185
186 186 // Time
187 187 connect(timeWidget, SIGNAL(timeUpdated(SqpDateTime)), &sqpApp->timeController(),
188 188 SLOT(onTimeToUpdate(SqpDateTime)));
189 189
190 190 // Visualization
191 191 connect(&sqpApp->visualizationController(),
192 192 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), m_Ui->view,
193 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 199 // Widgets / widgets connections
196 200
197 201 // For the following connections, we use DirectConnection to allow each widget that can
198 202 // potentially attach a menu to the variable's menu to do so before this menu is displayed.
199 203 // The order of connections is also important, since it determines the order in which each
200 204 // widget will attach its menu
201 205 connect(
202 206 m_Ui->variableInspectorWidget,
203 207 SIGNAL(tableMenuAboutToBeDisplayed(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
204 208 m_Ui->view, SLOT(attachVariableMenu(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
205 209 Qt::DirectConnection);
206 210
207 211 /* QLopGUI::registerMenuBar(menuBar());
208 212 this->setWindowIcon(QIcon(":/sciqlopLOGO.svg"));
209 213 this->m_progressWidget = new QWidget();
210 214 this->m_progressLayout = new QVBoxLayout(this->m_progressWidget);
211 215 this->m_progressWidget->setLayout(this->m_progressLayout);
212 216 this->m_progressWidget->setWindowModality(Qt::WindowModal);
213 217 m_progressThreadIds = (int*) malloc(OMP_THREADS*sizeof(int));
214 218 for(int i=0;i<OMP_THREADS;i++)
215 219 {
216 220 this->m_progress.append(new QProgressBar(this->m_progressWidget));
217 221 this->m_progress.last()->setMinimum(0);
218 222 this->m_progress.last()->setMaximum(100);
219 223 this->m_progressLayout->addWidget(this->m_progress.last());
220 224 this->m_progressWidget->hide();
221 225 this->m_progressThreadIds[i] = -1;
222 226 }
223 227 this->m_progressWidget->setWindowTitle("Loading File");
224 228 const QList<QLopService*>ServicesToLoad=QList<QLopService*>()
225 229 << QLopCore::self()
226 230 << QLopPlotManager::self()
227 231 << QLopCodecManager::self()
228 232 << FileDownloader::self()
229 233 << QLopDataBase::self()
230 234 << SpaceData::self();
231 235
232 236 CDFCodec::registerToManager();
233 237 AMDATXTCodec::registerToManager();
234 238
235 239
236 240 for(int i=0;i<ServicesToLoad.count();i++)
237 241 {
238 242 qDebug()<<ServicesToLoad.at(i)->serviceName();
239 243 ServicesToLoad.at(i)->initialize(); //must be called before getGUI
240 244 QDockWidget* wdgt=ServicesToLoad.at(i)->getGUI();
241 245 if(wdgt)
242 246 {
243 247 wdgt->setAllowedAreas(Qt::AllDockWidgetAreas);
244 248 this->addDockWidget(Qt::TopDockWidgetArea,wdgt);
245 249 }
246 250 PythonQt::self()->getMainModule().addObject(ServicesToLoad.at(i)->serviceName(),(QObject*)ServicesToLoad.at(i));
247 251 }*/
248 252 }
249 253
250 254 MainWindow::~MainWindow()
251 255 {
252 256 }
253 257
254 258
255 259 void MainWindow::changeEvent(QEvent *e)
256 260 {
257 261 QMainWindow::changeEvent(e);
258 262 switch (e->type()) {
259 263 case QEvent::LanguageChange:
260 264 m_Ui->retranslateUi(this);
261 265 break;
262 266 default:
263 267 break;
264 268 }
265 269 }
@@ -1,70 +1,72
1 1 #ifndef SCIQLOP_IDATAPROVIDER_H
2 2 #define SCIQLOP_IDATAPROVIDER_H
3 3
4 4 #include <memory>
5 5
6 6 #include <QObject>
7 7 #include <QUuid>
8 8
9 9 #include <Common/MetaTypes.h>
10 10
11 11 #include <Data/SqpDateTime.h>
12 12
13 #include <functional>
14
13 15 class DataProviderParameters;
14 16 class IDataSeries;
15 17 class QNetworkReply;
16 18 class QNetworkRequest;
17 19
18 20 /**
19 21 * @brief The IDataProvider interface aims to declare a data provider.
20 22 *
21 23 * A data provider is an entity that generates data and returns it according to various parameters
22 24 * (time interval, product to retrieve the data, etc.)
23 25 *
24 26 * @sa IDataSeries
25 27 */
26 28 class IDataProvider : public QObject {
27 29
28 30 Q_OBJECT
29 31 public:
30 32 virtual ~IDataProvider() noexcept = default;
31 33
32 34 /**
33 35 * @brief requestDataLoading provide datas for the data identified by identifier and parameters
34 36 */
35 37 virtual void requestDataLoading(QUuid identifier, const DataProviderParameters &parameters) = 0;
36 38
37 39 /**
38 40 * @brief requestDataAborting stop data loading of the data identified by identifier
39 41 */
40 42 virtual void requestDataAborting(QUuid identifier) = 0;
41 43
42 44 signals:
43 45 /**
44 46 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
45 47 * identified by identifier
46 48 */
47 49 void dataProvided(QUuid identifier, std::shared_ptr<IDataSeries> dateSerie,
48 50 const SqpDateTime &dateTime);
49 51
50 52 /**
51 53 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
52 54 * identified by identifier
53 55 */
54 56 void dataProvidedProgress(QUuid identifier, double progress);
55 57
56 58
57 59 /**
58 60 * @brief requestConstructed send a request for the data identified by identifier
59 61 * @callback is the methode call by the reply of the request when it is finished.
60 62 */
61 63 void requestConstructed(const QNetworkRequest &request, QUuid identifier,
62 64 std::function<void(QNetworkReply *, QUuid)> callback);
63 65 };
64 66
65 67 // Required for using shared_ptr in signals/slots
66 68 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
67 69 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
68 70 std::function<void(QNetworkReply *, QUuid)>)
69 71
70 72 #endif // SCIQLOP_IDATAPROVIDER_H
@@ -1,48 +1,50
1 1 #ifndef SCIQLOP_DATASOURCEITEMACTION_H
2 2 #define SCIQLOP_DATASOURCEITEMACTION_H
3 3
4 4 #include <Common/spimpl.h>
5 5
6 6 #include <QLoggingCategory>
7 7 #include <QObject>
8 8
9 #include <functional>
10
9 11 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceItemAction)
10 12
11 13 class DataSourceItem;
12 14
13 15 /**
14 16 * @brief The DataSourceItemAction class represents an action on a data source item.
15 17 *
16 18 * An action is a function that will be executed when the slot execute() is called.
17 19 */
18 20 class DataSourceItemAction : public QObject {
19 21
20 22 Q_OBJECT
21 23
22 24 public:
23 25 /// Signature of the function associated to the action
24 26 using ExecuteFunction = std::function<void(DataSourceItem &dataSourceItem)>;
25 27
26 28 /**
27 29 * Ctor
28 30 * @param name the name of the action
29 31 * @param fun the function that will be called when the action is executed
30 32 * @sa execute()
31 33 */
32 34 explicit DataSourceItemAction(const QString &name, ExecuteFunction fun);
33 35
34 36 QString name() const noexcept;
35 37
36 38 /// Sets the data source item concerned by the action
37 39 void setDataSourceItem(DataSourceItem *dataSourceItem) noexcept;
38 40
39 41 public slots:
40 42 /// Executes the action
41 43 void execute();
42 44
43 45 private:
44 46 class DataSourceItemActionPrivate;
45 47 spimpl::unique_impl_ptr<DataSourceItemActionPrivate> impl;
46 48 };
47 49
48 50 #endif // SCIQLOP_DATASOURCEITEMACTION_H
@@ -1,92 +1,95
1 1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
2 2 #define SCIQLOP_VARIABLECONTROLLER_H
3 3
4 4 #include <Data/SqpDateTime.h>
5 5
6 6 #include <QLoggingCategory>
7 7 #include <QObject>
8 8
9 9 #include <Common/spimpl.h>
10 10
11 11 class IDataProvider;
12 12 class QItemSelectionModel;
13 13 class TimeController;
14 14 class Variable;
15 15 class VariableModel;
16 16
17 17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
18 18
19 19 /**
20 20 * @brief The VariableController class aims to handle the variables in SciQlop.
21 21 */
22 22 class VariableController : public QObject {
23 23 Q_OBJECT
24 24 public:
25 25 explicit VariableController(QObject *parent = 0);
26 26 virtual ~VariableController();
27 27
28 28 VariableModel *variableModel() noexcept;
29 29 QItemSelectionModel *variableSelectionModel() noexcept;
30 30
31 31 void setTimeController(TimeController *timeController) noexcept;
32 32
33 33 /**
34 34 * Deletes from the controller the variable passed in parameter.
35 35 *
36 36 * Delete a variable includes:
37 37 * - the deletion of the various references to the variable in SciQlop
38 38 * - the deletion of the model variable
39 39 * - the deletion of the provider associated with the variable
40 40 * - removing the cache associated with the variable
41 41 *
42 42 * @param variable the variable to delete from the controller.
43 43 */
44 44 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
45 45
46 46 /**
47 47 * Deletes from the controller the variables passed in parameter.
48 48 * @param variables the variables to delete from the controller.
49 49 * @sa deleteVariable()
50 50 */
51 51 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
52 52
53 53 /**
54 54 * @brief abort the variable retrieve data progression
55 55 */
56 56 void abortProgress(std::shared_ptr<Variable> variable);
57 57
58 58 signals:
59 59 /// Signal emitted when a variable is about to be deleted from the controller
60 60 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
61 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
62 65 public slots:
63 66 /// Request the data loading of the variable whithin dateTime
64 67 void onRequestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
65 68 /**
66 69 * Creates a new variable and adds it to the model
67 70 * @param name the name of the new variable
68 71 * @param metadata the metadata of the new variable
69 72 * @param provider the data provider for the new variable
70 73 */
71 74 void createVariable(const QString &name, const QVariantHash &metadata,
72 75 std::shared_ptr<IDataProvider> provider) noexcept;
73 76
74 77 /// Update the temporal parameters of every selected variable to dateTime
75 78 void onDateTimeOnSelection(const SqpDateTime &dateTime);
76 79
77 80
78 81 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
79 82
80 83 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
81 84
82 85 void initialize();
83 86 void finalize();
84 87
85 88 private:
86 89 void waitForFinish();
87 90
88 91 class VariableControllerPrivate;
89 92 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
90 93 };
91 94
92 95 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,44 +1,49
1 1 #ifndef SCIQLOP_VISUALIZATIONCONTROLLER_H
2 2 #define SCIQLOP_VISUALIZATIONCONTROLLER_H
3 3
4 #include <Data/SqpDateTime.h>
5
4 6 #include <QLoggingCategory>
5 7 #include <QObject>
6 8 #include <QUuid>
7 9
8 10 #include <Common/spimpl.h>
9 11
10 12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationController)
11 13
12 14 class DataSourceItem;
13 15 class Variable;
14 16
15 17 /**
16 18 * @brief The VisualizationController class aims to make the link between SciQlop and its plugins.
17 19 * This is the intermediate class that SciQlop has to use in the way to connect a data source.
18 20 * Please first use register method to initialize a plugin specified by its metadata name (JSON
19 21 * plugin source) then others specifics method will be able to access it. You can load a data source
20 22 * driver plugin then create a data source.
21 23 */
22 24 class VisualizationController : public QObject {
23 25 Q_OBJECT
24 26 public:
25 27 explicit VisualizationController(QObject *parent = 0);
26 28 virtual ~VisualizationController();
27 29
28 30 signals:
29 31 /// Signal emitted when a variable is about to be deleted from SciQlop
30 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 37 public slots:
33 38 /// Manage init/end of the controller
34 39 void initialize();
35 40 void finalize();
36 41
37 42 private:
38 43 void waitForFinish();
39 44
40 45 class VisualizationControllerPrivate;
41 46 spimpl::unique_impl_ptr<VisualizationControllerPrivate> impl;
42 47 };
43 48
44 49 #endif // SCIQLOP_VISUALIZATIONCONTROLLER_H
@@ -1,90 +1,90
1 1 #include "Variable/Variable.h"
2 2
3 3 #include <Data/IDataSeries.h>
4 4 #include <Data/SqpDateTime.h>
5 5
6 6 #include <QReadWriteLock>
7 7 #include <QThread>
8 8
9 9 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
10 10
11 11 struct Variable::VariablePrivate {
12 12 explicit VariablePrivate(const QString &name, const SqpDateTime &dateTime,
13 13 const QVariantHash &metadata)
14 14 : m_Name{name}, m_DateTime{dateTime}, m_Metadata{metadata}, m_DataSeries{nullptr}
15 15 {
16 16 }
17 17
18 18 QString m_Name;
19 19
20 20 SqpDateTime m_DateTime; // The dateTime available in the view and loaded. not the cache.
21 21 QVariantHash m_Metadata;
22 22 std::unique_ptr<IDataSeries> m_DataSeries;
23 23 };
24 24
25 25 Variable::Variable(const QString &name, const SqpDateTime &dateTime, const QVariantHash &metadata)
26 26 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
27 27 {
28 28 }
29 29
30 30 QString Variable::name() const noexcept
31 31 {
32 32 return impl->m_Name;
33 33 }
34 34
35 35 SqpDateTime Variable::dateTime() const noexcept
36 36 {
37 37 return impl->m_DateTime;
38 38 }
39 39
40 40 void Variable::setDateTime(const SqpDateTime &dateTime) noexcept
41 41 {
42 42 impl->m_DateTime = dateTime;
43 43 }
44 44
45 45 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
46 46 {
47 47 qCDebug(LOG_Variable()) << "Variable::setDataSeries" << QThread::currentThread()->objectName();
48 48 if (!dataSeries) {
49 49 /// @todo ALX : log
50 50 return;
51 51 }
52 52
53 53 // Inits the data series of the variable
54 54 if (!impl->m_DataSeries) {
55 55 impl->m_DataSeries = dataSeries->clone();
56 56 }
57 57 else {
58 58 dataSeries->lockWrite();
59 59 impl->m_DataSeries->lockWrite();
60 60 impl->m_DataSeries->merge(dataSeries.get());
61 61 impl->m_DataSeries->unlock();
62 62 dataSeries->unlock();
63 emit updated();
63 // emit updated();
64 64 }
65 65 }
66 66
67 67 IDataSeries *Variable::dataSeries() const noexcept
68 68 {
69 69 return impl->m_DataSeries.get();
70 70 }
71 71
72 72 QVariantHash Variable::metadata() const noexcept
73 73 {
74 74 return impl->m_Metadata;
75 75 }
76 76
77 77 bool Variable::contains(const SqpDateTime &dateTime) const noexcept
78 78 {
79 79 return impl->m_DateTime.contains(dateTime);
80 80 }
81 81
82 82 bool Variable::intersect(const SqpDateTime &dateTime) const noexcept
83 83 {
84 84 return impl->m_DateTime.intersect(dateTime);
85 85 }
86 86
87 87 bool Variable::isInside(const SqpDateTime &dateTime) const noexcept
88 88 {
89 89 return dateTime.contains(SqpDateTime{impl->m_DateTime.m_TStart, impl->m_DateTime.m_TEnd});
90 90 }
@@ -1,240 +1,242
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableCacheController.h>
3 3 #include <Variable/VariableController.h>
4 4 #include <Variable/VariableModel.h>
5 5
6 6 #include <Data/DataProviderParameters.h>
7 7 #include <Data/IDataProvider.h>
8 8 #include <Data/IDataSeries.h>
9 9 #include <Time/TimeController.h>
10 10
11 11 #include <QDateTime>
12 12 #include <QMutex>
13 13 #include <QThread>
14 14 #include <QUuid>
15 15 #include <QtCore/QItemSelectionModel>
16 16
17 17 #include <unordered_map>
18 18
19 19 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
20 20
21 21 struct VariableController::VariableControllerPrivate {
22 22 explicit VariableControllerPrivate(VariableController *parent)
23 23 : m_WorkingMutex{},
24 24 m_VariableModel{new VariableModel{parent}},
25 25 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
26 26 m_VariableCacheController{std::make_unique<VariableCacheController>()}
27 27 {
28 28 }
29 29
30 30 QMutex m_WorkingMutex;
31 31 /// Variable model. The VariableController has the ownership
32 32 VariableModel *m_VariableModel;
33 33 QItemSelectionModel *m_VariableSelectionModel;
34 34
35 35
36 36 TimeController *m_TimeController{nullptr};
37 37 std::unique_ptr<VariableCacheController> m_VariableCacheController;
38 38
39 39 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
40 40 m_VariableToProviderMap;
41 41 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
42 42 };
43 43
44 44 VariableController::VariableController(QObject *parent)
45 45 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
46 46 {
47 47 qCDebug(LOG_VariableController()) << tr("VariableController construction")
48 48 << QThread::currentThread();
49 49
50 50 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
51 51 &VariableController::onAbortProgressRequested);
52 52 }
53 53
54 54 VariableController::~VariableController()
55 55 {
56 56 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
57 57 << QThread::currentThread();
58 58 this->waitForFinish();
59 59 }
60 60
61 61 VariableModel *VariableController::variableModel() noexcept
62 62 {
63 63 return impl->m_VariableModel;
64 64 }
65 65
66 66 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
67 67 {
68 68 return impl->m_VariableSelectionModel;
69 69 }
70 70
71 71 void VariableController::setTimeController(TimeController *timeController) noexcept
72 72 {
73 73 impl->m_TimeController = timeController;
74 74 }
75 75
76 76 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
77 77 {
78 78 if (!variable) {
79 79 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
80 80 return;
81 81 }
82 82
83 83 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
84 84 // make some treatments before the deletion
85 85 emit variableAboutToBeDeleted(variable);
86 86
87 87 // Deletes identifier
88 88 impl->m_VariableToIdentifierMap.erase(variable);
89 89
90 90 // Deletes provider
91 91 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
92 92 qCDebug(LOG_VariableController())
93 93 << tr("Number of providers deleted for variable %1: %2")
94 94 .arg(variable->name(), QString::number(nbProvidersDeleted));
95 95
96 96 // Clears cache
97 97 impl->m_VariableCacheController->clear(variable);
98 98
99 99 // Deletes from model
100 100 impl->m_VariableModel->deleteVariable(variable);
101 101 }
102 102
103 103 void VariableController::deleteVariables(
104 104 const QVector<std::shared_ptr<Variable> > &variables) noexcept
105 105 {
106 106 for (auto variable : qAsConst(variables)) {
107 107 deleteVariable(variable);
108 108 }
109 109 }
110 110
111 111 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
112 112 {
113 113 }
114 114
115 115 void VariableController::createVariable(const QString &name, const QVariantHash &metadata,
116 116 std::shared_ptr<IDataProvider> provider) noexcept
117 117 {
118 118
119 119 if (!impl->m_TimeController) {
120 120 qCCritical(LOG_VariableController())
121 121 << tr("Impossible to create variable: The time controller is null");
122 122 return;
123 123 }
124 124
125 125 auto dateTime = impl->m_TimeController->dateTime();
126 126
127 127 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime, metadata)) {
128 128 auto identifier = QUuid::createUuid();
129 129
130 130 // store the provider
131 131 impl->m_VariableToProviderMap[newVariable] = provider;
132 132 impl->m_VariableToIdentifierMap[newVariable] = identifier;
133 133
134 134 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
135 135 QUuid identifier, auto dataSeriesAcquired, auto dateTimeToPutInCache)
136 136 {
137 137 if (auto variable = varW.lock()) {
138 138 auto varIdentifier = impl->m_VariableToIdentifierMap.at(variable);
139 139 if (varIdentifier == identifier) {
140 140 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
141 141 variable->setDataSeries(dataSeriesAcquired);
142 emit variable->updated();
142 143 }
143 144 }
144 145 };
145 146
146 147 connect(provider.get(), &IDataProvider::dataProvided, addDateTimeAcquired);
147 148 connect(provider.get(), &IDataProvider::dataProvidedProgress, this,
148 149 &VariableController::onVariableRetrieveDataInProgress);
149 150 this->onRequestDataLoading(newVariable, dateTime);
150 151 }
151 152 }
152 153
153 154 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
154 155 {
155 156 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
156 157 << QThread::currentThread()->objectName();
157 158 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
158 159
159 160 for (const auto &selectedRow : qAsConst(selectedRows)) {
160 161 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
161 162 selectedVariable->setDateTime(dateTime);
162 163 this->onRequestDataLoading(selectedVariable, dateTime);
164 emit rangeChanged(selectedVariable, dateTime);
163 165 }
164 166 }
165 167 }
166 168
167 169 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
168 170 {
169 171 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
170 172
171 173 auto end = impl->m_VariableToIdentifierMap.cend();
172 174 auto it = std::find_if(impl->m_VariableToIdentifierMap.cbegin(), end, findReply);
173 175 if (it != end) {
174 176 impl->m_VariableModel->setDataProgress(it->first, progress);
175 177 }
176 178 }
177 179
178 180 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
179 181 {
180 182 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
181 183 << QThread::currentThread()->objectName();
182 184
183 185 auto it = impl->m_VariableToIdentifierMap.find(variable);
184 186 if (it != impl->m_VariableToIdentifierMap.cend()) {
185 187 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
186 188 }
187 189 else {
188 190 qCWarning(LOG_VariableController())
189 191 << tr("Aborting progression of inexistant variable detected !!!")
190 192 << QThread::currentThread()->objectName();
191 193 }
192 194 }
193 195
194 196
195 197 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
196 198 const SqpDateTime &dateTime)
197 199 {
198 200 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
199 201 << QThread::currentThread()->objectName();
200 202 // we want to load data of the variable for the dateTime.
201 203 // First we check if the cache contains some of them.
202 204 // For the other, we ask the provider to give them.
203 205 if (variable) {
204 206
205 207 auto dateTimeListNotInCache
206 208 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
207 209
208 210 if (!dateTimeListNotInCache.empty()) {
209 211 // Ask the provider for each data on the dateTimeListNotInCache
210 212 auto identifier = impl->m_VariableToIdentifierMap.at(variable);
211 213 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
212 214 identifier,
213 215 DataProviderParameters{std::move(dateTimeListNotInCache), variable->metadata()});
214 216 }
215 217 else {
216 218 emit variable->updated();
217 219 }
218 220 }
219 221 else {
220 222 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
221 223 }
222 224 }
223 225
224 226
225 227 void VariableController::initialize()
226 228 {
227 229 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
228 230 impl->m_WorkingMutex.lock();
229 231 qCDebug(LOG_VariableController()) << tr("VariableController init END");
230 232 }
231 233
232 234 void VariableController::finalize()
233 235 {
234 236 impl->m_WorkingMutex.unlock();
235 237 }
236 238
237 239 void VariableController::waitForFinish()
238 240 {
239 241 QMutexLocker locker{&impl->m_WorkingMutex};
240 242 }
@@ -1,65 +1,66
1 1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5
6 6 #include <QLoggingCategory>
7 7 #include <QWidget>
8 8
9 9 #include <memory>
10 10
11 11 #include <Common/spimpl.h>
12 12
13 13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14 14
15 15 class QCPRange;
16 16 class SqpDateTime;
17 17 class Variable;
18 18
19 19 namespace Ui {
20 20 class VisualizationGraphWidget;
21 21 } // namespace Ui
22 22
23 23 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
24 24 Q_OBJECT
25 25
26 26 public:
27 27 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
28 28 virtual ~VisualizationGraphWidget();
29 29
30 30 void addVariable(std::shared_ptr<Variable> variable);
31 31 void addVariableUsingGraph(std::shared_ptr<Variable> variable);
32 32 /// Removes a variable from the graph
33 33 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
34 34
35 /// Rescale the X axe to range parameter
36 void setRange(std::shared_ptr<Variable> variable, const SqpDateTime &range);
37
35 38 // IVisualizationWidget interface
36 39 void accept(IVisualizationWidgetVisitor *visitor) override;
37 40 bool canDrop(const Variable &variable) const override;
38 41 bool contains(const Variable &variable) const override;
39 42 QString name() const override;
40 43
41 void updateDisplay(std::shared_ptr<Variable> variable);
42
43 44 signals:
44 45 void requestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
45 46
46 47
47 48 private:
48 49 Ui::VisualizationGraphWidget *ui;
49 50
50 51 class VisualizationGraphWidgetPrivate;
51 52 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
52 53
53 54 private slots:
54 55 /// Slot called when right clicking on the graph (displays a menu)
55 56 void onGraphMenuRequested(const QPoint &pos) noexcept;
56 57
57 58 void onRangeChanged(const QCPRange &t1);
58 59
59 60 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
60 61 void onMouseWheel(QWheelEvent *event) noexcept;
61 62
62 63 void onDataCacheVariableUpdated();
63 64 };
64 65
65 66 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,48 +1,51
1 1 #ifndef SCIQLOP_VISUALIZATIONWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 #include <Data/SqpDateTime.h>
5 6
6 7 #include <QLoggingCategory>
7 8 #include <QWidget>
8 9
9 10 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationWidget)
10 11
11 12 class QMenu;
12 13 class Variable;
13 14 class VisualizationTabWidget;
14 15
15 16 namespace Ui {
16 17 class VisualizationWidget;
17 18 } // namespace Ui
18 19
19 20 class VisualizationWidget : public QWidget, public IVisualizationWidget {
20 21 Q_OBJECT
21 22
22 23 public:
23 24 explicit VisualizationWidget(QWidget *parent = 0);
24 25 virtual ~VisualizationWidget();
25 26
26 27 // IVisualizationWidget interface
27 28 void accept(IVisualizationWidgetVisitor *visitor) override;
28 29 bool canDrop(const Variable &variable) const override;
29 30 bool contains(const Variable &variable) const override;
30 31 QString name() const override;
31 32
32 33 public slots:
33 34 /**
34 35 * Attaches to a menu the menu relative to the visualization of variables
35 36 * @param menu the parent menu of the generated menu
36 37 * @param variables the variables for which to generate the menu
37 38 */
38 39 void attachVariableMenu(QMenu *menu,
39 40 const QVector<std::shared_ptr<Variable> > &variables) noexcept;
40 41
41 42 /// Slot called when a variable is about to be deleted from SciQlop
42 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 47 private:
45 48 Ui::VisualizationWidget *ui;
46 49 };
47 50
48 51 #endif // VISUALIZATIONWIDGET_H
@@ -1,146 +1,151
1 1 #include "SqpApplication.h"
2 2
3 3 #include <Data/IDataProvider.h>
4 4 #include <DataSource/DataSourceController.h>
5 5 #include <Network/NetworkController.h>
6 6 #include <QThread>
7 7 #include <Time/TimeController.h>
8 8 #include <Variable/Variable.h>
9 9 #include <Variable/VariableController.h>
10 10 #include <Visualization/VisualizationController.h>
11 11
12 12 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
13 13
14 14 class SqpApplication::SqpApplicationPrivate {
15 15 public:
16 16 SqpApplicationPrivate()
17 17 : m_DataSourceController{std::make_unique<DataSourceController>()},
18 18 m_NetworkController{std::make_unique<NetworkController>()},
19 19 m_TimeController{std::make_unique<TimeController>()},
20 20 m_VariableController{std::make_unique<VariableController>()},
21 21 m_VisualizationController{std::make_unique<VisualizationController>()}
22 22 {
23 23 // /////////////////////////////// //
24 24 // Connections between controllers //
25 25 // /////////////////////////////// //
26 26
27 27 // VariableController <-> DataSourceController
28 28 connect(m_DataSourceController.get(),
29 29 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
30 30 std::shared_ptr<IDataProvider>)),
31 31 m_VariableController.get(),
32 32 SLOT(createVariable(const QString &, const QVariantHash &,
33 33 std::shared_ptr<IDataProvider>)));
34 34
35 35 // VariableController <-> VisualizationController
36 36 connect(m_VariableController.get(),
37 37 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
38 38 m_VisualizationController.get(),
39 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 47 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
43 48 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
44 49 m_NetworkController->moveToThread(&m_NetworkControllerThread);
45 50 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
46 51 m_VariableController->moveToThread(&m_VariableControllerThread);
47 52 m_VariableControllerThread.setObjectName("VariableControllerThread");
48 53 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
49 54 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
50 55
51 56
52 57 // Additionnal init
53 58 m_VariableController->setTimeController(m_TimeController.get());
54 59 }
55 60
56 61 virtual ~SqpApplicationPrivate()
57 62 {
58 63 qCInfo(LOG_SqpApplication()) << tr("SqpApplicationPrivate destruction");
59 64 m_DataSourceControllerThread.quit();
60 65 m_DataSourceControllerThread.wait();
61 66
62 67 m_NetworkControllerThread.quit();
63 68 m_NetworkControllerThread.wait();
64 69
65 70 m_VariableControllerThread.quit();
66 71 m_VariableControllerThread.wait();
67 72
68 73 m_VisualizationControllerThread.quit();
69 74 m_VisualizationControllerThread.wait();
70 75 }
71 76
72 77 std::unique_ptr<DataSourceController> m_DataSourceController;
73 78 std::unique_ptr<VariableController> m_VariableController;
74 79 std::unique_ptr<TimeController> m_TimeController;
75 80 std::unique_ptr<NetworkController> m_NetworkController;
76 81 std::unique_ptr<VisualizationController> m_VisualizationController;
77 82 QThread m_DataSourceControllerThread;
78 83 QThread m_NetworkControllerThread;
79 84 QThread m_VariableControllerThread;
80 85 QThread m_VisualizationControllerThread;
81 86 };
82 87
83 88
84 89 SqpApplication::SqpApplication(int &argc, char **argv)
85 90 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
86 91 {
87 92 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
88 93
89 94 connect(&impl->m_DataSourceControllerThread, &QThread::started,
90 95 impl->m_DataSourceController.get(), &DataSourceController::initialize);
91 96 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
92 97 impl->m_DataSourceController.get(), &DataSourceController::finalize);
93 98
94 99 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
95 100 &NetworkController::initialize);
96 101 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
97 102 &NetworkController::finalize);
98 103
99 104 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
100 105 &VariableController::initialize);
101 106 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
102 107 &VariableController::finalize);
103 108
104 109 connect(&impl->m_VisualizationControllerThread, &QThread::started,
105 110 impl->m_VisualizationController.get(), &VisualizationController::initialize);
106 111 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
107 112 impl->m_VisualizationController.get(), &VisualizationController::finalize);
108 113
109 114 impl->m_DataSourceControllerThread.start();
110 115 impl->m_NetworkControllerThread.start();
111 116 impl->m_VariableControllerThread.start();
112 117 impl->m_VisualizationControllerThread.start();
113 118 }
114 119
115 120 SqpApplication::~SqpApplication()
116 121 {
117 122 }
118 123
119 124 void SqpApplication::initialize()
120 125 {
121 126 }
122 127
123 128 DataSourceController &SqpApplication::dataSourceController() noexcept
124 129 {
125 130 return *impl->m_DataSourceController;
126 131 }
127 132
128 133 NetworkController &SqpApplication::networkController() noexcept
129 134 {
130 135 return *impl->m_NetworkController;
131 136 }
132 137
133 138 TimeController &SqpApplication::timeController() noexcept
134 139 {
135 140 return *impl->m_TimeController;
136 141 }
137 142
138 143 VariableController &SqpApplication::variableController() noexcept
139 144 {
140 145 return *impl->m_VariableController;
141 146 }
142 147
143 148 VisualizationController &SqpApplication::visualizationController() noexcept
144 149 {
145 150 return *impl->m_VisualizationController;
146 151 }
@@ -1,160 +1,159
1 1 #include "Visualization/VisualizationGraphHelper.h"
2 2 #include "Visualization/qcustomplot.h"
3 3
4 4 #include <Data/ScalarSeries.h>
5 5
6 6 #include <Variable/Variable.h>
7 7
8 8 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
9 9
10 10 namespace {
11 11
12 12 class SqpDataContainer : public QCPGraphDataContainer {
13 13 public:
14 14 void appendGraphDataUnsorted(const QCPGraphData &data) { mData.append(data); }
15 15 };
16 16
17 17
18 18 /// Format for datetimes on a axis
19 19 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
20 20
21 21 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
22 22 /// non-time data
23 23 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
24 24 {
25 25 if (isTimeAxis) {
26 26 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
27 27 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
28 28
29 29 return dateTicker;
30 30 }
31 31 else {
32 32 // default ticker
33 33 return QSharedPointer<QCPAxisTicker>::create();
34 34 }
35 35 }
36 36
37 37 void updateScalarData(QCPAbstractPlottable *component, ScalarSeries &scalarSeries,
38 38 const SqpDateTime &dateTime)
39 39 {
40 40 qCDebug(LOG_VisualizationGraphHelper()) << "TORM: updateScalarData"
41 41 << QThread::currentThread()->objectName();
42 42 if (auto qcpGraph = dynamic_cast<QCPGraph *>(component)) {
43 43 // Clean the graph
44 44 // NAIVE approch
45 45 scalarSeries.lockRead();
46 46 {
47 47 const auto xData = scalarSeries.xAxisData()->data();
48 48 const auto valuesData = scalarSeries.valuesData()->data();
49 49 const auto count = xData.count();
50 50 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points in cache"
51 51 << xData.count();
52 52
53 53 auto dataContainer = qcpGraph->data();
54 54 dataContainer->clear();
55 55 auto sqpDataContainer = QSharedPointer<SqpDataContainer>::create();
56 56 qcpGraph->setData(sqpDataContainer);
57 57
58 58 for (auto i = 0; i < count; ++i) {
59 59 const auto x = xData[i];
60 60 if (x >= dateTime.m_TStart && x <= dateTime.m_TEnd) {
61 61 sqpDataContainer->appendGraphDataUnsorted(QCPGraphData(x, valuesData[i]));
62 62 }
63 63 }
64 64 sqpDataContainer->sort();
65 65 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points displayed"
66 66 << sqpDataContainer->size();
67 67 }
68 68 scalarSeries.unlock();
69 69
70 70
71 71 // Display all data
72 component->rescaleAxes();
73 72 component->parentPlot()->replot();
74 73 }
75 74 else {
76 75 /// @todo DEBUG
77 76 }
78 77 }
79 78
80 79 QCPAbstractPlottable *createScalarSeriesComponent(ScalarSeries &scalarSeries, QCustomPlot &plot,
81 80 const SqpDateTime &dateTime)
82 81 {
83 82 auto component = plot.addGraph();
84 83
85 84 if (component) {
86 85 // // Graph data
87 86 component->setData(scalarSeries.xAxisData()->data(), scalarSeries.valuesData()->data(),
88 87 true);
89 88
90 89 updateScalarData(component, scalarSeries, dateTime);
91 90
92 91 // Axes properties
93 92 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
94 93 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
95 94
96 95 auto setAxisProperties = [](auto axis, const auto &unit) {
97 96 // label (unit name)
98 97 axis->setLabel(unit.m_Name);
99 98
100 99 // ticker (depending on the type of unit)
101 100 axis->setTicker(axisTicker(unit.m_TimeUnit));
102 101 };
103 102 setAxisProperties(plot.xAxis, scalarSeries.xAxisUnit());
104 103 setAxisProperties(plot.yAxis, scalarSeries.valuesUnit());
105 104
106 105 // Display all data
107 106 component->rescaleAxes();
108 107 plot.replot();
109 108 }
110 109 else {
111 110 qCDebug(LOG_VisualizationGraphHelper())
112 111 << QObject::tr("Can't create graph for the scalar series");
113 112 }
114 113
115 114 return component;
116 115 }
117 116
118 117 } // namespace
119 118
120 119 QVector<QCPAbstractPlottable *> VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
121 120 QCustomPlot &plot) noexcept
122 121 {
123 122 auto result = QVector<QCPAbstractPlottable *>{};
124 123
125 124 if (variable) {
126 125 // Gets the data series of the variable to call the creation of the right components
127 126 // according to its type
128 127 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(variable->dataSeries())) {
129 128 result.append(createScalarSeriesComponent(*scalarSeries, plot, variable->dateTime()));
130 129 }
131 130 else {
132 131 qCDebug(LOG_VisualizationGraphHelper())
133 132 << QObject::tr("Can't create graph plottables : unmanaged data series type");
134 133 }
135 134 }
136 135 else {
137 136 qCDebug(LOG_VisualizationGraphHelper())
138 137 << QObject::tr("Can't create graph plottables : the variable is null");
139 138 }
140 139
141 140 return result;
142 141 }
143 142
144 143 void VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *> plotableVect,
145 144 IDataSeries *dataSeries, const SqpDateTime &dateTime)
146 145 {
147 146 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(dataSeries)) {
148 147 if (plotableVect.size() == 1) {
149 148 updateScalarData(plotableVect.at(0), *scalarSeries, dateTime);
150 149 }
151 150 else {
152 151 qCCritical(LOG_VisualizationGraphHelper()) << QObject::tr(
153 152 "Can't update Data of a scalarSeries because there is not only one component "
154 153 "associated");
155 154 }
156 155 }
157 156 else {
158 157 /// @todo DEBUG
159 158 }
160 159 }
@@ -1,285 +1,307
1 1 #include "Visualization/VisualizationGraphWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "Visualization/VisualizationGraphHelper.h"
4 4 #include "ui_VisualizationGraphWidget.h"
5 5
6 6 #include <Data/ArrayData.h>
7 7 #include <Data/IDataSeries.h>
8 8 #include <SqpApplication.h>
9 9 #include <Variable/Variable.h>
10 10 #include <Variable/VariableController.h>
11 11
12 12 #include <unordered_map>
13 13
14 14 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
15 15
16 16 namespace {
17 17
18 18 /// Key pressed to enable zoom on horizontal axis
19 19 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
20 20
21 21 /// Key pressed to enable zoom on vertical axis
22 22 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
23 23
24 24 } // namespace
25 25
26 26 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
27 27
28 28 // 1 variable -> n qcpplot
29 29 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
30 30 };
31 31
32 32 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
33 33 : QWidget{parent},
34 34 ui{new Ui::VisualizationGraphWidget},
35 35 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
36 36 {
37 37 ui->setupUi(this);
38 38
39 39 ui->graphNameLabel->setText(name);
40 40
41 41 // 'Close' options : widget is deleted when closed
42 42 setAttribute(Qt::WA_DeleteOnClose);
43 43 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
44 44 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
45 45
46 46 // Set qcpplot properties :
47 47 // - Drag (on x-axis) and zoom are enabled
48 48 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
49 49 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
50 50 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
51 51 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
52 52 connect(ui->widget->xAxis,
53 53 static_cast<void (QCPAxis::*)(const QCPRange &)>(&QCPAxis::rangeChanged), this,
54 54 &VisualizationGraphWidget::onRangeChanged);
55 55
56 56 // Activates menu when right clicking on the graph
57 57 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
58 58 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
59 59 &VisualizationGraphWidget::onGraphMenuRequested);
60 60
61 61 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
62 62 &VariableController::onRequestDataLoading);
63 63 }
64 64
65 65
66 66 VisualizationGraphWidget::~VisualizationGraphWidget()
67 67 {
68 68 delete ui;
69 69 }
70 70
71 71 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
72 72 {
73 73 // Uses delegate to create the qcpplot components according to the variable
74 74 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
75 75
76 76 for (auto createdPlottable : qAsConst(createdPlottables)) {
77 77 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
78 78 }
79 79
80 80 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
81 81 }
82 82 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
83 83 {
84 84
85 85 // when adding a variable, we need to set its time range to the current graph range
86 86 auto grapheRange = ui->widget->xAxis->range();
87 87 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
88 88 variable->setDateTime(dateTime);
89 89
90 90 auto variableDateTimeWithTolerance = dateTime;
91 91
92 92 // add 10% tolerance for each side
93 93 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
94 94 variableDateTimeWithTolerance.m_TStart -= tolerance;
95 95 variableDateTimeWithTolerance.m_TEnd += tolerance;
96 96
97 97 // Uses delegate to create the qcpplot components according to the variable
98 98 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
99 99
100 100 for (auto createdPlottable : qAsConst(createdPlottables)) {
101 101 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
102 102 }
103 103
104 104 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
105 105
106 106 // CHangement detected, we need to ask controller to request data loading
107 107 emit requestDataLoading(variable, variableDateTimeWithTolerance);
108 108 }
109 109
110 110 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
111 111 {
112 112 // Each component associated to the variable :
113 113 // - is removed from qcpplot (which deletes it)
114 114 // - is no longer referenced in the map
115 115 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
116 116 for (auto it = componentsIt.first; it != componentsIt.second;) {
117 117 ui->widget->removePlottable(it->second);
118 118 it = impl->m_VariableToPlotMultiMap.erase(it);
119 119 }
120 120
121 121 // Updates graph
122 122 ui->widget->replot();
123 123 }
124 124
125 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable,
126 const SqpDateTime &range)
127 {
128 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
129 // for (auto it = componentsIt.first; it != componentsIt.second;) {
130 // }
131 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
132 }
133
125 134 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
126 135 {
127 136 if (visitor) {
128 137 visitor->visit(this);
129 138 }
130 139 else {
131 140 qCCritical(LOG_VisualizationGraphWidget())
132 141 << tr("Can't visit widget : the visitor is null");
133 142 }
134 143 }
135 144
136 145 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
137 146 {
138 147 /// @todo : for the moment, a graph can always accomodate a variable
139 148 Q_UNUSED(variable);
140 149 return true;
141 150 }
142 151
143 152 bool VisualizationGraphWidget::contains(const Variable &variable) const
144 153 {
145 154 // Finds the variable among the keys of the map
146 155 auto variablePtr = &variable;
147 156 auto findVariable
148 157 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
149 158
150 159 auto end = impl->m_VariableToPlotMultiMap.cend();
151 160 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
152 161 return it != end;
153 162 }
154 163
155 164 QString VisualizationGraphWidget::name() const
156 165 {
157 166 return ui->graphNameLabel->text();
158 167 }
159 168
160 169 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
161 170 {
162 171 QMenu graphMenu{};
163 172
164 173 // Iterates on variables (unique keys)
165 174 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
166 175 end = impl->m_VariableToPlotMultiMap.cend();
167 176 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
168 177 // 'Remove variable' action
169 178 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
170 179 [ this, var = it->first ]() { removeVariable(var); });
171 180 }
172 181
173 182 if (!graphMenu.isEmpty()) {
174 183 graphMenu.exec(mapToGlobal(pos));
175 184 }
176 185 }
177 186
178 187 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1)
179 188 {
180 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
189 qCInfo(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
181 190 << QThread::currentThread()->objectName();
182 191
183 192 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
184 193 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
185 194
186 195 auto variable = it->first;
187 196 auto dateTime = SqpDateTime{t1.lower, t1.upper};
197 auto dateTimeRange = dateTime;
188 198
189 if (!variable->contains(dateTime)) {
199 auto toleranceFactor = 0.2;
200 auto tolerance = toleranceFactor * (dateTime.m_TEnd - dateTime.m_TStart);
201 auto variableDateTimeWithTolerance = dateTime;
202 variableDateTimeWithTolerance.m_TStart -= tolerance;
203 variableDateTimeWithTolerance.m_TEnd += tolerance;
204
205 qCInfo(LOG_VisualizationGraphWidget()) << "v" << dateTime;
206 qCInfo(LOG_VisualizationGraphWidget()) << "vtol" << variableDateTimeWithTolerance;
207 // If new range with tol is upper than variable datetime parameters. we need to request new
208 // data
209 if (!variable->contains(variableDateTimeWithTolerance)) {
190 210
191 211 auto variableDateTimeWithTolerance = dateTime;
192 212 if (!variable->isInside(dateTime)) {
193 213 auto variableDateTime = variable->dateTime();
194 214 if (variableDateTime.m_TStart < dateTime.m_TStart) {
195 qCDebug(LOG_VisualizationGraphWidget()) << tr("TDetection pan to right:");
215 qCInfo(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to right:");
196 216
197 217 auto diffEndToKeepDelta = dateTime.m_TEnd - variableDateTime.m_TEnd;
198 218 dateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
199 219 // Tolerance have to be added to the right
200 // add 10% tolerance for right (end) side
201 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
220 // add tolerance for right (end) side
221 tolerance = toleranceFactor * (dateTime.m_TEnd - dateTime.m_TStart);
202 222 variableDateTimeWithTolerance.m_TEnd += tolerance;
203 223 }
204 224 else if (variableDateTime.m_TEnd > dateTime.m_TEnd) {
205 qCDebug(LOG_VisualizationGraphWidget()) << tr("Detection pan to left: ");
225 qCInfo(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to left: ");
206 226 auto diffStartToKeepDelta = variableDateTime.m_TStart - dateTime.m_TStart;
207 227 dateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
208 228 // Tolerance have to be added to the left
209 // add 10% tolerance for left (start) side
210 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
229 // add tolerance for left (start) side
230 tolerance = toleranceFactor * (dateTime.m_TEnd - dateTime.m_TStart);
211 231 variableDateTimeWithTolerance.m_TStart -= tolerance;
212 232 }
213 233 else {
214 234 qCWarning(LOG_VisualizationGraphWidget())
215 235 << tr("Detection anormal zoom detection: ");
216 236 }
217 237 }
218 238 else {
219 qCDebug(LOG_VisualizationGraphWidget()) << tr("Detection zoom out: ");
239 qCInfo(LOG_VisualizationGraphWidget()) << tr("Detection zoom out: ");
220 240 // add 10% tolerance for each side
221 auto tolerance = 0.1 * (dateTime.m_TEnd - dateTime.m_TStart);
241 tolerance = 0.2 * (dateTime.m_TEnd - dateTime.m_TStart);
222 242 variableDateTimeWithTolerance.m_TStart -= tolerance;
223 243 variableDateTimeWithTolerance.m_TEnd += tolerance;
224 244 }
245 if (!variable->contains(dateTimeRange)) {
246 qCInfo(LOG_VisualizationGraphWidget())
247 << "TORM: Modif on variable datetime detected" << dateTime;
225 248 variable->setDateTime(dateTime);
249 }
226 250
251 qCInfo(LOG_VisualizationGraphWidget()) << tr("Request data detection: ");
227 252 // CHangement detected, we need to ask controller to request data loading
228 253 emit requestDataLoading(variable, variableDateTimeWithTolerance);
229 254 }
230 255 else {
231 qCDebug(LOG_VisualizationGraphWidget()) << tr("Detection zoom in: ");
256 qCInfo(LOG_VisualizationGraphWidget()) << tr("Detection zoom in: ");
232 257 }
233 258 }
234 259 }
235 260
236 261 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
237 262 {
238 263 auto zoomOrientations = QFlags<Qt::Orientation>{};
239 264
240 265 // Lambda that enables a zoom orientation if the key modifier related to this orientation
241 266 // has
242 267 // been pressed
243 268 auto enableOrientation
244 269 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
245 270 auto orientationEnabled = event->modifiers().testFlag(modifier);
246 271 zoomOrientations.setFlag(orientation, orientationEnabled);
247 272 };
248 273 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
249 274 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
250 275
251 276 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
252 277 }
253 278
254 279 void VisualizationGraphWidget::onDataCacheVariableUpdated()
255 280 {
256 281 // NOTE:
257 282 // We don't want to call the method for each component of a variable unitarily, but for
258 283 // all
259 284 // its components at once (eg its three components in the case of a vector).
260 285
261 286 // The unordered_multimap does not do this easily, so the question is whether to:
262 287 // - use an ordered_multimap and the algos of std to group the values by key
263 288 // - use a map (unique keys) and store as values directly the list of components
264 289
290 auto grapheRange = ui->widget->xAxis->range();
291 auto dateTime = SqpDateTime{grapheRange.lower, grapheRange.upper};
292
265 293 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
266 294 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
267 295 auto variable = it->first;
296 qCInfo(LOG_VisualizationGraphWidget())
297 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S"
298 << variable->dateTime();
299 qCInfo(LOG_VisualizationGraphWidget())
300 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
301 if (dateTime.contains(variable->dateTime()) || dateTime.intersect(variable->dateTime())) {
302
268 303 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
269 304 variable->dataSeries(), variable->dateTime());
270 305 }
271 306 }
272
273 void VisualizationGraphWidget::updateDisplay(std::shared_ptr<Variable> variable)
274 {
275 auto abstractPlotableItPair = impl->m_VariableToPlotMultiMap.equal_range(variable);
276
277 auto abstractPlotableVect = QVector<QCPAbstractPlottable *>{};
278
279 for (auto it = abstractPlotableItPair.first; it != abstractPlotableItPair.second; ++it) {
280 abstractPlotableVect.push_back(it->second);
281 }
282
283 VisualizationGraphHelper::updateData(abstractPlotableVect, variable->dataSeries(),
284 variable->dateTime());
285 307 }
@@ -1,143 +1,152
1 1 #include "Visualization/VisualizationWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "Visualization/VisualizationGraphWidget.h"
4 4 #include "Visualization/VisualizationTabWidget.h"
5 5 #include "Visualization/VisualizationZoneWidget.h"
6 6 #include "Visualization/operations/GenerateVariableMenuOperation.h"
7 7 #include "Visualization/operations/RemoveVariableOperation.h"
8 #include "Visualization/operations/RescaleAxeOperation.h"
8 9 #include "Visualization/qcustomplot.h"
9 10
10 11 #include "ui_VisualizationWidget.h"
11 12
12 13 #include <QToolButton>
13 14
14 15 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
15 16
16 17 VisualizationWidget::VisualizationWidget(QWidget *parent)
17 18 : QWidget{parent}, ui{new Ui::VisualizationWidget}
18 19 {
19 20 ui->setupUi(this);
20 21
21 22 auto addTabViewButton = new QToolButton{ui->tabWidget};
22 23 addTabViewButton->setText(tr("Add View"));
23 24 addTabViewButton->setCursor(Qt::ArrowCursor);
24 25 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
25 26
26 27 auto enableMinimumCornerWidgetSize = [this](bool enable) {
27 28
28 29 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
29 30 auto width = enable ? tabViewCornerWidget->width() : 0;
30 31 auto height = enable ? tabViewCornerWidget->height() : 0;
31 32 tabViewCornerWidget->setMinimumHeight(height);
32 33 tabViewCornerWidget->setMinimumWidth(width);
33 34 ui->tabWidget->setMinimumHeight(height);
34 35 ui->tabWidget->setMinimumWidth(width);
35 36 };
36 37
37 38 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
38 39 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
39 40 ui->tabWidget};
40 41 auto index = ui->tabWidget->addTab(widget, widget->name());
41 42 if (ui->tabWidget->count() > 0) {
42 43 enableMinimumCornerWidgetSize(false);
43 44 }
44 45 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
45 46 };
46 47
47 48 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
48 49 if (ui->tabWidget->count() == 1) {
49 50 enableMinimumCornerWidgetSize(true);
50 51 }
51 52
52 53 // Removes widget from tab and closes it
53 54 auto widget = ui->tabWidget->widget(index);
54 55 ui->tabWidget->removeTab(index);
55 56 if (widget) {
56 57 widget->close();
57 58 }
58 59
59 60 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
60 61
61 62 };
62 63
63 64 ui->tabWidget->setTabsClosable(true);
64 65
65 66 connect(addTabViewButton, &QToolButton::clicked, addTabView);
66 67 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
67 68
68 69 // Adds default tab
69 70 addTabView();
70 71 }
71 72
72 73 VisualizationWidget::~VisualizationWidget()
73 74 {
74 75 delete ui;
75 76 }
76 77
77 78 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
78 79 {
79 80 if (visitor) {
80 81 visitor->visitEnter(this);
81 82
82 83 // Apply visitor for tab children
83 84 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
84 85 // Widgets different from tabs are not visited (no action)
85 86 if (auto visualizationTabWidget
86 87 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
87 88 visualizationTabWidget->accept(visitor);
88 89 }
89 90 }
90 91
91 92 visitor->visitLeave(this);
92 93 }
93 94 else {
94 95 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
95 96 }
96 97 }
97 98
98 99 bool VisualizationWidget::canDrop(const Variable &variable) const
99 100 {
100 101 // The main widget can never accomodate a variable
101 102 Q_UNUSED(variable);
102 103 return false;
103 104 }
104 105
105 106 bool VisualizationWidget::contains(const Variable &variable) const
106 107 {
107 108 Q_UNUSED(variable);
108 109 return false;
109 110 }
110 111
111 112 QString VisualizationWidget::name() const
112 113 {
113 114 return QStringLiteral("MainView");
114 115 }
115 116
116 117 void VisualizationWidget::attachVariableMenu(
117 118 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
118 119 {
119 120 // Menu is generated only if there is a single variable
120 121 if (variables.size() == 1) {
121 122 if (auto variable = variables.first()) {
122 123 // Generates the actions that make it possible to visualize the variable
123 124 auto generateVariableMenuOperation = GenerateVariableMenuOperation{menu, variable};
124 125 accept(&generateVariableMenuOperation);
125 126 }
126 127 else {
127 128 qCCritical(LOG_VisualizationWidget()) << tr(
128 129 "Can't generate the menu relative to the visualization: the variable is null");
129 130 }
130 131 }
131 132 else {
132 133 qCDebug(LOG_VisualizationWidget())
133 134 << tr("No generation of the menu related to the visualization: several variables are "
134 135 "selected");
135 136 }
136 137 }
137 138
138 139 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
139 140 {
140 141 // Calls the operation of removing all references to the variable in the visualization
141 142 auto removeVariableOperation = RemoveVariableOperation{variable};
142 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 removing all references to the variable in the visualization
150 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
151 accept(&rescaleVariableOperation);
152 }
General Comments 3
Under Review
author

Pull request updated. Auto status change to "Under Review"

Changed commits:
  * 3 added
  * 0 removed

Changed files:
  * A plugins/amda/tests-resources/TestAmdaResultParser/FileNotFound.txt
  * M gui/src/Visualization/operations/RescaleAxeOperation.cpp
  * M app/src/MainWindow.cpp
  * M core/include/Data/IDataProvider.h
  * M core/include/DataSource/DataSourceItemAction.h
  * M core/include/Variable/VariableController.h
  * M core/include/Variable/VariableModel.h
  * M core/include/Visualization/VisualizationController.h
  * M core/src/Network/NetworkController.cpp
  * M core/src/Variable/Variable.cpp
  * M core/src/Variable/VariableController.cpp
  * M core/src/Variable/VariableModel.cpp
  * M gui/include/Visualization/VisualizationGraphWidget.h
  * M gui/include/Visualization/VisualizationWidget.h
  * M gui/src/SqpApplication.cpp
  * M gui/src/Variable/VariableInspectorWidget.cpp
  * M gui/src/Visualization/VisualizationGraphHelper.cpp
  * M gui/src/Visualization/VisualizationGraphWidget.cpp
  * M gui/src/Visualization/VisualizationWidget.cpp
  * M gui/src/Visualization/VisualizationZoneWidget.cpp
  * M plugins/amda/include/AmdaProvider.h
  * M plugins/amda/src/AmdaProvider.cpp
  * M plugins/amda/src/AmdaResultParser.cpp
  * M plugins/amda/tests/TestAmdaResultParser.cpp
  * M plugins/mockplugin/include/CosinusProvider.h
  * M plugins/mockplugin/src/CosinusProvider.cpp
  * R COPYING
  * R app/ui/MainWindow.ui
  * R cmake/sciqlop_package_qt.cmake
  * R core/include/Common/MetaTypes.h
  * R core/include/Data/ArrayData.h
  * R core/include/Data/DataProviderParameters.h
  * R core/include/Data/DataSeries.h
  * R core/include/Data/IDataSeries.h
  * R core/include/Data/ScalarSeries.h
  * R core/include/Data/SqpDateTime.h
  * R core/include/Network/NetworkController.h
  * R core/include/Plugin/PluginManager.h
  * R core/include/Time/TimeController.h
  * R core/include/Variable/Variable.h
  * R core/include/Variable/VariableCacheController.h
  * R core/src/Data/ScalarSeries.cpp
  * R core/src/DataSource/DataSourceItemAction.cpp
  * R core/src/Plugin/PluginManager.cpp
  * R core/src/Time/TimeController.cpp
  * R core/src/Variable/VariableCacheController.cpp
  * R core/src/Visualization/VisualizationController.cpp
  * R core/tests/Variable/TestVariableCacheController.cpp
  * R gui/include/DataSource/DataSourceTreeWidgetItem.h
  * R gui/include/DataSource/DataSourceWidget.h
  * R gui/include/SidePane/SqpSidePane.h
  * R gui/include/TimeWidget/TimeWidget.h
  * R gui/include/Variable/VariableInspectorWidget.h
  * R gui/include/Variable/VariableMenuHeaderWidget.h
  * R gui/include/Visualization/IVariableContainer.h
  * R gui/include/Visualization/IVisualizationWidget.h
  * R gui/include/Visualization/IVisualizationWidgetVisitor.h
  * R gui/include/Visualization/VisualizationGraphHelper.h
  * R gui/include/Visualization/VisualizationTabWidget.h
  * R gui/include/Visualization/VisualizationZoneWidget.h
  * R gui/include/Visualization/operations/GenerateVariableMenuOperation.h
  * R gui/include/Visualization/operations/MenuBuilder.h
  * R gui/include/Visualization/operations/RemoveVariableOperation.h
  * R gui/include/Visualization/qcustomplot.h
  * R gui/resources/icones/dataSourceComponent.png
  * R gui/resources/icones/dataSourceNode.png
  * R gui/resources/icones/dataSourceProduct.png
  * R gui/resources/icones/dataSourceRoot.png
  * R gui/resources/icones/delete.png
  * R gui/resources/icones/next.png
  * R gui/resources/icones/openInspector.png
  * R gui/resources/icones/plot.png
  * R gui/resources/icones/previous.png
  * R gui/resources/icones/sciqlop2PNG_1024.png
  * R gui/resources/icones/unplot.png
  * R gui/resources/sqpguiresources.qrc
  * R gui/src/DataSource/DataSourceTreeWidgetItem.cpp
  * R gui/src/DataSource/DataSourceWidget.cpp
  * R gui/src/SidePane/SqpSidePane.cpp
  * R gui/src/TimeWidget/TimeWidget.cpp
  * R gui/src/Variable/VariableMenuHeaderWidget.cpp
  * R gui/src/Visualization/VisualizationTabWidget.cpp
  * R gui/src/Visualization/operations/GenerateVariableMenuOperation.cpp
  * R gui/src/Visualization/operations/MenuBuilder.cpp
  * R gui/src/Visualization/operations/RemoveVariableOperation.cpp
  * R gui/src/Visualization/qcustomplot.cpp
  * R gui/ui/DataSource/DataSourceWidget.ui
  * R gui/ui/SidePane/SqpSidePane.ui
  * R gui/ui/TimeWidget/TimeWidget.ui
  * R gui/ui/Variable/VariableInspectorWidget.ui
  * R gui/ui/Variable/VariableMenuHeaderWidget.ui
  * R gui/ui/Visualization/VisualizationGraphWidget.ui
  * R gui/ui/Visualization/VisualizationTabWidget.ui
  * R gui/ui/Visualization/VisualizationWidget.ui
  * R gui/ui/Visualization/VisualizationZoneWidget.ui
  * R gui/vera-exclusions/exclusions.txt
  * R plugin/CMakeLists.txt
  * R plugin/cmake/Findsciqlop-plugin.cmake
  * R plugin/include/Plugin/IPlugin.h
  * R plugins/amda/CMakeLists.txt
  * R plugins/amda/cmake/Findsciqlop-amda.cmake
  * R plugins/amda/include/AmdaDefs.h
  * R plugins/amda/include/AmdaGlobal.h
  * R plugins/amda/include/AmdaParser.h
  * R plugins/amda/include/AmdaPlugin.h
  * R plugins/amda/include/AmdaResultParser.h
  * R plugins/amda/resources/amda.json
  * R plugins/amda/resources/amdaresources.qrc
  * R plugins/amda/resources/samples/AmdaSample.json
  * R plugins/amda/src/AmdaDefs.cpp
  * R plugins/amda/src/AmdaParser.cpp
  * R plugins/amda/src/AmdaPlugin.cpp
  * R plugins/amda/tests-resources/TestAmdaParser/TwoRootsFile.json
  * R plugins/amda/tests-resources/TestAmdaParser/ValidFile1.json
  * R plugins/amda/tests-resources/TestAmdaParser/WrongRootKey.json
  * R plugins/amda/tests-resources/TestAmdaParser/WrongRootType.json
  * R plugins/amda/tests-resources/TestAmdaResultParser/NaNValue.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/NoUnit.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/TooManyValues.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/ValidScalar1.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/WrongDate.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/WrongUnit.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/WrongValue.txt
  * R plugins/amda/tests/TestAmdaParser.cpp
  * R plugins/mockplugin/CMakeLists.txt
  * R plugins/mockplugin/cmake/Findsciqlop-mockplugin.cmake
  * R plugins/mockplugin/include/MockPlugin.h
  * R plugins/mockplugin/include/MockPluginGlobal.h
  * R plugins/mockplugin/resources/mockplugin.json
  * R plugins/mockplugin/src/MockPlugin.cpp
  * R README.md
  * R app/CMakeLists.txt
  * R app/include/MainWindow.h
  * R app/src/Main.cpp
  * R app/vera-exclusions/exclusions.txt
  * R cmake/sciqlop.cmake
  * R cmake/sciqlop_applications.cmake
  * R cmake/sciqlop_package.cmake
  * R cmake/sciqlop_params.cmake
  * R core/CMakeLists.txt
  * R core/include/Common/spimpl.h
  * R core/include/DataSource/DataSourceController.h
  * R core/include/DataSource/DataSourceItem.h
  * R core/src/DataSource/DataSourceController.cpp
  * R core/src/DataSource/DataSourceItem.cpp
  * R core/tests/DataSource/TestDataSourceController.cpp
  * R core/vera-exclusions/exclusions.txt
  * R formatting/cmake/use_clangformat.cmake
  * R formatting/vera-exclusions/exclusions.txt
  * R gui/CMakeLists.txt
  * R gui/include/SqpApplication.h
  * R LICENSE
  * R app/src/mainwindow.cpp
  * R app/src/mainwindow.ui
Approved
author

Status change > Approved

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