##// END OF EJS Templates
Implement of the abort download process
perrinel -
r422:ff0aebb946e3
parent child
Show More
@@ -1,59 +1,64
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 13 class DataProviderParameters;
14 14 class IDataSeries;
15 15 class QNetworkReply;
16 16 class QNetworkRequest;
17 17
18 18 /**
19 19 * @brief The IDataProvider interface aims to declare a data provider.
20 20 *
21 21 * A data provider is an entity that generates data and returns it according to various parameters
22 22 * (time interval, product to retrieve the data, etc.)
23 23 *
24 24 * @sa IDataSeries
25 25 */
26 26 class IDataProvider : public QObject {
27 27
28 28 Q_OBJECT
29 29 public:
30 30 virtual ~IDataProvider() noexcept = default;
31 31
32 32 /**
33 33 * @brief requestDataLoading provide datas for the data identified by identifier and parameters
34 34 */
35 35 virtual void requestDataLoading(QUuid identifier, const DataProviderParameters &parameters) = 0;
36 36
37 /**
38 * @brief requestDataAborting stop data loading of the data identified by identifier
39 */
40 virtual void requestDataAborting(QUuid identifier) = 0;
41
37 42 signals:
38 43 /**
39 44 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
40 45 * identified by identifier
41 46 */
42 47 void dataProvided(QUuid identifier, std::shared_ptr<IDataSeries> dateSerie,
43 48 const SqpDateTime &dateTime);
44 49
45 50
46 51 /**
47 52 * @brief requestConstructed send a request for the data identified by identifier
48 53 * @callback is the methode call by the reply of the request when it is finished.
49 54 */
50 55 void requestConstructed(const QNetworkRequest &request, QUuid identifier,
51 56 std::function<void(QNetworkReply *, QUuid)> callback);
52 57 };
53 58
54 59 // Required for using shared_ptr in signals/slots
55 60 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
56 61 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
57 62 std::function<void(QNetworkReply *, QUuid)>)
58 63
59 64 #endif // SCIQLOP_IDATAPROVIDER_H
@@ -1,85 +1,92
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 /**
54 * @brief abort the variable retrieve data progression
55 */
56 void abortProgress(std::shared_ptr<Variable> variable);
57
53 58 signals:
54 59 /// Signal emitted when a variable is about to be deleted from the controller
55 60 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
56 61
57 62 public slots:
58 63 /// Request the data loading of the variable whithin dateTime
59 64 void onRequestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
60 65 /**
61 66 * Creates a new variable and adds it to the model
62 67 * @param name the name of the new variable
63 68 * @param metadata the metadata of the new variable
64 69 * @param provider the data provider for the new variable
65 70 */
66 71 void createVariable(const QString &name, const QVariantHash &metadata,
67 72 std::shared_ptr<IDataProvider> provider) noexcept;
68 73
69 74 /// Update the temporal parameters of every selected variable to dateTime
70 75 void onDateTimeOnSelection(const SqpDateTime &dateTime);
71 76
72 77
73 78 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
74 79
80 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
81
75 82 void initialize();
76 83 void finalize();
77 84
78 85 private:
79 86 void waitForFinish();
80 87
81 88 class VariableControllerPrivate;
82 89 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
83 90 };
84 91
85 92 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,71 +1,79
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 Q_OBJECT
25 26 public:
26 27 explicit VariableModel(QObject *parent = nullptr);
27 28
28 29 /**
29 30 * Creates a new variable in the model
30 31 * @param name the name of the new variable
31 32 * @param dateTime the dateTime of the new variable
32 33 * @param metadata the metadata associated to the new variable
33 34 * @return the pointer to the new variable
34 35 */
35 36 std::shared_ptr<Variable> createVariable(const QString &name, const SqpDateTime &dateTime,
36 37 const QVariantHash &metadata) noexcept;
37 38
38 39 /**
39 40 * Deletes a variable from the model, if it exists
40 41 * @param variable the variable to delete
41 42 */
42 43 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
43 44
44 45
45 46 std::shared_ptr<Variable> variable(int index) const;
46 47
47 48 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
48 49
50
49 51 // /////////////////////////// //
50 52 // QAbstractTableModel methods //
51 53 // /////////////////////////// //
52 54
53 55 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
54 56 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
55 57 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
56 58 virtual QVariant headerData(int section, Qt::Orientation orientation,
57 59 int role = Qt::DisplayRole) const override;
58 60
61
62 void abortProgress(const QModelIndex &index);
63
64 signals:
65 void abortProgessRequested(std::shared_ptr<Variable> variable);
66
59 67 private:
60 68 class VariableModelPrivate;
61 69 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
62 70
63 71 private slots:
64 72 /// Slot called when data of a variable has been updated
65 73 void onVariableUpdated() noexcept;
66 74 };
67 75
68 76 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
69 77 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
70 78
71 79 #endif // SCIQLOP_VARIABLEMODEL_H
@@ -1,215 +1,238
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
50 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
51 &VariableController::onAbortProgressRequested);
49 52 }
50 53
51 54 VariableController::~VariableController()
52 55 {
53 56 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
54 57 << QThread::currentThread();
55 58 this->waitForFinish();
56 59 }
57 60
58 61 VariableModel *VariableController::variableModel() noexcept
59 62 {
60 63 return impl->m_VariableModel;
61 64 }
62 65
63 66 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
64 67 {
65 68 return impl->m_VariableSelectionModel;
66 69 }
67 70
68 71 void VariableController::setTimeController(TimeController *timeController) noexcept
69 72 {
70 73 impl->m_TimeController = timeController;
71 74 }
72 75
73 76 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
74 77 {
75 78 if (!variable) {
76 79 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
77 80 return;
78 81 }
79 82
80 83 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
81 84 // make some treatments before the deletion
82 85 emit variableAboutToBeDeleted(variable);
83 86
84 87 // Deletes identifier
85 88 impl->m_VariableToIdentifierMap.erase(variable);
86 89
87 90 // Deletes provider
88 91 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
89 92 qCDebug(LOG_VariableController())
90 93 << tr("Number of providers deleted for variable %1: %2")
91 94 .arg(variable->name(), QString::number(nbProvidersDeleted));
92 95
93 96 // Clears cache
94 97 impl->m_VariableCacheController->clear(variable);
95 98
96 99 // Deletes from model
97 100 impl->m_VariableModel->deleteVariable(variable);
98 101 }
99 102
100 103 void VariableController::deleteVariables(
101 104 const QVector<std::shared_ptr<Variable> > &variables) noexcept
102 105 {
103 106 for (auto variable : qAsConst(variables)) {
104 107 deleteVariable(variable);
105 108 }
106 109 }
107 110
111 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
112 {
113 }
114
108 115 void VariableController::createVariable(const QString &name, const QVariantHash &metadata,
109 116 std::shared_ptr<IDataProvider> provider) noexcept
110 117 {
111 118
112 119 if (!impl->m_TimeController) {
113 120 qCCritical(LOG_VariableController())
114 121 << tr("Impossible to create variable: The time controller is null");
115 122 return;
116 123 }
117 124
118 125 auto dateTime = impl->m_TimeController->dateTime();
119 126
120 127 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime, metadata)) {
121 128 auto identifier = QUuid::createUuid();
122 129
123 130 // store the provider
124 131 impl->m_VariableToProviderMap[newVariable] = provider;
125 132 impl->m_VariableToIdentifierMap[newVariable] = identifier;
126 133
127 134 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
128 135 QUuid identifier, auto dataSeriesAcquired, auto dateTimeToPutInCache)
129 136 {
130 137 if (auto variable = varW.lock()) {
131 138 auto varIdentifier = impl->m_VariableToIdentifierMap.at(variable);
132 139 if (varIdentifier == identifier) {
133 140 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
134 141 variable->setDataSeries(dataSeriesAcquired);
135 142 }
136 143 }
137 144 };
138 145
139 146 connect(provider.get(), &IDataProvider::dataProvided, addDateTimeAcquired);
140 147 this->onRequestDataLoading(newVariable, dateTime);
141 148 }
142 149 }
143 150
144 151 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
145 152 {
146 153 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
147 154 << QThread::currentThread()->objectName();
148 155 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
149 156
150 157 for (const auto &selectedRow : qAsConst(selectedRows)) {
151 158 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
152 159 selectedVariable->setDateTime(dateTime);
153 160 this->onRequestDataLoading(selectedVariable, dateTime);
154 161 }
155 162 }
156 163 }
157 164
158 165 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
159 166 {
160 167 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
161 168
162 169 auto end = impl->m_VariableToIdentifierMap.cend();
163 170 auto it = std::find_if(impl->m_VariableToIdentifierMap.cbegin(), end, findReply);
164 171 if (it != end) {
165 172 impl->m_VariableModel->setDataProgress(it->first, progress);
166 173 }
167 174 }
168 175
176 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
177 {
178 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
179 << QThread::currentThread()->objectName();
180
181 auto it = impl->m_VariableToIdentifier.find(variable);
182 if (it != impl->m_VariableToIdentifier.cend()) {
183 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
184 }
185 else {
186 qCWarning(LOG_VariableController())
187 << tr("Aborting progression of inexistant variable detected !!!")
188 << QThread::currentThread()->objectName();
189 }
190 }
191
169 192
170 193 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
171 194 const SqpDateTime &dateTime)
172 195 {
173 196 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
174 197 << QThread::currentThread()->objectName();
175 198 // we want to load data of the variable for the dateTime.
176 199 // First we check if the cache contains some of them.
177 200 // For the other, we ask the provider to give them.
178 201 if (variable) {
179 202
180 203 auto dateTimeListNotInCache
181 204 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
182 205
183 206 if (!dateTimeListNotInCache.empty()) {
184 207 // Ask the provider for each data on the dateTimeListNotInCache
185 208 auto identifier = impl->m_VariableToIdentifierMap.at(variable);
186 209 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
187 210 identifier,
188 211 DataProviderParameters{std::move(dateTimeListNotInCache), variable->metadata()});
189 212 }
190 213 else {
191 214 emit variable->updated();
192 215 }
193 216 }
194 217 else {
195 218 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
196 219 }
197 220 }
198 221
199 222
200 223 void VariableController::initialize()
201 224 {
202 225 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
203 226 impl->m_WorkingMutex.lock();
204 227 qCDebug(LOG_VariableController()) << tr("VariableController init END");
205 228 }
206 229
207 230 void VariableController::finalize()
208 231 {
209 232 impl->m_WorkingMutex.unlock();
210 233 }
211 234
212 235 void VariableController::waitForFinish()
213 236 {
214 237 QMutexLocker locker{&impl->m_WorkingMutex};
215 238 }
@@ -1,236 +1,243
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 /// Return the row index of the variable. -1 if it's not found
53 53 int indexOfVariable(Variable *variable) const noexcept;
54 54 };
55 55
56 56 VariableModel::VariableModel(QObject *parent)
57 57 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
58 58 {
59 59 }
60 60
61 61 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
62 62 const SqpDateTime &dateTime,
63 63 const QVariantHash &metadata) noexcept
64 64 {
65 65 auto insertIndex = rowCount();
66 66 beginInsertRows({}, insertIndex, insertIndex);
67 67
68 68 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
69 69
70 70 impl->m_Variables.push_back(variable);
71 71 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
72 72
73 73 endInsertRows();
74 74
75 75 return variable;
76 76 }
77 77
78 78 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
79 79 {
80 80 if (!variable) {
81 81 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
82 82 return;
83 83 }
84 84
85 85 // Finds variable in the model
86 86 auto begin = impl->m_Variables.cbegin();
87 87 auto end = impl->m_Variables.cend();
88 88 auto it = std::find(begin, end, variable);
89 89 if (it != end) {
90 90 auto removeIndex = std::distance(begin, it);
91 91
92 92 // Deletes variable
93 93 beginRemoveRows({}, removeIndex, removeIndex);
94 94 impl->m_Variables.erase(it);
95 95 endRemoveRows();
96 96 }
97 97 else {
98 98 qCritical(LOG_VariableModel())
99 99 << tr("Can't delete variable %1 from the model: the variable is not in the model")
100 100 .arg(variable->name());
101 101 }
102 102
103 103 // Removes variable from progress map
104 104 impl->m_VariableToProgress.erase(variable);
105 105 }
106 106
107 107
108 108 std::shared_ptr<Variable> VariableModel::variable(int index) const
109 109 {
110 110 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
111 111 }
112 112
113 113 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
114 114 {
115 115 impl->m_VariableToProgress[variable] = progress;
116 116 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
117 117
118 118 emit dataChanged(modelIndex, modelIndex);
119 119 }
120 120
121 121 int VariableModel::columnCount(const QModelIndex &parent) const
122 122 {
123 123 Q_UNUSED(parent);
124 124
125 125 return NB_COLUMNS;
126 126 }
127 127
128 128 int VariableModel::rowCount(const QModelIndex &parent) const
129 129 {
130 130 Q_UNUSED(parent);
131 131
132 132 return impl->m_Variables.size();
133 133 }
134 134
135 135 QVariant VariableModel::data(const QModelIndex &index, int role) const
136 136 {
137 137 if (!index.isValid()) {
138 138 return QVariant{};
139 139 }
140 140
141 141 if (index.row() < 0 || index.row() >= rowCount()) {
142 142 return QVariant{};
143 143 }
144 144
145 145 if (role == Qt::DisplayRole) {
146 146 if (auto variable = impl->m_Variables.at(index.row()).get()) {
147 147 /// Lambda function that builds the variant to return for a time value
148 148 auto dateTimeVariant = [](double time) {
149 149 auto dateTime = QDateTime::fromMSecsSinceEpoch(time * 1000.);
150 150 return dateTime.toString(DATETIME_FORMAT);
151 151 };
152 152
153 153 switch (index.column()) {
154 154 case NAME_COLUMN:
155 155 return variable->name();
156 156 case TSTART_COLUMN:
157 157 return dateTimeVariant(variable->dateTime().m_TStart);
158 158 case TEND_COLUMN:
159 159 return dateTimeVariant(variable->dateTime().m_TEnd);
160 160 default:
161 161 // No action
162 162 break;
163 163 }
164 164
165 165 qWarning(LOG_VariableModel())
166 166 << tr("Can't get data (unknown column %1)").arg(index.column());
167 167 }
168 168 else {
169 169 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
170 170 }
171 171 }
172 172 else if (role == VariableRoles::ProgressRole) {
173 173 if (auto variable = impl->m_Variables.at(index.row())) {
174 174
175 175 auto it = impl->m_VariableToProgress.find(variable);
176 176 if (it != impl->m_VariableToProgress.cend()) {
177 177 return it->second;
178 178 }
179 179 }
180 180 }
181 181
182 182 return QVariant{};
183 183 }
184 184
185 185 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
186 186 {
187 187 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
188 188 return QVariant{};
189 189 }
190 190
191 191 if (orientation == Qt::Horizontal) {
192 192 auto propertiesIt = COLUMN_PROPERTIES.find(section);
193 193 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
194 194 // Role is either DisplayRole or SizeHintRole
195 195 return (role == Qt::DisplayRole)
196 196 ? QVariant{propertiesIt->m_Name}
197 197 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
198 198 }
199 199 else {
200 200 qWarning(LOG_VariableModel())
201 201 << tr("Can't get header data (unknown column %1)").arg(section);
202 202 }
203 203 }
204 204
205 205 return QVariant{};
206 206 }
207 207
208 void VariableModel::abortProgress(const QModelIndex &index)
209 {
210 if (auto variable = impl->m_Variables.at(index.row())) {
211 emit abortProgessRequested(variable);
212 }
213 }
214
208 215 void VariableModel::onVariableUpdated() noexcept
209 216 {
210 217 // Finds variable that has been updated in the model
211 218 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
212 219 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
213 220
214 221 if (updatedVariableIndex > -1) {
215 222 emit dataChanged(createIndex(updatedVariableIndex, 0),
216 223 createIndex(updatedVariableIndex, columnCount() - 1));
217 224 }
218 225 }
219 226 }
220 227
221 228 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
222 229 {
223 230 auto begin = std::cbegin(m_Variables);
224 231 auto end = std::cend(m_Variables);
225 232 auto it
226 233 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
227 234
228 235 if (it != end) {
229 236 // Gets the index of the variable in the model: we assume here that views have the same
230 237 // order as the model
231 238 return std::distance(begin, it);
232 239 }
233 240 else {
234 241 return -1;
235 242 }
236 243 }
@@ -1,140 +1,200
1 1 #include <Variable/VariableController.h>
2 2 #include <Variable/VariableInspectorWidget.h>
3 3 #include <Variable/VariableMenuHeaderWidget.h>
4 4 #include <Variable/VariableModel.h>
5 5
6 6 #include <ui_VariableInspectorWidget.h>
7 7
8 #include <QMouseEvent>
8 9 #include <QSortFilterProxyModel>
9 10 #include <QStyledItemDelegate>
10 11 #include <QWidgetAction>
11 12
12 13 #include <SqpApplication.h>
13 14
14 15 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
15 16
16 17
17 18 class QProgressBarItemDelegate : public QStyledItemDelegate {
18 19
19 20 public:
20 21 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
21 22
22 23 void paint(QPainter *painter, const QStyleOptionViewItem &option,
23 24 const QModelIndex &index) const
24 25 {
25 26 auto data = index.data(Qt::DisplayRole);
26 27 auto progressData = index.data(VariableRoles::ProgressRole);
27 28 if (data.isValid() && progressData.isValid()) {
28 29 auto name = data.value<QString>();
29 30 auto progress = progressData.value<double>();
30 if (progress >= 0) {
31 if (progress > 0) {
32 auto cancelButtonWidth = 20;
31 33 auto progressBarOption = QStyleOptionProgressBar{};
32 progressBarOption.rect = option.rect;
34 auto progressRect = option.rect;
35 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
36 progressBarOption.rect = progressRect;
33 37 progressBarOption.minimum = 0;
34 38 progressBarOption.maximum = 100;
35 39 progressBarOption.progress = progress;
36 40 progressBarOption.text
37 41 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
38 42 progressBarOption.textVisible = true;
39 43 progressBarOption.textAlignment = Qt::AlignCenter;
40 44
45
41 46 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
42 47 painter);
48
49 // Cancel button
50 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
51 option.rect.height());
52 auto buttonOption = QStyleOptionButton{};
53 buttonOption.rect = buttonRect;
54 buttonOption.text = "X";
55
56 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
57 }
58 else {
59 QStyledItemDelegate::paint(painter, option, index);
43 60 }
44 61 }
45 62 else {
46 63 QStyledItemDelegate::paint(painter, option, index);
47 64 }
48 65 }
66
67 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
68 const QModelIndex &index)
69 {
70 if (event->type() == QEvent::MouseButtonRelease) {
71 auto data = index.data(Qt::DisplayRole);
72 auto progressData = index.data(VariableRoles::ProgressRole);
73 if (data.isValid() && progressData.isValid()) {
74 auto cancelButtonWidth = 20;
75 auto progressRect = option.rect;
76 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
77 // Cancel button
78 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
79 option.rect.height());
80
81 QMouseEvent *e = (QMouseEvent *)event;
82 int clickX = e->x();
83 int clickY = e->y();
84
85 auto x = buttonRect.left(); // the X coordinate
86 auto y = buttonRect.top(); // the Y coordinate
87 auto w = buttonRect.width(); // button width
88 auto h = buttonRect.height(); // button height
89
90 if (clickX > x && clickX < x + w) {
91 if (clickY > y && clickY < y + h) {
92 qCritical(LOG_VariableInspectorWidget()) << tr("editorEvent CLIC");
93 auto variableModel = sqpApp->variableController().variableModel();
94 variableModel->abortProgress(index);
95 }
96 }
97 else {
98 QStyledItemDelegate::editorEvent(event, model, option, index);
99 }
100 }
101 else {
102 QStyledItemDelegate::editorEvent(event, model, option, index);
103 }
104 }
105 else {
106 QStyledItemDelegate::editorEvent(event, model, option, index);
107 }
108 }
49 109 };
50 110
51 111 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
52 112 : QWidget{parent},
53 113 ui{new Ui::VariableInspectorWidget},
54 114 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
55 115 {
56 116 ui->setupUi(this);
57 117
58 118 // Sets model for table
59 119 // auto sortFilterModel = new QSortFilterProxyModel{this};
60 120 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
61 121
62 122 auto variableModel = sqpApp->variableController().variableModel();
63 123 ui->tableView->setModel(variableModel);
64 124
65 125 // Adds extra signal/slot between view and model, so the view can be updated instantly when
66 126 // there is a change of data in the model
67 127 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
68 128 SLOT(refresh()));
69 129
70 130 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
71 131 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
72 132
73 133 // Fixes column sizes
74 134 auto model = ui->tableView->model();
75 135 const auto count = model->columnCount();
76 136 for (auto i = 0; i < count; ++i) {
77 137 ui->tableView->setColumnWidth(
78 138 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
79 139 }
80 140
81 141 // Sets selection options
82 142 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
83 143 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
84 144
85 145 // Connection to show a menu when right clicking on the tree
86 146 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
87 147 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
88 148 &VariableInspectorWidget::onTableMenuRequested);
89 149 }
90 150
91 151 VariableInspectorWidget::~VariableInspectorWidget()
92 152 {
93 153 delete ui;
94 154 }
95 155
96 156 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
97 157 {
98 158 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
99 159
100 160 // Gets the model to retrieve the underlying selected variables
101 161 auto model = sqpApp->variableController().variableModel();
102 162 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
103 163 for (const auto &selectedRow : qAsConst(selectedRows)) {
104 164 if (auto selectedVariable = model->variable(selectedRow.row())) {
105 165 selectedVariables.push_back(selectedVariable);
106 166 }
107 167 }
108 168
109 169 QMenu tableMenu{};
110 170
111 171 // Emits a signal so that potential receivers can populate the menu before displaying it
112 172 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
113 173
114 174 // Adds menu-specific actions
115 175 if (!selectedVariables.isEmpty()) {
116 176 // 'Delete' action
117 177 auto deleteFun = [&selectedVariables]() {
118 178 sqpApp->variableController().deleteVariables(selectedVariables);
119 179 };
120 180
121 181 tableMenu.addSeparator();
122 182 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
123 183 }
124 184
125 185 if (!tableMenu.isEmpty()) {
126 186 // Generates menu header (inserted before first action)
127 187 auto firstAction = tableMenu.actions().first();
128 188 auto headerAction = new QWidgetAction{&tableMenu};
129 189 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
130 190 tableMenu.insertAction(firstAction, headerAction);
131 191
132 192 // Displays menu
133 193 tableMenu.exec(mapToGlobal(pos));
134 194 }
135 195 }
136 196
137 197 void VariableInspectorWidget::refresh() noexcept
138 198 {
139 199 ui->tableView->viewport()->update();
140 200 }
@@ -1,28 +1,30
1 1 #ifndef SCIQLOP_AMDAPROVIDER_H
2 2 #define SCIQLOP_AMDAPROVIDER_H
3 3
4 4 #include "AmdaGlobal.h"
5 5
6 6 #include <Data/IDataProvider.h>
7 7
8 8 #include <QLoggingCategory>
9 9
10 10
11 11 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
12 12
13 13 class QNetworkReply;
14 14
15 15 /**
16 16 * @brief The AmdaProvider class is an example of how a data provider can generate data
17 17 */
18 18 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
19 19 public:
20 20 explicit AmdaProvider();
21 21
22 22 void requestDataLoading(QUuid token, const DataProviderParameters &parameters) override;
23 23
24 void requestDataAborting(QUuid identifier) override;
25
24 26 private:
25 27 void retrieveData(QUuid token, const SqpDateTime &dateTime, const QVariantHash &data);
26 28 };
27 29
28 30 #endif // SCIQLOP_AMDAPROVIDER_H
@@ -1,129 +1,134
1 1 #include "AmdaProvider.h"
2 2 #include "AmdaDefs.h"
3 3 #include "AmdaResultParser.h"
4 4
5 5 #include <Data/DataProviderParameters.h>
6 6 #include <Network/NetworkController.h>
7 7 #include <SqpApplication.h>
8 8 #include <Variable/Variable.h>
9 9
10 10 #include <QNetworkAccessManager>
11 11 #include <QNetworkReply>
12 12 #include <QTemporaryFile>
13 13 #include <QThread>
14 14
15 15 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
16 16
17 17 namespace {
18 18
19 19 /// URL format for a request on AMDA server. The parameters are as follows:
20 20 /// - %1: start date
21 21 /// - %2: end date
22 22 /// - %3: parameter id
23 23 const auto AMDA_URL_FORMAT = QStringLiteral(
24 24 "http://amda.irap.omp.eu/php/rest/"
25 25 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&sampling=60&outputFormat=ASCII&"
26 26 "timeFormat=ISO8601&gzip=0");
27 27
28 28 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
29 29 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:ss");
30 30
31 31 /// Formats a time to a date that can be passed in URL
32 32 QString dateFormat(double sqpDateTime) noexcept
33 33 {
34 34 auto dateTime = QDateTime::fromMSecsSinceEpoch(sqpDateTime * 1000.);
35 35 return dateTime.toString(AMDA_TIME_FORMAT);
36 36 }
37 37
38 38 } // namespace
39 39
40 40 AmdaProvider::AmdaProvider()
41 41 {
42 42 qCDebug(LOG_NetworkController()) << tr("AmdaProvider::AmdaProvider")
43 43 << QThread::currentThread();
44 44 if (auto app = sqpApp) {
45 45 auto &networkController = app->networkController();
46 46 connect(this, SIGNAL(requestConstructed(QNetworkRequest, QUuid,
47 47 std::function<void(QNetworkReply *, QUuid)>)),
48 48 &networkController,
49 49 SLOT(onProcessRequested(QNetworkRequest, QUuid,
50 50 std::function<void(QNetworkReply *, QUuid)>)));
51 51 }
52 52 }
53 53
54 54 void AmdaProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
55 55 {
56 56 // NOTE: Try to use multithread if possible
57 57 const auto times = parameters.m_Times;
58 58 const auto data = parameters.m_Data;
59 59 for (const auto &dateTime : qAsConst(times)) {
60 60 retrieveData(token, dateTime, data);
61 61 }
62 62 }
63 63
64 void AmdaProvider::requestDataAborting(QUuid identifier)
65 {
66 if (auto app = sqpApp) {
67 auto &networkController = app->networkController();
68 networkController.onReplyCanceled(identifier);
69 }
70 }
71
64 72 void AmdaProvider::retrieveData(QUuid token, const SqpDateTime &dateTime, const QVariantHash &data)
65 73 {
66 74 // Retrieves product ID from data: if the value is invalid, no request is made
67 75 auto productId = data.value(AMDA_XML_ID_KEY).toString();
68 76 if (productId.isNull()) {
69 77 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
70 78 return;
71 79 }
72 80
73 81 // /////////// //
74 82 // Creates URL //
75 83 // /////////// //
76 84
77 85 auto startDate = dateFormat(dateTime.m_TStart);
78 86 auto endDate = dateFormat(dateTime.m_TEnd);
79 87
80 88 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
81 89
82 90 auto tempFile = std::make_shared<QTemporaryFile>();
83 91
84 92 // LAMBDA
85 93 auto httpDownloadFinished
86 94 = [this, dateTime, tempFile, token](QNetworkReply *reply, QUuid dataId) noexcept {
87 95 Q_UNUSED(dataId);
88 96
89 97 if (tempFile) {
90 98 auto replyReadAll = reply->readAll();
91 99 if (!replyReadAll.isEmpty()) {
92 100 tempFile->write(replyReadAll);
93 101 }
94 102 tempFile->close();
95 103
96 104 // Parse results file
97 105 if (auto dataSeries = AmdaResultParser::readTxt(tempFile->fileName())) {
98 106 emit dataProvided(token, dataSeries, dateTime);
99 107 }
100 108 else {
101 109 /// @todo ALX : debug
102 110 }
103 111 }
104 112
105 // Deletes reply
106 reply->deleteLater();
107 reply = nullptr;
113
108 114 };
109 115 auto httpFinishedLambda = [this, httpDownloadFinished, tempFile](QNetworkReply *reply,
110 116 QUuid dataId) noexcept {
111 117
112 118 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
113 // Deletes old reply
114 reply->deleteLater();
119
115 120
116 121 // Executes request for downloading file //
117 122
118 123 // Creates destination file
119 124 if (tempFile->open()) {
120 125 // Executes request
121 126 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId, httpDownloadFinished);
122 127 }
123 128 };
124 129
125 130 // //////////////// //
126 131 // Executes request //
127 132 // //////////////// //
128 133 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
129 134 }
@@ -1,25 +1,28
1 1 #ifndef SCIQLOP_COSINUSPROVIDER_H
2 2 #define SCIQLOP_COSINUSPROVIDER_H
3 3
4 4 #include "MockPluginGlobal.h"
5 5
6 6 #include <Data/IDataProvider.h>
7 7
8 8 #include <QLoggingCategory>
9 9
10 10 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
11 11
12 12 /**
13 13 * @brief The CosinusProvider class is an example of how a data provider can generate data
14 14 */
15 15 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
16 16 public:
17 17 void requestDataLoading(QUuid token, const DataProviderParameters &parameters) override;
18 18
19 19
20 void requestDataAborting(QUuid identifier) override;
21
22
20 23 private:
21 24 /// @sa IDataProvider::retrieveData()
22 25 std::shared_ptr<IDataSeries> retrieveData(const SqpDateTime &dateTime) const;
23 26 };
24 27
25 28 #endif // SCIQLOP_COSINUSPROVIDER_H
@@ -1,48 +1,53
1 1 #include "CosinusProvider.h"
2 2
3 3 #include <Data/DataProviderParameters.h>
4 4 #include <Data/ScalarSeries.h>
5 5
6 6 #include <cmath>
7 7
8 8 #include <QDateTime>
9 9 #include <QThread>
10 10
11 11 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
12 12
13 13 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(const SqpDateTime &dateTime) const
14 14 {
15 15 auto dataIndex = 0;
16 16
17 17 // Gets the timerange from the parameters
18 18 double freq = 100.0;
19 19 double start = dateTime.m_TStart * freq; // 100 htz
20 20 double end = dateTime.m_TEnd * freq; // 100 htz
21 21
22 22 // We assure that timerange is valid
23 23 if (end < start) {
24 24 std::swap(start, end);
25 25 }
26 26
27 27 // Generates scalar series containing cosinus values (one value per second)
28 28 auto scalarSeries
29 29 = std::make_shared<ScalarSeries>(end - start, Unit{QStringLiteral("t"), true}, Unit{});
30 30
31 31 for (auto time = start; time < end; ++time, ++dataIndex) {
32 32 const auto timeOnFreq = time / freq;
33 33 scalarSeries->setData(dataIndex, timeOnFreq, std::cos(timeOnFreq));
34 34 }
35 35 return scalarSeries;
36 36 }
37 37
38 38 void CosinusProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
39 39 {
40 40 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataLoading"
41 41 << QThread::currentThread()->objectName();
42 42 // NOTE: Try to use multithread if possible
43 43 const auto times = parameters.m_Times;
44 44 for (const auto &dateTime : qAsConst(times)) {
45 45 auto scalarSeries = this->retrieveData(dateTime);
46 46 emit dataProvided(token, scalarSeries, dateTime);
47 47 }
48 48 }
49
50 void CosinusProvider::requestDataAborting(QUuid identifier)
51 {
52 // TODO
53 }
General Comments 0
You need to be logged in to leave comments. Login now