##// END OF EJS Templates
Uses DateUtils
Alexandre Leroux -
r488:5b65a4cc471b
parent child
Show More
@@ -1,44 +1,43
1 1 #ifndef SCIQLOP_SQPDATETIME_H
2 2 #define SCIQLOP_SQPDATETIME_H
3 3
4 4 #include <QObject>
5 5
6 #include <QDateTime>
7 6 #include <QDebug>
8 7
8 #include <Common/DateUtils.h>
9 9 #include <Common/MetaTypes.h>
10 10
11 11 /**
12 12 * @brief The SqpDateTime struct holds the information of time parameters
13 13 */
14 14 struct SqpDateTime {
15 15 /// Start time
16 16 double m_TStart;
17 17 /// End time
18 18 double m_TEnd;
19 19
20 20 bool contains(const SqpDateTime &dateTime) const noexcept
21 21 {
22 22 return (m_TStart <= dateTime.m_TStart && m_TEnd >= dateTime.m_TEnd);
23 23 }
24 24
25 25 bool intersect(const SqpDateTime &dateTime) const noexcept
26 26 {
27 27 return (m_TEnd >= dateTime.m_TStart && m_TStart <= dateTime.m_TEnd);
28 28 }
29 29 };
30 30
31 31 inline QDebug operator<<(QDebug d, SqpDateTime obj)
32 32 {
33 auto tendDateTimeStart = QDateTime::fromMSecsSinceEpoch(obj.m_TStart * 1000);
34 auto tendDateTimeEnd = QDateTime::fromMSecsSinceEpoch(obj.m_TEnd * 1000);
33 auto tendDateTimeStart = DateUtils::dateTime(obj.m_TStart);
34 auto tendDateTimeEnd = DateUtils::dateTime(obj.m_TEnd);
35 35
36 // QDebug << "ts: " << tendDateTimeStart << " te: " << tendDateTimeEnd;
37 36 d << "ts: " << tendDateTimeStart << " te: " << tendDateTimeEnd;
38 37 return d;
39 38 }
40 39
41 40 // Required for using shared_ptr in signals/slots
42 41 SCIQLOP_REGISTER_META_TYPE(SQPDATETIME_REGISTRY, SqpDateTime)
43 42
44 43 #endif // SCIQLOP_SQPDATETIME_H
@@ -1,248 +1,249
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableModel.h>
3 3
4 #include <Common/DateUtils.h>
5
4 6 #include <Data/IDataSeries.h>
5 7
6 #include <QDateTime>
7 8 #include <QSize>
8 9 #include <unordered_map>
9 10
10 11 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
11 12
12 13 namespace {
13 14
14 15 // Column indexes
15 16 const auto NAME_COLUMN = 0;
16 17 const auto TSTART_COLUMN = 1;
17 18 const auto TEND_COLUMN = 2;
18 19 const auto NB_COLUMNS = 3;
19 20
20 21 // Column properties
21 22 const auto DEFAULT_HEIGHT = 25;
22 23 const auto DEFAULT_WIDTH = 100;
23 24
24 25 struct ColumnProperties {
25 26 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
26 27 int height = DEFAULT_HEIGHT)
27 28 : m_Name{name}, m_Width{width}, m_Height{height}
28 29 {
29 30 }
30 31
31 32 QString m_Name;
32 33 int m_Width;
33 34 int m_Height;
34 35 };
35 36
36 37 const auto COLUMN_PROPERTIES
37 38 = QHash<int, ColumnProperties>{{NAME_COLUMN, {QObject::tr("Name")}},
38 39 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
39 40 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}};
40 41
41 42 /// Format for datetimes
42 43 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
43 44
44 45
45 46 } // namespace
46 47
47 48 struct VariableModel::VariableModelPrivate {
48 49 /// Variables created in SciQlop
49 50 std::vector<std::shared_ptr<Variable> > m_Variables;
50 51 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
51 52
52 53 /// Return the row index of the variable. -1 if it's not found
53 54 int indexOfVariable(Variable *variable) const noexcept;
54 55 };
55 56
56 57 VariableModel::VariableModel(QObject *parent)
57 58 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
58 59 {
59 60 }
60 61
61 62 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
62 63 const SqpDateTime &dateTime,
63 64 const QVariantHash &metadata) noexcept
64 65 {
65 66 auto insertIndex = rowCount();
66 67 beginInsertRows({}, insertIndex, insertIndex);
67 68
68 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 // Removes variable from progress map
104 105 impl->m_VariableToProgress.erase(variable);
105 106 }
106 107
107 108
108 109 std::shared_ptr<Variable> VariableModel::variable(int index) const
109 110 {
110 111 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
111 112 }
112 113
113 114 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
114 115 {
115 116 if (progress > 0.0) {
116 117 impl->m_VariableToProgress[variable] = progress;
117 118 }
118 119 else {
119 120 impl->m_VariableToProgress.erase(variable);
120 121 }
121 122 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
122 123
123 124 emit dataChanged(modelIndex, modelIndex);
124 125 }
125 126
126 127 int VariableModel::columnCount(const QModelIndex &parent) const
127 128 {
128 129 Q_UNUSED(parent);
129 130
130 131 return NB_COLUMNS;
131 132 }
132 133
133 134 int VariableModel::rowCount(const QModelIndex &parent) const
134 135 {
135 136 Q_UNUSED(parent);
136 137
137 138 return impl->m_Variables.size();
138 139 }
139 140
140 141 QVariant VariableModel::data(const QModelIndex &index, int role) const
141 142 {
142 143 if (!index.isValid()) {
143 144 return QVariant{};
144 145 }
145 146
146 147 if (index.row() < 0 || index.row() >= rowCount()) {
147 148 return QVariant{};
148 149 }
149 150
150 151 if (role == Qt::DisplayRole) {
151 152 if (auto variable = impl->m_Variables.at(index.row()).get()) {
152 153 /// Lambda function that builds the variant to return for a time value
153 auto dateTimeVariant = [](double time) {
154 auto dateTime = QDateTime::fromMSecsSinceEpoch(time * 1000.);
154 auto dateTimeVariant = [](double secs) {
155 auto dateTime = DateUtils::dateTime(secs);
155 156 return dateTime.toString(DATETIME_FORMAT);
156 157 };
157 158
158 159 switch (index.column()) {
159 160 case NAME_COLUMN:
160 161 return variable->name();
161 162 case TSTART_COLUMN:
162 163 return dateTimeVariant(variable->dateTime().m_TStart);
163 164 case TEND_COLUMN:
164 165 return dateTimeVariant(variable->dateTime().m_TEnd);
165 166 default:
166 167 // No action
167 168 break;
168 169 }
169 170
170 171 qWarning(LOG_VariableModel())
171 172 << tr("Can't get data (unknown column %1)").arg(index.column());
172 173 }
173 174 else {
174 175 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
175 176 }
176 177 }
177 178 else if (role == VariableRoles::ProgressRole) {
178 179 if (auto variable = impl->m_Variables.at(index.row())) {
179 180
180 181 auto it = impl->m_VariableToProgress.find(variable);
181 182 if (it != impl->m_VariableToProgress.cend()) {
182 183 return it->second;
183 184 }
184 185 }
185 186 }
186 187
187 188 return QVariant{};
188 189 }
189 190
190 191 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
191 192 {
192 193 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
193 194 return QVariant{};
194 195 }
195 196
196 197 if (orientation == Qt::Horizontal) {
197 198 auto propertiesIt = COLUMN_PROPERTIES.find(section);
198 199 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
199 200 // Role is either DisplayRole or SizeHintRole
200 201 return (role == Qt::DisplayRole)
201 202 ? QVariant{propertiesIt->m_Name}
202 203 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
203 204 }
204 205 else {
205 206 qWarning(LOG_VariableModel())
206 207 << tr("Can't get header data (unknown column %1)").arg(section);
207 208 }
208 209 }
209 210
210 211 return QVariant{};
211 212 }
212 213
213 214 void VariableModel::abortProgress(const QModelIndex &index)
214 215 {
215 216 if (auto variable = impl->m_Variables.at(index.row())) {
216 217 emit abortProgessRequested(variable);
217 218 }
218 219 }
219 220
220 221 void VariableModel::onVariableUpdated() noexcept
221 222 {
222 223 // Finds variable that has been updated in the model
223 224 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
224 225 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
225 226
226 227 if (updatedVariableIndex > -1) {
227 228 emit dataChanged(createIndex(updatedVariableIndex, 0),
228 229 createIndex(updatedVariableIndex, columnCount() - 1));
229 230 }
230 231 }
231 232 }
232 233
233 234 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
234 235 {
235 236 auto begin = std::cbegin(m_Variables);
236 237 auto end = std::cend(m_Variables);
237 238 auto it
238 239 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
239 240
240 241 if (it != end) {
241 242 // Gets the index of the variable in the model: we assume here that views have the same
242 243 // order as the model
243 244 return std::distance(begin, it);
244 245 }
245 246 else {
246 247 return -1;
247 248 }
248 249 }
@@ -1,48 +1,47
1 1 #include "TimeWidget/TimeWidget.h"
2 2 #include "ui_TimeWidget.h"
3 3
4 4 #include <SqpApplication.h>
5 5 #include <Time/TimeController.h>
6 6
7 7 TimeWidget::TimeWidget(QWidget *parent) : QWidget{parent}, ui{new Ui::TimeWidget}
8 8 {
9 9 ui->setupUi(this);
10 10
11 11 ui->applyToolButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_DialogApplyButton));
12 12
13 13 // Connection
14 14 connect(ui->startDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
15 15 &TimeWidget::onTimeUpdateRequested);
16 16
17 17 connect(ui->endDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
18 18 &TimeWidget::onTimeUpdateRequested);
19 19
20 20
21 21 connect(ui->applyToolButton, &QToolButton::clicked, &sqpApp->timeController(),
22 22 &TimeController::onTimeNotify);
23 23
24 24 // Initialisation
25 25 ui->startDateTimeEdit->setDateTime(
26 26 QDateTime::currentDateTime().addSecs(-3600)); // one hour berefore
27 27 ui->endDateTimeEdit->setDateTime(QDateTime::currentDateTime());
28 28
29 29 auto dateTime
30 30 = SqpDateTime{QDateTime::currentDateTime().addSecs(-3600).toMSecsSinceEpoch() / 1000.0,
31 31 QDateTime::currentDateTime().toMSecsSinceEpoch() / 1000.0};
32 32 sqpApp->timeController().onTimeToUpdate(dateTime);
33 33 }
34 34
35 35
36 36 TimeWidget::~TimeWidget()
37 37 {
38 38 delete ui;
39 39 }
40 40
41 41 void TimeWidget::onTimeUpdateRequested()
42 42 {
43 auto dateTime = SqpDateTime{
44 static_cast<double>(ui->startDateTimeEdit->dateTime().toMSecsSinceEpoch() / 1000.),
45 static_cast<double>(ui->endDateTimeEdit->dateTime().toMSecsSinceEpoch()) / 1000.};
43 auto dateTime = SqpDateTime{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
44 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
46 45
47 46 emit timeUpdated(std::move(dateTime));
48 47 }
@@ -1,147 +1,148
1 1 #include "AmdaProvider.h"
2 2 #include "AmdaDefs.h"
3 3 #include "AmdaResultParser.h"
4 4
5 #include <Common/DateUtils.h>
5 6 #include <Data/DataProviderParameters.h>
6 7 #include <Network/NetworkController.h>
7 8 #include <SqpApplication.h>
8 9 #include <Variable/Variable.h>
9 10
10 11 #include <QNetworkAccessManager>
11 12 #include <QNetworkReply>
12 13 #include <QTemporaryFile>
13 14 #include <QThread>
14 15
15 16 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
16 17
17 18 namespace {
18 19
19 20 /// URL format for a request on AMDA server. The parameters are as follows:
20 21 /// - %1: start date
21 22 /// - %2: end date
22 23 /// - %3: parameter id
23 24 const auto AMDA_URL_FORMAT = QStringLiteral(
24 25 "http://amda.irap.omp.eu/php/rest/"
25 26 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&outputFormat=ASCII&"
26 27 "timeFormat=ISO8601&gzip=0");
27 28
28 29 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
29 30 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
30 31
31 32 /// Formats a time to a date that can be passed in URL
32 33 QString dateFormat(double sqpDateTime) noexcept
33 34 {
34 auto dateTime = QDateTime::fromMSecsSinceEpoch(sqpDateTime * 1000.);
35 auto dateTime = DateUtils::dateTime(sqpDateTime);
35 36 return dateTime.toString(AMDA_TIME_FORMAT);
36 37 }
37 38
38 39 } // namespace
39 40
40 41 AmdaProvider::AmdaProvider()
41 42 {
42 43 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
43 44 if (auto app = sqpApp) {
44 45 auto &networkController = app->networkController();
45 46 connect(this, SIGNAL(requestConstructed(QNetworkRequest, QUuid,
46 47 std::function<void(QNetworkReply *, QUuid)>)),
47 48 &networkController,
48 49 SLOT(onProcessRequested(QNetworkRequest, QUuid,
49 50 std::function<void(QNetworkReply *, QUuid)>)));
50 51
51 52
52 53 connect(&sqpApp->networkController(), SIGNAL(replyDownloadProgress(QUuid, double)), this,
53 54 SIGNAL(dataProvidedProgress(QUuid, double)));
54 55 }
55 56 }
56 57
57 58 void AmdaProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
58 59 {
59 60 // NOTE: Try to use multithread if possible
60 61 const auto times = parameters.m_Times;
61 62 const auto data = parameters.m_Data;
62 63 for (const auto &dateTime : qAsConst(times)) {
63 64 retrieveData(token, dateTime, data);
64 65 }
65 66 }
66 67
67 68 void AmdaProvider::requestDataAborting(QUuid identifier)
68 69 {
69 70 if (auto app = sqpApp) {
70 71 auto &networkController = app->networkController();
71 72 networkController.onReplyCanceled(identifier);
72 73 }
73 74 }
74 75
75 76 void AmdaProvider::retrieveData(QUuid token, const SqpDateTime &dateTime, const QVariantHash &data)
76 77 {
77 78 // Retrieves product ID from data: if the value is invalid, no request is made
78 79 auto productId = data.value(AMDA_XML_ID_KEY).toString();
79 80 if (productId.isNull()) {
80 81 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
81 82 return;
82 83 }
83 84 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData") << dateTime;
84 85
85 86 // /////////// //
86 87 // Creates URL //
87 88 // /////////// //
88 89
89 90 auto startDate = dateFormat(dateTime.m_TStart);
90 91 auto endDate = dateFormat(dateTime.m_TEnd);
91 92
92 93 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
93 94 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData url:") << url;
94 95 auto tempFile = std::make_shared<QTemporaryFile>();
95 96
96 97 // LAMBDA
97 98 auto httpDownloadFinished
98 99 = [this, dateTime, tempFile, token](QNetworkReply *reply, QUuid dataId) noexcept {
99 100 Q_UNUSED(dataId);
100 101
101 102 // Don't do anything if the reply was abort
102 103 if (reply->error() != QNetworkReply::OperationCanceledError) {
103 104
104 105 if (tempFile) {
105 106 auto replyReadAll = reply->readAll();
106 107 if (!replyReadAll.isEmpty()) {
107 108 tempFile->write(replyReadAll);
108 109 }
109 110 tempFile->close();
110 111
111 112 // Parse results file
112 113 if (auto dataSeries = AmdaResultParser::readTxt(tempFile->fileName())) {
113 114 emit dataProvided(token, dataSeries, dateTime);
114 115 }
115 116 else {
116 117 /// @todo ALX : debug
117 118 }
118 119 }
119 120 }
120 121
121 122 };
122 123 auto httpFinishedLambda
123 124 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
124 125
125 126 // Don't do anything if the reply was abort
126 127 if (reply->error() != QNetworkReply::OperationCanceledError) {
127 128 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
128 129
129 130
130 131 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData downloadFileUrl:")
131 132 << downloadFileUrl;
132 133 // Executes request for downloading file //
133 134
134 135 // Creates destination file
135 136 if (tempFile->open()) {
136 137 // Executes request
137 138 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId,
138 139 httpDownloadFinished);
139 140 }
140 141 }
141 142 };
142 143
143 144 // //////////////// //
144 145 // Executes request //
145 146 // //////////////// //
146 147 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
147 148 }
General Comments 0
You need to be logged in to leave comments. Login now