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