@@ -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 |
|
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 |
|
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