##// END OF EJS Templates
store events with changes in the catalogue controller
trabillard -
r1292:1ee6a92bae00
parent child
Show More
@@ -1,80 +1,81
1 1 #ifndef SCIQLOP_CATALOGUECONTROLLER_H
2 2 #define SCIQLOP_CATALOGUECONTROLLER_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Data/SqpRange.h>
7 7
8 8 #include <QLoggingCategory>
9 9 #include <QObject>
10 10 #include <QUuid>
11 11
12 12 #include <Common/spimpl.h>
13 13
14 14 #include <memory>
15 15
16 16 class DBCatalogue;
17 17 class DBEvent;
18 18 class DBEventProduct;
19 19
20 20 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueController)
21 21
22 22 class DataSourceItem;
23 23 class Variable;
24 24
25 25 /**
26 26 * @brief The CatalogueController class aims to handle catalogues and event using the CatalogueAPI
27 27 * library.
28 28 */
29 29 class SCIQLOP_CORE_EXPORT CatalogueController : public QObject {
30 30 Q_OBJECT
31 31 public:
32 32 explicit CatalogueController(QObject *parent = 0);
33 33 virtual ~CatalogueController();
34 34
35 35 // DB
36 36 QStringList getRepositories() const;
37 37 void addDB(const QString &dbPath);
38 38 void saveDB(const QString &destinationPath, const QString &repository);
39 39
40 40 // Event
41 41 /// retrieveEvents with empty repository retrieve them from the default repository
42 42 std::list<std::shared_ptr<DBEvent> > retrieveEvents(const QString &repository) const;
43 43 std::list<std::shared_ptr<DBEvent> > retrieveAllEvents() const;
44 44 std::list<std::shared_ptr<DBEvent> >
45 45 retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const;
46 46 void addEvent(std::shared_ptr<DBEvent> event);
47 47 void updateEvent(std::shared_ptr<DBEvent> event);
48 48 void updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct);
49 49 void removeEvent(std::shared_ptr<DBEvent> event);
50 50 // void trashEvent(std::shared_ptr<DBEvent> event);
51 51 // void restore(QUuid eventId);
52 52 void saveEvent(std::shared_ptr<DBEvent> event);
53 bool eventHasChanges(std::shared_ptr<DBEvent> event) const;
53 54
54 55 // Catalogue
55 56 // bool createCatalogue(const QString &name, QVector<QUuid> eventList);
56 57 /// retrieveEvents with empty repository retrieve them from the default repository
57 58 std::list<std::shared_ptr<DBCatalogue> > retrieveCatalogues(const QString &repository
58 59 = QString()) const;
59 60 void updateCatalogue(std::shared_ptr<DBCatalogue> catalogue);
60 61 void removeCatalogue(std::shared_ptr<DBCatalogue> catalogue);
61 62 void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue);
62 63
63 64 void saveAll();
64 65
65 66 /// Returns the MIME data associated to a list of variables
66 67 QByteArray mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const;
67 68
68 69 /// Returns the list of variables contained in a MIME data
69 70 QVector<std::shared_ptr<DBEvent> > eventsForMimeData(const QByteArray &mimeData) const;
70 71
71 72 public slots:
72 73 /// Manage init/end of the controller
73 74 void initialize();
74 75
75 76 private:
76 77 class CatalogueControllerPrivate;
77 78 spimpl::unique_impl_ptr<CatalogueControllerPrivate> impl;
78 79 };
79 80
80 81 #endif // SCIQLOP_CATALOGUECONTROLLER_H
@@ -1,368 +1,388
1 1 #include <Catalogue/CatalogueController.h>
2 2
3 3 #include <Variable/Variable.h>
4 4
5 5 #include <CatalogueDao.h>
6 6
7 7 #include <ComparaisonPredicate.h>
8 8 #include <CompoundPredicate.h>
9 9 #include <DBCatalogue.h>
10 10 #include <DBEvent.h>
11 11 #include <DBEventProduct.h>
12 12 #include <DBTag.h>
13 13 #include <IRequestPredicate.h>
14 14
15 15 #include <QDataStream>
16 16 #include <QMutex>
17 17 #include <QThread>
18 18
19 19 #include <QDir>
20 20 #include <QStandardPaths>
21 21
22 22 Q_LOGGING_CATEGORY(LOG_CatalogueController, "CatalogueController")
23 23
24 24 namespace {
25 25
26 26 static QString REPOSITORY_WORK_SUFFIX = QString{"_work"};
27 27 static QString REPOSITORY_TRASH_SUFFIX = QString{"_trash"};
28 28 }
29 29
30 30 class CatalogueController::CatalogueControllerPrivate {
31 31
32 32 public:
33 33 explicit CatalogueControllerPrivate(CatalogueController *parent) : m_Q{parent} {}
34 34
35 35 CatalogueDao m_CatalogueDao;
36 36
37 37 QStringList m_RepositoryList;
38 38 CatalogueController *m_Q;
39 39
40 QSet<QString> m_EventKeysWithChanges;
41
42 QString eventUniqueKey(const std::shared_ptr<DBEvent> &event) const;
43
40 44 void copyDBtoDB(const QString &dbFrom, const QString &dbTo);
41 45 QString toWorkRepository(QString repository);
42 46 QString toSyncRepository(QString repository);
43 47 void savAllDB();
44 48
45 49 void saveEvent(std::shared_ptr<DBEvent> event, bool persist = true);
46 50 void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool persist = true);
47 51 };
48 52
49 53 CatalogueController::CatalogueController(QObject *parent)
50 54 : impl{spimpl::make_unique_impl<CatalogueControllerPrivate>(this)}
51 55 {
52 56 qCDebug(LOG_CatalogueController()) << tr("CatalogueController construction")
53 57 << QThread::currentThread();
54 58 }
55 59
56 60 CatalogueController::~CatalogueController()
57 61 {
58 62 qCDebug(LOG_CatalogueController()) << tr("CatalogueController destruction")
59 63 << QThread::currentThread();
60 64 }
61 65
62 66 QStringList CatalogueController::getRepositories() const
63 67 {
64 68 return impl->m_RepositoryList;
65 69 }
66 70
67 71 void CatalogueController::addDB(const QString &dbPath)
68 72 {
69 73 QDir dbDir(dbPath);
70 74 if (dbDir.exists()) {
71 75 auto dirName = dbDir.dirName();
72 76
73 77 if (std::find(impl->m_RepositoryList.cbegin(), impl->m_RepositoryList.cend(), dirName)
74 78 != impl->m_RepositoryList.cend()) {
75 79 qCCritical(LOG_CatalogueController())
76 80 << tr("Impossible to addDB that is already loaded");
77 81 }
78 82
79 83 if (!impl->m_CatalogueDao.addDB(dbPath, dirName)) {
80 84 qCCritical(LOG_CatalogueController())
81 85 << tr("Impossible to addDB %1 from %2 ").arg(dirName, dbPath);
82 86 }
83 87 else {
84 88 impl->m_RepositoryList << dirName;
85 89 impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName));
86 90 }
87 91 }
88 92 else {
89 93 qCCritical(LOG_CatalogueController()) << tr("Impossible to addDB that not exists: ")
90 94 << dbPath;
91 95 }
92 96 }
93 97
94 98 void CatalogueController::saveDB(const QString &destinationPath, const QString &repository)
95 99 {
96 100 if (!impl->m_CatalogueDao.saveDB(destinationPath, repository)) {
97 101 qCCritical(LOG_CatalogueController())
98 102 << tr("Impossible to saveDB %1 from %2 ").arg(repository, destinationPath);
99 103 }
100 104 }
101 105
102 106 std::list<std::shared_ptr<DBEvent> >
103 107 CatalogueController::retrieveEvents(const QString &repository) const
104 108 {
105 109 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
106 110
107 111 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
108 112 auto events = impl->m_CatalogueDao.getEvents(impl->toWorkRepository(dbDireName));
109 113 for (auto event : events) {
110 114 eventsShared.push_back(std::make_shared<DBEvent>(event));
111 115 }
112 116 return eventsShared;
113 117 }
114 118
115 119 std::list<std::shared_ptr<DBEvent> > CatalogueController::retrieveAllEvents() const
116 120 {
117 121 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
118 122 for (auto repository : impl->m_RepositoryList) {
119 123 eventsShared.splice(eventsShared.end(), retrieveEvents(repository));
120 124 }
121 125
122 126 return eventsShared;
123 127 }
124 128
125 129 std::list<std::shared_ptr<DBEvent> >
126 130 CatalogueController::retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const
127 131 {
128 132 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
129 133 auto events = impl->m_CatalogueDao.getCatalogueEvents(*catalogue);
130 134 for (auto event : events) {
131 135 eventsShared.push_back(std::make_shared<DBEvent>(event));
132 136 }
133 137 return eventsShared;
134 138 }
135 139
136 140 void CatalogueController::updateEvent(std::shared_ptr<DBEvent> event)
137 141 {
138 142 event->setRepository(impl->toWorkRepository(event->getRepository()));
139 143
144 auto uniqueId = impl->eventUniqueKey(event);
145 impl->m_EventKeysWithChanges.insert(uniqueId);
146
140 147 impl->m_CatalogueDao.updateEvent(*event);
141 148 }
142 149
143 150 void CatalogueController::updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct)
144 151 {
145 152 impl->m_CatalogueDao.updateEventProduct(*eventProduct);
146 153 }
147 154
148 155 void CatalogueController::removeEvent(std::shared_ptr<DBEvent> event)
149 156 {
150 157 // Remove it from both repository and repository_work
151 158 event->setRepository(impl->toWorkRepository(event->getRepository()));
152 159 impl->m_CatalogueDao.removeEvent(*event);
153 160 event->setRepository(impl->toSyncRepository(event->getRepository()));
154 161 impl->m_CatalogueDao.removeEvent(*event);
155 162 }
156 163
157 164 void CatalogueController::addEvent(std::shared_ptr<DBEvent> event)
158 165 {
159 166 event->setRepository(impl->toWorkRepository(event->getRepository()));
160 167
161 168 auto eventTemp = *event;
162 169 impl->m_CatalogueDao.addEvent(eventTemp);
163 170
164 171 // Call update is necessary at the creation of add Event if it has some tags or some event
165 172 // products
166 173 if (!event->getEventProducts().empty() || !event->getTags().empty()) {
167 174
168 175 auto eventProductsTemp = eventTemp.getEventProducts();
169 176 auto eventProductTempUpdated = std::list<DBEventProduct>{};
170 177 for (auto eventProductTemp : eventProductsTemp) {
171 178 eventProductTemp.setEvent(eventTemp);
172 179 eventProductTempUpdated.push_back(eventProductTemp);
173 180 }
174 181 eventTemp.setEventProducts(eventProductTempUpdated);
175 182
176 183 impl->m_CatalogueDao.updateEvent(eventTemp);
177 184 }
178 185 }
179 186
180 187 void CatalogueController::saveEvent(std::shared_ptr<DBEvent> event)
181 188 {
182 189 impl->saveEvent(event, true);
190 impl->m_EventKeysWithChanges.remove(impl->eventUniqueKey(event));
191 }
192
193 bool CatalogueController::eventHasChanges(std::shared_ptr<DBEvent> event) const
194 {
195 return impl->m_EventKeysWithChanges.contains(impl->eventUniqueKey(event));
183 196 }
184 197
185 198 std::list<std::shared_ptr<DBCatalogue> >
186 199 CatalogueController::retrieveCatalogues(const QString &repository) const
187 200 {
188 201 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
189 202
190 203 auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
191 204 auto catalogues = impl->m_CatalogueDao.getCatalogues(impl->toWorkRepository(dbDireName));
192 205 for (auto catalogue : catalogues) {
193 206 cataloguesShared.push_back(std::make_shared<DBCatalogue>(catalogue));
194 207 }
195 208 return cataloguesShared;
196 209 }
197 210
198 211 void CatalogueController::updateCatalogue(std::shared_ptr<DBCatalogue> catalogue)
199 212 {
200 213 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
201 214
202 215 impl->m_CatalogueDao.updateCatalogue(*catalogue);
203 216 }
204 217
205 218 void CatalogueController::removeCatalogue(std::shared_ptr<DBCatalogue> catalogue)
206 219 {
207 220 // Remove it from both repository and repository_work
208 221 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
209 222 impl->m_CatalogueDao.removeCatalogue(*catalogue);
210 223 catalogue->setRepository(impl->toSyncRepository(catalogue->getRepository()));
211 224 impl->m_CatalogueDao.removeCatalogue(*catalogue);
212 225 }
213 226
214 227 void CatalogueController::saveCatalogue(std::shared_ptr<DBCatalogue> catalogue)
215 228 {
216 229 impl->saveCatalogue(catalogue, true);
217 230 }
218 231
219 232 void CatalogueController::saveAll()
220 233 {
221 234 for (auto repository : impl->m_RepositoryList) {
222 235 // Save Event
223 236 auto events = this->retrieveEvents(repository);
224 237 for (auto event : events) {
225 238 impl->saveEvent(event, false);
226 239 }
227 240
228 241 // Save Catalogue
229 242 auto catalogues = this->retrieveCatalogues(repository);
230 243 for (auto catalogue : catalogues) {
231 244 impl->saveCatalogue(catalogue, false);
232 245 }
233 246 }
234 247
235 248 impl->savAllDB();
249 impl->m_EventKeysWithChanges.clear();
236 250 }
237 251
238 252 QByteArray
239 253 CatalogueController::mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const
240 254 {
241 255 auto encodedData = QByteArray{};
242 256
243 257 QMap<QString, QVariantList> idsPerRepository;
244 258 for (auto event : events) {
245 259 idsPerRepository[event->getRepository()] << event->getUniqId();
246 260 }
247 261
248 262 QDataStream stream{&encodedData, QIODevice::WriteOnly};
249 263 stream << idsPerRepository;
250 264
251 265 return encodedData;
252 266 }
253 267
254 268 QVector<std::shared_ptr<DBEvent> >
255 269 CatalogueController::eventsForMimeData(const QByteArray &mimeData) const
256 270 {
257 271 auto events = QVector<std::shared_ptr<DBEvent> >{};
258 272 QDataStream stream{mimeData};
259 273
260 274 QMap<QString, QVariantList> idsPerRepository;
261 275 stream >> idsPerRepository;
262 276
263 277 for (auto it = idsPerRepository.cbegin(); it != idsPerRepository.cend(); ++it) {
264 278 auto repository = it.key();
265 279 auto allRepositoryEvent = retrieveEvents(repository);
266 280 for (auto uuid : it.value()) {
267 281 for (auto repositoryEvent : allRepositoryEvent) {
268 282 if (uuid.toUuid() == repositoryEvent->getUniqId()) {
269 283 events << repositoryEvent;
270 284 }
271 285 }
272 286 }
273 287 }
274 288
275 289 return events;
276 290 }
277 291
278 292 void CatalogueController::initialize()
279 293 {
280 294 <<<<<<< HEAD
281 295 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init")
282 296 << QThread::currentThread();
283 297 impl->m_WorkingMutex.lock();
284 298 =======
285 299 qCDebug(LOG_CatalogueController())
286 300 << tr("CatalogueController init") << QThread::currentThread();
287 301 >>>>>>> 286decc... unthread the catalogue controller
288 302 impl->m_CatalogueDao.initialize();
289 303 auto defaultRepositoryLocation
290 304 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
291 305
292 306 QDir defaultRepositoryLocationDir;
293 307 if (defaultRepositoryLocationDir.mkpath(defaultRepositoryLocation)) {
294 308 defaultRepositoryLocationDir.cd(defaultRepositoryLocation);
295 309 auto defaultRepository = defaultRepositoryLocationDir.absoluteFilePath(REPOSITORY_DEFAULT);
296 310 qCInfo(LOG_CatalogueController()) << tr("Persistant data loading from: ")
297 311 << defaultRepository;
298 312 this->addDB(defaultRepository);
299 313 }
300 314 else {
301 315 qCWarning(LOG_CatalogueController())
302 316 << tr("Cannot load the persistent default repository from ")
303 317 << defaultRepositoryLocation;
304 318 }
305 319
306 320 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init END");
307 321 }
308 322
323 QString CatalogueController::CatalogueControllerPrivate::eventUniqueKey(
324 const std::shared_ptr<DBEvent> &event) const
325 {
326 return event->getUniqId().toString().append(event->getRepository());
327 }
328
309 329 void CatalogueController::CatalogueControllerPrivate::copyDBtoDB(const QString &dbFrom,
310 330 const QString &dbTo)
311 331 {
312 332 // auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
313 333 auto catalogues = m_CatalogueDao.getCatalogues(dbFrom);
314 334 auto events = m_CatalogueDao.getEvents(dbFrom);
315 335 for (auto catalogue : catalogues) {
316 336 m_CatalogueDao.copyCatalogue(catalogue, dbTo, true);
317 337 }
318 338
319 339 for (auto event : events) {
320 340 m_CatalogueDao.copyEvent(event, dbTo, true);
321 341 }
322 342 }
323 343
324 344 QString CatalogueController::CatalogueControllerPrivate::toWorkRepository(QString repository)
325 345 {
326 346 auto syncRepository = toSyncRepository(repository);
327 347
328 348 return QString("%1%2").arg(syncRepository, REPOSITORY_WORK_SUFFIX);
329 349 }
330 350
331 351 QString CatalogueController::CatalogueControllerPrivate::toSyncRepository(QString repository)
332 352 {
333 353 auto syncRepository = repository;
334 354 if (repository.endsWith(REPOSITORY_WORK_SUFFIX)) {
335 355 syncRepository.remove(REPOSITORY_WORK_SUFFIX);
336 356 }
337 357 else if (repository.endsWith(REPOSITORY_TRASH_SUFFIX)) {
338 358 syncRepository.remove(REPOSITORY_TRASH_SUFFIX);
339 359 }
340 360 return syncRepository;
341 361 }
342 362
343 363 void CatalogueController::CatalogueControllerPrivate::savAllDB()
344 364 {
345 365 for (auto repository : m_RepositoryList) {
346 366 auto defaultRepositoryLocation
347 367 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
348 368 m_CatalogueDao.saveDB(defaultRepositoryLocation, repository);
349 369 }
350 370 }
351 371
352 372 void CatalogueController::CatalogueControllerPrivate::saveEvent(std::shared_ptr<DBEvent> event,
353 373 bool persist)
354 374 {
355 375 m_CatalogueDao.copyEvent(*event, toSyncRepository(event->getRepository()), true);
356 376 if (persist) {
357 377 savAllDB();
358 378 }
359 379 }
360 380
361 381 void CatalogueController::CatalogueControllerPrivate::saveCatalogue(
362 382 std::shared_ptr<DBCatalogue> catalogue, bool persist)
363 383 {
364 384 m_CatalogueDao.copyCatalogue(*catalogue, toSyncRepository(catalogue->getRepository()), true);
365 385 if (persist) {
366 386 savAllDB();
367 387 }
368 388 }
@@ -1,456 +1,437
1 1 #include "Catalogue/CatalogueEventsModel.h"
2 2
3 3 #include <Catalogue/CatalogueController.h>
4 4 #include <Common/DateUtils.h>
5 5 #include <Common/MimeTypesDef.h>
6 6 #include <DBEvent.h>
7 7 #include <DBEventProduct.h>
8 8 #include <DBTag.h>
9 9 #include <Data/SqpRange.h>
10 10 #include <SqpApplication.h>
11 11 #include <Time/TimeController.h>
12 12
13 13 #include <list>
14 14 #include <unordered_map>
15 15
16 16 #include <QHash>
17 17 #include <QMimeData>
18 18
19 19 Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
20 20
21 21 const auto EVENT_ITEM_TYPE = 1;
22 22 const auto EVENT_PRODUCT_ITEM_TYPE = 2;
23 23
24 24 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
25 25 QVector<std::shared_ptr<DBEvent> > m_Events;
26 26 std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
27 std::unordered_set<std::shared_ptr<DBEvent> > m_EventsWithChanges;
28 27
29 28 QStringList columnNames()
30 29 {
31 30 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"),
32 31 tr("Tags"), tr("Product"), tr("")};
33 32 }
34 33
35 34 QVariant sortData(int col, const std::shared_ptr<DBEvent> &event) const
36 35 {
37 36 if (col == (int)CatalogueEventsModel::Column::Validation) {
38 return m_EventsWithChanges.find(event) != m_EventsWithChanges.cend() ? true
39 : QVariant();
37 auto hasChanges = sqpApp->catalogueController().eventHasChanges(event);
38 return hasChanges ? true : QVariant();
40 39 }
41 40
42 41 return eventData(col, event);
43 42 }
44 43
45 44 QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
46 45 {
47 46 switch (static_cast<Column>(col)) {
48 47 case CatalogueEventsModel::Column::Name:
49 48 return event->getName();
50 49 case CatalogueEventsModel::Column::TStart:
51 50 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart())
52 51 : QVariant{};
53 52 case CatalogueEventsModel::Column::TEnd:
54 53 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd())
55 54 : QVariant{};
56 55 case CatalogueEventsModel::Column::Product:
57 56 return QString::number(nbEventProducts(event)) + " product(s)";
58 57 case CatalogueEventsModel::Column::Tags: {
59 58 QString tagList;
60 59 auto tags = event->getTags();
61 60 for (auto tag : tags) {
62 61 tagList += tag.getName();
63 62 tagList += ' ';
64 63 }
65 64
66 65 return tagList;
67 66 }
68 67 case CatalogueEventsModel::Column::Validation:
69 68 return QVariant();
70 69 default:
71 70 break;
72 71 }
73 72
74 73 Q_ASSERT(false);
75 74 return QStringLiteral("Unknown Data");
76 75 }
77 76
78 77 void parseEventProduct(const std::shared_ptr<DBEvent> &event)
79 78 {
80 79 for (auto product : event->getEventProducts()) {
81 80 m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
82 81 }
83 82 }
84 83
85 84 int nbEventProducts(const std::shared_ptr<DBEvent> &event) const
86 85 {
87 86 auto eventProductsIt = m_EventProducts.find(event.get());
88 87 if (eventProductsIt != m_EventProducts.cend()) {
89 88 return m_EventProducts.at(event.get()).count();
90 89 }
91 90 else {
92 91 return 0;
93 92 }
94 93 }
95 94
96 95 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
97 96 {
98 97 switch (static_cast<Column>(col)) {
99 98 case CatalogueEventsModel::Column::Name:
100 99 return eventProduct->getProductId();
101 100 case CatalogueEventsModel::Column::TStart:
102 101 return DateUtils::dateTime(eventProduct->getTStart());
103 102 case CatalogueEventsModel::Column::TEnd:
104 103 return DateUtils::dateTime(eventProduct->getTEnd());
105 104 case CatalogueEventsModel::Column::Product:
106 105 return eventProduct->getProductId();
107 106 case CatalogueEventsModel::Column::Tags:
108 107 return QString();
109 108 case CatalogueEventsModel::Column::Validation:
110 109 return QVariant();
111 110 default:
112 111 break;
113 112 }
114 113
115 114 Q_ASSERT(false);
116 115 return QStringLiteral("Unknown Data");
117 116 }
118 117
119 118 void refreshChildrenOfIndex(CatalogueEventsModel *model, const QModelIndex &index) const
120 119 {
121 120 auto childCount = model->rowCount(index);
122 121 auto colCount = model->columnCount();
123 122 emit model->dataChanged(model->index(0, 0, index),
124 123 model->index(childCount, colCount, index));
125 124 }
126 125 };
127 126
128 127 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
129 128 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
130 129 {
131 130 }
132 131
133 132 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
134 133 {
135 134 beginResetModel();
136 135
137 136 impl->m_Events = events;
138 137 impl->m_EventProducts.clear();
139 impl->m_EventsWithChanges.clear();
140 138 for (auto event : events) {
141 139 impl->parseEventProduct(event);
142 140 }
143 141
144 142 endResetModel();
145 143 }
146 144
147 145 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
148 146 {
149 147 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
150 148 return impl->m_Events.value(index.row());
151 149 }
152 150 else {
153 151 return nullptr;
154 152 }
155 153 }
156 154
157 155 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
158 156 {
159 157 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
160 158 return getEvent(index.parent());
161 159 }
162 160 else {
163 161 return nullptr;
164 162 }
165 163 }
166 164
167 165 std::shared_ptr<DBEventProduct>
168 166 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
169 167 {
170 168 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
171 169 auto event = static_cast<DBEvent *>(index.internalPointer());
172 170 return impl->m_EventProducts.at(event).value(index.row());
173 171 }
174 172 else {
175 173 return nullptr;
176 174 }
177 175 }
178 176
179 177 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
180 178 {
181 179 beginInsertRows(QModelIndex(), impl->m_Events.count(), impl->m_Events.count());
182 180 impl->m_Events.append(event);
183 181 impl->parseEventProduct(event);
184 182 endInsertRows();
185 183
186 184 // Also refreshes its children event products
187 185 auto eventIndex = index(impl->m_Events.count(), 0);
188 186 impl->refreshChildrenOfIndex(this, eventIndex);
189 187 }
190 188
191 189 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
192 190 {
193 191 auto index = impl->m_Events.indexOf(event);
194 192 if (index >= 0) {
195 193 beginRemoveRows(QModelIndex(), index, index);
196 194 impl->m_Events.removeAt(index);
197 195 impl->m_EventProducts.erase(event.get());
198 impl->m_EventsWithChanges.erase(event);
199 196 endRemoveRows();
200 197 }
201 198 }
202 199
203 200 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
204 201 {
205 202 return impl->m_Events;
206 203 }
207 204
208 205 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event)
209 206 {
210 207 auto eventIndex = indexOf(event);
211 208 if (eventIndex.isValid()) {
212 209
213 210 // Refreshes the event line
214 211 auto colCount = columnCount();
215 212 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
216 213
217 214 // Also refreshes its children event products
218 215 impl->refreshChildrenOfIndex(this, eventIndex);
219 216 }
220 217 else {
221 218 qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
222 219 }
223 220 }
224 221
225 222 QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
226 223 {
227 224 auto row = impl->m_Events.indexOf(event);
228 225 if (row >= 0) {
229 226 return index(row, 0);
230 227 }
231 228
232 229 return QModelIndex();
233 230 }
234 231
235 void CatalogueEventsModel::setEventHasChanges(const std::shared_ptr<DBEvent> &event,
236 bool hasChanges)
237 {
238 if (hasChanges) {
239 impl->m_EventsWithChanges.insert(event);
240 }
241 else {
242 impl->m_EventsWithChanges.erase(event);
243 }
244 }
245
246 bool CatalogueEventsModel::eventsHasChanges(const std::shared_ptr<DBEvent> &event) const
247 {
248 return impl->m_EventsWithChanges.find(event) != impl->m_EventsWithChanges.cend();
249 }
250
251 232 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
252 233 {
253 234 if (!hasIndex(row, column, parent)) {
254 235 return QModelIndex();
255 236 }
256 237
257 238 switch (itemTypeOf(parent)) {
258 239 case CatalogueEventsModel::ItemType::Root:
259 240 return createIndex(row, column);
260 241 case CatalogueEventsModel::ItemType::Event: {
261 242 auto event = getEvent(parent);
262 243 return createIndex(row, column, event.get());
263 244 }
264 245 case CatalogueEventsModel::ItemType::EventProduct:
265 246 break;
266 247 default:
267 248 break;
268 249 }
269 250
270 251 return QModelIndex();
271 252 }
272 253
273 254 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
274 255 {
275 256 switch (itemTypeOf(index)) {
276 257 case CatalogueEventsModel::ItemType::EventProduct: {
277 258 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
278 259 auto it
279 260 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
280 261 [parentEvent](auto event) { return event.get() == parentEvent; });
281 262
282 263 if (it != impl->m_Events.cend()) {
283 264 return createIndex(it - impl->m_Events.cbegin(), 0);
284 265 }
285 266 else {
286 267 return QModelIndex();
287 268 }
288 269 }
289 270 case CatalogueEventsModel::ItemType::Root:
290 271 break;
291 272 case CatalogueEventsModel::ItemType::Event:
292 273 break;
293 274 default:
294 275 break;
295 276 }
296 277
297 278 return QModelIndex();
298 279 }
299 280
300 281 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
301 282 {
302 283 if (parent.column() > 0) {
303 284 return 0;
304 285 }
305 286
306 287 switch (itemTypeOf(parent)) {
307 288 case CatalogueEventsModel::ItemType::Root:
308 289 return impl->m_Events.count();
309 290 case CatalogueEventsModel::ItemType::Event: {
310 291 auto event = getEvent(parent);
311 292 return impl->m_EventProducts[event.get()].count();
312 293 }
313 294 case CatalogueEventsModel::ItemType::EventProduct:
314 295 break;
315 296 default:
316 297 break;
317 298 }
318 299
319 300 return 0;
320 301 }
321 302
322 303 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
323 304 {
324 305 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
325 306 }
326 307
327 308 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
328 309 {
329 310 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
330 311 }
331 312
332 313 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
333 314 {
334 315 if (index.isValid()) {
335 316
336 317 auto type = itemTypeOf(index);
337 318 if (type == CatalogueEventsModel::ItemType::Event) {
338 319 auto event = getEvent(index);
339 320 switch (role) {
340 321 case Qt::DisplayRole:
341 322 return impl->eventData(index.column(), event);
342 323 break;
343 324 }
344 325 }
345 326 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
346 327 auto product = getEventProduct(index);
347 328 switch (role) {
348 329 case Qt::DisplayRole:
349 330 return impl->eventProductData(index.column(), product);
350 331 break;
351 332 }
352 333 }
353 334 }
354 335
355 336 return QVariant{};
356 337 }
357 338
358 339 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
359 340 {
360 341 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
361 342 return impl->columnNames().value(section);
362 343 }
363 344
364 345 return QVariant();
365 346 }
366 347
367 348 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
368 349 {
369 350 beginResetModel();
370 351 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
371 352 [this, column, order](auto e1, auto e2) {
372 353 auto data1 = impl->sortData(column, e1);
373 354 auto data2 = impl->sortData(column, e2);
374 355
375 356 auto result = data1.toString() < data2.toString();
376 357
377 358 return order == Qt::AscendingOrder ? result : !result;
378 359 });
379 360
380 361 endResetModel();
381 362 emit modelSorted();
382 363 }
383 364
384 365 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
385 366 {
386 367 return Qt::CopyAction;
387 368 }
388 369
389 370 QStringList CatalogueEventsModel::mimeTypes() const
390 371 {
391 372 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_TIME_RANGE};
392 373 }
393 374
394 375 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
395 376 {
396 377 auto mimeData = new QMimeData;
397 378
398 379 bool isFirst = true;
399 380
400 381 QVector<std::shared_ptr<DBEvent> > eventList;
401 382 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
402 383
403 384 SqpRange firstTimeRange;
404 385 for (const auto &index : indexes) {
405 386 if (index.column() == 0) { // only the first column
406 387
407 388 auto type = itemTypeOf(index);
408 389 if (type == ItemType::Event) {
409 390 auto event = getEvent(index);
410 391 eventList << event;
411 392
412 393 if (isFirst) {
413 394 isFirst = false;
414 395 firstTimeRange.m_TStart = event->getTStart();
415 396 firstTimeRange.m_TEnd = event->getTEnd();
416 397 }
417 398 }
418 399 else if (type == ItemType::EventProduct) {
419 400 auto product = getEventProduct(index);
420 401 eventProductList << product;
421 402
422 403 if (isFirst) {
423 404 isFirst = false;
424 405 firstTimeRange.m_TStart = product->getTStart();
425 406 firstTimeRange.m_TEnd = product->getTEnd();
426 407 }
427 408 }
428 409 }
429 410 }
430 411
431 412 if (!eventList.isEmpty() && eventProductList.isEmpty()) {
432 413 auto eventsEncodedData = sqpApp->catalogueController().mimeDataForEvents(eventList);
433 414 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
434 415 }
435 416
436 417 if (eventList.count() + eventProductList.count() == 1) {
437 418 // No time range MIME data if multiple events are dragged
438 419 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
439 420 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
440 421 }
441 422
442 423 return mimeData;
443 424 }
444 425
445 426 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
446 427 {
447 428 if (!index.isValid()) {
448 429 return ItemType::Root;
449 430 }
450 431 else if (index.internalPointer() == nullptr) {
451 432 return ItemType::Event;
452 433 }
453 434 else {
454 435 return ItemType::EventProduct;
455 436 }
456 437 }
@@ -1,409 +1,418
1 1 #include "Catalogue/CatalogueEventsWidget.h"
2 2 #include "ui_CatalogueEventsWidget.h"
3 3
4 4 #include <Catalogue/CatalogueController.h>
5 5 #include <Catalogue/CatalogueEventsModel.h>
6 6 #include <Catalogue/CatalogueExplorerHelper.h>
7 7 #include <CatalogueDao.h>
8 8 #include <DBCatalogue.h>
9 9 #include <SqpApplication.h>
10 10 #include <Visualization/VisualizationTabWidget.h>
11 11 #include <Visualization/VisualizationWidget.h>
12 12 #include <Visualization/VisualizationZoneWidget.h>
13 13
14 14 #include <QDialog>
15 15 #include <QDialogButtonBox>
16 16 #include <QListWidget>
17 17
18 18 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
19 19
20 20 /// Fixed size of the validation column
21 21 const auto VALIDATION_COLUMN_SIZE = 35;
22 22
23 23 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
24 24
25 25 CatalogueEventsModel *m_Model = nullptr;
26 26 QStringList m_ZonesForTimeMode;
27 27 QString m_ZoneForGraphMode;
28 28 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
29 29
30 30 VisualizationWidget *m_VisualizationWidget = nullptr;
31 31
32 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, QTreeView *treeView)
32 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget)
33 33 {
34 treeView->setSortingEnabled(false);
34 widget->ui->treeView->setSortingEnabled(false);
35 35 m_Model->setEvents(events);
36 treeView->setSortingEnabled(true);
36 widget->ui->treeView->setSortingEnabled(true);
37
38 for (auto event : events) {
39 if (sqpApp->catalogueController().eventHasChanges(event)) {
40 auto index = m_Model->indexOf(event);
41 widget->setEventChanges(event, true);
42 }
43 }
37 44 }
38 45
39 46 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
40 47 {
41 48 treeView->setSortingEnabled(false);
42 49 m_Model->addEvent(event);
43 50 treeView->setSortingEnabled(true);
44 51 }
45 52
46 53 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
47 54 {
48 55 treeView->setSortingEnabled(false);
49 56 m_Model->removeEvent(event);
50 57 treeView->setSortingEnabled(true);
51 58 }
52 59
53 60 QStringList getAvailableVisualizationZoneList() const
54 61 {
55 62 if (m_VisualizationWidget) {
56 63 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
57 64 return tab->availableZoneWidgets();
58 65 }
59 66 }
60 67
61 68 return QStringList{};
62 69 }
63 70
64 71 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
65 72 bool allowMultiSelection, const QPoint &location)
66 73 {
67 74 auto availableZones = getAvailableVisualizationZoneList();
68 75 if (availableZones.isEmpty()) {
69 76 return QStringList{};
70 77 }
71 78
72 79 QDialog d(parent, Qt::Tool);
73 80 d.setWindowTitle("Choose a zone");
74 81 auto layout = new QVBoxLayout{&d};
75 82 layout->setContentsMargins(0, 0, 0, 0);
76 83 auto listWidget = new QListWidget{&d};
77 84 layout->addWidget(listWidget);
78 85
79 86 QSet<QListWidgetItem *> checkedItems;
80 87 for (auto zone : availableZones) {
81 88 auto item = new QListWidgetItem{zone};
82 89 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
83 90 if (selectedZones.contains(zone)) {
84 91 item->setCheckState(Qt::Checked);
85 92 checkedItems << item;
86 93 }
87 94 else {
88 95 item->setCheckState(Qt::Unchecked);
89 96 }
90 97
91 98 listWidget->addItem(item);
92 99 }
93 100
94 101 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
95 102 layout->addWidget(buttonBox);
96 103
97 104 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
98 105 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
99 106
100 107 QObject::connect(listWidget, &QListWidget::itemChanged,
101 108 [&checkedItems, allowMultiSelection, listWidget](auto item) {
102 109 if (item->checkState() == Qt::Checked) {
103 110 if (!allowMultiSelection) {
104 111 for (auto checkedItem : checkedItems) {
105 112 listWidget->blockSignals(true);
106 113 checkedItem->setCheckState(Qt::Unchecked);
107 114 listWidget->blockSignals(false);
108 115 }
109 116
110 117 checkedItems.clear();
111 118 }
112 119 checkedItems << item;
113 120 }
114 121 else {
115 122 checkedItems.remove(item);
116 123 }
117 124 });
118 125
119 126 QStringList result;
120 127
121 128 d.setMinimumWidth(120);
122 129 d.resize(d.minimumSizeHint());
123 130 d.move(location);
124 131 if (d.exec() == QDialog::Accepted) {
125 132 for (auto item : checkedItems) {
126 133 result += item->text();
127 134 }
128 135 }
129 136 else {
130 137 result = selectedZones;
131 138 }
132 139
133 140 return result;
134 141 }
135 142
136 143 void updateForTimeMode(QTreeView *treeView)
137 144 {
138 145 auto selectedRows = treeView->selectionModel()->selectedRows();
139 146
140 147 if (selectedRows.count() == 1) {
141 148 auto event = m_Model->getEvent(selectedRows.first());
142 149 if (event) {
143 150 if (m_VisualizationWidget) {
144 151 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
145 152
146 153 for (auto zoneName : m_ZonesForTimeMode) {
147 154 if (auto zone = tab->getZoneWithName(zoneName)) {
148 155 SqpRange eventRange;
149 156 eventRange.m_TStart = event->getTStart();
150 157 eventRange.m_TEnd = event->getTEnd();
151 158 zone->setZoneRange(eventRange);
152 159 }
153 160 }
154 161 }
155 162 else {
156 163 qCWarning(LOG_CatalogueEventsWidget())
157 164 << "updateTimeZone: no tab found in the visualization";
158 165 }
159 166 }
160 167 else {
161 168 qCWarning(LOG_CatalogueEventsWidget())
162 169 << "updateTimeZone: visualization widget not found";
163 170 }
164 171 }
165 172 }
166 173 else {
167 174 qCWarning(LOG_CatalogueEventsWidget())
168 175 << "updateTimeZone: not compatible with multiple events selected";
169 176 }
170 177 }
171 178
172 179 void updateForGraphMode(QTreeView *treeView)
173 180 {
174 181 auto selectedRows = treeView->selectionModel()->selectedRows();
175 182
176 183 if (selectedRows.count() == 1) {
177 184 auto event = m_Model->getEvent(selectedRows.first());
178 185 if (m_VisualizationWidget) {
179 186 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
180 187 if (auto zone = tab->getZoneWithName(m_ZoneForGraphMode)) {
181 188 // TODO
182 189 }
183 190 }
184 191 else {
185 192 qCWarning(LOG_CatalogueEventsWidget())
186 193 << "updateGraphMode: no tab found in the visualization";
187 194 }
188 195 }
189 196 else {
190 197 qCWarning(LOG_CatalogueEventsWidget())
191 198 << "updateGraphMode: visualization widget not found";
192 199 }
193 200 }
194 201 else {
195 202 qCWarning(LOG_CatalogueEventsWidget())
196 203 << "updateGraphMode: not compatible with multiple events selected";
197 204 }
198 205 }
199 206 };
200 207
201 208 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
202 209 : QWidget(parent),
203 210 ui(new Ui::CatalogueEventsWidget),
204 211 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
205 212 {
206 213 ui->setupUi(this);
207 214
208 215 impl->m_Model = new CatalogueEventsModel{this};
209 216 ui->treeView->setModel(impl->m_Model);
210 217
211 218 ui->treeView->setSortingEnabled(true);
212 219 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
213 220 ui->treeView->setDragEnabled(true);
214 221
215 222 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
216 223 if (checked) {
217 224 ui->btnChart->setChecked(false);
218 225 impl->m_ZonesForTimeMode
219 226 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
220 227 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
221 228
222 229 impl->updateForTimeMode(ui->treeView);
223 230 }
224 231 });
225 232
226 233 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
227 234 if (checked) {
228 235 ui->btnTime->setChecked(false);
229 236 impl->m_ZoneForGraphMode
230 237 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
231 238 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
232 239 .value(0);
233 240
234 241 impl->updateForGraphMode(ui->treeView);
235 242 }
236 243 });
237 244
238 245 auto emitSelection = [this]() {
239 246 QVector<std::shared_ptr<DBEvent> > events;
240 247 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
241 248
242 249 for (auto rowIndex : ui->treeView->selectionModel()->selectedRows()) {
243 250
244 251 auto itemType = impl->m_Model->itemTypeOf(rowIndex);
245 252 if (itemType == CatalogueEventsModel::ItemType::Event) {
246 253 events << impl->m_Model->getEvent(rowIndex);
247 254 }
248 255 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
249 256 eventProducts << qMakePair(impl->m_Model->getParentEvent(rowIndex),
250 257 impl->m_Model->getEventProduct(rowIndex));
251 258 }
252 259 }
253 260
254 261 if (!events.isEmpty() && eventProducts.isEmpty()) {
255 262 emit this->eventsSelected(events);
256 263 }
257 264 else if (events.isEmpty() && !eventProducts.isEmpty()) {
258 265 emit this->eventProductsSelected(eventProducts);
259 266 }
260 267 else {
261 268 emit this->selectionCleared();
262 269 }
263 270 };
264 271
265 272 connect(ui->treeView, &QTreeView::clicked, emitSelection);
266 273 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, emitSelection);
267 274
268 275 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
269 276 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
270 277 ui->btnChart->setEnabled(isNotMultiSelection);
271 278 ui->btnTime->setEnabled(isNotMultiSelection);
272 279
273 280 if (isNotMultiSelection && ui->btnTime->isChecked()) {
274 281 impl->updateForTimeMode(ui->treeView);
275 282 }
276 283 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
277 284 impl->updateForGraphMode(ui->treeView);
278 285 }
279 286 });
280 287
281 288 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
282 289 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
283 290 QHeaderView::Stretch);
284 291 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
285 292 QHeaderView::Fixed);
286 293 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
287 294 VALIDATION_COLUMN_SIZE);
288 295 ui->treeView->header()->setSortIndicatorShown(true);
289 296
290 297 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
291 298 auto allEvents = impl->m_Model->events();
292 299 for (auto event : allEvents) {
293 setEventChanges(event, impl->m_Model->eventsHasChanges(event));
300 setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event));
294 301 }
295 302 });
296 303
297 304 populateWithAllEvents();
298 305 }
299 306
300 307 CatalogueEventsWidget::~CatalogueEventsWidget()
301 308 {
302 309 delete ui;
303 310 }
304 311
305 312 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
306 313 {
307 314 impl->m_VisualizationWidget = visualization;
308 315 }
309 316
310 317 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
311 318 {
312 319 impl->addEvent(event, ui->treeView);
313 320 }
314 321
315 322 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
316 323 {
317 324 impl->m_Model->refreshEvent(event);
318 325
319 326 auto eventIndex = impl->m_Model->indexOf(event);
320 327 auto validationIndex
321 328 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
322 329
323 330 if (validationIndex.isValid()) {
324 331 if (hasChanges) {
325 332 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
326 333 auto widget = CatalogueExplorerHelper::buildValidationWidget(
327 334 ui->treeView,
328 335 [this, event]() {
329 336 sqpApp->catalogueController().saveEvent(event);
330 337 setEventChanges(event, false);
331 338 },
332 339 [this, event]() { setEventChanges(event, false); });
333 340 ui->treeView->setIndexWidget(validationIndex, widget);
334 341 }
335
336 impl->m_Model->setEventHasChanges(event, hasChanges);
342 }
343 else {
344 // Note: the widget is destroyed
345 ui->treeView->setIndexWidget(validationIndex, nullptr);
337 346 }
338 347 }
339 348 else {
340 349 qCWarning(LOG_CatalogueEventsWidget())
341 350 << "setEventChanges: the event is not displayed in the model.";
342 351 }
343 352 }
344 353
345 354 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
346 355 {
347 356 return impl->m_DisplayedCatalogues;
348 357 }
349 358
350 359 bool CatalogueEventsWidget::isAllEventsDisplayed() const
351 360 {
352 361 return impl->m_DisplayedCatalogues.isEmpty() && !impl->m_Model->events().isEmpty();
353 362 }
354 363
355 364 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
356 365 {
357 366 return impl->m_Model->indexOf(event).isValid();
358 367 }
359 368
360 369 void CatalogueEventsWidget::populateWithCatalogues(
361 370 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
362 371 {
363 372 impl->m_DisplayedCatalogues = catalogues;
364 373
365 374 QSet<QUuid> eventIds;
366 375 QVector<std::shared_ptr<DBEvent> > events;
367 376
368 377 for (auto catalogue : catalogues) {
369 378 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
370 379 for (auto event : catalogueEvents) {
371 380 if (!eventIds.contains(event->getUniqId())) {
372 381 events << event;
373 382 eventIds.insert(event->getUniqId());
374 383 }
375 384 }
376 385 }
377 386
378 impl->setEvents(events, ui->treeView);
387 impl->setEvents(events, this);
379 388 }
380 389
381 390 void CatalogueEventsWidget::populateWithAllEvents()
382 391 {
383 392 impl->m_DisplayedCatalogues.clear();
384 393
385 394 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
386 395
387 396 QVector<std::shared_ptr<DBEvent> > events;
388 397 for (auto event : allEvents) {
389 398 events << event;
390 399 }
391 400
392 impl->setEvents(events, ui->treeView);
401 impl->setEvents(events, this);
393 402 }
394 403
395 404 void CatalogueEventsWidget::clear()
396 405 {
397 406 impl->m_DisplayedCatalogues.clear();
398 impl->setEvents({}, ui->treeView);
407 impl->setEvents({}, this);
399 408 }
400 409
401 410 void CatalogueEventsWidget::refresh()
402 411 {
403 412 if (impl->m_DisplayedCatalogues.isEmpty()) {
404 413 populateWithAllEvents();
405 414 }
406 415 else {
407 416 populateWithCatalogues(impl->m_DisplayedCatalogues);
408 417 }
409 418 }
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

Status change > Approved

You need to be logged in to leave comments. Login now