##// END OF EJS Templates
Fix bug time precision with catalogue
perrinel -
r1369:b20dcec1c57b
parent child
Show More
@@ -1,19 +1,23
1 #ifndef SCIQLOP_DATEUTILS_H
1 #ifndef SCIQLOP_DATEUTILS_H
2 #define SCIQLOP_DATEUTILS_H
2 #define SCIQLOP_DATEUTILS_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <QDateTime>
6 #include <QDateTime>
7
7
8 /// Format for datetimes
9 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
10 const auto DATETIME_FORMAT_ONE_LINE = QStringLiteral("dd/MM/yyyy hh:mm:ss:zzz");
11
8 /**
12 /**
9 * Utility class with methods for dates
13 * Utility class with methods for dates
10 */
14 */
11 struct SCIQLOP_CORE_EXPORT DateUtils {
15 struct SCIQLOP_CORE_EXPORT DateUtils {
12 /// Converts seconds (since epoch) to datetime. By default, the datetime is in UTC
16 /// Converts seconds (since epoch) to datetime. By default, the datetime is in UTC
13 static QDateTime dateTime(double secs, Qt::TimeSpec timeSpec = Qt::UTC) noexcept;
17 static QDateTime dateTime(double secs, Qt::TimeSpec timeSpec = Qt::UTC) noexcept;
14
18
15 /// Converts datetime to seconds since epoch
19 /// Converts datetime to seconds since epoch
16 static double secondsSinceEpoch(const QDateTime &dateTime) noexcept;
20 static double secondsSinceEpoch(const QDateTime &dateTime) noexcept;
17 };
21 };
18
22
19 #endif // SCIQLOP_DATEUTILS_H
23 #endif // SCIQLOP_DATEUTILS_H
@@ -1,396 +1,393
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableController.h>
2 #include <Variable/VariableController.h>
3 #include <Variable/VariableModel.h>
3 #include <Variable/VariableModel.h>
4
4
5 #include <Common/DateUtils.h>
5 #include <Common/DateUtils.h>
6 #include <Common/MimeTypesDef.h>
6 #include <Common/MimeTypesDef.h>
7 #include <Common/StringUtils.h>
7 #include <Common/StringUtils.h>
8
8
9 #include <Data/IDataSeries.h>
9 #include <Data/IDataSeries.h>
10
10
11 #include <DataSource/DataSourceController.h>
11 #include <DataSource/DataSourceController.h>
12 #include <Time/TimeController.h>
12 #include <Time/TimeController.h>
13
13
14 #include <QMimeData>
14 #include <QMimeData>
15 #include <QSize>
15 #include <QSize>
16 #include <QTimer>
16 #include <QTimer>
17 #include <unordered_map>
17 #include <unordered_map>
18
18
19 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
19 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
20
20
21 namespace {
21 namespace {
22
22
23 // Column indexes
23 // Column indexes
24 const auto NAME_COLUMN = 0;
24 const auto NAME_COLUMN = 0;
25 const auto TSTART_COLUMN = 1;
25 const auto TSTART_COLUMN = 1;
26 const auto TEND_COLUMN = 2;
26 const auto TEND_COLUMN = 2;
27 const auto NBPOINTS_COLUMN = 3;
27 const auto NBPOINTS_COLUMN = 3;
28 const auto UNIT_COLUMN = 4;
28 const auto UNIT_COLUMN = 4;
29 const auto MISSION_COLUMN = 5;
29 const auto MISSION_COLUMN = 5;
30 const auto PLUGIN_COLUMN = 6;
30 const auto PLUGIN_COLUMN = 6;
31 const auto NB_COLUMNS = 7;
31 const auto NB_COLUMNS = 7;
32
32
33 // Column properties
33 // Column properties
34 const auto DEFAULT_HEIGHT = 25;
34 const auto DEFAULT_HEIGHT = 25;
35 const auto DEFAULT_WIDTH = 100;
35 const auto DEFAULT_WIDTH = 100;
36
36
37 struct ColumnProperties {
37 struct ColumnProperties {
38 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
38 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
39 int height = DEFAULT_HEIGHT)
39 int height = DEFAULT_HEIGHT)
40 : m_Name{name}, m_Width{width}, m_Height{height}
40 : m_Name{name}, m_Width{width}, m_Height{height}
41 {
41 {
42 }
42 }
43
43
44 QString m_Name;
44 QString m_Name;
45 int m_Width;
45 int m_Width;
46 int m_Height;
46 int m_Height;
47 };
47 };
48
48
49 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
49 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
50 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
50 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
51 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
51 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
52 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
52 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
53 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
53 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
54
54
55 /// Format for datetimes
56 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
57
58 QString uniqueName(const QString &defaultName,
55 QString uniqueName(const QString &defaultName,
59 const std::vector<std::shared_ptr<Variable> > &variables)
56 const std::vector<std::shared_ptr<Variable> > &variables)
60 {
57 {
61 auto forbiddenNames = std::vector<QString>(variables.size());
58 auto forbiddenNames = std::vector<QString>(variables.size());
62 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
59 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
63 [](const auto &variable) { return variable->name(); });
60 [](const auto &variable) { return variable->name(); });
64 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
61 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
65 Q_ASSERT(!uniqueName.isEmpty());
62 Q_ASSERT(!uniqueName.isEmpty());
66
63
67 return uniqueName;
64 return uniqueName;
68 }
65 }
69
66
70 } // namespace
67 } // namespace
71
68
72 struct VariableModel::VariableModelPrivate {
69 struct VariableModel::VariableModelPrivate {
73 /// Variables created in SciQlop
70 /// Variables created in SciQlop
74 std::vector<std::shared_ptr<Variable> > m_Variables;
71 std::vector<std::shared_ptr<Variable> > m_Variables;
75 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
72 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
76 VariableController *m_VariableController;
73 VariableController *m_VariableController;
77
74
78 /// Return the row index of the variable. -1 if it's not found
75 /// Return the row index of the variable. -1 if it's not found
79 int indexOfVariable(Variable *variable) const noexcept;
76 int indexOfVariable(Variable *variable) const noexcept;
80 };
77 };
81
78
82 VariableModel::VariableModel(VariableController *parent)
79 VariableModel::VariableModel(VariableController *parent)
83 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
80 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
84 {
81 {
85 impl->m_VariableController = parent;
82 impl->m_VariableController = parent;
86 }
83 }
87
84
88 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
85 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
89 {
86 {
90 auto insertIndex = rowCount();
87 auto insertIndex = rowCount();
91 beginInsertRows({}, insertIndex, insertIndex);
88 beginInsertRows({}, insertIndex, insertIndex);
92
89
93 // Generates unique name for the variable
90 // Generates unique name for the variable
94 variable->setName(uniqueName(variable->name(), impl->m_Variables));
91 variable->setName(uniqueName(variable->name(), impl->m_Variables));
95
92
96 impl->m_Variables.push_back(variable);
93 impl->m_Variables.push_back(variable);
97 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
94 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
98
95
99 endInsertRows();
96 endInsertRows();
100 }
97 }
101
98
102 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
99 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
103 {
100 {
104 auto end = impl->m_Variables.cend();
101 auto end = impl->m_Variables.cend();
105 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
102 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
106 }
103 }
107
104
108 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
105 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
109 const QVariantHash &metadata) noexcept
106 const QVariantHash &metadata) noexcept
110 {
107 {
111 auto variable = std::make_shared<Variable>(name, metadata);
108 auto variable = std::make_shared<Variable>(name, metadata);
112 addVariable(variable);
109 addVariable(variable);
113
110
114 return variable;
111 return variable;
115 }
112 }
116
113
117 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
114 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
118 {
115 {
119 if (!variable) {
116 if (!variable) {
120 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
117 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
121 return;
118 return;
122 }
119 }
123
120
124 // Finds variable in the model
121 // Finds variable in the model
125 auto begin = impl->m_Variables.cbegin();
122 auto begin = impl->m_Variables.cbegin();
126 auto end = impl->m_Variables.cend();
123 auto end = impl->m_Variables.cend();
127 auto it = std::find(begin, end, variable);
124 auto it = std::find(begin, end, variable);
128 if (it != end) {
125 if (it != end) {
129 auto removeIndex = std::distance(begin, it);
126 auto removeIndex = std::distance(begin, it);
130
127
131 // Deletes variable
128 // Deletes variable
132 beginRemoveRows({}, removeIndex, removeIndex);
129 beginRemoveRows({}, removeIndex, removeIndex);
133 impl->m_Variables.erase(it);
130 impl->m_Variables.erase(it);
134 endRemoveRows();
131 endRemoveRows();
135 }
132 }
136 else {
133 else {
137 qCritical(LOG_VariableModel())
134 qCritical(LOG_VariableModel())
138 << tr("Can't delete variable %1 from the model: the variable is not in the model")
135 << tr("Can't delete variable %1 from the model: the variable is not in the model")
139 .arg(variable->name());
136 .arg(variable->name());
140 }
137 }
141
138
142 // Removes variable from progress map
139 // Removes variable from progress map
143 impl->m_VariableToProgress.erase(variable);
140 impl->m_VariableToProgress.erase(variable);
144 }
141 }
145
142
146
143
147 std::shared_ptr<Variable> VariableModel::variable(int index) const
144 std::shared_ptr<Variable> VariableModel::variable(int index) const
148 {
145 {
149 return (index >= 0u && static_cast<size_t>(index) < impl->m_Variables.size())
146 return (index >= 0u && static_cast<size_t>(index) < impl->m_Variables.size())
150 ? impl->m_Variables[index]
147 ? impl->m_Variables[index]
151 : nullptr;
148 : nullptr;
152 }
149 }
153
150
154 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
151 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
155 {
152 {
156 return impl->m_Variables;
153 return impl->m_Variables;
157 }
154 }
158
155
159 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
156 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
160 {
157 {
161 if (progress > 0.0) {
158 if (progress > 0.0) {
162 impl->m_VariableToProgress[variable] = progress;
159 impl->m_VariableToProgress[variable] = progress;
163 }
160 }
164 else {
161 else {
165 impl->m_VariableToProgress.erase(variable);
162 impl->m_VariableToProgress.erase(variable);
166 }
163 }
167 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
164 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
168
165
169 emit dataChanged(modelIndex, modelIndex);
166 emit dataChanged(modelIndex, modelIndex);
170 }
167 }
171
168
172 int VariableModel::columnCount(const QModelIndex &parent) const
169 int VariableModel::columnCount(const QModelIndex &parent) const
173 {
170 {
174 Q_UNUSED(parent);
171 Q_UNUSED(parent);
175
172
176 return NB_COLUMNS;
173 return NB_COLUMNS;
177 }
174 }
178
175
179 int VariableModel::rowCount(const QModelIndex &parent) const
176 int VariableModel::rowCount(const QModelIndex &parent) const
180 {
177 {
181 Q_UNUSED(parent);
178 Q_UNUSED(parent);
182
179
183 return impl->m_Variables.size();
180 return impl->m_Variables.size();
184 }
181 }
185
182
186 QVariant VariableModel::data(const QModelIndex &index, int role) const
183 QVariant VariableModel::data(const QModelIndex &index, int role) const
187 {
184 {
188 if (!index.isValid()) {
185 if (!index.isValid()) {
189 return QVariant{};
186 return QVariant{};
190 }
187 }
191
188
192 if (index.row() < 0 || index.row() >= rowCount()) {
189 if (index.row() < 0 || index.row() >= rowCount()) {
193 return QVariant{};
190 return QVariant{};
194 }
191 }
195
192
196 if (role == Qt::DisplayRole) {
193 if (role == Qt::DisplayRole) {
197 if (auto variable = impl->m_Variables.at(index.row()).get()) {
194 if (auto variable = impl->m_Variables.at(index.row()).get()) {
198 switch (index.column()) {
195 switch (index.column()) {
199 case NAME_COLUMN:
196 case NAME_COLUMN:
200 return variable->name();
197 return variable->name();
201 case TSTART_COLUMN: {
198 case TSTART_COLUMN: {
202 auto range = variable->realRange();
199 auto range = variable->realRange();
203 return range != INVALID_RANGE
200 return range != INVALID_RANGE
204 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
201 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
205 : QVariant{};
202 : QVariant{};
206 }
203 }
207 case TEND_COLUMN: {
204 case TEND_COLUMN: {
208 auto range = variable->realRange();
205 auto range = variable->realRange();
209 return range != INVALID_RANGE
206 return range != INVALID_RANGE
210 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
207 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
211 : QVariant{};
208 : QVariant{};
212 }
209 }
213 case NBPOINTS_COLUMN:
210 case NBPOINTS_COLUMN:
214 return variable->nbPoints();
211 return variable->nbPoints();
215 case UNIT_COLUMN:
212 case UNIT_COLUMN:
216 return variable->metadata().value(QStringLiteral("units"));
213 return variable->metadata().value(QStringLiteral("units"));
217 case MISSION_COLUMN:
214 case MISSION_COLUMN:
218 return variable->metadata().value(QStringLiteral("mission"));
215 return variable->metadata().value(QStringLiteral("mission"));
219 case PLUGIN_COLUMN:
216 case PLUGIN_COLUMN:
220 return variable->metadata().value(QStringLiteral("plugin"));
217 return variable->metadata().value(QStringLiteral("plugin"));
221 default:
218 default:
222 // No action
219 // No action
223 break;
220 break;
224 }
221 }
225
222
226 qWarning(LOG_VariableModel())
223 qWarning(LOG_VariableModel())
227 << tr("Can't get data (unknown column %1)").arg(index.column());
224 << tr("Can't get data (unknown column %1)").arg(index.column());
228 }
225 }
229 else {
226 else {
230 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
227 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
231 }
228 }
232 }
229 }
233 else if (role == VariableRoles::ProgressRole) {
230 else if (role == VariableRoles::ProgressRole) {
234 if (auto variable = impl->m_Variables.at(index.row())) {
231 if (auto variable = impl->m_Variables.at(index.row())) {
235
232
236 auto it = impl->m_VariableToProgress.find(variable);
233 auto it = impl->m_VariableToProgress.find(variable);
237 if (it != impl->m_VariableToProgress.cend()) {
234 if (it != impl->m_VariableToProgress.cend()) {
238 return it->second;
235 return it->second;
239 }
236 }
240 }
237 }
241 }
238 }
242
239
243 return QVariant{};
240 return QVariant{};
244 }
241 }
245
242
246 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
243 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
247 {
244 {
248 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
245 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
249 return QVariant{};
246 return QVariant{};
250 }
247 }
251
248
252 if (orientation == Qt::Horizontal) {
249 if (orientation == Qt::Horizontal) {
253 auto propertiesIt = COLUMN_PROPERTIES.find(section);
250 auto propertiesIt = COLUMN_PROPERTIES.find(section);
254 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
251 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
255 // Role is either DisplayRole or SizeHintRole
252 // Role is either DisplayRole or SizeHintRole
256 return (role == Qt::DisplayRole)
253 return (role == Qt::DisplayRole)
257 ? QVariant{propertiesIt->m_Name}
254 ? QVariant{propertiesIt->m_Name}
258 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
255 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
259 }
256 }
260 else {
257 else {
261 qWarning(LOG_VariableModel())
258 qWarning(LOG_VariableModel())
262 << tr("Can't get header data (unknown column %1)").arg(section);
259 << tr("Can't get header data (unknown column %1)").arg(section);
263 }
260 }
264 }
261 }
265
262
266 return QVariant{};
263 return QVariant{};
267 }
264 }
268
265
269 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
266 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
270 {
267 {
271 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
268 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
272 }
269 }
273
270
274 Qt::DropActions VariableModel::supportedDropActions() const
271 Qt::DropActions VariableModel::supportedDropActions() const
275 {
272 {
276 return Qt::CopyAction | Qt::MoveAction;
273 return Qt::CopyAction | Qt::MoveAction;
277 }
274 }
278
275
279 Qt::DropActions VariableModel::supportedDragActions() const
276 Qt::DropActions VariableModel::supportedDragActions() const
280 {
277 {
281 return Qt::CopyAction | Qt::MoveAction;
278 return Qt::CopyAction | Qt::MoveAction;
282 }
279 }
283
280
284 QStringList VariableModel::mimeTypes() const
281 QStringList VariableModel::mimeTypes() const
285 {
282 {
286 return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE};
283 return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE};
287 }
284 }
288
285
289 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
286 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
290 {
287 {
291 auto mimeData = new QMimeData;
288 auto mimeData = new QMimeData;
292
289
293 QList<std::shared_ptr<Variable> > variableList;
290 QList<std::shared_ptr<Variable> > variableList;
294
291
295
292
296 SqpRange firstTimeRange;
293 SqpRange firstTimeRange;
297 for (const auto &index : indexes) {
294 for (const auto &index : indexes) {
298 if (index.column() == 0) { // only the first column
295 if (index.column() == 0) { // only the first column
299 auto variable = impl->m_Variables.at(index.row());
296 auto variable = impl->m_Variables.at(index.row());
300 if (variable.get() && index.isValid()) {
297 if (variable.get() && index.isValid()) {
301
298
302 if (variableList.isEmpty()) {
299 if (variableList.isEmpty()) {
303 // Gets the range of the first variable
300 // Gets the range of the first variable
304 firstTimeRange = std::move(variable->range());
301 firstTimeRange = std::move(variable->range());
305 }
302 }
306
303
307 variableList << variable;
304 variableList << variable;
308 }
305 }
309 }
306 }
310 }
307 }
311
308
312 auto variablesEncodedData = impl->m_VariableController->mimeDataForVariables(variableList);
309 auto variablesEncodedData = impl->m_VariableController->mimeDataForVariables(variableList);
313 mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData);
310 mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData);
314
311
315 if (variableList.count() == 1) {
312 if (variableList.count() == 1) {
316 // No time range MIME data if multiple variables are dragged
313 // No time range MIME data if multiple variables are dragged
317 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
314 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
318 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
315 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
319 }
316 }
320
317
321 return mimeData;
318 return mimeData;
322 }
319 }
323
320
324 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
321 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
325 int column, const QModelIndex &parent) const
322 int column, const QModelIndex &parent) const
326 {
323 {
327 // drop of a product
324 // drop of a product
328 return data->hasFormat(MIME_TYPE_PRODUCT_LIST)
325 return data->hasFormat(MIME_TYPE_PRODUCT_LIST)
329 || (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()
326 || (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()
330 && !data->hasFormat(MIME_TYPE_VARIABLE_LIST));
327 && !data->hasFormat(MIME_TYPE_VARIABLE_LIST));
331 }
328 }
332
329
333 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
330 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
334 const QModelIndex &parent)
331 const QModelIndex &parent)
335 {
332 {
336 auto dropDone = false;
333 auto dropDone = false;
337
334
338 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
335 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
339
336
340 auto productList
337 auto productList
341 = DataSourceController::productsDataForMimeData(data->data(MIME_TYPE_PRODUCT_LIST));
338 = DataSourceController::productsDataForMimeData(data->data(MIME_TYPE_PRODUCT_LIST));
342
339
343 for (auto metaData : productList) {
340 for (auto metaData : productList) {
344 emit requestVariable(metaData.toHash());
341 emit requestVariable(metaData.toHash());
345 }
342 }
346
343
347 dropDone = true;
344 dropDone = true;
348 }
345 }
349 else if (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()) {
346 else if (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()) {
350 auto variable = this->variable(parent.row());
347 auto variable = this->variable(parent.row());
351 auto range = TimeController::timeRangeForMimeData(data->data(MIME_TYPE_TIME_RANGE));
348 auto range = TimeController::timeRangeForMimeData(data->data(MIME_TYPE_TIME_RANGE));
352
349
353 emit requestVariableRangeUpdate(variable, range);
350 emit requestVariableRangeUpdate(variable, range);
354
351
355 dropDone = true;
352 dropDone = true;
356 }
353 }
357
354
358 return dropDone;
355 return dropDone;
359 }
356 }
360
357
361 void VariableModel::abortProgress(const QModelIndex &index)
358 void VariableModel::abortProgress(const QModelIndex &index)
362 {
359 {
363 if (auto variable = impl->m_Variables.at(index.row())) {
360 if (auto variable = impl->m_Variables.at(index.row())) {
364 emit abortProgessRequested(variable);
361 emit abortProgessRequested(variable);
365 }
362 }
366 }
363 }
367
364
368 void VariableModel::onVariableUpdated() noexcept
365 void VariableModel::onVariableUpdated() noexcept
369 {
366 {
370 // Finds variable that has been updated in the model
367 // Finds variable that has been updated in the model
371 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
368 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
372 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
369 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
373
370
374 if (updatedVariableIndex > -1) {
371 if (updatedVariableIndex > -1) {
375 emit dataChanged(createIndex(updatedVariableIndex, 0),
372 emit dataChanged(createIndex(updatedVariableIndex, 0),
376 createIndex(updatedVariableIndex, columnCount() - 1));
373 createIndex(updatedVariableIndex, columnCount() - 1));
377 }
374 }
378 }
375 }
379 }
376 }
380
377
381 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
378 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
382 {
379 {
383 auto begin = std::cbegin(m_Variables);
380 auto begin = std::cbegin(m_Variables);
384 auto end = std::cend(m_Variables);
381 auto end = std::cend(m_Variables);
385 auto it
382 auto it
386 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
383 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
387
384
388 if (it != end) {
385 if (it != end) {
389 // Gets the index of the variable in the model: we assume here that views have the same
386 // Gets the index of the variable in the model: we assume here that views have the same
390 // order as the model
387 // order as the model
391 return std::distance(begin, it);
388 return std::distance(begin, it);
392 }
389 }
393 else {
390 else {
394 return -1;
391 return -1;
395 }
392 }
396 }
393 }
@@ -1,478 +1,484
1 #include "Catalogue/CatalogueEventsModel.h"
1 #include "Catalogue/CatalogueEventsModel.h"
2
2
3 #include <Catalogue/CatalogueController.h>
3 #include <Catalogue/CatalogueController.h>
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5 #include <Common/MimeTypesDef.h>
5 #include <Common/MimeTypesDef.h>
6 #include <DBEvent.h>
6 #include <DBEvent.h>
7 #include <DBEventProduct.h>
7 #include <DBEventProduct.h>
8 #include <DBTag.h>
8 #include <DBTag.h>
9 #include <Data/SqpRange.h>
9 #include <Data/SqpRange.h>
10 #include <SqpApplication.h>
10 #include <SqpApplication.h>
11 #include <Time/TimeController.h>
11 #include <Time/TimeController.h>
12
12
13 #include <list>
13 #include <list>
14 #include <unordered_map>
14 #include <unordered_map>
15
15
16 #include <QHash>
16 #include <QHash>
17 #include <QMimeData>
17 #include <QMimeData>
18
18
19 Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
19 Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
20
20
21 const auto EVENT_ITEM_TYPE = 1;
21 const auto EVENT_ITEM_TYPE = 1;
22 const auto EVENT_PRODUCT_ITEM_TYPE = 2;
22 const auto EVENT_PRODUCT_ITEM_TYPE = 2;
23
23
24 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
24 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
25 QVector<std::shared_ptr<DBEvent> > m_Events;
25 QVector<std::shared_ptr<DBEvent> > m_Events;
26 std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
26 std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
27 QVector<std::shared_ptr<DBCatalogue> > m_SourceCatalogue;
27 QVector<std::shared_ptr<DBCatalogue> > m_SourceCatalogue;
28
28
29 QStringList columnNames()
29 QStringList columnNames()
30 {
30 {
31 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"),
31 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"),
32 tr("Tags"), tr("Product"), tr("")};
32 tr("Tags"), tr("Product"), tr("")};
33 }
33 }
34
34
35 QVariant sortData(int col, const std::shared_ptr<DBEvent> &event) const
35 QVariant sortData(int col, const std::shared_ptr<DBEvent> &event) const
36 {
36 {
37 if (col == (int)CatalogueEventsModel::Column::Validation) {
37 if (col == (int)CatalogueEventsModel::Column::Validation) {
38 auto hasChanges = sqpApp->catalogueController().eventHasChanges(event);
38 auto hasChanges = sqpApp->catalogueController().eventHasChanges(event);
39 return hasChanges ? true : QVariant();
39 return hasChanges ? true : QVariant();
40 }
40 }
41
41
42 return eventData(col, event);
42 return eventData(col, event);
43 }
43 }
44
44
45 QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
45 QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
46 {
46 {
47 switch (static_cast<Column>(col)) {
47 switch (static_cast<Column>(col)) {
48 case CatalogueEventsModel::Column::Name:
48 case CatalogueEventsModel::Column::Name:
49 return event->getName();
49 return event->getName();
50 case CatalogueEventsModel::Column::TStart:
50 case CatalogueEventsModel::Column::TStart:
51 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart())
51 return nbEventProducts(event) > 0
52 : QVariant{};
52 ? DateUtils::dateTime(event->getTStart())
53 .toString(DATETIME_FORMAT_ONE_LINE)
54 : QVariant{};
53 case CatalogueEventsModel::Column::TEnd:
55 case CatalogueEventsModel::Column::TEnd:
54 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd())
56 return nbEventProducts(event) > 0
55 : QVariant{};
57 ? DateUtils::dateTime(event->getTEnd())
58 .toString(DATETIME_FORMAT_ONE_LINE)
59 : QVariant{};
56 case CatalogueEventsModel::Column::Product: {
60 case CatalogueEventsModel::Column::Product: {
57 auto eventProducts = event->getEventProducts();
61 auto eventProducts = event->getEventProducts();
58 QStringList eventProductList;
62 QStringList eventProductList;
59 for (auto evtProduct : eventProducts) {
63 for (auto evtProduct : eventProducts) {
60 eventProductList << evtProduct.getProductId();
64 eventProductList << evtProduct.getProductId();
61 }
65 }
62 return eventProductList.join(";");
66 return eventProductList.join(";");
63 }
67 }
64 case CatalogueEventsModel::Column::Tags: {
68 case CatalogueEventsModel::Column::Tags: {
65 QString tagList;
69 QString tagList;
66 auto tags = event->getTags();
70 auto tags = event->getTags();
67 for (auto tag : tags) {
71 for (auto tag : tags) {
68 tagList += tag.getName();
72 tagList += tag.getName();
69 tagList += ' ';
73 tagList += ' ';
70 }
74 }
71
75
72 return tagList;
76 return tagList;
73 }
77 }
74 case CatalogueEventsModel::Column::Validation:
78 case CatalogueEventsModel::Column::Validation:
75 return QVariant();
79 return QVariant();
76 default:
80 default:
77 break;
81 break;
78 }
82 }
79
83
80 Q_ASSERT(false);
84 Q_ASSERT(false);
81 return QStringLiteral("Unknown Data");
85 return QStringLiteral("Unknown Data");
82 }
86 }
83
87
84 void parseEventProduct(const std::shared_ptr<DBEvent> &event)
88 void parseEventProduct(const std::shared_ptr<DBEvent> &event)
85 {
89 {
86 for (auto product : event->getEventProducts()) {
90 for (auto product : event->getEventProducts()) {
87 m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
91 m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
88 }
92 }
89 }
93 }
90
94
91 int nbEventProducts(const std::shared_ptr<DBEvent> &event) const
95 int nbEventProducts(const std::shared_ptr<DBEvent> &event) const
92 {
96 {
93 auto eventProductsIt = m_EventProducts.find(event.get());
97 auto eventProductsIt = m_EventProducts.find(event.get());
94 if (eventProductsIt != m_EventProducts.cend()) {
98 if (eventProductsIt != m_EventProducts.cend()) {
95 return m_EventProducts.at(event.get()).count();
99 return m_EventProducts.at(event.get()).count();
96 }
100 }
97 else {
101 else {
98 return 0;
102 return 0;
99 }
103 }
100 }
104 }
101
105
102 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
106 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
103 {
107 {
104 switch (static_cast<Column>(col)) {
108 switch (static_cast<Column>(col)) {
105 case CatalogueEventsModel::Column::Name:
109 case CatalogueEventsModel::Column::Name:
106 return eventProduct->getProductId();
110 return eventProduct->getProductId();
107 case CatalogueEventsModel::Column::TStart:
111 case CatalogueEventsModel::Column::TStart:
108 return DateUtils::dateTime(eventProduct->getTStart());
112 return DateUtils::dateTime(eventProduct->getTStart())
113 .toString(DATETIME_FORMAT_ONE_LINE);
109 case CatalogueEventsModel::Column::TEnd:
114 case CatalogueEventsModel::Column::TEnd:
110 return DateUtils::dateTime(eventProduct->getTEnd());
115 return DateUtils::dateTime(eventProduct->getTEnd())
116 .toString(DATETIME_FORMAT_ONE_LINE);
111 case CatalogueEventsModel::Column::Product:
117 case CatalogueEventsModel::Column::Product:
112 return eventProduct->getProductId();
118 return eventProduct->getProductId();
113 case CatalogueEventsModel::Column::Tags:
119 case CatalogueEventsModel::Column::Tags:
114 return QString();
120 return QString();
115 case CatalogueEventsModel::Column::Validation:
121 case CatalogueEventsModel::Column::Validation:
116 return QVariant();
122 return QVariant();
117 default:
123 default:
118 break;
124 break;
119 }
125 }
120
126
121 Q_ASSERT(false);
127 Q_ASSERT(false);
122 return QStringLiteral("Unknown Data");
128 return QStringLiteral("Unknown Data");
123 }
129 }
124
130
125 void refreshChildrenOfIndex(CatalogueEventsModel *model, const QModelIndex &index) const
131 void refreshChildrenOfIndex(CatalogueEventsModel *model, const QModelIndex &index) const
126 {
132 {
127 auto childCount = model->rowCount(index);
133 auto childCount = model->rowCount(index);
128 auto colCount = model->columnCount();
134 auto colCount = model->columnCount();
129 emit model->dataChanged(model->index(0, 0, index),
135 emit model->dataChanged(model->index(0, 0, index),
130 model->index(childCount, colCount, index));
136 model->index(childCount, colCount, index));
131 }
137 }
132 };
138 };
133
139
134 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
140 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
135 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
141 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
136 {
142 {
137 }
143 }
138
144
139 void CatalogueEventsModel::setSourceCatalogues(
145 void CatalogueEventsModel::setSourceCatalogues(
140 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
146 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
141 {
147 {
142 impl->m_SourceCatalogue = catalogues;
148 impl->m_SourceCatalogue = catalogues;
143 }
149 }
144
150
145 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
151 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
146 {
152 {
147 beginResetModel();
153 beginResetModel();
148
154
149 impl->m_Events = events;
155 impl->m_Events = events;
150 impl->m_EventProducts.clear();
156 impl->m_EventProducts.clear();
151 for (auto event : events) {
157 for (auto event : events) {
152 impl->parseEventProduct(event);
158 impl->parseEventProduct(event);
153 }
159 }
154
160
155 endResetModel();
161 endResetModel();
156 }
162 }
157
163
158 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
164 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
159 {
165 {
160 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
166 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
161 return impl->m_Events.value(index.row());
167 return impl->m_Events.value(index.row());
162 }
168 }
163 else {
169 else {
164 return nullptr;
170 return nullptr;
165 }
171 }
166 }
172 }
167
173
168 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
174 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
169 {
175 {
170 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
176 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
171 return getEvent(index.parent());
177 return getEvent(index.parent());
172 }
178 }
173 else {
179 else {
174 return nullptr;
180 return nullptr;
175 }
181 }
176 }
182 }
177
183
178 std::shared_ptr<DBEventProduct>
184 std::shared_ptr<DBEventProduct>
179 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
185 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
180 {
186 {
181 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
187 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
182 auto event = static_cast<DBEvent *>(index.internalPointer());
188 auto event = static_cast<DBEvent *>(index.internalPointer());
183 return impl->m_EventProducts.at(event).value(index.row());
189 return impl->m_EventProducts.at(event).value(index.row());
184 }
190 }
185 else {
191 else {
186 return nullptr;
192 return nullptr;
187 }
193 }
188 }
194 }
189
195
190 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
196 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
191 {
197 {
192 beginInsertRows(QModelIndex(), impl->m_Events.count(), impl->m_Events.count());
198 beginInsertRows(QModelIndex(), impl->m_Events.count(), impl->m_Events.count());
193 impl->m_Events.append(event);
199 impl->m_Events.append(event);
194 impl->parseEventProduct(event);
200 impl->parseEventProduct(event);
195 endInsertRows();
201 endInsertRows();
196
202
197 // Also refreshes its children event products
203 // Also refreshes its children event products
198 auto eventIndex = index(impl->m_Events.count(), 0);
204 auto eventIndex = index(impl->m_Events.count(), 0);
199 impl->refreshChildrenOfIndex(this, eventIndex);
205 impl->refreshChildrenOfIndex(this, eventIndex);
200 }
206 }
201
207
202 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
208 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
203 {
209 {
204 auto index = impl->m_Events.indexOf(event);
210 auto index = impl->m_Events.indexOf(event);
205 if (index >= 0) {
211 if (index >= 0) {
206 beginRemoveRows(QModelIndex(), index, index);
212 beginRemoveRows(QModelIndex(), index, index);
207 impl->m_Events.removeAt(index);
213 impl->m_Events.removeAt(index);
208 impl->m_EventProducts.erase(event.get());
214 impl->m_EventProducts.erase(event.get());
209 endRemoveRows();
215 endRemoveRows();
210 }
216 }
211 }
217 }
212
218
213 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
219 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
214 {
220 {
215 return impl->m_Events;
221 return impl->m_Events;
216 }
222 }
217
223
218 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event,
224 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event,
219 bool refreshEventProducts)
225 bool refreshEventProducts)
220 {
226 {
221 auto eventIndex = indexOf(event);
227 auto eventIndex = indexOf(event);
222 if (eventIndex.isValid()) {
228 if (eventIndex.isValid()) {
223
229
224 if (refreshEventProducts) {
230 if (refreshEventProducts) {
225 // Reparse the associated event products
231 // Reparse the associated event products
226
232
227 auto nbEventProducts = impl->nbEventProducts(event);
233 auto nbEventProducts = impl->nbEventProducts(event);
228 auto newNbOfEventProducts = event->getEventProducts().size();
234 auto newNbOfEventProducts = event->getEventProducts().size();
229 if (newNbOfEventProducts < nbEventProducts) {
235 if (newNbOfEventProducts < nbEventProducts) {
230 beginRemoveRows(eventIndex, newNbOfEventProducts, nbEventProducts - 1);
236 beginRemoveRows(eventIndex, newNbOfEventProducts, nbEventProducts - 1);
231 impl->m_EventProducts.erase(event.get());
237 impl->m_EventProducts.erase(event.get());
232 impl->parseEventProduct(event);
238 impl->parseEventProduct(event);
233 endRemoveRows();
239 endRemoveRows();
234 }
240 }
235 else if (newNbOfEventProducts > nbEventProducts) {
241 else if (newNbOfEventProducts > nbEventProducts) {
236 beginInsertRows(eventIndex, nbEventProducts, newNbOfEventProducts - 1);
242 beginInsertRows(eventIndex, nbEventProducts, newNbOfEventProducts - 1);
237 impl->m_EventProducts.erase(event.get());
243 impl->m_EventProducts.erase(event.get());
238 impl->parseEventProduct(event);
244 impl->parseEventProduct(event);
239 endInsertRows();
245 endInsertRows();
240 }
246 }
241 else { // newNbOfEventProducts == nbEventProducts
247 else { // newNbOfEventProducts == nbEventProducts
242 impl->m_EventProducts.erase(event.get());
248 impl->m_EventProducts.erase(event.get());
243 impl->parseEventProduct(event);
249 impl->parseEventProduct(event);
244 }
250 }
245 }
251 }
246
252
247 // Refreshes the event line
253 // Refreshes the event line
248 auto colCount = columnCount();
254 auto colCount = columnCount();
249 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
255 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
250
256
251 // Also refreshes its children event products
257 // Also refreshes its children event products
252 impl->refreshChildrenOfIndex(this, eventIndex);
258 impl->refreshChildrenOfIndex(this, eventIndex);
253 }
259 }
254 else {
260 else {
255 qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
261 qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
256 }
262 }
257 }
263 }
258
264
259 QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
265 QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
260 {
266 {
261 auto row = impl->m_Events.indexOf(event);
267 auto row = impl->m_Events.indexOf(event);
262 if (row >= 0) {
268 if (row >= 0) {
263 return index(row, 0);
269 return index(row, 0);
264 }
270 }
265
271
266 return QModelIndex();
272 return QModelIndex();
267 }
273 }
268
274
269 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
275 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
270 {
276 {
271 if (!hasIndex(row, column, parent)) {
277 if (!hasIndex(row, column, parent)) {
272 return QModelIndex();
278 return QModelIndex();
273 }
279 }
274
280
275 switch (itemTypeOf(parent)) {
281 switch (itemTypeOf(parent)) {
276 case CatalogueEventsModel::ItemType::Root:
282 case CatalogueEventsModel::ItemType::Root:
277 return createIndex(row, column);
283 return createIndex(row, column);
278 case CatalogueEventsModel::ItemType::Event: {
284 case CatalogueEventsModel::ItemType::Event: {
279 auto event = getEvent(parent);
285 auto event = getEvent(parent);
280 return createIndex(row, column, event.get());
286 return createIndex(row, column, event.get());
281 }
287 }
282 case CatalogueEventsModel::ItemType::EventProduct:
288 case CatalogueEventsModel::ItemType::EventProduct:
283 break;
289 break;
284 default:
290 default:
285 break;
291 break;
286 }
292 }
287
293
288 return QModelIndex();
294 return QModelIndex();
289 }
295 }
290
296
291 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
297 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
292 {
298 {
293 switch (itemTypeOf(index)) {
299 switch (itemTypeOf(index)) {
294 case CatalogueEventsModel::ItemType::EventProduct: {
300 case CatalogueEventsModel::ItemType::EventProduct: {
295 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
301 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
296 auto it
302 auto it
297 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
303 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
298 [parentEvent](auto event) { return event.get() == parentEvent; });
304 [parentEvent](auto event) { return event.get() == parentEvent; });
299
305
300 if (it != impl->m_Events.cend()) {
306 if (it != impl->m_Events.cend()) {
301 return createIndex(it - impl->m_Events.cbegin(), 0);
307 return createIndex(it - impl->m_Events.cbegin(), 0);
302 }
308 }
303 else {
309 else {
304 return QModelIndex();
310 return QModelIndex();
305 }
311 }
306 }
312 }
307 case CatalogueEventsModel::ItemType::Root:
313 case CatalogueEventsModel::ItemType::Root:
308 break;
314 break;
309 case CatalogueEventsModel::ItemType::Event:
315 case CatalogueEventsModel::ItemType::Event:
310 break;
316 break;
311 default:
317 default:
312 break;
318 break;
313 }
319 }
314
320
315 return QModelIndex();
321 return QModelIndex();
316 }
322 }
317
323
318 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
324 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
319 {
325 {
320 if (parent.column() > 0) {
326 if (parent.column() > 0) {
321 return 0;
327 return 0;
322 }
328 }
323
329
324 switch (itemTypeOf(parent)) {
330 switch (itemTypeOf(parent)) {
325 case CatalogueEventsModel::ItemType::Root:
331 case CatalogueEventsModel::ItemType::Root:
326 return impl->m_Events.count();
332 return impl->m_Events.count();
327 case CatalogueEventsModel::ItemType::Event: {
333 case CatalogueEventsModel::ItemType::Event: {
328 auto event = getEvent(parent);
334 auto event = getEvent(parent);
329 return impl->m_EventProducts[event.get()].count();
335 return impl->m_EventProducts[event.get()].count();
330 }
336 }
331 case CatalogueEventsModel::ItemType::EventProduct:
337 case CatalogueEventsModel::ItemType::EventProduct:
332 break;
338 break;
333 default:
339 default:
334 break;
340 break;
335 }
341 }
336
342
337 return 0;
343 return 0;
338 }
344 }
339
345
340 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
346 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
341 {
347 {
342 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
348 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
343 }
349 }
344
350
345 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
351 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
346 {
352 {
347 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
353 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
348 }
354 }
349
355
350 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
356 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
351 {
357 {
352 if (index.isValid()) {
358 if (index.isValid()) {
353
359
354 auto type = itemTypeOf(index);
360 auto type = itemTypeOf(index);
355 if (type == CatalogueEventsModel::ItemType::Event) {
361 if (type == CatalogueEventsModel::ItemType::Event) {
356 auto event = getEvent(index);
362 auto event = getEvent(index);
357 switch (role) {
363 switch (role) {
358 case Qt::DisplayRole:
364 case Qt::DisplayRole:
359 return impl->eventData(index.column(), event);
365 return impl->eventData(index.column(), event);
360 break;
366 break;
361 }
367 }
362 }
368 }
363 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
369 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
364 auto product = getEventProduct(index);
370 auto product = getEventProduct(index);
365 switch (role) {
371 switch (role) {
366 case Qt::DisplayRole:
372 case Qt::DisplayRole:
367 return impl->eventProductData(index.column(), product);
373 return impl->eventProductData(index.column(), product);
368 break;
374 break;
369 }
375 }
370 }
376 }
371 }
377 }
372
378
373 return QVariant{};
379 return QVariant{};
374 }
380 }
375
381
376 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
382 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
377 {
383 {
378 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
384 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
379 return impl->columnNames().value(section);
385 return impl->columnNames().value(section);
380 }
386 }
381
387
382 return QVariant();
388 return QVariant();
383 }
389 }
384
390
385 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
391 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
386 {
392 {
387 beginResetModel();
393 beginResetModel();
388 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
394 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
389 [this, column, order](auto e1, auto e2) {
395 [this, column, order](auto e1, auto e2) {
390 auto data1 = impl->sortData(column, e1);
396 auto data1 = impl->sortData(column, e1);
391 auto data2 = impl->sortData(column, e2);
397 auto data2 = impl->sortData(column, e2);
392
398
393 auto result = data1.toString() < data2.toString();
399 auto result = data1.toString() < data2.toString();
394
400
395 return order == Qt::AscendingOrder ? result : !result;
401 return order == Qt::AscendingOrder ? result : !result;
396 });
402 });
397
403
398 endResetModel();
404 endResetModel();
399 emit modelSorted();
405 emit modelSorted();
400 }
406 }
401
407
402 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
408 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
403 {
409 {
404 return Qt::CopyAction | Qt::MoveAction;
410 return Qt::CopyAction | Qt::MoveAction;
405 }
411 }
406
412
407 QStringList CatalogueEventsModel::mimeTypes() const
413 QStringList CatalogueEventsModel::mimeTypes() const
408 {
414 {
409 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_SOURCE_CATALOGUE_LIST, MIME_TYPE_TIME_RANGE};
415 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_SOURCE_CATALOGUE_LIST, MIME_TYPE_TIME_RANGE};
410 }
416 }
411
417
412 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
418 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
413 {
419 {
414 auto mimeData = new QMimeData;
420 auto mimeData = new QMimeData;
415
421
416 bool isFirst = true;
422 bool isFirst = true;
417
423
418 QVector<std::shared_ptr<DBEvent> > eventList;
424 QVector<std::shared_ptr<DBEvent> > eventList;
419 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
425 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
420
426
421 SqpRange firstTimeRange;
427 SqpRange firstTimeRange;
422 for (const auto &index : indexes) {
428 for (const auto &index : indexes) {
423 if (index.column() == 0) { // only the first column
429 if (index.column() == 0) { // only the first column
424
430
425 auto type = itemTypeOf(index);
431 auto type = itemTypeOf(index);
426 if (type == ItemType::Event) {
432 if (type == ItemType::Event) {
427 auto event = getEvent(index);
433 auto event = getEvent(index);
428 eventList << event;
434 eventList << event;
429
435
430 if (isFirst) {
436 if (isFirst) {
431 isFirst = false;
437 isFirst = false;
432 firstTimeRange.m_TStart = event->getTStart();
438 firstTimeRange.m_TStart = event->getTStart();
433 firstTimeRange.m_TEnd = event->getTEnd();
439 firstTimeRange.m_TEnd = event->getTEnd();
434 }
440 }
435 }
441 }
436 else if (type == ItemType::EventProduct) {
442 else if (type == ItemType::EventProduct) {
437 auto product = getEventProduct(index);
443 auto product = getEventProduct(index);
438 eventProductList << product;
444 eventProductList << product;
439
445
440 if (isFirst) {
446 if (isFirst) {
441 isFirst = false;
447 isFirst = false;
442 firstTimeRange.m_TStart = product->getTStart();
448 firstTimeRange.m_TStart = product->getTStart();
443 firstTimeRange.m_TEnd = product->getTEnd();
449 firstTimeRange.m_TEnd = product->getTEnd();
444 }
450 }
445 }
451 }
446 }
452 }
447 }
453 }
448
454
449 if (!eventList.isEmpty() && eventProductList.isEmpty()) {
455 if (!eventList.isEmpty() && eventProductList.isEmpty()) {
450 auto eventsEncodedData = sqpApp->catalogueController().mimeDataForEvents(eventList);
456 auto eventsEncodedData = sqpApp->catalogueController().mimeDataForEvents(eventList);
451 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
457 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
452
458
453 auto sourceCataloguesEncodedData
459 auto sourceCataloguesEncodedData
454 = sqpApp->catalogueController().mimeDataForCatalogues(impl->m_SourceCatalogue);
460 = sqpApp->catalogueController().mimeDataForCatalogues(impl->m_SourceCatalogue);
455 mimeData->setData(MIME_TYPE_SOURCE_CATALOGUE_LIST, sourceCataloguesEncodedData);
461 mimeData->setData(MIME_TYPE_SOURCE_CATALOGUE_LIST, sourceCataloguesEncodedData);
456 }
462 }
457
463
458 if (eventList.count() + eventProductList.count() == 1) {
464 if (eventList.count() + eventProductList.count() == 1) {
459 // No time range MIME data if multiple events are dragged
465 // No time range MIME data if multiple events are dragged
460 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
466 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
461 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
467 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
462 }
468 }
463
469
464 return mimeData;
470 return mimeData;
465 }
471 }
466
472
467 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
473 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
468 {
474 {
469 if (!index.isValid()) {
475 if (!index.isValid()) {
470 return ItemType::Root;
476 return ItemType::Root;
471 }
477 }
472 else if (index.internalPointer() == nullptr) {
478 else if (index.internalPointer() == nullptr) {
473 return ItemType::Event;
479 return ItemType::Event;
474 }
480 }
475 else {
481 else {
476 return ItemType::EventProduct;
482 return ItemType::EventProduct;
477 }
483 }
478 }
484 }
@@ -1,627 +1,632
1 #include "Catalogue/CatalogueEventsWidget.h"
1 #include "Catalogue/CatalogueEventsWidget.h"
2 #include "ui_CatalogueEventsWidget.h"
2 #include "ui_CatalogueEventsWidget.h"
3
3
4 #include <Catalogue/CatalogueController.h>
4 #include <Catalogue/CatalogueController.h>
5 #include <Catalogue/CatalogueEventsModel.h>
5 #include <Catalogue/CatalogueEventsModel.h>
6 #include <Catalogue/CatalogueExplorerHelper.h>
6 #include <Catalogue/CatalogueExplorerHelper.h>
7 #include <CatalogueDao.h>
7 #include <CatalogueDao.h>
8 #include <DBCatalogue.h>
8 #include <DBCatalogue.h>
9 #include <DBEventProduct.h>
9 #include <DBEventProduct.h>
10 #include <DataSource/DataSourceController.h>
10 #include <DataSource/DataSourceController.h>
11 #include <DataSource/DataSourceItem.h>
11 #include <DataSource/DataSourceItem.h>
12 #include <SqpApplication.h>
12 #include <SqpApplication.h>
13 #include <Variable/Variable.h>
13 #include <Variable/Variable.h>
14 #include <Variable/VariableController.h>
14 #include <Variable/VariableController.h>
15 #include <Visualization/VisualizationGraphWidget.h>
15 #include <Visualization/VisualizationGraphWidget.h>
16 #include <Visualization/VisualizationTabWidget.h>
16 #include <Visualization/VisualizationTabWidget.h>
17 #include <Visualization/VisualizationWidget.h>
17 #include <Visualization/VisualizationWidget.h>
18 #include <Visualization/VisualizationZoneWidget.h>
18 #include <Visualization/VisualizationZoneWidget.h>
19
19
20 #include <QDialog>
20 #include <QDialog>
21 #include <QDialogButtonBox>
21 #include <QDialogButtonBox>
22 #include <QKeyEvent>
22 #include <QKeyEvent>
23 #include <QListWidget>
23 #include <QListWidget>
24 #include <QMessageBox>
24 #include <QMessageBox>
25
25
26 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
26 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
27
27
28 /// Fixed size of the validation column
28 /// Fixed size of the validation column
29 const auto VALIDATION_COLUMN_SIZE = 35;
29 const auto VALIDATION_COLUMN_SIZE = 35;
30
30
31 /// Percentage added to the range of a event when it is displayed
31 /// Percentage added to the range of a event when it is displayed
32 const auto EVENT_RANGE_MARGE = 30; // in %
32 const auto EVENT_RANGE_MARGE = 30; // in %
33
33
34 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
34 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
35
35
36 CatalogueEventsModel *m_Model = nullptr;
36 CatalogueEventsModel *m_Model = nullptr;
37 QStringList m_ZonesForTimeMode;
37 QStringList m_ZonesForTimeMode;
38 QString m_ZoneForGraphMode;
38 QString m_ZoneForGraphMode;
39 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
39 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
40 bool m_AllEventDisplayed = false;
40 bool m_AllEventDisplayed = false;
41 QVector<VisualizationGraphWidget *> m_CustomGraphs;
41 QVector<VisualizationGraphWidget *> m_CustomGraphs;
42
42
43 VisualizationWidget *m_VisualizationWidget = nullptr;
43 VisualizationWidget *m_VisualizationWidget = nullptr;
44
44
45 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget)
45 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget)
46 {
46 {
47 widget->ui->treeView->setSortingEnabled(false);
47 widget->ui->treeView->setSortingEnabled(false);
48 m_Model->setSourceCatalogues(m_DisplayedCatalogues);
48 m_Model->setSourceCatalogues(m_DisplayedCatalogues);
49 m_Model->setEvents(events);
49 m_Model->setEvents(events);
50 widget->ui->treeView->setSortingEnabled(true);
50 widget->ui->treeView->setSortingEnabled(true);
51
51
52 for (auto event : events) {
52 for (auto event : events) {
53 if (sqpApp->catalogueController().eventHasChanges(event)) {
53 if (sqpApp->catalogueController().eventHasChanges(event)) {
54 auto index = m_Model->indexOf(event);
54 auto index = m_Model->indexOf(event);
55 widget->setEventChanges(event, true);
55 widget->setEventChanges(event, true);
56 }
56 }
57 }
57 }
58 }
58 }
59
59
60 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
60 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
61 {
61 {
62 treeView->setSortingEnabled(false);
62 treeView->setSortingEnabled(false);
63 m_Model->addEvent(event);
63 m_Model->addEvent(event);
64 treeView->setSortingEnabled(true);
64 treeView->setSortingEnabled(true);
65 }
65 }
66
66
67 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
67 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
68 {
68 {
69 treeView->setSortingEnabled(false);
69 treeView->setSortingEnabled(false);
70 m_Model->removeEvent(event);
70 m_Model->removeEvent(event);
71 treeView->setSortingEnabled(true);
71 treeView->setSortingEnabled(true);
72 }
72 }
73
73
74 QStringList getAvailableVisualizationZoneList() const
74 QStringList getAvailableVisualizationZoneList() const
75 {
75 {
76 if (m_VisualizationWidget) {
76 if (m_VisualizationWidget) {
77 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
77 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
78 return tab->availableZoneWidgets();
78 return tab->availableZoneWidgets();
79 }
79 }
80 }
80 }
81
81
82 return QStringList{};
82 return QStringList{};
83 }
83 }
84
84
85 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
85 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
86 bool allowMultiSelection, const QPoint &location)
86 bool allowMultiSelection, const QPoint &location)
87 {
87 {
88 auto availableZones = getAvailableVisualizationZoneList();
88 auto availableZones = getAvailableVisualizationZoneList();
89 if (availableZones.isEmpty()) {
89 if (availableZones.isEmpty()) {
90 return QStringList{};
90 return QStringList{};
91 }
91 }
92
92
93 QDialog d(parent, Qt::Tool);
93 QDialog d(parent, Qt::Tool);
94 d.setWindowTitle("Choose a zone");
94 d.setWindowTitle("Choose a zone");
95 auto layout = new QVBoxLayout{&d};
95 auto layout = new QVBoxLayout{&d};
96 layout->setContentsMargins(0, 0, 0, 0);
96 layout->setContentsMargins(0, 0, 0, 0);
97 auto listWidget = new QListWidget{&d};
97 auto listWidget = new QListWidget{&d};
98 layout->addWidget(listWidget);
98 layout->addWidget(listWidget);
99
99
100 QSet<QListWidgetItem *> checkedItems;
100 QSet<QListWidgetItem *> checkedItems;
101 for (auto zone : availableZones) {
101 for (auto zone : availableZones) {
102 auto item = new QListWidgetItem{zone};
102 auto item = new QListWidgetItem{zone};
103 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
103 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
104 if (selectedZones.contains(zone)) {
104 if (selectedZones.contains(zone)) {
105 item->setCheckState(Qt::Checked);
105 item->setCheckState(Qt::Checked);
106 checkedItems << item;
106 checkedItems << item;
107 }
107 }
108 else {
108 else {
109 item->setCheckState(Qt::Unchecked);
109 item->setCheckState(Qt::Unchecked);
110 }
110 }
111
111
112 listWidget->addItem(item);
112 listWidget->addItem(item);
113 }
113 }
114
114
115 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
115 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
116 layout->addWidget(buttonBox);
116 layout->addWidget(buttonBox);
117
117
118 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
118 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
119 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
119 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
120
120
121 QObject::connect(listWidget, &QListWidget::itemChanged,
121 QObject::connect(listWidget, &QListWidget::itemChanged,
122 [&checkedItems, allowMultiSelection, listWidget](auto item) {
122 [&checkedItems, allowMultiSelection, listWidget](auto item) {
123 if (item->checkState() == Qt::Checked) {
123 if (item->checkState() == Qt::Checked) {
124 if (!allowMultiSelection) {
124 if (!allowMultiSelection) {
125 for (auto checkedItem : checkedItems) {
125 for (auto checkedItem : checkedItems) {
126 listWidget->blockSignals(true);
126 listWidget->blockSignals(true);
127 checkedItem->setCheckState(Qt::Unchecked);
127 checkedItem->setCheckState(Qt::Unchecked);
128 listWidget->blockSignals(false);
128 listWidget->blockSignals(false);
129 }
129 }
130
130
131 checkedItems.clear();
131 checkedItems.clear();
132 }
132 }
133 checkedItems << item;
133 checkedItems << item;
134 }
134 }
135 else {
135 else {
136 checkedItems.remove(item);
136 checkedItems.remove(item);
137 }
137 }
138 });
138 });
139
139
140 QStringList result;
140 QStringList result;
141
141
142 d.setMinimumWidth(120);
142 d.setMinimumWidth(120);
143 d.resize(d.minimumSizeHint());
143 d.resize(d.minimumSizeHint());
144 d.move(location);
144 d.move(location);
145 if (d.exec() == QDialog::Accepted) {
145 if (d.exec() == QDialog::Accepted) {
146 for (auto item : checkedItems) {
146 for (auto item : checkedItems) {
147 result += item->text();
147 result += item->text();
148 }
148 }
149 }
149 }
150 else {
150 else {
151 result = selectedZones;
151 result = selectedZones;
152 }
152 }
153
153
154 return result;
154 return result;
155 }
155 }
156
156
157 void updateForTimeMode(QTreeView *treeView)
157 void updateForTimeMode(QTreeView *treeView)
158 {
158 {
159 auto selectedRows = treeView->selectionModel()->selectedRows();
159 auto selectedRows = treeView->selectionModel()->selectedRows();
160
160
161 if (selectedRows.count() == 1) {
161 if (selectedRows.count() == 1) {
162 auto event = m_Model->getEvent(selectedRows.first());
162 auto event = m_Model->getEvent(selectedRows.first());
163 if (event) {
163 if (event) {
164 if (m_VisualizationWidget) {
164 if (m_VisualizationWidget) {
165 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
165 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
166
166
167 for (auto zoneName : m_ZonesForTimeMode) {
167 for (auto zoneName : m_ZonesForTimeMode) {
168 if (auto zone = tab->getZoneWithName(zoneName)) {
168 if (auto zone = tab->getZoneWithName(zoneName)) {
169 SqpRange eventRange;
169 SqpRange eventRange;
170 eventRange.m_TStart = event->getTStart();
170 eventRange.m_TStart = event->getTStart();
171 eventRange.m_TEnd = event->getTEnd();
171 eventRange.m_TEnd = event->getTEnd();
172 zone->setZoneRange(eventRange);
172 zone->setZoneRange(eventRange);
173 }
173 }
174 }
174 }
175 }
175 }
176 else {
176 else {
177 qCWarning(LOG_CatalogueEventsWidget())
177 qCWarning(LOG_CatalogueEventsWidget())
178 << "updateTimeZone: no tab found in the visualization";
178 << "updateTimeZone: no tab found in the visualization";
179 }
179 }
180 }
180 }
181 else {
181 else {
182 qCWarning(LOG_CatalogueEventsWidget())
182 qCWarning(LOG_CatalogueEventsWidget())
183 << "updateTimeZone: visualization widget not found";
183 << "updateTimeZone: visualization widget not found";
184 }
184 }
185 }
185 }
186 }
186 }
187 else {
187 else {
188 qCWarning(LOG_CatalogueEventsWidget())
188 qCWarning(LOG_CatalogueEventsWidget())
189 << "updateTimeZone: not compatible with multiple events selected";
189 << "updateTimeZone: not compatible with multiple events selected";
190 }
190 }
191 }
191 }
192
192
193 QVector<SqpRange> getGraphRanges(const std::shared_ptr<DBEvent> &event)
193 QVector<SqpRange> getGraphRanges(const std::shared_ptr<DBEvent> &event)
194 {
194 {
195 // Retrieves the range of each product and the maximum size
195 // Retrieves the range of each product and the maximum size
196 QVector<SqpRange> graphRanges;
196 QVector<SqpRange> graphRanges;
197 double maxDt = 0;
197 double maxDt = 0;
198 for (auto eventProduct : event->getEventProducts()) {
198 for (auto eventProduct : event->getEventProducts()) {
199 SqpRange eventRange;
199 SqpRange eventRange;
200 eventRange.m_TStart = eventProduct.getTStart();
200 eventRange.m_TStart = eventProduct.getTStart();
201 eventRange.m_TEnd = eventProduct.getTEnd();
201 eventRange.m_TEnd = eventProduct.getTEnd();
202 graphRanges << eventRange;
202 graphRanges << eventRange;
203
203
204 auto dt = eventRange.m_TEnd - eventRange.m_TStart;
204 auto dt = eventRange.m_TEnd - eventRange.m_TStart;
205 if (dt > maxDt) {
205 if (dt > maxDt) {
206 maxDt = dt;
206 maxDt = dt;
207 }
207 }
208 }
208 }
209
209
210 // Adds the marge
210 // Adds the marge
211 maxDt *= (100.0 + EVENT_RANGE_MARGE) / 100.0;
211 maxDt *= (100.0 + EVENT_RANGE_MARGE) / 100.0;
212
212
213 // Corrects the graph ranges so that they all have the same size
213 // Corrects the graph ranges so that they all have the same size
214 QVector<SqpRange> correctedGraphRanges;
214 QVector<SqpRange> correctedGraphRanges;
215 for (auto range : graphRanges) {
215 for (auto range : graphRanges) {
216 auto dt = range.m_TEnd - range.m_TStart;
216 auto dt = range.m_TEnd - range.m_TStart;
217 auto diff = qAbs((maxDt - dt) / 2.0);
217 auto diff = qAbs((maxDt - dt) / 2.0);
218
218
219 SqpRange correctedRange;
219 SqpRange correctedRange;
220 correctedRange.m_TStart = range.m_TStart - diff;
220 correctedRange.m_TStart = range.m_TStart - diff;
221 correctedRange.m_TEnd = range.m_TEnd + diff;
221 correctedRange.m_TEnd = range.m_TEnd + diff;
222
222
223 correctedGraphRanges << correctedRange;
223 correctedGraphRanges << correctedRange;
224 }
224 }
225
225
226 return correctedGraphRanges;
226 return correctedGraphRanges;
227 }
227 }
228
228
229 void updateForGraphMode(CatalogueEventsWidget *catalogueEventWidget)
229 void updateForGraphMode(CatalogueEventsWidget *catalogueEventWidget)
230 {
230 {
231 auto selectedRows = catalogueEventWidget->ui->treeView->selectionModel()->selectedRows();
231 auto selectedRows = catalogueEventWidget->ui->treeView->selectionModel()->selectedRows();
232 if (selectedRows.count() != 1) {
232 if (selectedRows.count() != 1) {
233 qCWarning(LOG_CatalogueEventsWidget())
233 qCWarning(LOG_CatalogueEventsWidget())
234 << "updateGraphMode: not compatible with multiple events selected";
234 << "updateGraphMode: not compatible with multiple events selected";
235 return;
235 return;
236 }
236 }
237
237
238 if (!m_VisualizationWidget) {
238 if (!m_VisualizationWidget) {
239 qCWarning(LOG_CatalogueEventsWidget())
239 qCWarning(LOG_CatalogueEventsWidget())
240 << "updateGraphMode: visualization widget not found";
240 << "updateGraphMode: visualization widget not found";
241 return;
241 return;
242 }
242 }
243
243
244 auto event = m_Model->getEvent(selectedRows.first());
244 auto event = m_Model->getEvent(selectedRows.first());
245 if (!event) {
245 if (!event) {
246 // A event product is probably selected
246 // A event product is probably selected
247 qCInfo(LOG_CatalogueEventsWidget()) << "updateGraphMode: no events are selected";
247 qCInfo(LOG_CatalogueEventsWidget()) << "updateGraphMode: no events are selected";
248 return;
248 return;
249 }
249 }
250
250
251 auto tab = m_VisualizationWidget->currentTabWidget();
251 auto tab = m_VisualizationWidget->currentTabWidget();
252 if (!tab) {
252 if (!tab) {
253 qCWarning(LOG_CatalogueEventsWidget())
253 qCWarning(LOG_CatalogueEventsWidget())
254 << "updateGraphMode: no tab found in the visualization";
254 << "updateGraphMode: no tab found in the visualization";
255 return;
255 return;
256 }
256 }
257
257
258 auto zone = tab->getZoneWithName(m_ZoneForGraphMode);
258 auto zone = tab->getZoneWithName(m_ZoneForGraphMode);
259 if (!zone) {
259 if (!zone) {
260 qCWarning(LOG_CatalogueEventsWidget()) << "updateGraphMode: zone not found";
260 qCWarning(LOG_CatalogueEventsWidget()) << "updateGraphMode: zone not found";
261 return;
261 return;
262 }
262 }
263
263
264 // Closes the previous graph and delete the asociated variables
264 // Closes the previous graph and delete the asociated variables
265 for (auto graph : m_CustomGraphs) {
265 for (auto graph : m_CustomGraphs) {
266 graph->close();
266 graph->close();
267 auto variables = graph->variables().toVector();
267 auto variables = graph->variables().toVector();
268
268
269 QMetaObject::invokeMethod(&sqpApp->variableController(), "deleteVariables",
269 QMetaObject::invokeMethod(&sqpApp->variableController(), "deleteVariables",
270 Qt::QueuedConnection,
270 Qt::QueuedConnection,
271 Q_ARG(QVector<std::shared_ptr<Variable> >, variables));
271 Q_ARG(QVector<std::shared_ptr<Variable> >, variables));
272 }
272 }
273 m_CustomGraphs.clear();
273 m_CustomGraphs.clear();
274
274
275 // Closes the remaining graphs inside the zone
275 // Closes the remaining graphs inside the zone
276 zone->closeAllGraphs();
276 zone->closeAllGraphs();
277
277
278 // Calculates the range of each graph which will be created
278 // Calculates the range of each graph which will be created
279 auto graphRange = getGraphRanges(event);
279 auto graphRange = getGraphRanges(event);
280
280
281 // Loops through the event products and create the graph
281 // Loops through the event products and create the graph
282 auto itRange = graphRange.cbegin();
282 auto itRange = graphRange.cbegin();
283 for (auto eventProduct : event->getEventProducts()) {
283 for (auto eventProduct : event->getEventProducts()) {
284 auto productId = eventProduct.getProductId();
284 auto productId = eventProduct.getProductId();
285
285
286 auto range = *itRange;
286 auto range = *itRange;
287 ++itRange;
287 ++itRange;
288
288
289 SqpRange productRange;
289 SqpRange productRange;
290 productRange.m_TStart = eventProduct.getTStart();
290 productRange.m_TStart = eventProduct.getTStart();
291 productRange.m_TEnd = eventProduct.getTEnd();
291 productRange.m_TEnd = eventProduct.getTEnd();
292
292
293 auto context = new QObject{catalogueEventWidget};
293 auto context = new QObject{catalogueEventWidget};
294 QObject::connect(
294 QObject::connect(
295 &sqpApp->variableController(), &VariableController::variableAdded, context,
295 &sqpApp->variableController(), &VariableController::variableAdded, context,
296 [this, catalogueEventWidget, zone, context, event, range, productRange,
296 [this, catalogueEventWidget, zone, context, event, range, productRange,
297 productId](auto variable) {
297 productId](auto variable) {
298
298
299 if (variable->metadata().value(DataSourceItem::ID_DATA_KEY).toString()
299 if (variable->metadata().value(DataSourceItem::ID_DATA_KEY).toString()
300 == productId) {
300 == productId) {
301 auto graph = zone->createGraph(variable);
301 auto graph = zone->createGraph(variable);
302 graph->setAutoRangeOnVariableInitialization(false);
302 graph->setAutoRangeOnVariableInitialization(false);
303
303
304 auto selectionZone
304 auto selectionZone
305 = graph->addSelectionZone(event->getName(), productRange);
305 = graph->addSelectionZone(event->getName(), productRange);
306 emit catalogueEventWidget->selectionZoneAdded(event, productId,
306 emit catalogueEventWidget->selectionZoneAdded(event, productId,
307 selectionZone);
307 selectionZone);
308 m_CustomGraphs << graph;
308 m_CustomGraphs << graph;
309
309
310 graph->setGraphRange(range, true);
310 graph->setGraphRange(range, true);
311
311
312 // Removes the graph from the graph list if it is closed manually
312 // Removes the graph from the graph list if it is closed manually
313 QObject::connect(graph, &VisualizationGraphWidget::destroyed,
313 QObject::connect(graph, &VisualizationGraphWidget::destroyed,
314 [this, graph]() { m_CustomGraphs.removeAll(graph); });
314 [this, graph]() { m_CustomGraphs.removeAll(graph); });
315
315
316 delete context; // removes the connection
316 delete context; // removes the connection
317 }
317 }
318 },
318 },
319 Qt::QueuedConnection);
319 Qt::QueuedConnection);
320
320
321 QMetaObject::invokeMethod(&sqpApp->dataSourceController(),
321 QMetaObject::invokeMethod(&sqpApp->dataSourceController(),
322 "requestVariableFromProductIdKey", Qt::QueuedConnection,
322 "requestVariableFromProductIdKey", Qt::QueuedConnection,
323 Q_ARG(QString, productId));
323 Q_ARG(QString, productId));
324 }
324 }
325 }
325 }
326
326
327 void getSelectedItems(
327 void getSelectedItems(
328 QTreeView *treeView, QVector<std::shared_ptr<DBEvent> > &events,
328 QTreeView *treeView, QVector<std::shared_ptr<DBEvent> > &events,
329 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > &eventProducts)
329 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > &eventProducts)
330 {
330 {
331 for (auto rowIndex : treeView->selectionModel()->selectedRows()) {
331 for (auto rowIndex : treeView->selectionModel()->selectedRows()) {
332 auto itemType = m_Model->itemTypeOf(rowIndex);
332 auto itemType = m_Model->itemTypeOf(rowIndex);
333 if (itemType == CatalogueEventsModel::ItemType::Event) {
333 if (itemType == CatalogueEventsModel::ItemType::Event) {
334 events << m_Model->getEvent(rowIndex);
334 events << m_Model->getEvent(rowIndex);
335 }
335 }
336 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
336 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
337 eventProducts << qMakePair(m_Model->getParentEvent(rowIndex),
337 eventProducts << qMakePair(m_Model->getParentEvent(rowIndex),
338 m_Model->getEventProduct(rowIndex));
338 m_Model->getEventProduct(rowIndex));
339 }
339 }
340 }
340 }
341 }
341 }
342 };
342 };
343
343
344 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
344 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
345 : QWidget(parent),
345 : QWidget(parent),
346 ui(new Ui::CatalogueEventsWidget),
346 ui(new Ui::CatalogueEventsWidget),
347 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
347 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
348 {
348 {
349 ui->setupUi(this);
349 ui->setupUi(this);
350
350
351 impl->m_Model = new CatalogueEventsModel{this};
351 impl->m_Model = new CatalogueEventsModel{this};
352 ui->treeView->setModel(impl->m_Model);
352 ui->treeView->setModel(impl->m_Model);
353
353
354 ui->treeView->setSortingEnabled(true);
354 ui->treeView->setSortingEnabled(true);
355 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
355 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
356 ui->treeView->setDragEnabled(true);
356 ui->treeView->setDragEnabled(true);
357
357
358
358 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
359 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
359 if (checked) {
360 if (checked) {
360 ui->btnChart->setChecked(false);
361 ui->btnChart->setChecked(false);
361 impl->m_ZonesForTimeMode
362 impl->m_ZonesForTimeMode
362 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
363 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
363 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
364 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
364
365
365 impl->updateForTimeMode(ui->treeView);
366 impl->updateForTimeMode(ui->treeView);
366 }
367 }
367 });
368 });
368
369
369 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
370 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
370 if (checked) {
371 if (checked) {
371 ui->btnTime->setChecked(false);
372 ui->btnTime->setChecked(false);
372 impl->m_ZoneForGraphMode
373 impl->m_ZoneForGraphMode
373 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
374 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
374 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
375 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
375 .value(0);
376 .value(0);
376
377
377 impl->updateForGraphMode(this);
378 impl->updateForGraphMode(this);
378 }
379 }
379 });
380 });
380
381
381 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
382 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
382 QVector<std::shared_ptr<DBEvent> > events;
383 QVector<std::shared_ptr<DBEvent> > events;
383 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
384 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
384 impl->getSelectedItems(ui->treeView, events, eventProducts);
385 impl->getSelectedItems(ui->treeView, events, eventProducts);
385
386
386 if (!events.isEmpty() && eventProducts.isEmpty()) {
387 if (!events.isEmpty() && eventProducts.isEmpty()) {
387
388
388 auto canRemoveEvent
389 auto canRemoveEvent
389 = !this->isAllEventsDisplayed()
390 = !this->isAllEventsDisplayed()
390 || (QMessageBox::warning(
391 || (QMessageBox::warning(
391 this, tr("Remove Event(s)"),
392 this, tr("Remove Event(s)"),
392 tr("The selected event(s) will be permanently removed "
393 tr("The selected event(s) will be permanently removed "
393 "from the repository!\nAre you sure you want to continue?"),
394 "from the repository!\nAre you sure you want to continue?"),
394 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
395 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
395 == QMessageBox::Yes);
396 == QMessageBox::Yes);
396
397
397 if (canRemoveEvent) {
398 if (canRemoveEvent) {
398 for (auto event : events) {
399 for (auto event : events) {
399 if (this->isAllEventsDisplayed()) {
400 if (this->isAllEventsDisplayed()) {
400 sqpApp->catalogueController().removeEvent(event);
401 sqpApp->catalogueController().removeEvent(event);
401 impl->removeEvent(event, ui->treeView);
402 impl->removeEvent(event, ui->treeView);
402 }
403 }
403 else {
404 else {
404 QVector<std::shared_ptr<DBCatalogue> > modifiedCatalogues;
405 QVector<std::shared_ptr<DBCatalogue> > modifiedCatalogues;
405 for (auto catalogue : this->displayedCatalogues()) {
406 for (auto catalogue : this->displayedCatalogues()) {
406 if (catalogue->removeEvent(event->getUniqId())) {
407 if (catalogue->removeEvent(event->getUniqId())) {
407 sqpApp->catalogueController().updateCatalogue(catalogue);
408 sqpApp->catalogueController().updateCatalogue(catalogue);
408 modifiedCatalogues << catalogue;
409 modifiedCatalogues << catalogue;
409 }
410 }
410 }
411 }
411 if (!modifiedCatalogues.empty()) {
412 if (!modifiedCatalogues.empty()) {
412 emit eventCataloguesModified(modifiedCatalogues);
413 emit eventCataloguesModified(modifiedCatalogues);
413 }
414 }
414 }
415 }
415 impl->m_Model->removeEvent(event);
416 impl->m_Model->removeEvent(event);
416 }
417 }
417
418
418
419
419 emit this->eventsRemoved(events);
420 emit this->eventsRemoved(events);
420 }
421 }
421 }
422 }
422 });
423 });
423
424
424 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueEventsWidget::emitSelection);
425 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueEventsWidget::emitSelection);
425 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
426 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
426 &CatalogueEventsWidget::emitSelection);
427 &CatalogueEventsWidget::emitSelection);
427
428
428 ui->btnRemove->setEnabled(false); // Disabled by default when nothing is selected
429 ui->btnRemove->setEnabled(false); // Disabled by default when nothing is selected
429 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
430 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
430 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
431 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
431 ui->btnChart->setEnabled(isNotMultiSelection);
432 ui->btnChart->setEnabled(isNotMultiSelection);
432 ui->btnTime->setEnabled(isNotMultiSelection);
433 ui->btnTime->setEnabled(isNotMultiSelection);
433
434
434 if (isNotMultiSelection && ui->btnTime->isChecked()) {
435 if (isNotMultiSelection && ui->btnTime->isChecked()) {
435 impl->updateForTimeMode(ui->treeView);
436 impl->updateForTimeMode(ui->treeView);
436 }
437 }
437 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
438 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
438 impl->updateForGraphMode(this);
439 impl->updateForGraphMode(this);
439 }
440 }
440
441
441 QVector<std::shared_ptr<DBEvent> > events;
442 QVector<std::shared_ptr<DBEvent> > events;
442 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
443 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
443 impl->getSelectedItems(ui->treeView, events, eventProducts);
444 impl->getSelectedItems(ui->treeView, events, eventProducts);
444 ui->btnRemove->setEnabled(!events.isEmpty() && eventProducts.isEmpty());
445 ui->btnRemove->setEnabled(!events.isEmpty() && eventProducts.isEmpty());
445 });
446 });
446
447
447 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
448 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
448 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Tags,
449 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Tags,
449 QHeaderView::Stretch);
450 QHeaderView::Stretch);
450 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
451 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
451 QHeaderView::Fixed);
452 QHeaderView::Fixed);
452 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
453 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
453 QHeaderView::Interactive);
454 QHeaderView::Interactive);
454 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
455 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
455 VALIDATION_COLUMN_SIZE);
456 VALIDATION_COLUMN_SIZE);
457 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::TStart,
458 QHeaderView::ResizeToContents);
459 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::TEnd,
460 QHeaderView::ResizeToContents);
456 ui->treeView->header()->setSortIndicatorShown(true);
461 ui->treeView->header()->setSortIndicatorShown(true);
457
462
458 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
463 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
459 auto allEvents = impl->m_Model->events();
464 auto allEvents = impl->m_Model->events();
460 for (auto event : allEvents) {
465 for (auto event : allEvents) {
461 setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event));
466 setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event));
462 }
467 }
463 });
468 });
464
469
465 populateWithAllEvents();
470 populateWithAllEvents();
466 }
471 }
467
472
468 CatalogueEventsWidget::~CatalogueEventsWidget()
473 CatalogueEventsWidget::~CatalogueEventsWidget()
469 {
474 {
470 delete ui;
475 delete ui;
471 }
476 }
472
477
473 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
478 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
474 {
479 {
475 impl->m_VisualizationWidget = visualization;
480 impl->m_VisualizationWidget = visualization;
476 }
481 }
477
482
478 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
483 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
479 {
484 {
480 impl->addEvent(event, ui->treeView);
485 impl->addEvent(event, ui->treeView);
481 }
486 }
482
487
483 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
488 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
484 {
489 {
485 impl->m_Model->refreshEvent(event);
490 impl->m_Model->refreshEvent(event);
486
491
487 auto eventIndex = impl->m_Model->indexOf(event);
492 auto eventIndex = impl->m_Model->indexOf(event);
488 auto validationIndex
493 auto validationIndex
489 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
494 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
490
495
491 if (validationIndex.isValid()) {
496 if (validationIndex.isValid()) {
492 if (hasChanges) {
497 if (hasChanges) {
493 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
498 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
494 auto widget = CatalogueExplorerHelper::buildValidationWidget(
499 auto widget = CatalogueExplorerHelper::buildValidationWidget(
495 ui->treeView,
500 ui->treeView,
496 [this, event]() {
501 [this, event]() {
497 sqpApp->catalogueController().saveEvent(event);
502 sqpApp->catalogueController().saveEvent(event);
498 setEventChanges(event, false);
503 setEventChanges(event, false);
499 },
504 },
500 [this, event]() {
505 [this, event]() {
501 bool removed = false;
506 bool removed = false;
502 sqpApp->catalogueController().discardEvent(event, removed);
507 sqpApp->catalogueController().discardEvent(event, removed);
503 if (removed) {
508 if (removed) {
504 impl->m_Model->removeEvent(event);
509 impl->m_Model->removeEvent(event);
505 }
510 }
506 else {
511 else {
507 setEventChanges(event, false);
512 setEventChanges(event, false);
508 impl->m_Model->refreshEvent(event, true);
513 impl->m_Model->refreshEvent(event, true);
509 }
514 }
510 emitSelection();
515 emitSelection();
511 });
516 });
512 ui->treeView->setIndexWidget(validationIndex, widget);
517 ui->treeView->setIndexWidget(validationIndex, widget);
513 }
518 }
514 }
519 }
515 else {
520 else {
516 // Note: the widget is destroyed
521 // Note: the widget is destroyed
517 ui->treeView->setIndexWidget(validationIndex, nullptr);
522 ui->treeView->setIndexWidget(validationIndex, nullptr);
518 }
523 }
519 }
524 }
520 else {
525 else {
521 qCWarning(LOG_CatalogueEventsWidget())
526 qCWarning(LOG_CatalogueEventsWidget())
522 << "setEventChanges: the event is not displayed in the model.";
527 << "setEventChanges: the event is not displayed in the model.";
523 }
528 }
524 }
529 }
525
530
526 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
531 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
527 {
532 {
528 return impl->m_DisplayedCatalogues;
533 return impl->m_DisplayedCatalogues;
529 }
534 }
530
535
531 bool CatalogueEventsWidget::isAllEventsDisplayed() const
536 bool CatalogueEventsWidget::isAllEventsDisplayed() const
532 {
537 {
533 return impl->m_AllEventDisplayed;
538 return impl->m_AllEventDisplayed;
534 }
539 }
535
540
536 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
541 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
537 {
542 {
538 return impl->m_Model->indexOf(event).isValid();
543 return impl->m_Model->indexOf(event).isValid();
539 }
544 }
540
545
541 void CatalogueEventsWidget::refreshEvent(const std::shared_ptr<DBEvent> &event)
546 void CatalogueEventsWidget::refreshEvent(const std::shared_ptr<DBEvent> &event)
542 {
547 {
543 impl->m_Model->refreshEvent(event, true);
548 impl->m_Model->refreshEvent(event, true);
544 }
549 }
545
550
546 void CatalogueEventsWidget::populateWithCatalogues(
551 void CatalogueEventsWidget::populateWithCatalogues(
547 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
552 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
548 {
553 {
549 impl->m_DisplayedCatalogues = catalogues;
554 impl->m_DisplayedCatalogues = catalogues;
550 impl->m_AllEventDisplayed = false;
555 impl->m_AllEventDisplayed = false;
551
556
552 QSet<QUuid> eventIds;
557 QSet<QUuid> eventIds;
553 QVector<std::shared_ptr<DBEvent> > events;
558 QVector<std::shared_ptr<DBEvent> > events;
554
559
555 for (auto catalogue : catalogues) {
560 for (auto catalogue : catalogues) {
556 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
561 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
557 for (auto event : catalogueEvents) {
562 for (auto event : catalogueEvents) {
558 if (!eventIds.contains(event->getUniqId())) {
563 if (!eventIds.contains(event->getUniqId())) {
559 events << event;
564 events << event;
560 eventIds.insert(event->getUniqId());
565 eventIds.insert(event->getUniqId());
561 }
566 }
562 }
567 }
563 }
568 }
564
569
565 impl->setEvents(events, this);
570 impl->setEvents(events, this);
566 }
571 }
567
572
568 void CatalogueEventsWidget::populateWithAllEvents()
573 void CatalogueEventsWidget::populateWithAllEvents()
569 {
574 {
570 impl->m_DisplayedCatalogues.clear();
575 impl->m_DisplayedCatalogues.clear();
571 impl->m_AllEventDisplayed = true;
576 impl->m_AllEventDisplayed = true;
572
577
573 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
578 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
574
579
575 QVector<std::shared_ptr<DBEvent> > events;
580 QVector<std::shared_ptr<DBEvent> > events;
576 for (auto event : allEvents) {
581 for (auto event : allEvents) {
577 events << event;
582 events << event;
578 }
583 }
579
584
580 impl->setEvents(events, this);
585 impl->setEvents(events, this);
581 }
586 }
582
587
583 void CatalogueEventsWidget::clear()
588 void CatalogueEventsWidget::clear()
584 {
589 {
585 impl->m_DisplayedCatalogues.clear();
590 impl->m_DisplayedCatalogues.clear();
586 impl->m_AllEventDisplayed = false;
591 impl->m_AllEventDisplayed = false;
587 impl->setEvents({}, this);
592 impl->setEvents({}, this);
588 }
593 }
589
594
590 void CatalogueEventsWidget::refresh()
595 void CatalogueEventsWidget::refresh()
591 {
596 {
592 if (isAllEventsDisplayed()) {
597 if (isAllEventsDisplayed()) {
593 populateWithAllEvents();
598 populateWithAllEvents();
594 }
599 }
595 else if (!impl->m_DisplayedCatalogues.isEmpty()) {
600 else if (!impl->m_DisplayedCatalogues.isEmpty()) {
596 populateWithCatalogues(impl->m_DisplayedCatalogues);
601 populateWithCatalogues(impl->m_DisplayedCatalogues);
597 }
602 }
598 }
603 }
599
604
600 void CatalogueEventsWidget::emitSelection()
605 void CatalogueEventsWidget::emitSelection()
601 {
606 {
602 QVector<std::shared_ptr<DBEvent> > events;
607 QVector<std::shared_ptr<DBEvent> > events;
603 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
608 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
604 impl->getSelectedItems(ui->treeView, events, eventProducts);
609 impl->getSelectedItems(ui->treeView, events, eventProducts);
605
610
606 if (!events.isEmpty() && eventProducts.isEmpty()) {
611 if (!events.isEmpty() && eventProducts.isEmpty()) {
607 emit eventsSelected(events);
612 emit eventsSelected(events);
608 }
613 }
609 else if (events.isEmpty() && !eventProducts.isEmpty()) {
614 else if (events.isEmpty() && !eventProducts.isEmpty()) {
610 emit eventProductsSelected(eventProducts);
615 emit eventProductsSelected(eventProducts);
611 }
616 }
612 else {
617 else {
613 emit selectionCleared();
618 emit selectionCleared();
614 }
619 }
615 }
620 }
616
621
617
622
618 void CatalogueEventsWidget::keyPressEvent(QKeyEvent *event)
623 void CatalogueEventsWidget::keyPressEvent(QKeyEvent *event)
619 {
624 {
620 switch (event->key()) {
625 switch (event->key()) {
621 case Qt::Key_Delete: {
626 case Qt::Key_Delete: {
622 ui->btnRemove->click();
627 ui->btnRemove->click();
623 }
628 }
624 default:
629 default:
625 break;
630 break;
626 }
631 }
627 }
632 }
@@ -1,233 +1,236
1 #include "Catalogue/CatalogueInspectorWidget.h"
1 #include "Catalogue/CatalogueInspectorWidget.h"
2 #include "ui_CatalogueInspectorWidget.h"
2 #include "ui_CatalogueInspectorWidget.h"
3
3
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5 #include <DBCatalogue.h>
5 #include <DBCatalogue.h>
6 #include <DBEvent.h>
6 #include <DBEvent.h>
7 #include <DBEventProduct.h>
7 #include <DBEventProduct.h>
8 #include <DBTag.h>
8 #include <DBTag.h>
9
9
10 struct CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate {
10 struct CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate {
11 std::shared_ptr<DBCatalogue> m_DisplayedCatalogue = nullptr;
11 std::shared_ptr<DBCatalogue> m_DisplayedCatalogue = nullptr;
12 std::shared_ptr<DBEvent> m_DisplayedEvent = nullptr;
12 std::shared_ptr<DBEvent> m_DisplayedEvent = nullptr;
13 std::shared_ptr<DBEventProduct> m_DisplayedEventProduct = nullptr;
13 std::shared_ptr<DBEventProduct> m_DisplayedEventProduct = nullptr;
14
14
15 void connectCatalogueUpdateSignals(CatalogueInspectorWidget *inspector,
15 void connectCatalogueUpdateSignals(CatalogueInspectorWidget *inspector,
16 Ui::CatalogueInspectorWidget *ui);
16 Ui::CatalogueInspectorWidget *ui);
17 void connectEventUpdateSignals(CatalogueInspectorWidget *inspector,
17 void connectEventUpdateSignals(CatalogueInspectorWidget *inspector,
18 Ui::CatalogueInspectorWidget *ui);
18 Ui::CatalogueInspectorWidget *ui);
19 };
19 };
20
20
21 CatalogueInspectorWidget::CatalogueInspectorWidget(QWidget *parent)
21 CatalogueInspectorWidget::CatalogueInspectorWidget(QWidget *parent)
22 : QWidget(parent),
22 : QWidget(parent),
23 ui(new Ui::CatalogueInspectorWidget),
23 ui(new Ui::CatalogueInspectorWidget),
24 impl{spimpl::make_unique_impl<CatalogueInspectorWidgetPrivate>()}
24 impl{spimpl::make_unique_impl<CatalogueInspectorWidgetPrivate>()}
25 {
25 {
26 ui->setupUi(this);
26 ui->setupUi(this);
27 showPage(Page::Empty);
27 showPage(Page::Empty);
28
28
29 impl->connectCatalogueUpdateSignals(this, ui);
29 impl->connectCatalogueUpdateSignals(this, ui);
30 impl->connectEventUpdateSignals(this, ui);
30 impl->connectEventUpdateSignals(this, ui);
31
32 ui->dateTimeEventTStart->setDisplayFormat(DATETIME_FORMAT);
33 ui->dateTimeEventTEnd->setDisplayFormat(DATETIME_FORMAT);
31 }
34 }
32
35
33 CatalogueInspectorWidget::~CatalogueInspectorWidget()
36 CatalogueInspectorWidget::~CatalogueInspectorWidget()
34 {
37 {
35 delete ui;
38 delete ui;
36 }
39 }
37
40
38 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectCatalogueUpdateSignals(
41 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectCatalogueUpdateSignals(
39 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
42 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
40 {
43 {
41 connect(ui->leCatalogueName, &QLineEdit::editingFinished, [ui, inspector, this]() {
44 connect(ui->leCatalogueName, &QLineEdit::editingFinished, [ui, inspector, this]() {
42 if (ui->leCatalogueName->text() != m_DisplayedCatalogue->getName()) {
45 if (ui->leCatalogueName->text() != m_DisplayedCatalogue->getName()) {
43 m_DisplayedCatalogue->setName(ui->leCatalogueName->text());
46 m_DisplayedCatalogue->setName(ui->leCatalogueName->text());
44 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
47 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
45 }
48 }
46 });
49 });
47
50
48 connect(ui->leCatalogueAuthor, &QLineEdit::editingFinished, [ui, inspector, this]() {
51 connect(ui->leCatalogueAuthor, &QLineEdit::editingFinished, [ui, inspector, this]() {
49 if (ui->leCatalogueAuthor->text() != m_DisplayedCatalogue->getAuthor()) {
52 if (ui->leCatalogueAuthor->text() != m_DisplayedCatalogue->getAuthor()) {
50 m_DisplayedCatalogue->setAuthor(ui->leCatalogueAuthor->text());
53 m_DisplayedCatalogue->setAuthor(ui->leCatalogueAuthor->text());
51 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
54 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
52 }
55 }
53 });
56 });
54 }
57 }
55
58
56 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectEventUpdateSignals(
59 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectEventUpdateSignals(
57 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
60 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
58 {
61 {
59 connect(ui->leEventName, &QLineEdit::editingFinished, [ui, inspector, this]() {
62 connect(ui->leEventName, &QLineEdit::editingFinished, [ui, inspector, this]() {
60 if (ui->leEventName->text() != m_DisplayedEvent->getName()) {
63 if (ui->leEventName->text() != m_DisplayedEvent->getName()) {
61 m_DisplayedEvent->setName(ui->leEventName->text());
64 m_DisplayedEvent->setName(ui->leEventName->text());
62 emit inspector->eventUpdated(m_DisplayedEvent);
65 emit inspector->eventUpdated(m_DisplayedEvent);
63 }
66 }
64 });
67 });
65
68
66 connect(ui->leEventTags, &QLineEdit::editingFinished, [ui, inspector, this]() {
69 connect(ui->leEventTags, &QLineEdit::editingFinished, [ui, inspector, this]() {
67 auto tags = ui->leEventTags->text().split(QRegExp("\\s+"), QString::SkipEmptyParts);
70 auto tags = ui->leEventTags->text().split(QRegExp("\\s+"), QString::SkipEmptyParts);
68 std::list<QString> tagNames;
71 std::list<QString> tagNames;
69 for (auto tag : tags) {
72 for (auto tag : tags) {
70 tagNames.push_back(tag);
73 tagNames.push_back(tag);
71 }
74 }
72
75
73 if (m_DisplayedEvent->getTagsNames() != tagNames) {
76 if (m_DisplayedEvent->getTagsNames() != tagNames) {
74 m_DisplayedEvent->setTagsNames(tagNames);
77 m_DisplayedEvent->setTagsNames(tagNames);
75 emit inspector->eventUpdated(m_DisplayedEvent);
78 emit inspector->eventUpdated(m_DisplayedEvent);
76 }
79 }
77 });
80 });
78
81
79 connect(ui->leEventProduct, &QLineEdit::editingFinished, [ui, inspector, this]() {
82 connect(ui->leEventProduct, &QLineEdit::editingFinished, [ui, inspector, this]() {
80 if (ui->leEventProduct->text() != m_DisplayedEventProduct->getProductId()) {
83 if (ui->leEventProduct->text() != m_DisplayedEventProduct->getProductId()) {
81 auto oldProductId = m_DisplayedEventProduct->getProductId();
84 auto oldProductId = m_DisplayedEventProduct->getProductId();
82 m_DisplayedEventProduct->setProductId(ui->leEventProduct->text());
85 m_DisplayedEventProduct->setProductId(ui->leEventProduct->text());
83
86
84 auto eventProducts = m_DisplayedEvent->getEventProducts();
87 auto eventProducts = m_DisplayedEvent->getEventProducts();
85 for (auto &eventProduct : eventProducts) {
88 for (auto &eventProduct : eventProducts) {
86 if (eventProduct.getProductId() == oldProductId) {
89 if (eventProduct.getProductId() == oldProductId) {
87 eventProduct.setProductId(m_DisplayedEventProduct->getProductId());
90 eventProduct.setProductId(m_DisplayedEventProduct->getProductId());
88 }
91 }
89 }
92 }
90 m_DisplayedEvent->setEventProducts(eventProducts);
93 m_DisplayedEvent->setEventProducts(eventProducts);
91
94
92 emit inspector->eventUpdated(m_DisplayedEvent);
95 emit inspector->eventUpdated(m_DisplayedEvent);
93 }
96 }
94 });
97 });
95
98
96 connect(ui->dateTimeEventTStart, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
99 connect(ui->dateTimeEventTStart, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
97 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTStart->dateTime());
100 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTStart->dateTime());
98 if (time != m_DisplayedEventProduct->getTStart()) {
101 if (time != m_DisplayedEventProduct->getTStart()) {
99 m_DisplayedEventProduct->setTStart(time);
102 m_DisplayedEventProduct->setTStart(time);
100
103
101 auto eventProducts = m_DisplayedEvent->getEventProducts();
104 auto eventProducts = m_DisplayedEvent->getEventProducts();
102 for (auto &eventProduct : eventProducts) {
105 for (auto &eventProduct : eventProducts) {
103 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
106 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
104 eventProduct.setTStart(m_DisplayedEventProduct->getTStart());
107 eventProduct.setTStart(m_DisplayedEventProduct->getTStart());
105 }
108 }
106 }
109 }
107 m_DisplayedEvent->setEventProducts(eventProducts);
110 m_DisplayedEvent->setEventProducts(eventProducts);
108
111
109 emit inspector->eventUpdated(m_DisplayedEvent);
112 emit inspector->eventUpdated(m_DisplayedEvent);
110 }
113 }
111 });
114 });
112
115
113 connect(ui->dateTimeEventTEnd, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
116 connect(ui->dateTimeEventTEnd, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
114 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTEnd->dateTime());
117 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTEnd->dateTime());
115 if (time != m_DisplayedEventProduct->getTEnd()) {
118 if (time != m_DisplayedEventProduct->getTEnd()) {
116 m_DisplayedEventProduct->setTEnd(time);
119 m_DisplayedEventProduct->setTEnd(time);
117
120
118 auto eventProducts = m_DisplayedEvent->getEventProducts();
121 auto eventProducts = m_DisplayedEvent->getEventProducts();
119 for (auto &eventProduct : eventProducts) {
122 for (auto &eventProduct : eventProducts) {
120 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
123 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
121 eventProduct.setTEnd(m_DisplayedEventProduct->getTEnd());
124 eventProduct.setTEnd(m_DisplayedEventProduct->getTEnd());
122 }
125 }
123 }
126 }
124 m_DisplayedEvent->setEventProducts(eventProducts);
127 m_DisplayedEvent->setEventProducts(eventProducts);
125
128
126 emit inspector->eventUpdated(m_DisplayedEvent);
129 emit inspector->eventUpdated(m_DisplayedEvent);
127 }
130 }
128 });
131 });
129 }
132 }
130
133
131 void CatalogueInspectorWidget::showPage(CatalogueInspectorWidget::Page page)
134 void CatalogueInspectorWidget::showPage(CatalogueInspectorWidget::Page page)
132 {
135 {
133 ui->stackedWidget->setCurrentIndex(static_cast<int>(page));
136 ui->stackedWidget->setCurrentIndex(static_cast<int>(page));
134 }
137 }
135
138
136 CatalogueInspectorWidget::Page CatalogueInspectorWidget::currentPage() const
139 CatalogueInspectorWidget::Page CatalogueInspectorWidget::currentPage() const
137 {
140 {
138 return static_cast<Page>(ui->stackedWidget->currentIndex());
141 return static_cast<Page>(ui->stackedWidget->currentIndex());
139 }
142 }
140
143
141 void CatalogueInspectorWidget::setEvent(const std::shared_ptr<DBEvent> &event)
144 void CatalogueInspectorWidget::setEvent(const std::shared_ptr<DBEvent> &event)
142 {
145 {
143 impl->m_DisplayedEvent = event;
146 impl->m_DisplayedEvent = event;
144
147
145 blockSignals(true);
148 blockSignals(true);
146
149
147 showPage(Page::EventProperties);
150 showPage(Page::EventProperties);
148 ui->leEventName->setEnabled(true);
151 ui->leEventName->setEnabled(true);
149 ui->leEventName->setText(event->getName());
152 ui->leEventName->setText(event->getName());
150 ui->leEventProduct->setEnabled(false);
153 ui->leEventProduct->setEnabled(false);
151
154
152 auto eventProducts = event->getEventProducts();
155 auto eventProducts = event->getEventProducts();
153 QStringList eventProductList;
156 QStringList eventProductList;
154 for (auto evtProduct : eventProducts) {
157 for (auto evtProduct : eventProducts) {
155 eventProductList << evtProduct.getProductId();
158 eventProductList << evtProduct.getProductId();
156 }
159 }
157
160
158 ui->leEventProduct->setText(eventProductList.join(";"));
161 ui->leEventProduct->setText(eventProductList.join(";"));
159
162
160 QString tagList;
163 QString tagList;
161 auto tags = event->getTagsNames();
164 auto tags = event->getTagsNames();
162 for (auto tag : tags) {
165 for (auto tag : tags) {
163 tagList += tag;
166 tagList += tag;
164 tagList += ' ';
167 tagList += ' ';
165 }
168 }
166
169
167 ui->leEventTags->setEnabled(true);
170 ui->leEventTags->setEnabled(true);
168 ui->leEventTags->setText(tagList);
171 ui->leEventTags->setText(tagList);
169
172
170 ui->dateTimeEventTStart->setEnabled(false);
173 ui->dateTimeEventTStart->setEnabled(false);
171 ui->dateTimeEventTEnd->setEnabled(false);
174 ui->dateTimeEventTEnd->setEnabled(false);
172
175
173 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(event->getTStart()));
176 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(event->getTStart()));
174 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(event->getTEnd()));
177 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(event->getTEnd()));
175
178
176 blockSignals(false);
179 blockSignals(false);
177 }
180 }
178
181
179 void CatalogueInspectorWidget::setEventProduct(const std::shared_ptr<DBEvent> &event,
182 void CatalogueInspectorWidget::setEventProduct(const std::shared_ptr<DBEvent> &event,
180 const std::shared_ptr<DBEventProduct> &eventProduct)
183 const std::shared_ptr<DBEventProduct> &eventProduct)
181 {
184 {
182
185
183 impl->m_DisplayedEvent = event;
186 impl->m_DisplayedEvent = event;
184 impl->m_DisplayedEventProduct = eventProduct;
187 impl->m_DisplayedEventProduct = eventProduct;
185
188
186 blockSignals(true);
189 blockSignals(true);
187
190
188 showPage(Page::EventProperties);
191 showPage(Page::EventProperties);
189 ui->leEventName->setEnabled(false);
192 ui->leEventName->setEnabled(false);
190 ui->leEventName->setText(event->getName());
193 ui->leEventName->setText(event->getName());
191 ui->leEventProduct->setEnabled(false);
194 ui->leEventProduct->setEnabled(false);
192 ui->leEventProduct->setText(eventProduct->getProductId());
195 ui->leEventProduct->setText(eventProduct->getProductId());
193
196
194 ui->leEventTags->setEnabled(false);
197 ui->leEventTags->setEnabled(false);
195 ui->leEventTags->clear();
198 ui->leEventTags->clear();
196
199
197 ui->dateTimeEventTStart->setEnabled(true);
200 ui->dateTimeEventTStart->setEnabled(true);
198 ui->dateTimeEventTEnd->setEnabled(true);
201 ui->dateTimeEventTEnd->setEnabled(true);
199
202
200 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(eventProduct->getTStart()));
203 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(eventProduct->getTStart()));
201 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(eventProduct->getTEnd()));
204 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(eventProduct->getTEnd()));
202
205
203 blockSignals(false);
206 blockSignals(false);
204 }
207 }
205
208
206 void CatalogueInspectorWidget::setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue)
209 void CatalogueInspectorWidget::setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue)
207 {
210 {
208 impl->m_DisplayedCatalogue = catalogue;
211 impl->m_DisplayedCatalogue = catalogue;
209
212
210 blockSignals(true);
213 blockSignals(true);
211
214
212 showPage(Page::CatalogueProperties);
215 showPage(Page::CatalogueProperties);
213 ui->leCatalogueName->setText(catalogue->getName());
216 ui->leCatalogueName->setText(catalogue->getName());
214 ui->leCatalogueAuthor->setText(catalogue->getAuthor());
217 ui->leCatalogueAuthor->setText(catalogue->getAuthor());
215
218
216 blockSignals(false);
219 blockSignals(false);
217 }
220 }
218
221
219 void CatalogueInspectorWidget::refresh()
222 void CatalogueInspectorWidget::refresh()
220 {
223 {
221 switch (static_cast<Page>(ui->stackedWidget->currentIndex())) {
224 switch (static_cast<Page>(ui->stackedWidget->currentIndex())) {
222 case Page::CatalogueProperties:
225 case Page::CatalogueProperties:
223 setCatalogue(impl->m_DisplayedCatalogue);
226 setCatalogue(impl->m_DisplayedCatalogue);
224 break;
227 break;
225 case Page::EventProperties: {
228 case Page::EventProperties: {
226 auto isEventShowed = ui->leEventName->isEnabled();
229 auto isEventShowed = ui->leEventName->isEnabled();
227 setEvent(impl->m_DisplayedEvent);
230 setEvent(impl->m_DisplayedEvent);
228 if (!isEventShowed && impl->m_DisplayedEvent) {
231 if (!isEventShowed && impl->m_DisplayedEvent) {
229 setEventProduct(impl->m_DisplayedEvent, impl->m_DisplayedEventProduct);
232 setEventProduct(impl->m_DisplayedEvent, impl->m_DisplayedEventProduct);
230 }
233 }
231 }
234 }
232 }
235 }
233 }
236 }
@@ -1,207 +1,205
1 #include "Visualization/AxisRenderingUtils.h"
1 #include "Visualization/AxisRenderingUtils.h"
2
2
3 #include <Data/ScalarSeries.h>
3 #include <Data/ScalarSeries.h>
4 #include <Data/SpectrogramSeries.h>
4 #include <Data/SpectrogramSeries.h>
5 #include <Data/VectorSeries.h>
5 #include <Data/VectorSeries.h>
6
6
7 #include <Variable/Variable.h>
7 #include <Variable/Variable.h>
8
8
9 #include <Visualization/SqpColorScale.h>
9 #include <Visualization/SqpColorScale.h>
10 #include <Visualization/qcustomplot.h>
10 #include <Visualization/qcustomplot.h>
11
11
12 Q_LOGGING_CATEGORY(LOG_AxisRenderingUtils, "AxisRenderingUtils")
12 Q_LOGGING_CATEGORY(LOG_AxisRenderingUtils, "AxisRenderingUtils")
13
13
14 namespace {
14 namespace {
15
15
16 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
17
18 /// Format for datetimes on a axis
16 /// Format for datetimes on a axis
19 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
17 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
20
18
21 const auto NUMBER_FORMAT = 'g';
19 const auto NUMBER_FORMAT = 'g';
22 const auto NUMBER_PRECISION = 9;
20 const auto NUMBER_PRECISION = 9;
23
21
24 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
22 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
25 /// non-time data
23 /// non-time data
26 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis, QCPAxis::ScaleType scaleType)
24 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis, QCPAxis::ScaleType scaleType)
27 {
25 {
28 if (isTimeAxis) {
26 if (isTimeAxis) {
29 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
27 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
30 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
28 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
31 dateTicker->setDateTimeSpec(Qt::UTC);
29 dateTicker->setDateTimeSpec(Qt::UTC);
32
30
33 return dateTicker;
31 return dateTicker;
34 }
32 }
35 else if (scaleType == QCPAxis::stLogarithmic) {
33 else if (scaleType == QCPAxis::stLogarithmic) {
36 return QSharedPointer<QCPAxisTickerLog>::create();
34 return QSharedPointer<QCPAxisTickerLog>::create();
37 }
35 }
38 else {
36 else {
39 // default ticker
37 // default ticker
40 return QSharedPointer<QCPAxisTicker>::create();
38 return QSharedPointer<QCPAxisTicker>::create();
41 }
39 }
42 }
40 }
43
41
44 /**
42 /**
45 * Sets properties of the axis passed as parameter
43 * Sets properties of the axis passed as parameter
46 * @param axis the axis to set
44 * @param axis the axis to set
47 * @param unit the unit to set for the axis
45 * @param unit the unit to set for the axis
48 * @param scaleType the scale type to set for the axis
46 * @param scaleType the scale type to set for the axis
49 */
47 */
50 void setAxisProperties(QCPAxis &axis, const Unit &unit,
48 void setAxisProperties(QCPAxis &axis, const Unit &unit,
51 QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
49 QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
52 {
50 {
53 // label (unit name)
51 // label (unit name)
54 axis.setLabel(unit.m_Name);
52 axis.setLabel(unit.m_Name);
55
53
56 // scale type
54 // scale type
57 axis.setScaleType(scaleType);
55 axis.setScaleType(scaleType);
58 if (scaleType == QCPAxis::stLogarithmic) {
56 if (scaleType == QCPAxis::stLogarithmic) {
59 // Scientific notation
57 // Scientific notation
60 axis.setNumberPrecision(0);
58 axis.setNumberPrecision(0);
61 axis.setNumberFormat("eb");
59 axis.setNumberFormat("eb");
62 }
60 }
63
61
64 // ticker (depending on the type of unit)
62 // ticker (depending on the type of unit)
65 axis.setTicker(axisTicker(unit.m_TimeUnit, scaleType));
63 axis.setTicker(axisTicker(unit.m_TimeUnit, scaleType));
66 }
64 }
67
65
68 /**
66 /**
69 * Delegate used to set axes properties
67 * Delegate used to set axes properties
70 */
68 */
71 template <typename T, typename Enabled = void>
69 template <typename T, typename Enabled = void>
72 struct AxisSetter {
70 struct AxisSetter {
73 static void setProperties(QCustomPlot &, SqpColorScale &)
71 static void setProperties(QCustomPlot &, SqpColorScale &)
74 {
72 {
75 // Default implementation does nothing
73 // Default implementation does nothing
76 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
74 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
77 }
75 }
78
76
79 static void setUnits(T &, QCustomPlot &, SqpColorScale &)
77 static void setUnits(T &, QCustomPlot &, SqpColorScale &)
80 {
78 {
81 // Default implementation does nothing
79 // Default implementation does nothing
82 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis units: unmanaged type of data";
80 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis units: unmanaged type of data";
83 }
81 }
84 };
82 };
85
83
86 /**
84 /**
87 * Specialization of AxisSetter for scalars and vectors
85 * Specialization of AxisSetter for scalars and vectors
88 * @sa ScalarSeries
86 * @sa ScalarSeries
89 * @sa VectorSeries
87 * @sa VectorSeries
90 */
88 */
91 template <typename T>
89 template <typename T>
92 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
90 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
93 or std::is_base_of<VectorSeries, T>::value> > {
91 or std::is_base_of<VectorSeries, T>::value> > {
94 static void setProperties(QCustomPlot &, SqpColorScale &)
92 static void setProperties(QCustomPlot &, SqpColorScale &)
95 {
93 {
96 // Nothing to do
94 // Nothing to do
97 }
95 }
98
96
99 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
97 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
100 {
98 {
101 dataSeries.lockRead();
99 dataSeries.lockRead();
102 auto xAxisUnit = dataSeries.xAxisUnit();
100 auto xAxisUnit = dataSeries.xAxisUnit();
103 auto valuesUnit = dataSeries.valuesUnit();
101 auto valuesUnit = dataSeries.valuesUnit();
104 dataSeries.unlock();
102 dataSeries.unlock();
105
103
106 setAxisProperties(*plot.xAxis, xAxisUnit);
104 setAxisProperties(*plot.xAxis, xAxisUnit);
107 setAxisProperties(*plot.yAxis, valuesUnit);
105 setAxisProperties(*plot.yAxis, valuesUnit);
108 }
106 }
109 };
107 };
110
108
111 /**
109 /**
112 * Specialization of AxisSetter for spectrograms
110 * Specialization of AxisSetter for spectrograms
113 * @sa SpectrogramSeries
111 * @sa SpectrogramSeries
114 */
112 */
115 template <typename T>
113 template <typename T>
116 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
114 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
117 static void setProperties(QCustomPlot &plot, SqpColorScale &colorScale)
115 static void setProperties(QCustomPlot &plot, SqpColorScale &colorScale)
118 {
116 {
119 // Displays color scale in plot
117 // Displays color scale in plot
120 plot.plotLayout()->insertRow(0);
118 plot.plotLayout()->insertRow(0);
121 plot.plotLayout()->addElement(0, 0, colorScale.m_Scale);
119 plot.plotLayout()->addElement(0, 0, colorScale.m_Scale);
122 colorScale.m_Scale->setType(QCPAxis::atTop);
120 colorScale.m_Scale->setType(QCPAxis::atTop);
123 colorScale.m_Scale->setMinimumMargins(QMargins{0, 0, 0, 0});
121 colorScale.m_Scale->setMinimumMargins(QMargins{0, 0, 0, 0});
124
122
125 // Aligns color scale with axes
123 // Aligns color scale with axes
126 auto marginGroups = plot.axisRect()->marginGroups();
124 auto marginGroups = plot.axisRect()->marginGroups();
127 for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it) {
125 for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it) {
128 colorScale.m_Scale->setMarginGroup(it.key(), it.value());
126 colorScale.m_Scale->setMarginGroup(it.key(), it.value());
129 }
127 }
130
128
131 // Set color scale properties
129 // Set color scale properties
132 colorScale.m_AutomaticThreshold = true;
130 colorScale.m_AutomaticThreshold = true;
133 }
131 }
134
132
135 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
133 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
136 {
134 {
137 dataSeries.lockRead();
135 dataSeries.lockRead();
138 auto xAxisUnit = dataSeries.xAxisUnit();
136 auto xAxisUnit = dataSeries.xAxisUnit();
139 auto yAxisUnit = dataSeries.yAxisUnit();
137 auto yAxisUnit = dataSeries.yAxisUnit();
140 auto valuesUnit = dataSeries.valuesUnit();
138 auto valuesUnit = dataSeries.valuesUnit();
141 dataSeries.unlock();
139 dataSeries.unlock();
142
140
143 setAxisProperties(*plot.xAxis, xAxisUnit);
141 setAxisProperties(*plot.xAxis, xAxisUnit);
144 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
142 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
145 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
143 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
146 }
144 }
147 };
145 };
148
146
149 /**
147 /**
150 * Default implementation of IAxisHelper, which takes data series to set axes properties
148 * Default implementation of IAxisHelper, which takes data series to set axes properties
151 * @tparam T the data series' type
149 * @tparam T the data series' type
152 */
150 */
153 template <typename T>
151 template <typename T>
154 struct AxisHelper : public IAxisHelper {
152 struct AxisHelper : public IAxisHelper {
155 explicit AxisHelper(std::shared_ptr<T> dataSeries) : m_DataSeries{dataSeries} {}
153 explicit AxisHelper(std::shared_ptr<T> dataSeries) : m_DataSeries{dataSeries} {}
156
154
157 void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
155 void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
158 {
156 {
159 AxisSetter<T>::setProperties(plot, colorScale);
157 AxisSetter<T>::setProperties(plot, colorScale);
160 }
158 }
161
159
162 void setUnits(QCustomPlot &plot, SqpColorScale &colorScale) override
160 void setUnits(QCustomPlot &plot, SqpColorScale &colorScale) override
163 {
161 {
164 if (m_DataSeries) {
162 if (m_DataSeries) {
165 AxisSetter<T>::setUnits(*m_DataSeries, plot, colorScale);
163 AxisSetter<T>::setUnits(*m_DataSeries, plot, colorScale);
166 }
164 }
167 else {
165 else {
168 qCCritical(LOG_AxisRenderingUtils()) << "Can't set units: inconsistency between the "
166 qCCritical(LOG_AxisRenderingUtils()) << "Can't set units: inconsistency between the "
169 "type of data series and the type supposed";
167 "type of data series and the type supposed";
170 }
168 }
171 }
169 }
172
170
173 std::shared_ptr<T> m_DataSeries;
171 std::shared_ptr<T> m_DataSeries;
174 };
172 };
175
173
176 } // namespace
174 } // namespace
177
175
178 QString formatValue(double value, const QCPAxis &axis)
176 QString formatValue(double value, const QCPAxis &axis)
179 {
177 {
180 // If the axis is a time axis, formats the value as a date
178 // If the axis is a time axis, formats the value as a date
181 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
179 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
182 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
180 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
183 }
181 }
184 else {
182 else {
185 return QString::number(value, NUMBER_FORMAT, NUMBER_PRECISION);
183 return QString::number(value, NUMBER_FORMAT, NUMBER_PRECISION);
186 }
184 }
187 }
185 }
188
186
189 std::unique_ptr<IAxisHelper> IAxisHelperFactory::create(const Variable &variable) noexcept
187 std::unique_ptr<IAxisHelper> IAxisHelperFactory::create(const Variable &variable) noexcept
190 {
188 {
191 switch (variable.type()) {
189 switch (variable.type()) {
192 case DataSeriesType::SCALAR:
190 case DataSeriesType::SCALAR:
193 return std::make_unique<AxisHelper<ScalarSeries> >(
191 return std::make_unique<AxisHelper<ScalarSeries> >(
194 std::dynamic_pointer_cast<ScalarSeries>(variable.dataSeries()));
192 std::dynamic_pointer_cast<ScalarSeries>(variable.dataSeries()));
195 case DataSeriesType::SPECTROGRAM:
193 case DataSeriesType::SPECTROGRAM:
196 return std::make_unique<AxisHelper<SpectrogramSeries> >(
194 return std::make_unique<AxisHelper<SpectrogramSeries> >(
197 std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()));
195 std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()));
198 case DataSeriesType::VECTOR:
196 case DataSeriesType::VECTOR:
199 return std::make_unique<AxisHelper<VectorSeries> >(
197 return std::make_unique<AxisHelper<VectorSeries> >(
200 std::dynamic_pointer_cast<VectorSeries>(variable.dataSeries()));
198 std::dynamic_pointer_cast<VectorSeries>(variable.dataSeries()));
201 default:
199 default:
202 // Creates default helper
200 // Creates default helper
203 break;
201 break;
204 }
202 }
205
203
206 return std::make_unique<AxisHelper<IDataSeries> >(nullptr);
204 return std::make_unique<AxisHelper<IDataSeries> >(nullptr);
207 }
205 }
@@ -1,69 +1,69
1 #include "Visualization/VisualizationMultiZoneSelectionDialog.h"
1 #include "Visualization/VisualizationMultiZoneSelectionDialog.h"
2 #include "ui_VisualizationMultiZoneSelectionDialog.h"
2 #include "ui_VisualizationMultiZoneSelectionDialog.h"
3
3
4 #include "Common/DateUtils.h"
4 #include "Common/DateUtils.h"
5 #include "Visualization/VisualizationSelectionZoneItem.h"
5 #include "Visualization/VisualizationSelectionZoneItem.h"
6
6
7 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss");
7 const auto DATETIME_FORMAT_S = QStringLiteral("yyyy/MM/dd hh:mm:ss");
8
8
9 struct VisualizationMultiZoneSelectionDialog::VisualizationMultiZoneSelectionDialogPrivate {
9 struct VisualizationMultiZoneSelectionDialog::VisualizationMultiZoneSelectionDialogPrivate {
10 QVector<VisualizationSelectionZoneItem *> m_Zones;
10 QVector<VisualizationSelectionZoneItem *> m_Zones;
11 };
11 };
12
12
13 VisualizationMultiZoneSelectionDialog::VisualizationMultiZoneSelectionDialog(QWidget *parent)
13 VisualizationMultiZoneSelectionDialog::VisualizationMultiZoneSelectionDialog(QWidget *parent)
14 : QDialog(parent, Qt::Tool),
14 : QDialog(parent, Qt::Tool),
15 ui(new Ui::VisualizationMultiZoneSelectionDialog),
15 ui(new Ui::VisualizationMultiZoneSelectionDialog),
16 impl{spimpl::make_unique_impl<VisualizationMultiZoneSelectionDialogPrivate>()}
16 impl{spimpl::make_unique_impl<VisualizationMultiZoneSelectionDialogPrivate>()}
17 {
17 {
18 ui->setupUi(this);
18 ui->setupUi(this);
19
19
20 connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
20 connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
21 &VisualizationMultiZoneSelectionDialog::accept);
21 &VisualizationMultiZoneSelectionDialog::accept);
22 connect(ui->buttonBox, &QDialogButtonBox::rejected, this,
22 connect(ui->buttonBox, &QDialogButtonBox::rejected, this,
23 &VisualizationMultiZoneSelectionDialog::reject);
23 &VisualizationMultiZoneSelectionDialog::reject);
24 }
24 }
25
25
26 VisualizationMultiZoneSelectionDialog::~VisualizationMultiZoneSelectionDialog()
26 VisualizationMultiZoneSelectionDialog::~VisualizationMultiZoneSelectionDialog()
27 {
27 {
28 delete ui;
28 delete ui;
29 }
29 }
30
30
31 void VisualizationMultiZoneSelectionDialog::setZones(
31 void VisualizationMultiZoneSelectionDialog::setZones(
32 const QVector<VisualizationSelectionZoneItem *> &zones)
32 const QVector<VisualizationSelectionZoneItem *> &zones)
33 {
33 {
34 impl->m_Zones = zones;
34 impl->m_Zones = zones;
35
35
36 // Sorts the zones to display them in temporal order
36 // Sorts the zones to display them in temporal order
37 std::sort(impl->m_Zones.begin(), impl->m_Zones.end(), [](auto zone1, auto zone2) {
37 std::sort(impl->m_Zones.begin(), impl->m_Zones.end(), [](auto zone1, auto zone2) {
38 return zone1->range().m_TStart < zone2->range().m_TStart;
38 return zone1->range().m_TStart < zone2->range().m_TStart;
39 });
39 });
40
40
41 // Adds the zones in the listwidget
41 // Adds the zones in the listwidget
42 for (auto zone : impl->m_Zones) {
42 for (auto zone : impl->m_Zones) {
43 auto name = zone->name();
43 auto name = zone->name();
44 if (!name.isEmpty()) {
44 if (!name.isEmpty()) {
45 name += tr(": ");
45 name += tr(": ");
46 }
46 }
47
47
48 auto range = zone->range();
48 auto range = zone->range();
49 name += DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT);
49 name += DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT_S);
50 name += " - ";
50 name += " - ";
51 name += DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT);
51 name += DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT_S);
52
52
53 auto item = new QListWidgetItem(name, ui->listWidget);
53 auto item = new QListWidgetItem(name, ui->listWidget);
54 item->setSelected(zone->selected());
54 item->setSelected(zone->selected());
55 }
55 }
56 }
56 }
57
57
58 QMap<VisualizationSelectionZoneItem *, bool>
58 QMap<VisualizationSelectionZoneItem *, bool>
59 VisualizationMultiZoneSelectionDialog::selectedZones() const
59 VisualizationMultiZoneSelectionDialog::selectedZones() const
60 {
60 {
61 QMap<VisualizationSelectionZoneItem *, bool> selectedZones;
61 QMap<VisualizationSelectionZoneItem *, bool> selectedZones;
62
62
63 for (auto i = 0; i < ui->listWidget->count(); ++i) {
63 for (auto i = 0; i < ui->listWidget->count(); ++i) {
64 auto item = ui->listWidget->item(i);
64 auto item = ui->listWidget->item(i);
65 selectedZones[impl->m_Zones[i]] = item->isSelected();
65 selectedZones[impl->m_Zones[i]] = item->isSelected();
66 }
66 }
67
67
68 return selectedZones;
68 return selectedZones;
69 }
69 }
@@ -1,145 +1,144
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>CatalogueEventsWidget</class>
3 <class>CatalogueEventsWidget</class>
4 <widget class="QWidget" name="CatalogueEventsWidget">
4 <widget class="QWidget" name="CatalogueEventsWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>566</width>
9 <width>566</width>
10 <height>258</height>
10 <height>258</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="windowTitle">
13 <property name="windowTitle">
14 <string>Form</string>
14 <string>Form</string>
15 </property>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout">
16 <layout class="QVBoxLayout" name="verticalLayout">
17 <property name="leftMargin">
17 <property name="leftMargin">
18 <number>0</number>
18 <number>0</number>
19 </property>
19 </property>
20 <property name="topMargin">
20 <property name="topMargin">
21 <number>0</number>
21 <number>0</number>
22 </property>
22 </property>
23 <property name="rightMargin">
23 <property name="rightMargin">
24 <number>0</number>
24 <number>0</number>
25 </property>
25 </property>
26 <property name="bottomMargin">
26 <property name="bottomMargin">
27 <number>0</number>
27 <number>0</number>
28 </property>
28 </property>
29 <item>
29 <item>
30 <layout class="QHBoxLayout" name="horizontalLayout">
30 <layout class="QHBoxLayout" name="horizontalLayout">
31 <item>
31 <item>
32 <widget class="QToolButton" name="btnAdd">
32 <widget class="QToolButton" name="btnAdd">
33 <property name="enabled">
33 <property name="enabled">
34 <bool>false</bool>
34 <bool>false</bool>
35 </property>
35 </property>
36 <property name="text">
36 <property name="text">
37 <string>+</string>
37 <string>+</string>
38 </property>
38 </property>
39 <property name="icon">
39 <property name="icon">
40 <iconset resource="../../resources/sqpguiresources.qrc">
40 <iconset resource="../../resources/sqpguiresources.qrc">
41 <normaloff>:/icones/add.png</normaloff>:/icones/add.png</iconset>
41 <normaloff>:/icones/add.png</normaloff>:/icones/add.png</iconset>
42 </property>
42 </property>
43 <property name="autoRaise">
43 <property name="autoRaise">
44 <bool>true</bool>
44 <bool>true</bool>
45 </property>
45 </property>
46 </widget>
46 </widget>
47 </item>
47 </item>
48 <item>
48 <item>
49 <widget class="QToolButton" name="btnRemove">
49 <widget class="QToolButton" name="btnRemove">
50 <property name="text">
50 <property name="text">
51 <string> - </string>
51 <string> - </string>
52 </property>
52 </property>
53 <property name="icon">
53 <property name="icon">
54 <iconset resource="../../resources/sqpguiresources.qrc">
54 <iconset resource="../../resources/sqpguiresources.qrc">
55 <normaloff>:/icones/remove.png</normaloff>:/icones/remove.png</iconset>
55 <normaloff>:/icones/remove.png</normaloff>:/icones/remove.png</iconset>
56 </property>
56 </property>
57 <property name="autoRaise">
57 <property name="autoRaise">
58 <bool>true</bool>
58 <bool>true</bool>
59 </property>
59 </property>
60 </widget>
60 </widget>
61 </item>
61 </item>
62 <item>
62 <item>
63 <widget class="Line" name="line">
63 <widget class="Line" name="line">
64 <property name="orientation">
64 <property name="orientation">
65 <enum>Qt::Vertical</enum>
65 <enum>Qt::Vertical</enum>
66 </property>
66 </property>
67 </widget>
67 </widget>
68 </item>
68 </item>
69 <item>
69 <item>
70 <widget class="QToolButton" name="btnTime">
70 <widget class="QToolButton" name="btnTime">
71 <property name="text">
71 <property name="text">
72 <string>T</string>
72 <string>T</string>
73 </property>
73 </property>
74 <property name="icon">
74 <property name="icon">
75 <iconset resource="../../resources/sqpguiresources.qrc">
75 <iconset resource="../../resources/sqpguiresources.qrc">
76 <normaloff>:/icones/time.png</normaloff>:/icones/time.png</iconset>
76 <normaloff>:/icones/time.png</normaloff>:/icones/time.png</iconset>
77 </property>
77 </property>
78 <property name="checkable">
78 <property name="checkable">
79 <bool>true</bool>
79 <bool>true</bool>
80 </property>
80 </property>
81 <property name="autoRaise">
81 <property name="autoRaise">
82 <bool>true</bool>
82 <bool>true</bool>
83 </property>
83 </property>
84 </widget>
84 </widget>
85 </item>
85 </item>
86 <item>
86 <item>
87 <widget class="QToolButton" name="btnChart">
87 <widget class="QToolButton" name="btnChart">
88 <property name="text">
88 <property name="text">
89 <string>G</string>
89 <string>G</string>
90 </property>
90 </property>
91 <property name="icon">
91 <property name="icon">
92 <iconset resource="../../resources/sqpguiresources.qrc">
92 <iconset resource="../../resources/sqpguiresources.qrc">
93 <normaloff>:/icones/chart.png</normaloff>:/icones/chart.png</iconset>
93 <normaloff>:/icones/chart.png</normaloff>:/icones/chart.png</iconset>
94 </property>
94 </property>
95 <property name="checkable">
95 <property name="checkable">
96 <bool>true</bool>
96 <bool>true</bool>
97 </property>
97 </property>
98 <property name="autoRaise">
98 <property name="autoRaise">
99 <bool>true</bool>
99 <bool>true</bool>
100 </property>
100 </property>
101 </widget>
101 </widget>
102 </item>
102 </item>
103 <item>
103 <item>
104 <widget class="Line" name="line_2">
104 <widget class="Line" name="line_2">
105 <property name="orientation">
105 <property name="orientation">
106 <enum>Qt::Vertical</enum>
106 <enum>Qt::Vertical</enum>
107 </property>
107 </property>
108 </widget>
108 </widget>
109 </item>
109 </item>
110 <item>
110 <item>
111 <widget class="QLineEdit" name="lineEdit">
111 <widget class="QLineEdit" name="lineEdit">
112 <property name="enabled">
112 <property name="enabled">
113 <bool>false</bool>
113 <bool>false</bool>
114 </property>
114 </property>
115 </widget>
115 </widget>
116 </item>
116 </item>
117 </layout>
117 </layout>
118 </item>
118 </item>
119 <item>
119 <item>
120 <widget class="QTreeView" name="treeView">
120 <widget class="QTreeView" name="treeView">
121 <property name="dragEnabled">
121 <property name="dragEnabled">
122 <bool>true</bool>
122 <bool>true</bool>
123 </property>
123 </property>
124 <property name="dragDropMode">
124 <property name="dragDropMode">
125 <enum>QAbstractItemView::DragDrop</enum>
125 <enum>QAbstractItemView::DragDrop</enum>
126 </property>
126 </property>
127 <property name="selectionMode">
127 <property name="selectionMode">
128 <enum>QAbstractItemView::ExtendedSelection</enum>
128 <enum>QAbstractItemView::ExtendedSelection</enum>
129 </property>
129 </property>
130 <property name="selectionBehavior">
130 <property name="selectionBehavior">
131 <enum>QAbstractItemView::SelectRows</enum>
131 <enum>QAbstractItemView::SelectRows</enum>
132 </property>
132 </property>
133 <attribute name="headerStretchLastSection">
133 <attribute name="headerStretchLastSection">
134 <bool>false</bool>
134 <bool>false</bool>
135 </attribute>
135 </attribute>
136 </widget>
136 </widget>
137 </item>
137 </item>
138 </layout>
138 </layout>
139 </widget>
139 </widget>
140 <resources>
140 <resources>
141 <include location="../../resources/sqpguiresources.qrc"/>
141 <include location="../../resources/sqpguiresources.qrc"/>
142 <include location="../../resources/sqpguiresources.qrc"/>
143 </resources>
142 </resources>
144 <connections/>
143 <connections/>
145 </ui>
144 </ui>
General Comments 0
You need to be logged in to leave comments. Login now