##// END OF EJS Templates
Updates variable creation to pass metadata...
Alexandre Leroux -
r410:af1b645db780
parent child
Show More
@@ -1,90 +1,92
1 1 #ifndef SCIQLOP_DATASOURCECONTROLLER_H
2 2 #define SCIQLOP_DATASOURCECONTROLLER_H
3 3
4 4 #include <QLoggingCategory>
5 5 #include <QObject>
6 6 #include <QUuid>
7 7
8 8 #include <Common/spimpl.h>
9 9
10 10 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController)
11 11
12 12 class DataSourceItem;
13 13 class IDataProvider;
14 14
15 15 /**
16 16 * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This
17 17 * is the intermediate class that SciQlop has to use in the way to connect a data source. Please
18 18 * first use register method to initialize a plugin specified by its metadata name (JSON plugin
19 19 * source) then others specifics method will be able to access it. You can load a data source driver
20 20 * plugin then create a data source.
21 21 */
22 22 class DataSourceController : public QObject {
23 23 Q_OBJECT
24 24 public:
25 25 explicit DataSourceController(QObject *parent = 0);
26 26 virtual ~DataSourceController();
27 27
28 28 /**
29 29 * Registers a data source. The method delivers a unique id that can be used afterwards to
30 30 * access to the data source properties (structure, connection parameters, data provider, etc.)
31 31 * @param dataSourceName the name of the data source
32 32 * @return the unique id with which the data source has been registered
33 33 */
34 34 QUuid registerDataSource(const QString &dataSourceName) noexcept;
35 35
36 36 /**
37 37 * Sets the structure of a data source. The controller takes ownership of the structure.
38 38 * @param dataSourceUid the unique id with which the data source has been registered into the
39 39 * controller. If it is invalid, the method has no effect.
40 40 * @param dataSourceItem the structure of the data source. It must be not null to be registered
41 41 * @sa registerDataSource()
42 42 */
43 43 void setDataSourceItem(const QUuid &dataSourceUid,
44 44 std::unique_ptr<DataSourceItem> dataSourceItem) noexcept;
45 45
46 46 /**
47 47 * Sets the data provider used to retrieve data from of a data source. The controller takes
48 48 * ownership of the provider.
49 49 * @param dataSourceUid the unique id with which the data source has been registered into the
50 50 * controller. If it is invalid, the method has no effect.
51 51 * @param dataProvider the provider of the data source
52 52 * @sa registerDataSource()
53 53 */
54 54 void setDataProvider(const QUuid &dataSourceUid,
55 55 std::unique_ptr<IDataProvider> dataProvider) noexcept;
56 56
57 57 /**
58 58 * Loads an item (product) as a variable in SciQlop
59 59 * @param dataSourceUid the unique id of the data source containing the item. It is used to get
60 60 * the data provider associated to the data source, and pass it to for the variable creation
61 61 * @param productItem the item to load
62 62 */
63 63 void loadProductItem(const QUuid &dataSourceUid, const DataSourceItem &productItem) noexcept;
64 64
65 65 public slots:
66 66 /// Manage init/end of the controller
67 67 void initialize();
68 68 void finalize();
69 69
70 70 signals:
71 71 /// Signal emitted when a structure has been set for a data source
72 72 void dataSourceItemSet(DataSourceItem *dataSourceItem);
73 73
74 74 /**
75 75 * Signal emitted when a variable creation is asked for a product
76 76 * @param variableName the name of the variable
77 * @param variableMetadata the metadata of the variable
77 78 * @param variableProvider the provider that will be used to retrieve the data of the variable
78 79 * (can be null)
79 80 */
80 81 void variableCreationRequested(const QString &variableName,
82 const QVariantHash &variableMetadata,
81 83 std::shared_ptr<IDataProvider> variableProvider);
82 84
83 85 private:
84 86 void waitForFinish();
85 87
86 88 class DataSourceControllerPrivate;
87 89 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
88 90 };
89 91
90 92 #endif // SCIQLOP_DATASOURCECONTROLLER_H
@@ -1,83 +1,85
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 signals:
54 54 /// Signal emitted when a variable is about to be deleted from the controller
55 55 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
56 56
57 57 public slots:
58 58 /// Request the data loading of the variable whithin dateTime
59 59 void onRequestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
60 60 /**
61 61 * Creates a new variable and adds it to the model
62 62 * @param name the name of the new variable
63 * @param metadata the metadata of the new variable
63 64 * @param provider the data provider for the new variable
64 65 */
65 void createVariable(const QString &name, std::shared_ptr<IDataProvider> provider) noexcept;
66 void createVariable(const QString &name, const QVariantHash &metadata,
67 std::shared_ptr<IDataProvider> provider) noexcept;
66 68
67 69 /// Update the temporal parameters of every selected variable to dateTime
68 70 void onDateTimeOnSelection(const SqpDateTime &dateTime);
69 71
70 72
71 73 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
72 74
73 75 void initialize();
74 76 void finalize();
75 77
76 78 private:
77 79 void waitForFinish();
78 80
79 81 class VariableControllerPrivate;
80 82 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
81 83 };
82 84
83 85 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,70 +1,71
1 1 #ifndef SCIQLOP_VARIABLEMODEL_H
2 2 #define SCIQLOP_VARIABLEMODEL_H
3 3
4 4
5 5 #include <Data/SqpDateTime.h>
6 6
7 7 #include <QAbstractTableModel>
8 8 #include <QLoggingCategory>
9 9
10 10 #include <Common/MetaTypes.h>
11 11 #include <Common/spimpl.h>
12 12
13 13 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
14 14
15 15 enum VariableRoles { ProgressRole = Qt::UserRole };
16 16
17 17
18 18 class IDataSeries;
19 19 class Variable;
20 20
21 21 /**
22 22 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
23 23 */
24 24 class VariableModel : public QAbstractTableModel {
25 25 public:
26 26 explicit VariableModel(QObject *parent = nullptr);
27 27
28 28 /**
29 29 * Creates a new variable in the model
30 30 * @param name the name of the new variable
31 31 * @param dateTime the dateTime of the new variable
32 * @param metadata the metadata associated to the new variable
32 33 * @return the pointer to the new variable
33 34 */
34 std::shared_ptr<Variable> createVariable(const QString &name,
35 const SqpDateTime &dateTime) noexcept;
35 std::shared_ptr<Variable> createVariable(const QString &name, const SqpDateTime &dateTime,
36 const QVariantHash &metadata) noexcept;
36 37
37 38 /**
38 39 * Deletes a variable from the model, if it exists
39 40 * @param variable the variable to delete
40 41 */
41 42 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
42 43
43 44
44 45 std::shared_ptr<Variable> variable(int index) const;
45 46
46 47 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
47 48
48 49 // /////////////////////////// //
49 50 // QAbstractTableModel methods //
50 51 // /////////////////////////// //
51 52
52 53 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
53 54 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
54 55 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
55 56 virtual QVariant headerData(int section, Qt::Orientation orientation,
56 57 int role = Qt::DisplayRole) const override;
57 58
58 59 private:
59 60 class VariableModelPrivate;
60 61 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
61 62
62 63 private slots:
63 64 /// Slot called when data of a variable has been updated
64 65 void onVariableUpdated() noexcept;
65 66 };
66 67
67 68 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
68 69 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
69 70
70 71 #endif // SCIQLOP_VARIABLEMODEL_H
@@ -1,120 +1,120
1 1 #include "DataSource/DataSourceController.h"
2 2 #include "DataSource/DataSourceItem.h"
3 3
4 4 #include <Data/IDataProvider.h>
5 5
6 6 #include <QMutex>
7 7 #include <QThread>
8 8
9 9 #include <QDir>
10 10 #include <QStandardPaths>
11 11
12 12 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
13 13
14 14 class DataSourceController::DataSourceControllerPrivate {
15 15 public:
16 16 QMutex m_WorkingMutex;
17 17 /// Data sources registered
18 18 QHash<QUuid, QString> m_DataSources;
19 19 /// Data sources structures
20 20 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
21 21 /// Data providers registered
22 22 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
23 23 /// continue to live without necessarily the data source controller
24 24 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
25 25 };
26 26
27 27 DataSourceController::DataSourceController(QObject *parent)
28 28 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
29 29 {
30 30 qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction")
31 31 << QThread::currentThread();
32 32 }
33 33
34 34 DataSourceController::~DataSourceController()
35 35 {
36 36 qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction")
37 37 << QThread::currentThread();
38 38 this->waitForFinish();
39 39 }
40 40
41 41 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
42 42 {
43 43 auto dataSourceUid = QUuid::createUuid();
44 44 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
45 45
46 46 return dataSourceUid;
47 47 }
48 48
49 49 void DataSourceController::setDataSourceItem(
50 50 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
51 51 {
52 52 if (!dataSourceItem) {
53 53 qCWarning(LOG_DataSourceController())
54 54 << tr("Data source item can't be registered (null item)");
55 55 return;
56 56 }
57 57
58 58 if (impl->m_DataSources.contains(dataSourceUid)) {
59 59 // The data provider is implicitly converted to a shared_ptr
60 60 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
61 61
62 62 // Retrieves the data source item to emit the signal with it
63 63 auto it = impl->m_DataSourceItems.find(dataSourceUid);
64 64 if (it != impl->m_DataSourceItems.end()) {
65 65 emit dataSourceItemSet(it->second.get());
66 66 }
67 67 }
68 68 else {
69 69 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
70 70 "data source has been registered with the uid")
71 71 .arg(dataSourceUid.toString());
72 72 }
73 73 }
74 74
75 75 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
76 76 std::unique_ptr<IDataProvider> dataProvider) noexcept
77 77 {
78 78 if (impl->m_DataSources.contains(dataSourceUid)) {
79 79 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
80 80 }
81 81 else {
82 82 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
83 83 "source has been registered with the uid")
84 84 .arg(dataSourceUid.toString());
85 85 }
86 86 }
87 87
88 88 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
89 89 const DataSourceItem &productItem) noexcept
90 90 {
91 91 if (productItem.type() == DataSourceItemType::PRODUCT) {
92 92 /// Retrieves the data provider of the data source (if any)
93 93 auto it = impl->m_DataProviders.find(dataSourceUid);
94 94 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
95 95
96 96 /// @todo retrieve timerange, and pass it to the signal
97 emit variableCreationRequested(productItem.name(), dataProvider);
97 emit variableCreationRequested(productItem.name(), productItem.data(), dataProvider);
98 98 }
99 99 else {
100 100 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
101 101 }
102 102 }
103 103
104 104 void DataSourceController::initialize()
105 105 {
106 106 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init")
107 107 << QThread::currentThread();
108 108 impl->m_WorkingMutex.lock();
109 109 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
110 110 }
111 111
112 112 void DataSourceController::finalize()
113 113 {
114 114 impl->m_WorkingMutex.unlock();
115 115 }
116 116
117 117 void DataSourceController::waitForFinish()
118 118 {
119 119 QMutexLocker locker{&impl->m_WorkingMutex};
120 120 }
@@ -1,216 +1,217
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_VariableToIdentifier;
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
51 51 VariableController::~VariableController()
52 52 {
53 53 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
54 54 << QThread::currentThread();
55 55 this->waitForFinish();
56 56 }
57 57
58 58 VariableModel *VariableController::variableModel() noexcept
59 59 {
60 60 return impl->m_VariableModel;
61 61 }
62 62
63 63 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
64 64 {
65 65 return impl->m_VariableSelectionModel;
66 66 }
67 67
68 68 void VariableController::setTimeController(TimeController *timeController) noexcept
69 69 {
70 70 impl->m_TimeController = timeController;
71 71 }
72 72
73 73 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
74 74 {
75 75 if (!variable) {
76 76 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
77 77 return;
78 78 }
79 79
80 80 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
81 81 // make some treatments before the deletion
82 82 emit variableAboutToBeDeleted(variable);
83 83
84 84 // Deletes provider
85 85 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
86 86 qCDebug(LOG_VariableController())
87 87 << tr("Number of providers deleted for variable %1: %2")
88 88 .arg(variable->name(), QString::number(nbProvidersDeleted));
89 89
90 90 // Clears cache
91 91 impl->m_VariableCacheController->clear(variable);
92 92
93 93 // Deletes from model
94 94 impl->m_VariableModel->deleteVariable(variable);
95 95 }
96 96
97 97 void VariableController::deleteVariables(
98 98 const QVector<std::shared_ptr<Variable> > &variables) noexcept
99 99 {
100 100 for (auto variable : qAsConst(variables)) {
101 101 deleteVariable(variable);
102 102 }
103 103 }
104 104
105 void VariableController::createVariable(const QString &name,
105 void VariableController::createVariable(const QString &name, const QVariantHash &metadata,
106 106 std::shared_ptr<IDataProvider> provider) noexcept
107 107 {
108 108
109 109 if (!impl->m_TimeController) {
110 110 qCCritical(LOG_VariableController())
111 111 << tr("Impossible to create variable: The time controller is null");
112 112 return;
113 113 }
114 114
115 115
116 116 /// @todo : for the moment :
117 117 /// - the provider is only used to retrieve data from the variable for its initialization, but
118 118 /// it will be retained later
119 119 /// - default data are generated for the variable, without taking into account the timerange set
120 120 /// in sciqlop
121 121 auto dateTime = impl->m_TimeController->dateTime();
122 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime)) {
122
123 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime, metadata)) {
123 124 auto identifier = QUuid::createUuid();
124 125
125 126 // store the provider
126 127 impl->m_VariableToProviderMap[newVariable] = provider;
127 128 impl->m_VariableToIdentifier[newVariable] = identifier;
128 129
129 130 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
130 131 QUuid identifier, auto dataSeriesAcquired, auto dateTimeToPutInCache)
131 132 {
132 133 if (auto variable = varW.lock()) {
133 134 auto varIdentifier = impl->m_VariableToIdentifier.at(variable);
134 135 if (varIdentifier == identifier) {
135 136 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
136 137 variable->setDataSeries(dataSeriesAcquired);
137 138 }
138 139 }
139 140 };
140 141
141 142 connect(provider.get(), &IDataProvider::dataProvided, addDateTimeAcquired);
142 143 this->onRequestDataLoading(newVariable, dateTime);
143 144 }
144 145 }
145 146
146 147 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
147 148 {
148 149 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
149 150 << QThread::currentThread()->objectName();
150 151 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
151 152
152 153 for (const auto &selectedRow : qAsConst(selectedRows)) {
153 154 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
154 155 selectedVariable->setDateTime(dateTime);
155 156 this->onRequestDataLoading(selectedVariable, dateTime);
156 157 }
157 158 }
158 159 }
159 160
160 161 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
161 162 {
162 163 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
163 164
164 165 auto end = impl->m_VariableToIdentifier.cend();
165 166 auto it = std::find_if(impl->m_VariableToIdentifier.cbegin(), end, findReply);
166 167 if (it != end) {
167 168 impl->m_VariableModel->setDataProgress(it->first, progress);
168 169 }
169 170 }
170 171
171 172
172 173 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
173 174 const SqpDateTime &dateTime)
174 175 {
175 176 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
176 177 << QThread::currentThread()->objectName();
177 178 // we want to load data of the variable for the dateTime.
178 179 // First we check if the cache contains some of them.
179 180 // For the other, we ask the provider to give them.
180 181 if (variable) {
181 182
182 183 auto dateTimeListNotInCache
183 184 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
184 185
185 186 if (!dateTimeListNotInCache.empty()) {
186 187 // Ask the provider for each data on the dateTimeListNotInCache
187 188 auto identifier = impl->m_VariableToIdentifier.at(variable);
188 189 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
189 190 identifier, DataProviderParameters{std::move(dateTimeListNotInCache)});
190 191 }
191 192 else {
192 193 emit variable->updated();
193 194 }
194 195 }
195 196 else {
196 197 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
197 198 }
198 199 }
199 200
200 201
201 202 void VariableController::initialize()
202 203 {
203 204 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
204 205 impl->m_WorkingMutex.lock();
205 206 qCDebug(LOG_VariableController()) << tr("VariableController init END");
206 207 }
207 208
208 209 void VariableController::finalize()
209 210 {
210 211 impl->m_WorkingMutex.unlock();
211 212 }
212 213
213 214 void VariableController::waitForFinish()
214 215 {
215 216 QMutexLocker locker{&impl->m_WorkingMutex};
216 217 }
@@ -1,234 +1,235
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableModel.h>
3 3
4 4 #include <Data/IDataSeries.h>
5 5
6 6 #include <QDateTime>
7 7 #include <QSize>
8 8 #include <unordered_map>
9 9
10 10 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
11 11
12 12 namespace {
13 13
14 14 // Column indexes
15 15 const auto NAME_COLUMN = 0;
16 16 const auto TSTART_COLUMN = 1;
17 17 const auto TEND_COLUMN = 2;
18 18 const auto NB_COLUMNS = 3;
19 19
20 20 // Column properties
21 21 const auto DEFAULT_HEIGHT = 25;
22 22 const auto DEFAULT_WIDTH = 100;
23 23
24 24 struct ColumnProperties {
25 25 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
26 26 int height = DEFAULT_HEIGHT)
27 27 : m_Name{name}, m_Width{width}, m_Height{height}
28 28 {
29 29 }
30 30
31 31 QString m_Name;
32 32 int m_Width;
33 33 int m_Height;
34 34 };
35 35
36 36 const auto COLUMN_PROPERTIES
37 37 = QHash<int, ColumnProperties>{{NAME_COLUMN, {QObject::tr("Name")}},
38 38 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
39 39 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}};
40 40
41 41 /// Format for datetimes
42 42 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
43 43
44 44
45 45 } // namespace
46 46
47 47 struct VariableModel::VariableModelPrivate {
48 48 /// Variables created in SciQlop
49 49 std::vector<std::shared_ptr<Variable> > m_Variables;
50 50 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
51 51
52 52
53 53 /// Return the row index of the variable. -1 if it's not found
54 54 int indexOfVariable(Variable *variable) const noexcept;
55 55 };
56 56
57 57 VariableModel::VariableModel(QObject *parent)
58 58 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
59 59 {
60 60 }
61 61
62 62 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
63 const SqpDateTime &dateTime) noexcept
63 const SqpDateTime &dateTime,
64 const QVariantHash &metadata) noexcept
64 65 {
65 66 auto insertIndex = rowCount();
66 67 beginInsertRows({}, insertIndex, insertIndex);
67 68
68 auto variable = std::make_shared<Variable>(name, dateTime);
69 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
69 70
70 71 impl->m_Variables.push_back(variable);
71 72 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
72 73
73 74 endInsertRows();
74 75
75 76 return variable;
76 77 }
77 78
78 79 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
79 80 {
80 81 if (!variable) {
81 82 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
82 83 return;
83 84 }
84 85
85 86 // Finds variable in the model
86 87 auto begin = impl->m_Variables.cbegin();
87 88 auto end = impl->m_Variables.cend();
88 89 auto it = std::find(begin, end, variable);
89 90 if (it != end) {
90 91 auto removeIndex = std::distance(begin, it);
91 92
92 93 // Deletes variable
93 94 beginRemoveRows({}, removeIndex, removeIndex);
94 95 impl->m_Variables.erase(it);
95 96 endRemoveRows();
96 97 }
97 98 else {
98 99 qCritical(LOG_VariableModel())
99 100 << tr("Can't delete variable %1 from the model: the variable is not in the model")
100 101 .arg(variable->name());
101 102 }
102 103 }
103 104
104 105
105 106 std::shared_ptr<Variable> VariableModel::variable(int index) const
106 107 {
107 108 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
108 109 }
109 110
110 111 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
111 112 {
112 113
113 114 impl->m_VariableToProgress[variable] = progress;
114 115 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
115 116
116 117 emit dataChanged(modelIndex, modelIndex);
117 118 }
118 119
119 120 int VariableModel::columnCount(const QModelIndex &parent) const
120 121 {
121 122 Q_UNUSED(parent);
122 123
123 124 return NB_COLUMNS;
124 125 }
125 126
126 127 int VariableModel::rowCount(const QModelIndex &parent) const
127 128 {
128 129 Q_UNUSED(parent);
129 130
130 131 return impl->m_Variables.size();
131 132 }
132 133
133 134 QVariant VariableModel::data(const QModelIndex &index, int role) const
134 135 {
135 136 if (!index.isValid()) {
136 137 return QVariant{};
137 138 }
138 139
139 140 if (index.row() < 0 || index.row() >= rowCount()) {
140 141 return QVariant{};
141 142 }
142 143
143 144 if (role == Qt::DisplayRole) {
144 145 if (auto variable = impl->m_Variables.at(index.row()).get()) {
145 146 /// Lambda function that builds the variant to return for a time value
146 147 auto dateTimeVariant = [](double time) {
147 148 auto dateTime = QDateTime::fromMSecsSinceEpoch(time * 1000.);
148 149 return dateTime.toString(DATETIME_FORMAT);
149 150 };
150 151
151 152 switch (index.column()) {
152 153 case NAME_COLUMN:
153 154 return variable->name();
154 155 case TSTART_COLUMN:
155 156 return dateTimeVariant(variable->dateTime().m_TStart);
156 157 case TEND_COLUMN:
157 158 return dateTimeVariant(variable->dateTime().m_TEnd);
158 159 default:
159 160 // No action
160 161 break;
161 162 }
162 163
163 164 qWarning(LOG_VariableModel())
164 165 << tr("Can't get data (unknown column %1)").arg(index.column());
165 166 }
166 167 else {
167 168 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
168 169 }
169 170 }
170 171 else if (role == VariableRoles::ProgressRole) {
171 172 if (auto variable = impl->m_Variables.at(index.row())) {
172 173
173 174 auto it = impl->m_VariableToProgress.find(variable);
174 175 if (it != impl->m_VariableToProgress.cend()) {
175 176 return it->second;
176 177 }
177 178 }
178 179 }
179 180
180 181 return QVariant{};
181 182 }
182 183
183 184 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
184 185 {
185 186 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
186 187 return QVariant{};
187 188 }
188 189
189 190 if (orientation == Qt::Horizontal) {
190 191 auto propertiesIt = COLUMN_PROPERTIES.find(section);
191 192 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
192 193 // Role is either DisplayRole or SizeHintRole
193 194 return (role == Qt::DisplayRole)
194 195 ? QVariant{propertiesIt->m_Name}
195 196 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
196 197 }
197 198 else {
198 199 qWarning(LOG_VariableModel())
199 200 << tr("Can't get header data (unknown column %1)").arg(section);
200 201 }
201 202 }
202 203
203 204 return QVariant{};
204 205 }
205 206
206 207 void VariableModel::onVariableUpdated() noexcept
207 208 {
208 209 // Finds variable that has been updated in the model
209 210 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
210 211 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
211 212
212 213 if (updatedVariableIndex > -1) {
213 214 emit dataChanged(createIndex(updatedVariableIndex, 0),
214 215 createIndex(updatedVariableIndex, columnCount() - 1));
215 216 }
216 217 }
217 218 }
218 219
219 220 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
220 221 {
221 222 auto begin = std::cbegin(m_Variables);
222 223 auto end = std::cend(m_Variables);
223 224 auto it
224 225 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
225 226
226 227 if (it != end) {
227 228 // Gets the index of the variable in the model: we assume here that views have the same
228 229 // order as the model
229 230 return std::distance(begin, it);
230 231 }
231 232 else {
232 233 return -1;
233 234 }
234 235 }
@@ -1,145 +1,147
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 SIGNAL(variableCreationRequested(const QString &, std::shared_ptr<IDataProvider>)),
29 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
30 std::shared_ptr<IDataProvider>)),
30 31 m_VariableController.get(),
31 SLOT(createVariable(const QString &, std::shared_ptr<IDataProvider>)));
32 SLOT(createVariable(const QString &, const QVariantHash &,
33 std::shared_ptr<IDataProvider>)));
32 34
33 35 // VariableController <-> VisualizationController
34 36 connect(m_VariableController.get(),
35 37 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
36 38 m_VisualizationController.get(),
37 39 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
38 40
39 41
40 42 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
41 43 m_NetworkController->moveToThread(&m_NetworkControllerThread);
42 44 m_VariableController->moveToThread(&m_VariableControllerThread);
43 45 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
44 46
45 47
46 48 // Additionnal init
47 49 m_VariableController->setTimeController(m_TimeController.get());
48 50 }
49 51
50 52 virtual ~SqpApplicationPrivate()
51 53 {
52 54 qCInfo(LOG_SqpApplication()) << tr("SqpApplicationPrivate destruction");
53 55 m_DataSourceControllerThread.quit();
54 56 m_DataSourceControllerThread.wait();
55 57
56 58 m_NetworkControllerThread.quit();
57 59 m_NetworkControllerThread.wait();
58 60
59 61 m_VariableControllerThread.quit();
60 62 m_VariableControllerThread.wait();
61 63
62 64 m_VisualizationControllerThread.quit();
63 65 m_VisualizationControllerThread.wait();
64 66 }
65 67
66 68 std::unique_ptr<DataSourceController> m_DataSourceController;
67 69 std::unique_ptr<VariableController> m_VariableController;
68 70 std::unique_ptr<TimeController> m_TimeController;
69 71 std::unique_ptr<NetworkController> m_NetworkController;
70 72 std::unique_ptr<VisualizationController> m_VisualizationController;
71 73 QThread m_DataSourceControllerThread;
72 74 QThread m_NetworkControllerThread;
73 75 QThread m_VariableControllerThread;
74 76 QThread m_VisualizationControllerThread;
75 77 };
76 78
77 79
78 80 SqpApplication::SqpApplication(int &argc, char **argv)
79 81 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
80 82 {
81 83 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
82 84
83 85 connect(&impl->m_DataSourceControllerThread, &QThread::started,
84 86 impl->m_DataSourceController.get(), &DataSourceController::initialize);
85 87 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
86 88 impl->m_DataSourceController.get(), &DataSourceController::finalize);
87 89
88 90 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
89 91 &NetworkController::initialize);
90 92 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
91 93 &NetworkController::finalize);
92 94
93 95 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
94 96 &VariableController::initialize);
95 97 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
96 98 &VariableController::finalize);
97 99
98 100 connect(&impl->m_VisualizationControllerThread, &QThread::started,
99 101 impl->m_VisualizationController.get(), &VisualizationController::initialize);
100 102 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
101 103 impl->m_VisualizationController.get(), &VisualizationController::finalize);
102 104
103 105 impl->m_DataSourceControllerThread.start();
104 106 impl->m_NetworkControllerThread.start();
105 107 impl->m_VariableControllerThread.start();
106 108 impl->m_VisualizationControllerThread.start();
107 109
108 110 // Core connections:
109 111 // NetworkController <-> VariableController
110 112 connect(&sqpApp->networkController(), &NetworkController::replyDownloadProgress,
111 113 &sqpApp->variableController(), &VariableController::onVariableRetrieveDataInProgress);
112 114 }
113 115
114 116 SqpApplication::~SqpApplication()
115 117 {
116 118 }
117 119
118 120 void SqpApplication::initialize()
119 121 {
120 122 }
121 123
122 124 DataSourceController &SqpApplication::dataSourceController() noexcept
123 125 {
124 126 return *impl->m_DataSourceController;
125 127 }
126 128
127 129 NetworkController &SqpApplication::networkController() noexcept
128 130 {
129 131 return *impl->m_NetworkController;
130 132 }
131 133
132 134 TimeController &SqpApplication::timeController() noexcept
133 135 {
134 136 return *impl->m_TimeController;
135 137 }
136 138
137 139 VariableController &SqpApplication::variableController() noexcept
138 140 {
139 141 return *impl->m_VariableController;
140 142 }
141 143
142 144 VisualizationController &SqpApplication::visualizationController() noexcept
143 145 {
144 146 return *impl->m_VisualizationController;
145 147 }
General Comments 0
You need to be logged in to leave comments. Login now