##// END OF EJS Templates
Merge branch 'feature/FixCatalogue' into develop
perrinel -
r1373:989011859ba2 merge
parent child
Show More
@@ -1,19 +1,23
1 #ifndef SCIQLOP_DATEUTILS_H
1 #ifndef SCIQLOP_DATEUTILS_H
2 #define SCIQLOP_DATEUTILS_H
2 #define SCIQLOP_DATEUTILS_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <QDateTime>
6 #include <QDateTime>
7
7
8 /// Format for datetimes
9 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
10 const auto DATETIME_FORMAT_ONE_LINE = QStringLiteral("dd/MM/yyyy hh:mm:ss:zzz");
11
8 /**
12 /**
9 * Utility class with methods for dates
13 * Utility class with methods for dates
10 */
14 */
11 struct SCIQLOP_CORE_EXPORT DateUtils {
15 struct SCIQLOP_CORE_EXPORT DateUtils {
12 /// Converts seconds (since epoch) to datetime. By default, the datetime is in UTC
16 /// Converts seconds (since epoch) to datetime. By default, the datetime is in UTC
13 static QDateTime dateTime(double secs, Qt::TimeSpec timeSpec = Qt::UTC) noexcept;
17 static QDateTime dateTime(double secs, Qt::TimeSpec timeSpec = Qt::UTC) noexcept;
14
18
15 /// Converts datetime to seconds since epoch
19 /// Converts datetime to seconds since epoch
16 static double secondsSinceEpoch(const QDateTime &dateTime) noexcept;
20 static double secondsSinceEpoch(const QDateTime &dateTime) noexcept;
17 };
21 };
18
22
19 #endif // SCIQLOP_DATEUTILS_H
23 #endif // SCIQLOP_DATEUTILS_H
@@ -1,566 +1,574
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 /**
30 /**
31 * Possible types of an repository
31 * Possible types of an repository
32 */
32 */
33 enum class DBType { SYNC, WORK, TRASH };
33 enum class DBType { SYNC, WORK, TRASH };
34 class CatalogueController::CatalogueControllerPrivate {
34 class CatalogueController::CatalogueControllerPrivate {
35
35
36 public:
36 public:
37 explicit CatalogueControllerPrivate(CatalogueController *parent) : m_Q{parent} {}
37 explicit CatalogueControllerPrivate(CatalogueController *parent) : m_Q{parent} {}
38
38
39 CatalogueDao m_CatalogueDao;
39 CatalogueDao m_CatalogueDao;
40
40
41 QStringList m_RepositoryList;
41 QStringList m_RepositoryList;
42 CatalogueController *m_Q;
42 CatalogueController *m_Q;
43
43
44 QSet<QString> m_KeysWithChanges;
44 QSet<QString> m_KeysWithChanges;
45
45
46 QString eventUniqueKey(const std::shared_ptr<DBEvent> &event) const;
46 QString eventUniqueKey(const std::shared_ptr<DBEvent> &event) const;
47 QString catalogueUniqueKey(const std::shared_ptr<DBCatalogue> &catalogue) const;
47 QString catalogueUniqueKey(const std::shared_ptr<DBCatalogue> &catalogue) const;
48
48
49 void copyDBtoDB(const QString &dbFrom, const QString &dbTo);
49 void copyDBtoDB(const QString &dbFrom, const QString &dbTo);
50 QString toWorkRepository(QString repository);
50 QString toWorkRepository(QString repository);
51 QString toSyncRepository(QString repository);
51 QString toSyncRepository(QString repository);
52 void savAllDB();
52 void savAllDB();
53
53
54 void saveEvent(std::shared_ptr<DBEvent> event, bool persist = true);
54 void saveEvent(std::shared_ptr<DBEvent> event, bool persist = true);
55 void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool persist = true);
55 void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool persist = true);
56
56
57 std::shared_ptr<IRequestPredicate> createFinder(const QUuid &uniqId, const QString &repository,
57 std::shared_ptr<IRequestPredicate> createFinder(const QUuid &uniqId, const QString &repository,
58 DBType type);
58 DBType type);
59 };
59 };
60
60
61 CatalogueController::CatalogueController(QObject *parent)
61 CatalogueController::CatalogueController(QObject *parent)
62 : impl{spimpl::make_unique_impl<CatalogueControllerPrivate>(this)}
62 : impl{spimpl::make_unique_impl<CatalogueControllerPrivate>(this)}
63 {
63 {
64 qCDebug(LOG_CatalogueController()) << tr("CatalogueController construction")
64 qCDebug(LOG_CatalogueController()) << tr("CatalogueController construction")
65 << QThread::currentThread();
65 << QThread::currentThread();
66 }
66 }
67
67
68 CatalogueController::~CatalogueController()
68 CatalogueController::~CatalogueController()
69 {
69 {
70 qCDebug(LOG_CatalogueController()) << tr("CatalogueController destruction")
70 qCDebug(LOG_CatalogueController()) << tr("CatalogueController destruction")
71 << QThread::currentThread();
71 << QThread::currentThread();
72 }
72 }
73
73
74 QStringList CatalogueController::getRepositories() const
74 QStringList CatalogueController::getRepositories() const
75 {
75 {
76 return impl->m_RepositoryList;
76 return impl->m_RepositoryList;
77 }
77 }
78
78
79 void CatalogueController::addDB(const QString &dbPath)
79 void CatalogueController::addDB(const QString &dbPath)
80 {
80 {
81 QDir dbDir(dbPath);
81 QDir dbDir(dbPath);
82 if (dbDir.exists()) {
82 if (dbDir.exists()) {
83 auto dirName = dbDir.dirName();
83 auto dirName = dbDir.dirName();
84
84
85 if (std::find(impl->m_RepositoryList.cbegin(), impl->m_RepositoryList.cend(), dirName)
85 if (std::find(impl->m_RepositoryList.cbegin(), impl->m_RepositoryList.cend(), dirName)
86 != impl->m_RepositoryList.cend()) {
86 != impl->m_RepositoryList.cend()) {
87 qCCritical(LOG_CatalogueController())
87 qCCritical(LOG_CatalogueController())
88 << tr("Impossible to addDB that is already loaded");
88 << tr("Impossible to addDB that is already loaded");
89 }
89 }
90
90
91 if (!impl->m_CatalogueDao.addDB(dbPath, dirName)) {
91 if (!impl->m_CatalogueDao.addDB(dbPath, dirName)) {
92 qCCritical(LOG_CatalogueController())
92 qCCritical(LOG_CatalogueController())
93 << tr("Impossible to addDB %1 from %2 ").arg(dirName, dbPath);
93 << tr("Impossible to addDB %1 from %2 ").arg(dirName, dbPath);
94 }
94 }
95 else {
95 else {
96 impl->m_RepositoryList << dirName;
96 impl->m_RepositoryList << dirName;
97 impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName));
97 impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName));
98 }
98 }
99 }
99 }
100 else {
100 else {
101 qCCritical(LOG_CatalogueController()) << tr("Impossible to addDB that not exists: ")
101 qCCritical(LOG_CatalogueController()) << tr("Impossible to addDB that not exists: ")
102 << dbPath;
102 << dbPath;
103 }
103 }
104 }
104 }
105
105
106 void CatalogueController::saveDB(const QString &destinationPath, const QString &repository)
106 void CatalogueController::saveDB(const QString &destinationPath, const QString &repository)
107 {
107 {
108 if (!impl->m_CatalogueDao.saveDB(destinationPath, repository)) {
108 if (!impl->m_CatalogueDao.saveDB(destinationPath, repository)) {
109 qCCritical(LOG_CatalogueController())
109 qCCritical(LOG_CatalogueController())
110 << tr("Impossible to saveDB %1 from %2 ").arg(repository, destinationPath);
110 << tr("Impossible to saveDB %1 from %2 ").arg(repository, destinationPath);
111 }
111 }
112 }
112 }
113
113
114 std::list<std::shared_ptr<DBEvent> >
114 std::list<std::shared_ptr<DBEvent> >
115 CatalogueController::retrieveEvents(const QString &repository) const
115 CatalogueController::retrieveEvents(const QString &repository) const
116 {
116 {
117 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
117 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
118
118
119 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
119 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
120 auto events = impl->m_CatalogueDao.getEvents(impl->toWorkRepository(dbDireName));
120 auto events = impl->m_CatalogueDao.getEvents(impl->toWorkRepository(dbDireName));
121 for (auto event : events) {
121 for (auto event : events) {
122 eventsShared.push_back(std::make_shared<DBEvent>(event));
122 eventsShared.push_back(std::make_shared<DBEvent>(event));
123 }
123 }
124 return eventsShared;
124 return eventsShared;
125 }
125 }
126
126
127 std::list<std::shared_ptr<DBEvent> > CatalogueController::retrieveAllEvents() const
127 std::list<std::shared_ptr<DBEvent> > CatalogueController::retrieveAllEvents() const
128 {
128 {
129 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
129 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
130 for (auto repository : impl->m_RepositoryList) {
130 for (auto repository : impl->m_RepositoryList) {
131 eventsShared.splice(eventsShared.end(), retrieveEvents(repository));
131 eventsShared.splice(eventsShared.end(), retrieveEvents(repository));
132 }
132 }
133
133
134 return eventsShared;
134 return eventsShared;
135 }
135 }
136
136
137 std::list<std::shared_ptr<DBEvent> >
137 std::list<std::shared_ptr<DBEvent> >
138 CatalogueController::retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const
138 CatalogueController::retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const
139 {
139 {
140 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
140 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
141 auto events = impl->m_CatalogueDao.getCatalogueEvents(*catalogue);
141 auto events = impl->m_CatalogueDao.getCatalogueEvents(*catalogue);
142 for (auto event : events) {
142 for (auto event : events) {
143 eventsShared.push_back(std::make_shared<DBEvent>(event));
143 eventsShared.push_back(std::make_shared<DBEvent>(event));
144 }
144 }
145 return eventsShared;
145 return eventsShared;
146 }
146 }
147
147
148 void CatalogueController::updateEvent(std::shared_ptr<DBEvent> event)
148 void CatalogueController::updateEvent(std::shared_ptr<DBEvent> event)
149 {
149 {
150 event->setRepository(impl->toWorkRepository(event->getRepository()));
150 event->setRepository(impl->toWorkRepository(event->getRepository()));
151
151
152 auto uniqueId = impl->eventUniqueKey(event);
152 auto uniqueId = impl->eventUniqueKey(event);
153 impl->m_KeysWithChanges.insert(uniqueId);
153 impl->m_KeysWithChanges.insert(uniqueId);
154
154
155 impl->m_CatalogueDao.updateEvent(*event);
155 impl->m_CatalogueDao.updateEvent(*event);
156 }
156 }
157
157
158 void CatalogueController::updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct)
158 void CatalogueController::updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct)
159 {
159 {
160 impl->m_CatalogueDao.updateEventProduct(*eventProduct);
160 impl->m_CatalogueDao.updateEventProduct(*eventProduct);
161 }
161 }
162
162
163 void CatalogueController::removeEvent(std::shared_ptr<DBEvent> event)
163 void CatalogueController::removeEvent(std::shared_ptr<DBEvent> event)
164 {
164 {
165 // Remove it from both repository and repository_work
165 // Remove it from both repository and repository_work
166 event->setRepository(impl->toWorkRepository(event->getRepository()));
166 event->setRepository(impl->toWorkRepository(event->getRepository()));
167 impl->m_CatalogueDao.removeEvent(*event);
167 impl->m_CatalogueDao.removeEvent(*event);
168 event->setRepository(impl->toSyncRepository(event->getRepository()));
168 event->setRepository(impl->toSyncRepository(event->getRepository()));
169 impl->m_CatalogueDao.removeEvent(*event);
169 impl->m_CatalogueDao.removeEvent(*event);
170 impl->savAllDB();
170 impl->savAllDB();
171 }
171 }
172
172
173 void CatalogueController::addEvent(std::shared_ptr<DBEvent> event)
173 void CatalogueController::addEvent(std::shared_ptr<DBEvent> event)
174 {
174 {
175 event->setRepository(impl->toWorkRepository(event->getRepository()));
175 event->setRepository(impl->toWorkRepository(event->getRepository()));
176
176
177 auto eventTemp = *event;
177 auto eventTemp = *event;
178 impl->m_CatalogueDao.addEvent(eventTemp);
178 impl->m_CatalogueDao.addEvent(eventTemp);
179
179
180 // Call update is necessary at the creation of add Event if it has some tags or some event
180 // Call update is necessary at the creation of add Event if it has some tags or some event
181 // products
181 // products
182 if (!event->getEventProducts().empty() || !event->getTags().empty()) {
182 if (!event->getEventProducts().empty() || !event->getTags().empty()) {
183
183
184 auto eventProductsTemp = eventTemp.getEventProducts();
184 auto eventProductsTemp = eventTemp.getEventProducts();
185 auto eventProductTempUpdated = std::list<DBEventProduct>{};
185 auto eventProductTempUpdated = std::list<DBEventProduct>{};
186 for (auto eventProductTemp : eventProductsTemp) {
186 for (auto eventProductTemp : eventProductsTemp) {
187 eventProductTemp.setEvent(eventTemp);
187 eventProductTemp.setEvent(eventTemp);
188 eventProductTempUpdated.push_back(eventProductTemp);
188 eventProductTempUpdated.push_back(eventProductTemp);
189 }
189 }
190 eventTemp.setEventProducts(eventProductTempUpdated);
190 eventTemp.setEventProducts(eventProductTempUpdated);
191
191
192 impl->m_CatalogueDao.updateEvent(eventTemp);
192 impl->m_CatalogueDao.updateEvent(eventTemp);
193 }
193 }
194
194
195 auto workPred = impl->createFinder(event->getUniqId(), event->getRepository(), DBType::WORK);
195 auto workPred = impl->createFinder(event->getUniqId(), event->getRepository(), DBType::WORK);
196
196
197 auto workEvent = impl->m_CatalogueDao.getEvent(workPred);
197 auto workEvent = impl->m_CatalogueDao.getEvent(workPred);
198 *event = workEvent;
198 *event = workEvent;
199
199
200
200
201 auto uniqueId = impl->eventUniqueKey(event);
201 auto uniqueId = impl->eventUniqueKey(event);
202 impl->m_KeysWithChanges.insert(uniqueId);
202 impl->m_KeysWithChanges.insert(uniqueId);
203 }
203 }
204
204
205 void CatalogueController::saveEvent(std::shared_ptr<DBEvent> event)
205 void CatalogueController::saveEvent(std::shared_ptr<DBEvent> event)
206 {
206 {
207 impl->saveEvent(event, true);
207 impl->saveEvent(event, true);
208 impl->m_KeysWithChanges.remove(impl->eventUniqueKey(event));
208 impl->m_KeysWithChanges.remove(impl->eventUniqueKey(event));
209 }
209 }
210
210
211 void CatalogueController::discardEvent(std::shared_ptr<DBEvent> event, bool &removed)
211 void CatalogueController::discardEvent(std::shared_ptr<DBEvent> event, bool &removed)
212 {
212 {
213 auto syncPred = impl->createFinder(event->getUniqId(), event->getRepository(), DBType::SYNC);
213 auto syncPred = impl->createFinder(event->getUniqId(), event->getRepository(), DBType::SYNC);
214 auto workPred = impl->createFinder(event->getUniqId(), event->getRepository(), DBType::WORK);
214 auto workPred = impl->createFinder(event->getUniqId(), event->getRepository(), DBType::WORK);
215
215
216 auto syncEvent = impl->m_CatalogueDao.getEvent(syncPred);
216 auto syncEvent = impl->m_CatalogueDao.getEvent(syncPred);
217 if (!syncEvent.getUniqId().isNull()) {
217 if (!syncEvent.getUniqId().isNull()) {
218 removed = false;
218 removed = false;
219 impl->m_CatalogueDao.copyEvent(syncEvent, impl->toWorkRepository(event->getRepository()),
219 impl->m_CatalogueDao.copyEvent(syncEvent, impl->toWorkRepository(event->getRepository()),
220 true);
220 true);
221
221
222 auto workEvent = impl->m_CatalogueDao.getEvent(workPred);
222 auto workEvent = impl->m_CatalogueDao.getEvent(workPred);
223 *event = workEvent;
223 *event = workEvent;
224 impl->m_KeysWithChanges.remove(impl->eventUniqueKey(event));
224 impl->m_KeysWithChanges.remove(impl->eventUniqueKey(event));
225 }
225 }
226 else {
226 else {
227 removed = true;
227 removed = true;
228 // Since the element wasn't in sync repository. Discard it means remove it
228 // Since the element wasn't in sync repository. Discard it means remove it
229 event->setRepository(impl->toWorkRepository(event->getRepository()));
229 event->setRepository(impl->toWorkRepository(event->getRepository()));
230 impl->m_CatalogueDao.removeEvent(*event);
230 impl->m_CatalogueDao.removeEvent(*event);
231 }
231 }
232 }
232 }
233
233
234 bool CatalogueController::eventHasChanges(std::shared_ptr<DBEvent> event) const
234 bool CatalogueController::eventHasChanges(std::shared_ptr<DBEvent> event) const
235 {
235 {
236 return impl->m_KeysWithChanges.contains(impl->eventUniqueKey(event));
236 return impl->m_KeysWithChanges.contains(impl->eventUniqueKey(event));
237 }
237 }
238
238
239 std::list<std::shared_ptr<DBCatalogue> >
239 std::list<std::shared_ptr<DBCatalogue> >
240 CatalogueController::retrieveCatalogues(const QString &repository) const
240 CatalogueController::retrieveCatalogues(const QString &repository) const
241 {
241 {
242 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
242 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
243
243
244 auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
244 auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
245 auto catalogues = impl->m_CatalogueDao.getCatalogues(impl->toWorkRepository(dbDireName));
245 auto catalogues = impl->m_CatalogueDao.getCatalogues(impl->toWorkRepository(dbDireName));
246 for (auto catalogue : catalogues) {
246 for (auto catalogue : catalogues) {
247 cataloguesShared.push_back(std::make_shared<DBCatalogue>(catalogue));
247 cataloguesShared.push_back(std::make_shared<DBCatalogue>(catalogue));
248 }
248 }
249 return cataloguesShared;
249 return cataloguesShared;
250 }
250 }
251
251
252 void CatalogueController::addCatalogue(std::shared_ptr<DBCatalogue> catalogue)
252 void CatalogueController::addCatalogue(std::shared_ptr<DBCatalogue> catalogue)
253 {
253 {
254 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
254 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
255
255
256 auto catalogueTemp = *catalogue;
256 auto catalogueTemp = *catalogue;
257 impl->m_CatalogueDao.addCatalogue(catalogueTemp);
257 impl->m_CatalogueDao.addCatalogue(catalogueTemp);
258
258
259 auto workPred
259 auto workPred
260 = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::WORK);
260 = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::WORK);
261
261
262 auto workCatalogue = impl->m_CatalogueDao.getCatalogue(workPred);
262 auto workCatalogue = impl->m_CatalogueDao.getCatalogue(workPred);
263 *catalogue = workCatalogue;
263 *catalogue = workCatalogue;
264
264
265 auto uniqueId = impl->catalogueUniqueKey(catalogue);
265 auto uniqueId = impl->catalogueUniqueKey(catalogue);
266 impl->m_KeysWithChanges.insert(uniqueId);
266 impl->m_KeysWithChanges.insert(uniqueId);
267 }
267 }
268
268
269 void CatalogueController::updateCatalogue(std::shared_ptr<DBCatalogue> catalogue)
269 void CatalogueController::updateCatalogue(std::shared_ptr<DBCatalogue> catalogue)
270 {
270 {
271 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
271 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
272
272
273 auto uniqueId = impl->catalogueUniqueKey(catalogue);
273 auto uniqueId = impl->catalogueUniqueKey(catalogue);
274 impl->m_KeysWithChanges.insert(uniqueId);
274 impl->m_KeysWithChanges.insert(uniqueId);
275
275
276 impl->m_CatalogueDao.updateCatalogue(*catalogue);
276 impl->m_CatalogueDao.updateCatalogue(*catalogue);
277 }
277 }
278
278
279 void CatalogueController::removeCatalogue(std::shared_ptr<DBCatalogue> catalogue)
279 void CatalogueController::removeCatalogue(std::shared_ptr<DBCatalogue> catalogue)
280 {
280 {
281 // Remove it from both repository and repository_work
281 // Remove it from both repository and repository_work
282 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
282 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
283 impl->m_CatalogueDao.removeCatalogue(*catalogue);
283 impl->m_CatalogueDao.removeCatalogue(*catalogue);
284 catalogue->setRepository(impl->toSyncRepository(catalogue->getRepository()));
284 catalogue->setRepository(impl->toSyncRepository(catalogue->getRepository()));
285 impl->m_CatalogueDao.removeCatalogue(*catalogue);
285 impl->m_CatalogueDao.removeCatalogue(*catalogue);
286 impl->savAllDB();
286 impl->savAllDB();
287 }
287 }
288
288
289 void CatalogueController::saveCatalogue(std::shared_ptr<DBCatalogue> catalogue)
289 void CatalogueController::saveCatalogue(std::shared_ptr<DBCatalogue> catalogue)
290 {
290 {
291 impl->saveCatalogue(catalogue, true);
291 impl->saveCatalogue(catalogue, true);
292 impl->m_KeysWithChanges.remove(impl->catalogueUniqueKey(catalogue));
292 impl->m_KeysWithChanges.remove(impl->catalogueUniqueKey(catalogue));
293
294 // remove key of events of the catalogue
295 if (catalogue->getType() == CatalogueType::STATIC) {
296 auto events = this->retrieveEventsFromCatalogue(catalogue);
297 for (auto event : events) {
298 impl->m_KeysWithChanges.remove(impl->eventUniqueKey(event));
299 }
300 }
293 }
301 }
294
302
295 void CatalogueController::discardCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool &removed)
303 void CatalogueController::discardCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool &removed)
296 {
304 {
297 auto syncPred
305 auto syncPred
298 = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::SYNC);
306 = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::SYNC);
299 auto workPred
307 auto workPred
300 = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::WORK);
308 = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::WORK);
301
309
302 auto syncCatalogue = impl->m_CatalogueDao.getCatalogue(syncPred);
310 auto syncCatalogue = impl->m_CatalogueDao.getCatalogue(syncPred);
303 if (!syncCatalogue.getUniqId().isNull()) {
311 if (!syncCatalogue.getUniqId().isNull()) {
304 removed = false;
312 removed = false;
305 impl->m_CatalogueDao.copyCatalogue(
313 impl->m_CatalogueDao.copyCatalogue(
306 syncCatalogue, impl->toWorkRepository(catalogue->getRepository()), true);
314 syncCatalogue, impl->toWorkRepository(catalogue->getRepository()), true);
307
315
308 auto workCatalogue = impl->m_CatalogueDao.getCatalogue(workPred);
316 auto workCatalogue = impl->m_CatalogueDao.getCatalogue(workPred);
309 *catalogue = workCatalogue;
317 *catalogue = workCatalogue;
310 impl->m_KeysWithChanges.remove(impl->catalogueUniqueKey(catalogue));
318 impl->m_KeysWithChanges.remove(impl->catalogueUniqueKey(catalogue));
311 }
319 }
312 else {
320 else {
313 removed = true;
321 removed = true;
314 // Since the element wasn't in sync repository. Discard it means remove it
322 // Since the element wasn't in sync repository. Discard it means remove it
315 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
323 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
316 impl->m_CatalogueDao.removeCatalogue(*catalogue);
324 impl->m_CatalogueDao.removeCatalogue(*catalogue);
317 }
325 }
318 }
326 }
319
327
320 void CatalogueController::saveAll()
328 void CatalogueController::saveAll()
321 {
329 {
322 for (auto repository : impl->m_RepositoryList) {
330 for (auto repository : impl->m_RepositoryList) {
323 // Save Event
331 // Save Event
324 auto events = this->retrieveEvents(repository);
332 auto events = this->retrieveEvents(repository);
325 for (auto event : events) {
333 for (auto event : events) {
326 impl->saveEvent(event, false);
334 impl->saveEvent(event, false);
327 }
335 }
328
336
329 // Save Catalogue
337 // Save Catalogue
330 auto catalogues = this->retrieveCatalogues(repository);
338 auto catalogues = this->retrieveCatalogues(repository);
331 for (auto catalogue : catalogues) {
339 for (auto catalogue : catalogues) {
332 impl->saveCatalogue(catalogue, false);
340 impl->saveCatalogue(catalogue, false);
333 }
341 }
334 }
342 }
335
343
336 impl->savAllDB();
344 impl->savAllDB();
337 impl->m_KeysWithChanges.clear();
345 impl->m_KeysWithChanges.clear();
338 }
346 }
339
347
340 bool CatalogueController::hasChanges() const
348 bool CatalogueController::hasChanges() const
341 {
349 {
342 return !impl->m_KeysWithChanges.isEmpty();
350 return !impl->m_KeysWithChanges.isEmpty();
343 }
351 }
344
352
345 QByteArray
353 QByteArray
346 CatalogueController::mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const
354 CatalogueController::mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const
347 {
355 {
348 auto encodedData = QByteArray{};
356 auto encodedData = QByteArray{};
349
357
350 QMap<QString, QVariantList> idsPerRepository;
358 QMap<QString, QVariantList> idsPerRepository;
351 for (auto event : events) {
359 for (auto event : events) {
352 idsPerRepository[event->getRepository()] << event->getUniqId();
360 idsPerRepository[event->getRepository()] << event->getUniqId();
353 }
361 }
354
362
355 QDataStream stream{&encodedData, QIODevice::WriteOnly};
363 QDataStream stream{&encodedData, QIODevice::WriteOnly};
356 stream << idsPerRepository;
364 stream << idsPerRepository;
357
365
358 return encodedData;
366 return encodedData;
359 }
367 }
360
368
361 QVector<std::shared_ptr<DBEvent> >
369 QVector<std::shared_ptr<DBEvent> >
362 CatalogueController::eventsForMimeData(const QByteArray &mimeData) const
370 CatalogueController::eventsForMimeData(const QByteArray &mimeData) const
363 {
371 {
364 auto events = QVector<std::shared_ptr<DBEvent> >{};
372 auto events = QVector<std::shared_ptr<DBEvent> >{};
365 QDataStream stream{mimeData};
373 QDataStream stream{mimeData};
366
374
367 QMap<QString, QVariantList> idsPerRepository;
375 QMap<QString, QVariantList> idsPerRepository;
368 stream >> idsPerRepository;
376 stream >> idsPerRepository;
369
377
370 for (auto it = idsPerRepository.cbegin(); it != idsPerRepository.cend(); ++it) {
378 for (auto it = idsPerRepository.cbegin(); it != idsPerRepository.cend(); ++it) {
371 auto repository = it.key();
379 auto repository = it.key();
372 auto allRepositoryEvent = retrieveEvents(repository);
380 auto allRepositoryEvent = retrieveEvents(repository);
373 for (auto uuid : it.value()) {
381 for (auto uuid : it.value()) {
374 for (auto repositoryEvent : allRepositoryEvent) {
382 for (auto repositoryEvent : allRepositoryEvent) {
375 if (uuid.toUuid() == repositoryEvent->getUniqId()) {
383 if (uuid.toUuid() == repositoryEvent->getUniqId()) {
376 events << repositoryEvent;
384 events << repositoryEvent;
377 }
385 }
378 }
386 }
379 }
387 }
380 }
388 }
381
389
382 return events;
390 return events;
383 }
391 }
384
392
385 QByteArray CatalogueController::mimeDataForCatalogues(
393 QByteArray CatalogueController::mimeDataForCatalogues(
386 const QVector<std::shared_ptr<DBCatalogue> > &catalogues) const
394 const QVector<std::shared_ptr<DBCatalogue> > &catalogues) const
387 {
395 {
388 auto encodedData = QByteArray{};
396 auto encodedData = QByteArray{};
389
397
390 QMap<QString, QVariantList> idsPerRepository;
398 QMap<QString, QVariantList> idsPerRepository;
391 for (auto catalogue : catalogues) {
399 for (auto catalogue : catalogues) {
392 idsPerRepository[catalogue->getRepository()] << catalogue->getUniqId();
400 idsPerRepository[catalogue->getRepository()] << catalogue->getUniqId();
393 }
401 }
394
402
395 QDataStream stream{&encodedData, QIODevice::WriteOnly};
403 QDataStream stream{&encodedData, QIODevice::WriteOnly};
396 stream << idsPerRepository;
404 stream << idsPerRepository;
397
405
398 return encodedData;
406 return encodedData;
399 }
407 }
400
408
401 QVector<std::shared_ptr<DBCatalogue> >
409 QVector<std::shared_ptr<DBCatalogue> >
402 CatalogueController::cataloguesForMimeData(const QByteArray &mimeData) const
410 CatalogueController::cataloguesForMimeData(const QByteArray &mimeData) const
403 {
411 {
404 auto catalogues = QVector<std::shared_ptr<DBCatalogue> >{};
412 auto catalogues = QVector<std::shared_ptr<DBCatalogue> >{};
405 QDataStream stream{mimeData};
413 QDataStream stream{mimeData};
406
414
407 QMap<QString, QVariantList> idsPerRepository;
415 QMap<QString, QVariantList> idsPerRepository;
408 stream >> idsPerRepository;
416 stream >> idsPerRepository;
409
417
410 for (auto it = idsPerRepository.cbegin(); it != idsPerRepository.cend(); ++it) {
418 for (auto it = idsPerRepository.cbegin(); it != idsPerRepository.cend(); ++it) {
411 auto repository = it.key();
419 auto repository = it.key();
412 auto allRepositoryCatalogues = retrieveCatalogues(repository);
420 auto allRepositoryCatalogues = retrieveCatalogues(repository);
413 for (auto uuid : it.value()) {
421 for (auto uuid : it.value()) {
414 for (auto repositoryCatalogues : allRepositoryCatalogues) {
422 for (auto repositoryCatalogues : allRepositoryCatalogues) {
415 if (uuid.toUuid() == repositoryCatalogues->getUniqId()) {
423 if (uuid.toUuid() == repositoryCatalogues->getUniqId()) {
416 catalogues << repositoryCatalogues;
424 catalogues << repositoryCatalogues;
417 }
425 }
418 }
426 }
419 }
427 }
420 }
428 }
421
429
422 return catalogues;
430 return catalogues;
423 }
431 }
424
432
425 void CatalogueController::initialize()
433 void CatalogueController::initialize()
426 {
434 {
427 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init")
435 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init")
428 << QThread::currentThread();
436 << QThread::currentThread();
429
437
430 impl->m_CatalogueDao.initialize();
438 impl->m_CatalogueDao.initialize();
431 auto defaultRepositoryLocation
439 auto defaultRepositoryLocation
432 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
440 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
433
441
434 QDir defaultRepositoryLocationDir;
442 QDir defaultRepositoryLocationDir;
435 if (defaultRepositoryLocationDir.mkpath(defaultRepositoryLocation)) {
443 if (defaultRepositoryLocationDir.mkpath(defaultRepositoryLocation)) {
436 defaultRepositoryLocationDir.cd(defaultRepositoryLocation);
444 defaultRepositoryLocationDir.cd(defaultRepositoryLocation);
437 auto defaultRepository = defaultRepositoryLocationDir.absoluteFilePath(REPOSITORY_DEFAULT);
445 auto defaultRepository = defaultRepositoryLocationDir.absoluteFilePath(REPOSITORY_DEFAULT);
438
446
439 qCInfo(LOG_CatalogueController()) << tr("Persistant data loading from: ")
447 qCInfo(LOG_CatalogueController()) << tr("Persistant data loading from: ")
440 << defaultRepository;
448 << defaultRepository;
441
449
442 QDir dbDir(defaultRepository);
450 QDir dbDir(defaultRepository);
443 impl->m_RepositoryList << REPOSITORY_DEFAULT;
451 impl->m_RepositoryList << REPOSITORY_DEFAULT;
444 if (dbDir.exists()) {
452 if (dbDir.exists()) {
445 auto dirName = dbDir.dirName();
453 auto dirName = dbDir.dirName();
446
454
447 if (impl->m_CatalogueDao.addDB(defaultRepository, dirName)) {
455 if (impl->m_CatalogueDao.addDB(defaultRepository, dirName)) {
448 impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName));
456 impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName));
449 }
457 }
450 }
458 }
451 else {
459 else {
452 qCInfo(LOG_CatalogueController()) << tr("Initialisation of Default repository detected")
460 qCInfo(LOG_CatalogueController()) << tr("Initialisation of Default repository detected")
453 << defaultRepository;
461 << defaultRepository;
454 }
462 }
455 }
463 }
456 else {
464 else {
457 qCWarning(LOG_CatalogueController())
465 qCWarning(LOG_CatalogueController())
458 << tr("Cannot load the persistent default repository from ")
466 << tr("Cannot load the persistent default repository from ")
459 << defaultRepositoryLocation;
467 << defaultRepositoryLocation;
460 }
468 }
461
469
462 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init END");
470 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init END");
463 }
471 }
464
472
465 QString CatalogueController::CatalogueControllerPrivate::eventUniqueKey(
473 QString CatalogueController::CatalogueControllerPrivate::eventUniqueKey(
466 const std::shared_ptr<DBEvent> &event) const
474 const std::shared_ptr<DBEvent> &event) const
467 {
475 {
468 return event->getUniqId().toString().append(event->getRepository());
476 return event->getUniqId().toString().append(event->getRepository());
469 }
477 }
470
478
471 QString CatalogueController::CatalogueControllerPrivate::catalogueUniqueKey(
479 QString CatalogueController::CatalogueControllerPrivate::catalogueUniqueKey(
472 const std::shared_ptr<DBCatalogue> &catalogue) const
480 const std::shared_ptr<DBCatalogue> &catalogue) const
473 {
481 {
474 return catalogue->getUniqId().toString().append(catalogue->getRepository());
482 return catalogue->getUniqId().toString().append(catalogue->getRepository());
475 }
483 }
476
484
477 void CatalogueController::CatalogueControllerPrivate::copyDBtoDB(const QString &dbFrom,
485 void CatalogueController::CatalogueControllerPrivate::copyDBtoDB(const QString &dbFrom,
478 const QString &dbTo)
486 const QString &dbTo)
479 {
487 {
480 // auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
488 // auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
481 auto catalogues = m_CatalogueDao.getCatalogues(dbFrom);
489 auto catalogues = m_CatalogueDao.getCatalogues(dbFrom);
482 auto events = m_CatalogueDao.getEvents(dbFrom);
490 auto events = m_CatalogueDao.getEvents(dbFrom);
483 for (auto catalogue : catalogues) {
491 for (auto catalogue : catalogues) {
484 m_CatalogueDao.copyCatalogue(catalogue, dbTo, true);
492 m_CatalogueDao.copyCatalogue(catalogue, dbTo, true);
485 }
493 }
486
494
487 for (auto event : events) {
495 for (auto event : events) {
488 m_CatalogueDao.copyEvent(event, dbTo, true);
496 m_CatalogueDao.copyEvent(event, dbTo, true);
489 }
497 }
490 }
498 }
491
499
492 QString CatalogueController::CatalogueControllerPrivate::toWorkRepository(QString repository)
500 QString CatalogueController::CatalogueControllerPrivate::toWorkRepository(QString repository)
493 {
501 {
494 auto syncRepository = toSyncRepository(repository);
502 auto syncRepository = toSyncRepository(repository);
495
503
496 return QString("%1%2").arg(syncRepository, REPOSITORY_WORK_SUFFIX);
504 return QString("%1%2").arg(syncRepository, REPOSITORY_WORK_SUFFIX);
497 }
505 }
498
506
499 QString CatalogueController::CatalogueControllerPrivate::toSyncRepository(QString repository)
507 QString CatalogueController::CatalogueControllerPrivate::toSyncRepository(QString repository)
500 {
508 {
501 auto syncRepository = repository;
509 auto syncRepository = repository;
502 if (repository.endsWith(REPOSITORY_WORK_SUFFIX)) {
510 if (repository.endsWith(REPOSITORY_WORK_SUFFIX)) {
503 syncRepository.remove(REPOSITORY_WORK_SUFFIX);
511 syncRepository.remove(REPOSITORY_WORK_SUFFIX);
504 }
512 }
505 else if (repository.endsWith(REPOSITORY_TRASH_SUFFIX)) {
513 else if (repository.endsWith(REPOSITORY_TRASH_SUFFIX)) {
506 syncRepository.remove(REPOSITORY_TRASH_SUFFIX);
514 syncRepository.remove(REPOSITORY_TRASH_SUFFIX);
507 }
515 }
508 return syncRepository;
516 return syncRepository;
509 }
517 }
510
518
511 void CatalogueController::CatalogueControllerPrivate::savAllDB()
519 void CatalogueController::CatalogueControllerPrivate::savAllDB()
512 {
520 {
513 for (auto repository : m_RepositoryList) {
521 for (auto repository : m_RepositoryList) {
514 auto defaultRepositoryLocation
522 auto defaultRepositoryLocation
515 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
523 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
516 m_CatalogueDao.saveDB(defaultRepositoryLocation, repository);
524 m_CatalogueDao.saveDB(defaultRepositoryLocation, repository);
517 }
525 }
518 }
526 }
519
527
520 void CatalogueController::CatalogueControllerPrivate::saveEvent(std::shared_ptr<DBEvent> event,
528 void CatalogueController::CatalogueControllerPrivate::saveEvent(std::shared_ptr<DBEvent> event,
521 bool persist)
529 bool persist)
522 {
530 {
523 m_CatalogueDao.copyEvent(*event, toSyncRepository(event->getRepository()), true);
531 m_CatalogueDao.copyEvent(*event, toSyncRepository(event->getRepository()), true);
524 if (persist) {
532 if (persist) {
525 savAllDB();
533 savAllDB();
526 }
534 }
527 }
535 }
528
536
529 void CatalogueController::CatalogueControllerPrivate::saveCatalogue(
537 void CatalogueController::CatalogueControllerPrivate::saveCatalogue(
530 std::shared_ptr<DBCatalogue> catalogue, bool persist)
538 std::shared_ptr<DBCatalogue> catalogue, bool persist)
531 {
539 {
532 m_CatalogueDao.copyCatalogue(*catalogue, toSyncRepository(catalogue->getRepository()), true);
540 m_CatalogueDao.copyCatalogue(*catalogue, toSyncRepository(catalogue->getRepository()), true);
533 if (persist) {
541 if (persist) {
534 savAllDB();
542 savAllDB();
535 }
543 }
536 }
544 }
537
545
538 std::shared_ptr<IRequestPredicate> CatalogueController::CatalogueControllerPrivate::createFinder(
546 std::shared_ptr<IRequestPredicate> CatalogueController::CatalogueControllerPrivate::createFinder(
539 const QUuid &uniqId, const QString &repository, DBType type)
547 const QUuid &uniqId, const QString &repository, DBType type)
540 {
548 {
541 // update catalogue parameter
549 // update catalogue parameter
542 auto uniqIdPredicate = std::make_shared<ComparaisonPredicate>(QString{"uniqId"}, uniqId,
550 auto uniqIdPredicate = std::make_shared<ComparaisonPredicate>(QString{"uniqId"}, uniqId,
543 ComparaisonOperation::EQUALEQUAL);
551 ComparaisonOperation::EQUALEQUAL);
544
552
545 auto repositoryType = repository;
553 auto repositoryType = repository;
546 switch (type) {
554 switch (type) {
547 case DBType::SYNC:
555 case DBType::SYNC:
548 repositoryType = toSyncRepository(repositoryType);
556 repositoryType = toSyncRepository(repositoryType);
549 break;
557 break;
550 case DBType::WORK:
558 case DBType::WORK:
551 repositoryType = toWorkRepository(repositoryType);
559 repositoryType = toWorkRepository(repositoryType);
552 break;
560 break;
553 case DBType::TRASH:
561 case DBType::TRASH:
554 default:
562 default:
555 break;
563 break;
556 }
564 }
557
565
558 auto repositoryPredicate = std::make_shared<ComparaisonPredicate>(
566 auto repositoryPredicate = std::make_shared<ComparaisonPredicate>(
559 QString{"repository"}, repositoryType, ComparaisonOperation::EQUALEQUAL);
567 QString{"repository"}, repositoryType, ComparaisonOperation::EQUALEQUAL);
560
568
561 auto finderPred = std::make_shared<CompoundPredicate>(CompoundOperation::AND);
569 auto finderPred = std::make_shared<CompoundPredicate>(CompoundOperation::AND);
562 finderPred->AddRequestPredicate(uniqIdPredicate);
570 finderPred->AddRequestPredicate(uniqIdPredicate);
563 finderPred->AddRequestPredicate(repositoryPredicate);
571 finderPred->AddRequestPredicate(repositoryPredicate);
564
572
565 return finderPred;
573 return finderPred;
566 }
574 }
@@ -1,396 +1,393
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableController.h>
2 #include <Variable/VariableController.h>
3 #include <Variable/VariableModel.h>
3 #include <Variable/VariableModel.h>
4
4
5 #include <Common/DateUtils.h>
5 #include <Common/DateUtils.h>
6 #include <Common/MimeTypesDef.h>
6 #include <Common/MimeTypesDef.h>
7 #include <Common/StringUtils.h>
7 #include <Common/StringUtils.h>
8
8
9 #include <Data/IDataSeries.h>
9 #include <Data/IDataSeries.h>
10
10
11 #include <DataSource/DataSourceController.h>
11 #include <DataSource/DataSourceController.h>
12 #include <Time/TimeController.h>
12 #include <Time/TimeController.h>
13
13
14 #include <QMimeData>
14 #include <QMimeData>
15 #include <QSize>
15 #include <QSize>
16 #include <QTimer>
16 #include <QTimer>
17 #include <unordered_map>
17 #include <unordered_map>
18
18
19 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
19 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
20
20
21 namespace {
21 namespace {
22
22
23 // Column indexes
23 // Column indexes
24 const auto NAME_COLUMN = 0;
24 const auto NAME_COLUMN = 0;
25 const auto TSTART_COLUMN = 1;
25 const auto TSTART_COLUMN = 1;
26 const auto TEND_COLUMN = 2;
26 const auto TEND_COLUMN = 2;
27 const auto NBPOINTS_COLUMN = 3;
27 const auto NBPOINTS_COLUMN = 3;
28 const auto UNIT_COLUMN = 4;
28 const auto UNIT_COLUMN = 4;
29 const auto MISSION_COLUMN = 5;
29 const auto MISSION_COLUMN = 5;
30 const auto PLUGIN_COLUMN = 6;
30 const auto PLUGIN_COLUMN = 6;
31 const auto NB_COLUMNS = 7;
31 const auto NB_COLUMNS = 7;
32
32
33 // Column properties
33 // Column properties
34 const auto DEFAULT_HEIGHT = 25;
34 const auto DEFAULT_HEIGHT = 25;
35 const auto DEFAULT_WIDTH = 100;
35 const auto DEFAULT_WIDTH = 100;
36
36
37 struct ColumnProperties {
37 struct ColumnProperties {
38 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
38 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
39 int height = DEFAULT_HEIGHT)
39 int height = DEFAULT_HEIGHT)
40 : m_Name{name}, m_Width{width}, m_Height{height}
40 : m_Name{name}, m_Width{width}, m_Height{height}
41 {
41 {
42 }
42 }
43
43
44 QString m_Name;
44 QString m_Name;
45 int m_Width;
45 int m_Width;
46 int m_Height;
46 int m_Height;
47 };
47 };
48
48
49 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
49 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
50 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
50 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
51 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
51 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
52 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
52 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
53 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
53 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
54
54
55 /// Format for datetimes
56 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
57
58 QString uniqueName(const QString &defaultName,
55 QString uniqueName(const QString &defaultName,
59 const std::vector<std::shared_ptr<Variable> > &variables)
56 const std::vector<std::shared_ptr<Variable> > &variables)
60 {
57 {
61 auto forbiddenNames = std::vector<QString>(variables.size());
58 auto forbiddenNames = std::vector<QString>(variables.size());
62 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
59 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
63 [](const auto &variable) { return variable->name(); });
60 [](const auto &variable) { return variable->name(); });
64 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
61 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
65 Q_ASSERT(!uniqueName.isEmpty());
62 Q_ASSERT(!uniqueName.isEmpty());
66
63
67 return uniqueName;
64 return uniqueName;
68 }
65 }
69
66
70 } // namespace
67 } // namespace
71
68
72 struct VariableModel::VariableModelPrivate {
69 struct VariableModel::VariableModelPrivate {
73 /// Variables created in SciQlop
70 /// Variables created in SciQlop
74 std::vector<std::shared_ptr<Variable> > m_Variables;
71 std::vector<std::shared_ptr<Variable> > m_Variables;
75 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
72 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
76 VariableController *m_VariableController;
73 VariableController *m_VariableController;
77
74
78 /// Return the row index of the variable. -1 if it's not found
75 /// Return the row index of the variable. -1 if it's not found
79 int indexOfVariable(Variable *variable) const noexcept;
76 int indexOfVariable(Variable *variable) const noexcept;
80 };
77 };
81
78
82 VariableModel::VariableModel(VariableController *parent)
79 VariableModel::VariableModel(VariableController *parent)
83 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
80 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
84 {
81 {
85 impl->m_VariableController = parent;
82 impl->m_VariableController = parent;
86 }
83 }
87
84
88 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
85 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
89 {
86 {
90 auto insertIndex = rowCount();
87 auto insertIndex = rowCount();
91 beginInsertRows({}, insertIndex, insertIndex);
88 beginInsertRows({}, insertIndex, insertIndex);
92
89
93 // Generates unique name for the variable
90 // Generates unique name for the variable
94 variable->setName(uniqueName(variable->name(), impl->m_Variables));
91 variable->setName(uniqueName(variable->name(), impl->m_Variables));
95
92
96 impl->m_Variables.push_back(variable);
93 impl->m_Variables.push_back(variable);
97 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
94 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
98
95
99 endInsertRows();
96 endInsertRows();
100 }
97 }
101
98
102 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
99 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
103 {
100 {
104 auto end = impl->m_Variables.cend();
101 auto end = impl->m_Variables.cend();
105 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
102 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
106 }
103 }
107
104
108 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
105 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
109 const QVariantHash &metadata) noexcept
106 const QVariantHash &metadata) noexcept
110 {
107 {
111 auto variable = std::make_shared<Variable>(name, metadata);
108 auto variable = std::make_shared<Variable>(name, metadata);
112 addVariable(variable);
109 addVariable(variable);
113
110
114 return variable;
111 return variable;
115 }
112 }
116
113
117 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
114 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
118 {
115 {
119 if (!variable) {
116 if (!variable) {
120 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
117 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
121 return;
118 return;
122 }
119 }
123
120
124 // Finds variable in the model
121 // Finds variable in the model
125 auto begin = impl->m_Variables.cbegin();
122 auto begin = impl->m_Variables.cbegin();
126 auto end = impl->m_Variables.cend();
123 auto end = impl->m_Variables.cend();
127 auto it = std::find(begin, end, variable);
124 auto it = std::find(begin, end, variable);
128 if (it != end) {
125 if (it != end) {
129 auto removeIndex = std::distance(begin, it);
126 auto removeIndex = std::distance(begin, it);
130
127
131 // Deletes variable
128 // Deletes variable
132 beginRemoveRows({}, removeIndex, removeIndex);
129 beginRemoveRows({}, removeIndex, removeIndex);
133 impl->m_Variables.erase(it);
130 impl->m_Variables.erase(it);
134 endRemoveRows();
131 endRemoveRows();
135 }
132 }
136 else {
133 else {
137 qCritical(LOG_VariableModel())
134 qCritical(LOG_VariableModel())
138 << tr("Can't delete variable %1 from the model: the variable is not in the model")
135 << tr("Can't delete variable %1 from the model: the variable is not in the model")
139 .arg(variable->name());
136 .arg(variable->name());
140 }
137 }
141
138
142 // Removes variable from progress map
139 // Removes variable from progress map
143 impl->m_VariableToProgress.erase(variable);
140 impl->m_VariableToProgress.erase(variable);
144 }
141 }
145
142
146
143
147 std::shared_ptr<Variable> VariableModel::variable(int index) const
144 std::shared_ptr<Variable> VariableModel::variable(int index) const
148 {
145 {
149 return (index >= 0u && static_cast<size_t>(index) < impl->m_Variables.size())
146 return (index >= 0u && static_cast<size_t>(index) < impl->m_Variables.size())
150 ? impl->m_Variables[index]
147 ? impl->m_Variables[index]
151 : nullptr;
148 : nullptr;
152 }
149 }
153
150
154 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
151 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
155 {
152 {
156 return impl->m_Variables;
153 return impl->m_Variables;
157 }
154 }
158
155
159 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
156 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
160 {
157 {
161 if (progress > 0.0) {
158 if (progress > 0.0) {
162 impl->m_VariableToProgress[variable] = progress;
159 impl->m_VariableToProgress[variable] = progress;
163 }
160 }
164 else {
161 else {
165 impl->m_VariableToProgress.erase(variable);
162 impl->m_VariableToProgress.erase(variable);
166 }
163 }
167 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
164 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
168
165
169 emit dataChanged(modelIndex, modelIndex);
166 emit dataChanged(modelIndex, modelIndex);
170 }
167 }
171
168
172 int VariableModel::columnCount(const QModelIndex &parent) const
169 int VariableModel::columnCount(const QModelIndex &parent) const
173 {
170 {
174 Q_UNUSED(parent);
171 Q_UNUSED(parent);
175
172
176 return NB_COLUMNS;
173 return NB_COLUMNS;
177 }
174 }
178
175
179 int VariableModel::rowCount(const QModelIndex &parent) const
176 int VariableModel::rowCount(const QModelIndex &parent) const
180 {
177 {
181 Q_UNUSED(parent);
178 Q_UNUSED(parent);
182
179
183 return impl->m_Variables.size();
180 return impl->m_Variables.size();
184 }
181 }
185
182
186 QVariant VariableModel::data(const QModelIndex &index, int role) const
183 QVariant VariableModel::data(const QModelIndex &index, int role) const
187 {
184 {
188 if (!index.isValid()) {
185 if (!index.isValid()) {
189 return QVariant{};
186 return QVariant{};
190 }
187 }
191
188
192 if (index.row() < 0 || index.row() >= rowCount()) {
189 if (index.row() < 0 || index.row() >= rowCount()) {
193 return QVariant{};
190 return QVariant{};
194 }
191 }
195
192
196 if (role == Qt::DisplayRole) {
193 if (role == Qt::DisplayRole) {
197 if (auto variable = impl->m_Variables.at(index.row()).get()) {
194 if (auto variable = impl->m_Variables.at(index.row()).get()) {
198 switch (index.column()) {
195 switch (index.column()) {
199 case NAME_COLUMN:
196 case NAME_COLUMN:
200 return variable->name();
197 return variable->name();
201 case TSTART_COLUMN: {
198 case TSTART_COLUMN: {
202 auto range = variable->realRange();
199 auto range = variable->realRange();
203 return range != INVALID_RANGE
200 return range != INVALID_RANGE
204 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
201 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
205 : QVariant{};
202 : QVariant{};
206 }
203 }
207 case TEND_COLUMN: {
204 case TEND_COLUMN: {
208 auto range = variable->realRange();
205 auto range = variable->realRange();
209 return range != INVALID_RANGE
206 return range != INVALID_RANGE
210 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
207 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
211 : QVariant{};
208 : QVariant{};
212 }
209 }
213 case NBPOINTS_COLUMN:
210 case NBPOINTS_COLUMN:
214 return variable->nbPoints();
211 return variable->nbPoints();
215 case UNIT_COLUMN:
212 case UNIT_COLUMN:
216 return variable->metadata().value(QStringLiteral("units"));
213 return variable->metadata().value(QStringLiteral("units"));
217 case MISSION_COLUMN:
214 case MISSION_COLUMN:
218 return variable->metadata().value(QStringLiteral("mission"));
215 return variable->metadata().value(QStringLiteral("mission"));
219 case PLUGIN_COLUMN:
216 case PLUGIN_COLUMN:
220 return variable->metadata().value(QStringLiteral("plugin"));
217 return variable->metadata().value(QStringLiteral("plugin"));
221 default:
218 default:
222 // No action
219 // No action
223 break;
220 break;
224 }
221 }
225
222
226 qWarning(LOG_VariableModel())
223 qWarning(LOG_VariableModel())
227 << tr("Can't get data (unknown column %1)").arg(index.column());
224 << tr("Can't get data (unknown column %1)").arg(index.column());
228 }
225 }
229 else {
226 else {
230 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
227 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
231 }
228 }
232 }
229 }
233 else if (role == VariableRoles::ProgressRole) {
230 else if (role == VariableRoles::ProgressRole) {
234 if (auto variable = impl->m_Variables.at(index.row())) {
231 if (auto variable = impl->m_Variables.at(index.row())) {
235
232
236 auto it = impl->m_VariableToProgress.find(variable);
233 auto it = impl->m_VariableToProgress.find(variable);
237 if (it != impl->m_VariableToProgress.cend()) {
234 if (it != impl->m_VariableToProgress.cend()) {
238 return it->second;
235 return it->second;
239 }
236 }
240 }
237 }
241 }
238 }
242
239
243 return QVariant{};
240 return QVariant{};
244 }
241 }
245
242
246 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
243 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
247 {
244 {
248 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
245 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
249 return QVariant{};
246 return QVariant{};
250 }
247 }
251
248
252 if (orientation == Qt::Horizontal) {
249 if (orientation == Qt::Horizontal) {
253 auto propertiesIt = COLUMN_PROPERTIES.find(section);
250 auto propertiesIt = COLUMN_PROPERTIES.find(section);
254 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
251 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
255 // Role is either DisplayRole or SizeHintRole
252 // Role is either DisplayRole or SizeHintRole
256 return (role == Qt::DisplayRole)
253 return (role == Qt::DisplayRole)
257 ? QVariant{propertiesIt->m_Name}
254 ? QVariant{propertiesIt->m_Name}
258 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
255 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
259 }
256 }
260 else {
257 else {
261 qWarning(LOG_VariableModel())
258 qWarning(LOG_VariableModel())
262 << tr("Can't get header data (unknown column %1)").arg(section);
259 << tr("Can't get header data (unknown column %1)").arg(section);
263 }
260 }
264 }
261 }
265
262
266 return QVariant{};
263 return QVariant{};
267 }
264 }
268
265
269 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
266 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
270 {
267 {
271 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
268 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
272 }
269 }
273
270
274 Qt::DropActions VariableModel::supportedDropActions() const
271 Qt::DropActions VariableModel::supportedDropActions() const
275 {
272 {
276 return Qt::CopyAction | Qt::MoveAction;
273 return Qt::CopyAction | Qt::MoveAction;
277 }
274 }
278
275
279 Qt::DropActions VariableModel::supportedDragActions() const
276 Qt::DropActions VariableModel::supportedDragActions() const
280 {
277 {
281 return Qt::CopyAction | Qt::MoveAction;
278 return Qt::CopyAction | Qt::MoveAction;
282 }
279 }
283
280
284 QStringList VariableModel::mimeTypes() const
281 QStringList VariableModel::mimeTypes() const
285 {
282 {
286 return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE};
283 return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE};
287 }
284 }
288
285
289 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
286 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
290 {
287 {
291 auto mimeData = new QMimeData;
288 auto mimeData = new QMimeData;
292
289
293 QList<std::shared_ptr<Variable> > variableList;
290 QList<std::shared_ptr<Variable> > variableList;
294
291
295
292
296 SqpRange firstTimeRange;
293 SqpRange firstTimeRange;
297 for (const auto &index : indexes) {
294 for (const auto &index : indexes) {
298 if (index.column() == 0) { // only the first column
295 if (index.column() == 0) { // only the first column
299 auto variable = impl->m_Variables.at(index.row());
296 auto variable = impl->m_Variables.at(index.row());
300 if (variable.get() && index.isValid()) {
297 if (variable.get() && index.isValid()) {
301
298
302 if (variableList.isEmpty()) {
299 if (variableList.isEmpty()) {
303 // Gets the range of the first variable
300 // Gets the range of the first variable
304 firstTimeRange = std::move(variable->range());
301 firstTimeRange = std::move(variable->range());
305 }
302 }
306
303
307 variableList << variable;
304 variableList << variable;
308 }
305 }
309 }
306 }
310 }
307 }
311
308
312 auto variablesEncodedData = impl->m_VariableController->mimeDataForVariables(variableList);
309 auto variablesEncodedData = impl->m_VariableController->mimeDataForVariables(variableList);
313 mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData);
310 mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData);
314
311
315 if (variableList.count() == 1) {
312 if (variableList.count() == 1) {
316 // No time range MIME data if multiple variables are dragged
313 // No time range MIME data if multiple variables are dragged
317 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
314 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
318 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
315 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
319 }
316 }
320
317
321 return mimeData;
318 return mimeData;
322 }
319 }
323
320
324 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
321 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
325 int column, const QModelIndex &parent) const
322 int column, const QModelIndex &parent) const
326 {
323 {
327 // drop of a product
324 // drop of a product
328 return data->hasFormat(MIME_TYPE_PRODUCT_LIST)
325 return data->hasFormat(MIME_TYPE_PRODUCT_LIST)
329 || (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()
326 || (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()
330 && !data->hasFormat(MIME_TYPE_VARIABLE_LIST));
327 && !data->hasFormat(MIME_TYPE_VARIABLE_LIST));
331 }
328 }
332
329
333 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
330 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
334 const QModelIndex &parent)
331 const QModelIndex &parent)
335 {
332 {
336 auto dropDone = false;
333 auto dropDone = false;
337
334
338 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
335 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
339
336
340 auto productList
337 auto productList
341 = DataSourceController::productsDataForMimeData(data->data(MIME_TYPE_PRODUCT_LIST));
338 = DataSourceController::productsDataForMimeData(data->data(MIME_TYPE_PRODUCT_LIST));
342
339
343 for (auto metaData : productList) {
340 for (auto metaData : productList) {
344 emit requestVariable(metaData.toHash());
341 emit requestVariable(metaData.toHash());
345 }
342 }
346
343
347 dropDone = true;
344 dropDone = true;
348 }
345 }
349 else if (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()) {
346 else if (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()) {
350 auto variable = this->variable(parent.row());
347 auto variable = this->variable(parent.row());
351 auto range = TimeController::timeRangeForMimeData(data->data(MIME_TYPE_TIME_RANGE));
348 auto range = TimeController::timeRangeForMimeData(data->data(MIME_TYPE_TIME_RANGE));
352
349
353 emit requestVariableRangeUpdate(variable, range);
350 emit requestVariableRangeUpdate(variable, range);
354
351
355 dropDone = true;
352 dropDone = true;
356 }
353 }
357
354
358 return dropDone;
355 return dropDone;
359 }
356 }
360
357
361 void VariableModel::abortProgress(const QModelIndex &index)
358 void VariableModel::abortProgress(const QModelIndex &index)
362 {
359 {
363 if (auto variable = impl->m_Variables.at(index.row())) {
360 if (auto variable = impl->m_Variables.at(index.row())) {
364 emit abortProgessRequested(variable);
361 emit abortProgessRequested(variable);
365 }
362 }
366 }
363 }
367
364
368 void VariableModel::onVariableUpdated() noexcept
365 void VariableModel::onVariableUpdated() noexcept
369 {
366 {
370 // Finds variable that has been updated in the model
367 // Finds variable that has been updated in the model
371 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
368 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
372 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
369 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
373
370
374 if (updatedVariableIndex > -1) {
371 if (updatedVariableIndex > -1) {
375 emit dataChanged(createIndex(updatedVariableIndex, 0),
372 emit dataChanged(createIndex(updatedVariableIndex, 0),
376 createIndex(updatedVariableIndex, columnCount() - 1));
373 createIndex(updatedVariableIndex, columnCount() - 1));
377 }
374 }
378 }
375 }
379 }
376 }
380
377
381 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
378 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
382 {
379 {
383 auto begin = std::cbegin(m_Variables);
380 auto begin = std::cbegin(m_Variables);
384 auto end = std::cend(m_Variables);
381 auto end = std::cend(m_Variables);
385 auto it
382 auto it
386 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
383 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
387
384
388 if (it != end) {
385 if (it != end) {
389 // Gets the index of the variable in the model: we assume here that views have the same
386 // Gets the index of the variable in the model: we assume here that views have the same
390 // order as the model
387 // order as the model
391 return std::distance(begin, it);
388 return std::distance(begin, it);
392 }
389 }
393 else {
390 else {
394 return -1;
391 return -1;
395 }
392 }
396 }
393 }
@@ -1,64 +1,72
1 #ifndef SCIQLOP_CATALOGUEEVENTSWIDGET_H
1 #ifndef SCIQLOP_CATALOGUEEVENTSWIDGET_H
2 #define SCIQLOP_CATALOGUEEVENTSWIDGET_H
2 #define SCIQLOP_CATALOGUEEVENTSWIDGET_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 #include <QLoggingCategory>
6 #include <QWidget>
6 #include <QWidget>
7
7
8 class DBCatalogue;
8 class DBCatalogue;
9 class DBEvent;
9 class DBEvent;
10 class DBEventProduct;
10 class DBEventProduct;
11 class VisualizationWidget;
11 class VisualizationWidget;
12 class VisualizationSelectionZoneItem;
12 class VisualizationSelectionZoneItem;
13
13
14 namespace Ui {
14 namespace Ui {
15 class CatalogueEventsWidget;
15 class CatalogueEventsWidget;
16 }
16 }
17
17
18 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueEventsWidget)
18 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueEventsWidget)
19
19
20 class CatalogueEventsWidget : public QWidget {
20 class CatalogueEventsWidget : public QWidget {
21 Q_OBJECT
21 Q_OBJECT
22
22
23 signals:
23 signals:
24 void eventsSelected(const QVector<std::shared_ptr<DBEvent> > &event);
24 void eventsSelected(const QVector<std::shared_ptr<DBEvent> > &event);
25 void eventsRemoved(const QVector<std::shared_ptr<DBEvent> > &event);
25 void eventsRemoved(const QVector<std::shared_ptr<DBEvent> > &event);
26 void eventProductsSelected(
26 void eventProductsSelected(
27 const QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > >
27 const QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > >
28 &eventproducts);
28 &eventproducts);
29 void selectionCleared();
29 void selectionCleared();
30 void selectionZoneAdded(const std::shared_ptr<DBEvent> &event, const QString &productId,
30 void selectionZoneAdded(const std::shared_ptr<DBEvent> &event, const QString &productId,
31 VisualizationSelectionZoneItem *selectionZone);
31 VisualizationSelectionZoneItem *selectionZone);
32
32
33 void eventCataloguesModified(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
34
33 public:
35 public:
34 explicit CatalogueEventsWidget(QWidget *parent = 0);
36 explicit CatalogueEventsWidget(QWidget *parent = 0);
35 virtual ~CatalogueEventsWidget();
37 virtual ~CatalogueEventsWidget();
36
38
37 void setVisualizationWidget(VisualizationWidget *visualization);
39 void setVisualizationWidget(VisualizationWidget *visualization);
38
40
39 void addEvent(const std::shared_ptr<DBEvent> &event);
41 void addEvent(const std::shared_ptr<DBEvent> &event);
40 void setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges);
42 void setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges);
43 void setEventsChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges);
41
44
42 QVector<std::shared_ptr<DBCatalogue> > displayedCatalogues() const;
45 QVector<std::shared_ptr<DBCatalogue> > displayedCatalogues() const;
43 bool isAllEventsDisplayed() const;
46 bool isAllEventsDisplayed() const;
44 bool isEventDisplayed(const std::shared_ptr<DBEvent> &event) const;
47 bool isEventDisplayed(const std::shared_ptr<DBEvent> &event) const;
45
48
46 void refreshEvent(const std::shared_ptr<DBEvent> &event);
49 void refreshEvent(const std::shared_ptr<DBEvent> &event);
47
50
48 public slots:
51 public slots:
49 void populateWithCatalogues(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
52 void populateWithCatalogues(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
50 void populateWithAllEvents();
53 void populateWithAllEvents();
51 void clear();
54 void clear();
52 void refresh();
55 void refresh();
53
56
57 // QWidget interface
58 protected:
59 void keyPressEvent(QKeyEvent *event);
60
61
54 private:
62 private:
55 Ui::CatalogueEventsWidget *ui;
63 Ui::CatalogueEventsWidget *ui;
56
64
57 class CatalogueEventsWidgetPrivate;
65 class CatalogueEventsWidgetPrivate;
58 spimpl::unique_impl_ptr<CatalogueEventsWidgetPrivate> impl;
66 spimpl::unique_impl_ptr<CatalogueEventsWidgetPrivate> impl;
59
67
60 private slots:
68 private slots:
61 void emitSelection();
69 void emitSelection();
62 };
70 };
63
71
64 #endif // SCIQLOP_CATALOGUEEVENTSWIDGET_H
72 #endif // SCIQLOP_CATALOGUEEVENTSWIDGET_H
@@ -1,51 +1,56
1 #ifndef SCIQLOP_CATALOGUESIDEBARWIDGET_H
1 #ifndef SCIQLOP_CATALOGUESIDEBARWIDGET_H
2 #define SCIQLOP_CATALOGUESIDEBARWIDGET_H
2 #define SCIQLOP_CATALOGUESIDEBARWIDGET_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 #include <QLoggingCategory>
6 #include <QTreeWidgetItem>
6 #include <QTreeWidgetItem>
7 #include <QWidget>
7 #include <QWidget>
8
8
9 class CatalogueAbstractTreeItem;
9 class CatalogueAbstractTreeItem;
10 class DBCatalogue;
10 class DBCatalogue;
11
11
12 namespace Ui {
12 namespace Ui {
13 class CatalogueSideBarWidget;
13 class CatalogueSideBarWidget;
14 }
14 }
15
15
16 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget)
16 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget)
17
17
18 class CatalogueSideBarWidget : public QWidget {
18 class CatalogueSideBarWidget : public QWidget {
19 Q_OBJECT
19 Q_OBJECT
20
20
21 signals:
21 signals:
22 void catalogueSelected(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
22 void catalogueSelected(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
23 void databaseSelected(const QStringList &databases);
23 void databaseSelected(const QStringList &databases);
24 void allEventsSelected();
24 void allEventsSelected();
25 void trashSelected();
25 void trashSelected();
26 void selectionCleared();
26 void selectionCleared();
27 void catalogueSaved(const std::shared_ptr<DBCatalogue> &catalogue);
27
28
28 public:
29 public:
29 explicit CatalogueSideBarWidget(QWidget *parent = 0);
30 explicit CatalogueSideBarWidget(QWidget *parent = 0);
30 virtual ~CatalogueSideBarWidget();
31 virtual ~CatalogueSideBarWidget();
31
32
32 CatalogueAbstractTreeItem *addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
33 CatalogueAbstractTreeItem *addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
33 const QString &repository);
34 const QString &repository);
34 void setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue, bool hasChanges);
35 void setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue, bool hasChanges);
35
36
36 QVector<std::shared_ptr<DBCatalogue> > getCatalogues(const QString &repository) const;
37 QVector<std::shared_ptr<DBCatalogue> > getCatalogues(const QString &repository) const;
37
38
39 // QWidget interface
40 protected:
41 void keyPressEvent(QKeyEvent *event);
42
38 private slots:
43 private slots:
39 void emitSelection();
44 void emitSelection();
40
45
41 private:
46 private:
42 Ui::CatalogueSideBarWidget *ui;
47 Ui::CatalogueSideBarWidget *ui;
43
48
44 class CatalogueSideBarWidgetPrivate;
49 class CatalogueSideBarWidgetPrivate;
45 spimpl::unique_impl_ptr<CatalogueSideBarWidgetPrivate> impl;
50 spimpl::unique_impl_ptr<CatalogueSideBarWidgetPrivate> impl;
46
51
47 private slots:
52 private slots:
48 void onContextMenuRequested(const QPoint &pos);
53 void onContextMenuRequested(const QPoint &pos);
49 };
54 };
50
55
51 #endif // SCIQLOP_CATALOGUESIDEBARWIDGET_H
56 #endif // SCIQLOP_CATALOGUESIDEBARWIDGET_H
1 NO CONTENT: modified file chmod 100644 => 100755, binary diff hidden
NO CONTENT: modified file chmod 100644 => 100755, binary diff hidden
@@ -1,472 +1,484
1 #include "Catalogue/CatalogueEventsModel.h"
1 #include "Catalogue/CatalogueEventsModel.h"
2
2
3 #include <Catalogue/CatalogueController.h>
3 #include <Catalogue/CatalogueController.h>
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5 #include <Common/MimeTypesDef.h>
5 #include <Common/MimeTypesDef.h>
6 #include <DBEvent.h>
6 #include <DBEvent.h>
7 #include <DBEventProduct.h>
7 #include <DBEventProduct.h>
8 #include <DBTag.h>
8 #include <DBTag.h>
9 #include <Data/SqpRange.h>
9 #include <Data/SqpRange.h>
10 #include <SqpApplication.h>
10 #include <SqpApplication.h>
11 #include <Time/TimeController.h>
11 #include <Time/TimeController.h>
12
12
13 #include <list>
13 #include <list>
14 #include <unordered_map>
14 #include <unordered_map>
15
15
16 #include <QHash>
16 #include <QHash>
17 #include <QMimeData>
17 #include <QMimeData>
18
18
19 Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
19 Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
20
20
21 const auto EVENT_ITEM_TYPE = 1;
21 const auto EVENT_ITEM_TYPE = 1;
22 const auto EVENT_PRODUCT_ITEM_TYPE = 2;
22 const auto EVENT_PRODUCT_ITEM_TYPE = 2;
23
23
24 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
24 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
25 QVector<std::shared_ptr<DBEvent> > m_Events;
25 QVector<std::shared_ptr<DBEvent> > m_Events;
26 std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
26 std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
27 QVector<std::shared_ptr<DBCatalogue> > m_SourceCatalogue;
27 QVector<std::shared_ptr<DBCatalogue> > m_SourceCatalogue;
28
28
29 QStringList columnNames()
29 QStringList columnNames()
30 {
30 {
31 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"),
31 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"),
32 tr("Tags"), tr("Product"), tr("")};
32 tr("Tags"), tr("Product"), tr("")};
33 }
33 }
34
34
35 QVariant sortData(int col, const std::shared_ptr<DBEvent> &event) const
35 QVariant sortData(int col, const std::shared_ptr<DBEvent> &event) const
36 {
36 {
37 if (col == (int)CatalogueEventsModel::Column::Validation) {
37 if (col == (int)CatalogueEventsModel::Column::Validation) {
38 auto hasChanges = sqpApp->catalogueController().eventHasChanges(event);
38 auto hasChanges = sqpApp->catalogueController().eventHasChanges(event);
39 return hasChanges ? true : QVariant();
39 return hasChanges ? true : QVariant();
40 }
40 }
41
41
42 return eventData(col, event);
42 return eventData(col, event);
43 }
43 }
44
44
45 QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
45 QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
46 {
46 {
47 switch (static_cast<Column>(col)) {
47 switch (static_cast<Column>(col)) {
48 case CatalogueEventsModel::Column::Name:
48 case CatalogueEventsModel::Column::Name:
49 return event->getName();
49 return event->getName();
50 case CatalogueEventsModel::Column::TStart:
50 case CatalogueEventsModel::Column::TStart:
51 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart())
51 return nbEventProducts(event) > 0
52 : QVariant{};
52 ? DateUtils::dateTime(event->getTStart())
53 .toString(DATETIME_FORMAT_ONE_LINE)
54 : QVariant{};
53 case CatalogueEventsModel::Column::TEnd:
55 case CatalogueEventsModel::Column::TEnd:
54 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd())
56 return nbEventProducts(event) > 0
55 : QVariant{};
57 ? DateUtils::dateTime(event->getTEnd())
56 case CatalogueEventsModel::Column::Product:
58 .toString(DATETIME_FORMAT_ONE_LINE)
57 return QString::number(nbEventProducts(event)) + " product(s)";
59 : QVariant{};
60 case CatalogueEventsModel::Column::Product: {
61 auto eventProducts = event->getEventProducts();
62 QStringList eventProductList;
63 for (auto evtProduct : eventProducts) {
64 eventProductList << evtProduct.getProductId();
65 }
66 return eventProductList.join(";");
67 }
58 case CatalogueEventsModel::Column::Tags: {
68 case CatalogueEventsModel::Column::Tags: {
59 QString tagList;
69 QString tagList;
60 auto tags = event->getTags();
70 auto tags = event->getTags();
61 for (auto tag : tags) {
71 for (auto tag : tags) {
62 tagList += tag.getName();
72 tagList += tag.getName();
63 tagList += ' ';
73 tagList += ' ';
64 }
74 }
65
75
66 return tagList;
76 return tagList;
67 }
77 }
68 case CatalogueEventsModel::Column::Validation:
78 case CatalogueEventsModel::Column::Validation:
69 return QVariant();
79 return QVariant();
70 default:
80 default:
71 break;
81 break;
72 }
82 }
73
83
74 Q_ASSERT(false);
84 Q_ASSERT(false);
75 return QStringLiteral("Unknown Data");
85 return QStringLiteral("Unknown Data");
76 }
86 }
77
87
78 void parseEventProduct(const std::shared_ptr<DBEvent> &event)
88 void parseEventProduct(const std::shared_ptr<DBEvent> &event)
79 {
89 {
80 for (auto product : event->getEventProducts()) {
90 for (auto product : event->getEventProducts()) {
81 m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
91 m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
82 }
92 }
83 }
93 }
84
94
85 int nbEventProducts(const std::shared_ptr<DBEvent> &event) const
95 int nbEventProducts(const std::shared_ptr<DBEvent> &event) const
86 {
96 {
87 auto eventProductsIt = m_EventProducts.find(event.get());
97 auto eventProductsIt = m_EventProducts.find(event.get());
88 if (eventProductsIt != m_EventProducts.cend()) {
98 if (eventProductsIt != m_EventProducts.cend()) {
89 return m_EventProducts.at(event.get()).count();
99 return m_EventProducts.at(event.get()).count();
90 }
100 }
91 else {
101 else {
92 return 0;
102 return 0;
93 }
103 }
94 }
104 }
95
105
96 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
106 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
97 {
107 {
98 switch (static_cast<Column>(col)) {
108 switch (static_cast<Column>(col)) {
99 case CatalogueEventsModel::Column::Name:
109 case CatalogueEventsModel::Column::Name:
100 return eventProduct->getProductId();
110 return eventProduct->getProductId();
101 case CatalogueEventsModel::Column::TStart:
111 case CatalogueEventsModel::Column::TStart:
102 return DateUtils::dateTime(eventProduct->getTStart());
112 return DateUtils::dateTime(eventProduct->getTStart())
113 .toString(DATETIME_FORMAT_ONE_LINE);
103 case CatalogueEventsModel::Column::TEnd:
114 case CatalogueEventsModel::Column::TEnd:
104 return DateUtils::dateTime(eventProduct->getTEnd());
115 return DateUtils::dateTime(eventProduct->getTEnd())
116 .toString(DATETIME_FORMAT_ONE_LINE);
105 case CatalogueEventsModel::Column::Product:
117 case CatalogueEventsModel::Column::Product:
106 return eventProduct->getProductId();
118 return eventProduct->getProductId();
107 case CatalogueEventsModel::Column::Tags:
119 case CatalogueEventsModel::Column::Tags:
108 return QString();
120 return QString();
109 case CatalogueEventsModel::Column::Validation:
121 case CatalogueEventsModel::Column::Validation:
110 return QVariant();
122 return QVariant();
111 default:
123 default:
112 break;
124 break;
113 }
125 }
114
126
115 Q_ASSERT(false);
127 Q_ASSERT(false);
116 return QStringLiteral("Unknown Data");
128 return QStringLiteral("Unknown Data");
117 }
129 }
118
130
119 void refreshChildrenOfIndex(CatalogueEventsModel *model, const QModelIndex &index) const
131 void refreshChildrenOfIndex(CatalogueEventsModel *model, const QModelIndex &index) const
120 {
132 {
121 auto childCount = model->rowCount(index);
133 auto childCount = model->rowCount(index);
122 auto colCount = model->columnCount();
134 auto colCount = model->columnCount();
123 emit model->dataChanged(model->index(0, 0, index),
135 emit model->dataChanged(model->index(0, 0, index),
124 model->index(childCount, colCount, index));
136 model->index(childCount, colCount, index));
125 }
137 }
126 };
138 };
127
139
128 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
140 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
129 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
141 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
130 {
142 {
131 }
143 }
132
144
133 void CatalogueEventsModel::setSourceCatalogues(
145 void CatalogueEventsModel::setSourceCatalogues(
134 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
146 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
135 {
147 {
136 impl->m_SourceCatalogue = catalogues;
148 impl->m_SourceCatalogue = catalogues;
137 }
149 }
138
150
139 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
151 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
140 {
152 {
141 beginResetModel();
153 beginResetModel();
142
154
143 impl->m_Events = events;
155 impl->m_Events = events;
144 impl->m_EventProducts.clear();
156 impl->m_EventProducts.clear();
145 for (auto event : events) {
157 for (auto event : events) {
146 impl->parseEventProduct(event);
158 impl->parseEventProduct(event);
147 }
159 }
148
160
149 endResetModel();
161 endResetModel();
150 }
162 }
151
163
152 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
164 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
153 {
165 {
154 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
166 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
155 return impl->m_Events.value(index.row());
167 return impl->m_Events.value(index.row());
156 }
168 }
157 else {
169 else {
158 return nullptr;
170 return nullptr;
159 }
171 }
160 }
172 }
161
173
162 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
174 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
163 {
175 {
164 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
176 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
165 return getEvent(index.parent());
177 return getEvent(index.parent());
166 }
178 }
167 else {
179 else {
168 return nullptr;
180 return nullptr;
169 }
181 }
170 }
182 }
171
183
172 std::shared_ptr<DBEventProduct>
184 std::shared_ptr<DBEventProduct>
173 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
185 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
174 {
186 {
175 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
187 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
176 auto event = static_cast<DBEvent *>(index.internalPointer());
188 auto event = static_cast<DBEvent *>(index.internalPointer());
177 return impl->m_EventProducts.at(event).value(index.row());
189 return impl->m_EventProducts.at(event).value(index.row());
178 }
190 }
179 else {
191 else {
180 return nullptr;
192 return nullptr;
181 }
193 }
182 }
194 }
183
195
184 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
196 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
185 {
197 {
186 beginInsertRows(QModelIndex(), impl->m_Events.count(), impl->m_Events.count());
198 beginInsertRows(QModelIndex(), impl->m_Events.count(), impl->m_Events.count());
187 impl->m_Events.append(event);
199 impl->m_Events.append(event);
188 impl->parseEventProduct(event);
200 impl->parseEventProduct(event);
189 endInsertRows();
201 endInsertRows();
190
202
191 // Also refreshes its children event products
203 // Also refreshes its children event products
192 auto eventIndex = index(impl->m_Events.count(), 0);
204 auto eventIndex = index(impl->m_Events.count(), 0);
193 impl->refreshChildrenOfIndex(this, eventIndex);
205 impl->refreshChildrenOfIndex(this, eventIndex);
194 }
206 }
195
207
196 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
208 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
197 {
209 {
198 auto index = impl->m_Events.indexOf(event);
210 auto index = impl->m_Events.indexOf(event);
199 if (index >= 0) {
211 if (index >= 0) {
200 beginRemoveRows(QModelIndex(), index, index);
212 beginRemoveRows(QModelIndex(), index, index);
201 impl->m_Events.removeAt(index);
213 impl->m_Events.removeAt(index);
202 impl->m_EventProducts.erase(event.get());
214 impl->m_EventProducts.erase(event.get());
203 endRemoveRows();
215 endRemoveRows();
204 }
216 }
205 }
217 }
206
218
207 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
219 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
208 {
220 {
209 return impl->m_Events;
221 return impl->m_Events;
210 }
222 }
211
223
212 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event,
224 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event,
213 bool refreshEventProducts)
225 bool refreshEventProducts)
214 {
226 {
215 auto eventIndex = indexOf(event);
227 auto eventIndex = indexOf(event);
216 if (eventIndex.isValid()) {
228 if (eventIndex.isValid()) {
217
229
218 if (refreshEventProducts) {
230 if (refreshEventProducts) {
219 // Reparse the associated event products
231 // Reparse the associated event products
220
232
221 auto nbEventProducts = impl->nbEventProducts(event);
233 auto nbEventProducts = impl->nbEventProducts(event);
222 auto newNbOfEventProducts = event->getEventProducts().size();
234 auto newNbOfEventProducts = event->getEventProducts().size();
223 if (newNbOfEventProducts < nbEventProducts) {
235 if (newNbOfEventProducts < nbEventProducts) {
224 beginRemoveRows(eventIndex, newNbOfEventProducts, nbEventProducts - 1);
236 beginRemoveRows(eventIndex, newNbOfEventProducts, nbEventProducts - 1);
225 impl->m_EventProducts.erase(event.get());
237 impl->m_EventProducts.erase(event.get());
226 impl->parseEventProduct(event);
238 impl->parseEventProduct(event);
227 endRemoveRows();
239 endRemoveRows();
228 }
240 }
229 else if (newNbOfEventProducts > nbEventProducts) {
241 else if (newNbOfEventProducts > nbEventProducts) {
230 beginInsertRows(eventIndex, nbEventProducts, newNbOfEventProducts - 1);
242 beginInsertRows(eventIndex, nbEventProducts, newNbOfEventProducts - 1);
231 impl->m_EventProducts.erase(event.get());
243 impl->m_EventProducts.erase(event.get());
232 impl->parseEventProduct(event);
244 impl->parseEventProduct(event);
233 endInsertRows();
245 endInsertRows();
234 }
246 }
235 else { // newNbOfEventProducts == nbEventProducts
247 else { // newNbOfEventProducts == nbEventProducts
236 impl->m_EventProducts.erase(event.get());
248 impl->m_EventProducts.erase(event.get());
237 impl->parseEventProduct(event);
249 impl->parseEventProduct(event);
238 }
250 }
239 }
251 }
240
252
241 // Refreshes the event line
253 // Refreshes the event line
242 auto colCount = columnCount();
254 auto colCount = columnCount();
243 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
255 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
244
256
245 // Also refreshes its children event products
257 // Also refreshes its children event products
246 impl->refreshChildrenOfIndex(this, eventIndex);
258 impl->refreshChildrenOfIndex(this, eventIndex);
247 }
259 }
248 else {
260 else {
249 qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
261 qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
250 }
262 }
251 }
263 }
252
264
253 QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
265 QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
254 {
266 {
255 auto row = impl->m_Events.indexOf(event);
267 auto row = impl->m_Events.indexOf(event);
256 if (row >= 0) {
268 if (row >= 0) {
257 return index(row, 0);
269 return index(row, 0);
258 }
270 }
259
271
260 return QModelIndex();
272 return QModelIndex();
261 }
273 }
262
274
263 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
275 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
264 {
276 {
265 if (!hasIndex(row, column, parent)) {
277 if (!hasIndex(row, column, parent)) {
266 return QModelIndex();
278 return QModelIndex();
267 }
279 }
268
280
269 switch (itemTypeOf(parent)) {
281 switch (itemTypeOf(parent)) {
270 case CatalogueEventsModel::ItemType::Root:
282 case CatalogueEventsModel::ItemType::Root:
271 return createIndex(row, column);
283 return createIndex(row, column);
272 case CatalogueEventsModel::ItemType::Event: {
284 case CatalogueEventsModel::ItemType::Event: {
273 auto event = getEvent(parent);
285 auto event = getEvent(parent);
274 return createIndex(row, column, event.get());
286 return createIndex(row, column, event.get());
275 }
287 }
276 case CatalogueEventsModel::ItemType::EventProduct:
288 case CatalogueEventsModel::ItemType::EventProduct:
277 break;
289 break;
278 default:
290 default:
279 break;
291 break;
280 }
292 }
281
293
282 return QModelIndex();
294 return QModelIndex();
283 }
295 }
284
296
285 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
297 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
286 {
298 {
287 switch (itemTypeOf(index)) {
299 switch (itemTypeOf(index)) {
288 case CatalogueEventsModel::ItemType::EventProduct: {
300 case CatalogueEventsModel::ItemType::EventProduct: {
289 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
301 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
290 auto it
302 auto it
291 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
303 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
292 [parentEvent](auto event) { return event.get() == parentEvent; });
304 [parentEvent](auto event) { return event.get() == parentEvent; });
293
305
294 if (it != impl->m_Events.cend()) {
306 if (it != impl->m_Events.cend()) {
295 return createIndex(it - impl->m_Events.cbegin(), 0);
307 return createIndex(it - impl->m_Events.cbegin(), 0);
296 }
308 }
297 else {
309 else {
298 return QModelIndex();
310 return QModelIndex();
299 }
311 }
300 }
312 }
301 case CatalogueEventsModel::ItemType::Root:
313 case CatalogueEventsModel::ItemType::Root:
302 break;
314 break;
303 case CatalogueEventsModel::ItemType::Event:
315 case CatalogueEventsModel::ItemType::Event:
304 break;
316 break;
305 default:
317 default:
306 break;
318 break;
307 }
319 }
308
320
309 return QModelIndex();
321 return QModelIndex();
310 }
322 }
311
323
312 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
324 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
313 {
325 {
314 if (parent.column() > 0) {
326 if (parent.column() > 0) {
315 return 0;
327 return 0;
316 }
328 }
317
329
318 switch (itemTypeOf(parent)) {
330 switch (itemTypeOf(parent)) {
319 case CatalogueEventsModel::ItemType::Root:
331 case CatalogueEventsModel::ItemType::Root:
320 return impl->m_Events.count();
332 return impl->m_Events.count();
321 case CatalogueEventsModel::ItemType::Event: {
333 case CatalogueEventsModel::ItemType::Event: {
322 auto event = getEvent(parent);
334 auto event = getEvent(parent);
323 return impl->m_EventProducts[event.get()].count();
335 return impl->m_EventProducts[event.get()].count();
324 }
336 }
325 case CatalogueEventsModel::ItemType::EventProduct:
337 case CatalogueEventsModel::ItemType::EventProduct:
326 break;
338 break;
327 default:
339 default:
328 break;
340 break;
329 }
341 }
330
342
331 return 0;
343 return 0;
332 }
344 }
333
345
334 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
346 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
335 {
347 {
336 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
348 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
337 }
349 }
338
350
339 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
351 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
340 {
352 {
341 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
353 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
342 }
354 }
343
355
344 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
356 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
345 {
357 {
346 if (index.isValid()) {
358 if (index.isValid()) {
347
359
348 auto type = itemTypeOf(index);
360 auto type = itemTypeOf(index);
349 if (type == CatalogueEventsModel::ItemType::Event) {
361 if (type == CatalogueEventsModel::ItemType::Event) {
350 auto event = getEvent(index);
362 auto event = getEvent(index);
351 switch (role) {
363 switch (role) {
352 case Qt::DisplayRole:
364 case Qt::DisplayRole:
353 return impl->eventData(index.column(), event);
365 return impl->eventData(index.column(), event);
354 break;
366 break;
355 }
367 }
356 }
368 }
357 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
369 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
358 auto product = getEventProduct(index);
370 auto product = getEventProduct(index);
359 switch (role) {
371 switch (role) {
360 case Qt::DisplayRole:
372 case Qt::DisplayRole:
361 return impl->eventProductData(index.column(), product);
373 return impl->eventProductData(index.column(), product);
362 break;
374 break;
363 }
375 }
364 }
376 }
365 }
377 }
366
378
367 return QVariant{};
379 return QVariant{};
368 }
380 }
369
381
370 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
382 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
371 {
383 {
372 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
384 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
373 return impl->columnNames().value(section);
385 return impl->columnNames().value(section);
374 }
386 }
375
387
376 return QVariant();
388 return QVariant();
377 }
389 }
378
390
379 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
391 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
380 {
392 {
381 beginResetModel();
393 beginResetModel();
382 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
394 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
383 [this, column, order](auto e1, auto e2) {
395 [this, column, order](auto e1, auto e2) {
384 auto data1 = impl->sortData(column, e1);
396 auto data1 = impl->sortData(column, e1);
385 auto data2 = impl->sortData(column, e2);
397 auto data2 = impl->sortData(column, e2);
386
398
387 auto result = data1.toString() < data2.toString();
399 auto result = data1.toString() < data2.toString();
388
400
389 return order == Qt::AscendingOrder ? result : !result;
401 return order == Qt::AscendingOrder ? result : !result;
390 });
402 });
391
403
392 endResetModel();
404 endResetModel();
393 emit modelSorted();
405 emit modelSorted();
394 }
406 }
395
407
396 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
408 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
397 {
409 {
398 return Qt::CopyAction | Qt::MoveAction;
410 return Qt::CopyAction | Qt::MoveAction;
399 }
411 }
400
412
401 QStringList CatalogueEventsModel::mimeTypes() const
413 QStringList CatalogueEventsModel::mimeTypes() const
402 {
414 {
403 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_SOURCE_CATALOGUE_LIST, MIME_TYPE_TIME_RANGE};
415 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_SOURCE_CATALOGUE_LIST, MIME_TYPE_TIME_RANGE};
404 }
416 }
405
417
406 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
418 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
407 {
419 {
408 auto mimeData = new QMimeData;
420 auto mimeData = new QMimeData;
409
421
410 bool isFirst = true;
422 bool isFirst = true;
411
423
412 QVector<std::shared_ptr<DBEvent> > eventList;
424 QVector<std::shared_ptr<DBEvent> > eventList;
413 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
425 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
414
426
415 SqpRange firstTimeRange;
427 SqpRange firstTimeRange;
416 for (const auto &index : indexes) {
428 for (const auto &index : indexes) {
417 if (index.column() == 0) { // only the first column
429 if (index.column() == 0) { // only the first column
418
430
419 auto type = itemTypeOf(index);
431 auto type = itemTypeOf(index);
420 if (type == ItemType::Event) {
432 if (type == ItemType::Event) {
421 auto event = getEvent(index);
433 auto event = getEvent(index);
422 eventList << event;
434 eventList << event;
423
435
424 if (isFirst) {
436 if (isFirst) {
425 isFirst = false;
437 isFirst = false;
426 firstTimeRange.m_TStart = event->getTStart();
438 firstTimeRange.m_TStart = event->getTStart();
427 firstTimeRange.m_TEnd = event->getTEnd();
439 firstTimeRange.m_TEnd = event->getTEnd();
428 }
440 }
429 }
441 }
430 else if (type == ItemType::EventProduct) {
442 else if (type == ItemType::EventProduct) {
431 auto product = getEventProduct(index);
443 auto product = getEventProduct(index);
432 eventProductList << product;
444 eventProductList << product;
433
445
434 if (isFirst) {
446 if (isFirst) {
435 isFirst = false;
447 isFirst = false;
436 firstTimeRange.m_TStart = product->getTStart();
448 firstTimeRange.m_TStart = product->getTStart();
437 firstTimeRange.m_TEnd = product->getTEnd();
449 firstTimeRange.m_TEnd = product->getTEnd();
438 }
450 }
439 }
451 }
440 }
452 }
441 }
453 }
442
454
443 if (!eventList.isEmpty() && eventProductList.isEmpty()) {
455 if (!eventList.isEmpty() && eventProductList.isEmpty()) {
444 auto eventsEncodedData = sqpApp->catalogueController().mimeDataForEvents(eventList);
456 auto eventsEncodedData = sqpApp->catalogueController().mimeDataForEvents(eventList);
445 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
457 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
446
458
447 auto sourceCataloguesEncodedData
459 auto sourceCataloguesEncodedData
448 = sqpApp->catalogueController().mimeDataForCatalogues(impl->m_SourceCatalogue);
460 = sqpApp->catalogueController().mimeDataForCatalogues(impl->m_SourceCatalogue);
449 mimeData->setData(MIME_TYPE_SOURCE_CATALOGUE_LIST, sourceCataloguesEncodedData);
461 mimeData->setData(MIME_TYPE_SOURCE_CATALOGUE_LIST, sourceCataloguesEncodedData);
450 }
462 }
451
463
452 if (eventList.count() + eventProductList.count() == 1) {
464 if (eventList.count() + eventProductList.count() == 1) {
453 // No time range MIME data if multiple events are dragged
465 // No time range MIME data if multiple events are dragged
454 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
466 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
455 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
467 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
456 }
468 }
457
469
458 return mimeData;
470 return mimeData;
459 }
471 }
460
472
461 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
473 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
462 {
474 {
463 if (!index.isValid()) {
475 if (!index.isValid()) {
464 return ItemType::Root;
476 return ItemType::Root;
465 }
477 }
466 else if (index.internalPointer() == nullptr) {
478 else if (index.internalPointer() == nullptr) {
467 return ItemType::Event;
479 return ItemType::Event;
468 }
480 }
469 else {
481 else {
470 return ItemType::EventProduct;
482 return ItemType::EventProduct;
471 }
483 }
472 }
484 }
@@ -1,594 +1,629
1 #include "Catalogue/CatalogueEventsWidget.h"
1 #include "Catalogue/CatalogueEventsWidget.h"
2 #include "ui_CatalogueEventsWidget.h"
2 #include "ui_CatalogueEventsWidget.h"
3
3
4 #include <Catalogue/CatalogueController.h>
4 #include <Catalogue/CatalogueController.h>
5 #include <Catalogue/CatalogueEventsModel.h>
5 #include <Catalogue/CatalogueEventsModel.h>
6 #include <Catalogue/CatalogueExplorerHelper.h>
6 #include <Catalogue/CatalogueExplorerHelper.h>
7 #include <CatalogueDao.h>
7 #include <CatalogueDao.h>
8 #include <DBCatalogue.h>
8 #include <DBCatalogue.h>
9 #include <DBEventProduct.h>
9 #include <DBEventProduct.h>
10 #include <DataSource/DataSourceController.h>
10 #include <DataSource/DataSourceController.h>
11 #include <DataSource/DataSourceItem.h>
11 #include <DataSource/DataSourceItem.h>
12 #include <SqpApplication.h>
12 #include <SqpApplication.h>
13 #include <Variable/Variable.h>
13 #include <Variable/Variable.h>
14 #include <Variable/VariableController.h>
14 #include <Variable/VariableController.h>
15 #include <Visualization/VisualizationGraphWidget.h>
15 #include <Visualization/VisualizationGraphWidget.h>
16 #include <Visualization/VisualizationTabWidget.h>
16 #include <Visualization/VisualizationTabWidget.h>
17 #include <Visualization/VisualizationWidget.h>
17 #include <Visualization/VisualizationWidget.h>
18 #include <Visualization/VisualizationZoneWidget.h>
18 #include <Visualization/VisualizationZoneWidget.h>
19
19
20 #include <QDialog>
20 #include <QDialog>
21 #include <QDialogButtonBox>
21 #include <QDialogButtonBox>
22 #include <QKeyEvent>
22 #include <QListWidget>
23 #include <QListWidget>
23 #include <QMessageBox>
24 #include <QMessageBox>
24
25
25 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
26 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
26
27
27 /// Fixed size of the validation column
28 const auto VALIDATION_COLUMN_SIZE = 35;
29
30 /// Percentage added to the range of a event when it is displayed
28 /// Percentage added to the range of a event when it is displayed
31 const auto EVENT_RANGE_MARGE = 30; // in %
29 const auto EVENT_RANGE_MARGE = 30; // in %
32
30
33 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
31 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
34
32
35 CatalogueEventsModel *m_Model = nullptr;
33 CatalogueEventsModel *m_Model = nullptr;
36 QStringList m_ZonesForTimeMode;
34 QStringList m_ZonesForTimeMode;
37 QString m_ZoneForGraphMode;
35 QString m_ZoneForGraphMode;
38 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
36 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
39 bool m_AllEventDisplayed = false;
37 bool m_AllEventDisplayed = false;
40 QVector<VisualizationGraphWidget *> m_CustomGraphs;
38 QVector<VisualizationGraphWidget *> m_CustomGraphs;
41
39
42 VisualizationWidget *m_VisualizationWidget = nullptr;
40 VisualizationWidget *m_VisualizationWidget = nullptr;
43
41
44 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget)
42 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget)
45 {
43 {
46 widget->ui->treeView->setSortingEnabled(false);
44 widget->ui->treeView->setSortingEnabled(false);
47 m_Model->setSourceCatalogues(m_DisplayedCatalogues);
45 m_Model->setSourceCatalogues(m_DisplayedCatalogues);
48 m_Model->setEvents(events);
46 m_Model->setEvents(events);
49 widget->ui->treeView->setSortingEnabled(true);
47 widget->ui->treeView->setSortingEnabled(true);
50
48
51 for (auto event : events) {
49 for (auto event : events) {
52 if (sqpApp->catalogueController().eventHasChanges(event)) {
50 if (sqpApp->catalogueController().eventHasChanges(event)) {
53 auto index = m_Model->indexOf(event);
51 auto index = m_Model->indexOf(event);
54 widget->setEventChanges(event, true);
52 widget->setEventChanges(event, true);
55 }
53 }
56 }
54 }
57 }
55 }
58
56
59 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
57 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
60 {
58 {
61 treeView->setSortingEnabled(false);
59 treeView->setSortingEnabled(false);
62 m_Model->addEvent(event);
60 m_Model->addEvent(event);
63 treeView->setSortingEnabled(true);
61 treeView->setSortingEnabled(true);
64 }
62 }
65
63
66 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
64 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
67 {
65 {
68 treeView->setSortingEnabled(false);
66 treeView->setSortingEnabled(false);
69 m_Model->removeEvent(event);
67 m_Model->removeEvent(event);
70 treeView->setSortingEnabled(true);
68 treeView->setSortingEnabled(true);
71 }
69 }
72
70
73 QStringList getAvailableVisualizationZoneList() const
71 QStringList getAvailableVisualizationZoneList() const
74 {
72 {
75 if (m_VisualizationWidget) {
73 if (m_VisualizationWidget) {
76 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
74 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
77 return tab->availableZoneWidgets();
75 return tab->availableZoneWidgets();
78 }
76 }
79 }
77 }
80
78
81 return QStringList{};
79 return QStringList{};
82 }
80 }
83
81
84 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
82 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
85 bool allowMultiSelection, const QPoint &location)
83 bool allowMultiSelection, const QPoint &location)
86 {
84 {
87 auto availableZones = getAvailableVisualizationZoneList();
85 auto availableZones = getAvailableVisualizationZoneList();
88 if (availableZones.isEmpty()) {
86 if (availableZones.isEmpty()) {
89 return QStringList{};
87 return QStringList{};
90 }
88 }
91
89
92 QDialog d(parent, Qt::Tool);
90 QDialog d(parent, Qt::Tool);
93 d.setWindowTitle("Choose a zone");
91 d.setWindowTitle("Choose a zone");
94 auto layout = new QVBoxLayout{&d};
92 auto layout = new QVBoxLayout{&d};
95 layout->setContentsMargins(0, 0, 0, 0);
93 layout->setContentsMargins(0, 0, 0, 0);
96 auto listWidget = new QListWidget{&d};
94 auto listWidget = new QListWidget{&d};
97 layout->addWidget(listWidget);
95 layout->addWidget(listWidget);
98
96
99 QSet<QListWidgetItem *> checkedItems;
97 QSet<QListWidgetItem *> checkedItems;
100 for (auto zone : availableZones) {
98 for (auto zone : availableZones) {
101 auto item = new QListWidgetItem{zone};
99 auto item = new QListWidgetItem{zone};
102 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
100 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
103 if (selectedZones.contains(zone)) {
101 if (selectedZones.contains(zone)) {
104 item->setCheckState(Qt::Checked);
102 item->setCheckState(Qt::Checked);
105 checkedItems << item;
103 checkedItems << item;
106 }
104 }
107 else {
105 else {
108 item->setCheckState(Qt::Unchecked);
106 item->setCheckState(Qt::Unchecked);
109 }
107 }
110
108
111 listWidget->addItem(item);
109 listWidget->addItem(item);
112 }
110 }
113
111
114 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
112 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
115 layout->addWidget(buttonBox);
113 layout->addWidget(buttonBox);
116
114
117 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
115 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
118 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
116 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
119
117
120 QObject::connect(listWidget, &QListWidget::itemChanged,
118 QObject::connect(listWidget, &QListWidget::itemChanged,
121 [&checkedItems, allowMultiSelection, listWidget](auto item) {
119 [&checkedItems, allowMultiSelection, listWidget](auto item) {
122 if (item->checkState() == Qt::Checked) {
120 if (item->checkState() == Qt::Checked) {
123 if (!allowMultiSelection) {
121 if (!allowMultiSelection) {
124 for (auto checkedItem : checkedItems) {
122 for (auto checkedItem : checkedItems) {
125 listWidget->blockSignals(true);
123 listWidget->blockSignals(true);
126 checkedItem->setCheckState(Qt::Unchecked);
124 checkedItem->setCheckState(Qt::Unchecked);
127 listWidget->blockSignals(false);
125 listWidget->blockSignals(false);
128 }
126 }
129
127
130 checkedItems.clear();
128 checkedItems.clear();
131 }
129 }
132 checkedItems << item;
130 checkedItems << item;
133 }
131 }
134 else {
132 else {
135 checkedItems.remove(item);
133 checkedItems.remove(item);
136 }
134 }
137 });
135 });
138
136
139 QStringList result;
137 QStringList result;
140
138
141 d.setMinimumWidth(120);
139 d.setMinimumWidth(120);
142 d.resize(d.minimumSizeHint());
140 d.resize(d.minimumSizeHint());
143 d.move(location);
141 d.move(location);
144 if (d.exec() == QDialog::Accepted) {
142 if (d.exec() == QDialog::Accepted) {
145 for (auto item : checkedItems) {
143 for (auto item : checkedItems) {
146 result += item->text();
144 result += item->text();
147 }
145 }
148 }
146 }
149 else {
147 else {
150 result = selectedZones;
148 result = selectedZones;
151 }
149 }
152
150
153 return result;
151 return result;
154 }
152 }
155
153
156 void updateForTimeMode(QTreeView *treeView)
154 void updateForTimeMode(QTreeView *treeView)
157 {
155 {
158 auto selectedRows = treeView->selectionModel()->selectedRows();
156 auto selectedRows = treeView->selectionModel()->selectedRows();
159
157
160 if (selectedRows.count() == 1) {
158 if (selectedRows.count() == 1) {
161 auto event = m_Model->getEvent(selectedRows.first());
159 auto event = m_Model->getEvent(selectedRows.first());
162 if (event) {
160 if (event) {
163 if (m_VisualizationWidget) {
161 if (m_VisualizationWidget) {
164 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
162 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
165
163
166 for (auto zoneName : m_ZonesForTimeMode) {
164 for (auto zoneName : m_ZonesForTimeMode) {
167 if (auto zone = tab->getZoneWithName(zoneName)) {
165 if (auto zone = tab->getZoneWithName(zoneName)) {
168 SqpRange eventRange;
166 SqpRange eventRange;
169 eventRange.m_TStart = event->getTStart();
167 eventRange.m_TStart = event->getTStart();
170 eventRange.m_TEnd = event->getTEnd();
168 eventRange.m_TEnd = event->getTEnd();
171 zone->setZoneRange(eventRange);
169 zone->setZoneRange(eventRange);
172 }
170 }
173 }
171 }
174 }
172 }
175 else {
173 else {
176 qCWarning(LOG_CatalogueEventsWidget())
174 qCWarning(LOG_CatalogueEventsWidget())
177 << "updateTimeZone: no tab found in the visualization";
175 << "updateTimeZone: no tab found in the visualization";
178 }
176 }
179 }
177 }
180 else {
178 else {
181 qCWarning(LOG_CatalogueEventsWidget())
179 qCWarning(LOG_CatalogueEventsWidget())
182 << "updateTimeZone: visualization widget not found";
180 << "updateTimeZone: visualization widget not found";
183 }
181 }
184 }
182 }
185 }
183 }
186 else {
184 else {
187 qCWarning(LOG_CatalogueEventsWidget())
185 qCWarning(LOG_CatalogueEventsWidget())
188 << "updateTimeZone: not compatible with multiple events selected";
186 << "updateTimeZone: not compatible with multiple events selected";
189 }
187 }
190 }
188 }
191
189
192 QVector<SqpRange> getGraphRanges(const std::shared_ptr<DBEvent> &event)
190 QVector<SqpRange> getGraphRanges(const std::shared_ptr<DBEvent> &event)
193 {
191 {
194 // Retrieves the range of each product and the maximum size
192 // Retrieves the range of each product and the maximum size
195 QVector<SqpRange> graphRanges;
193 QVector<SqpRange> graphRanges;
196 double maxDt = 0;
194 double maxDt = 0;
197 for (auto eventProduct : event->getEventProducts()) {
195 for (auto eventProduct : event->getEventProducts()) {
198 SqpRange eventRange;
196 SqpRange eventRange;
199 eventRange.m_TStart = eventProduct.getTStart();
197 eventRange.m_TStart = eventProduct.getTStart();
200 eventRange.m_TEnd = eventProduct.getTEnd();
198 eventRange.m_TEnd = eventProduct.getTEnd();
201 graphRanges << eventRange;
199 graphRanges << eventRange;
202
200
203 auto dt = eventRange.m_TEnd - eventRange.m_TStart;
201 auto dt = eventRange.m_TEnd - eventRange.m_TStart;
204 if (dt > maxDt) {
202 if (dt > maxDt) {
205 maxDt = dt;
203 maxDt = dt;
206 }
204 }
207 }
205 }
208
206
209 // Adds the marge
207 // Adds the marge
210 maxDt *= (100.0 + EVENT_RANGE_MARGE) / 100.0;
208 maxDt *= (100.0 + EVENT_RANGE_MARGE) / 100.0;
211
209
212 // Corrects the graph ranges so that they all have the same size
210 // Corrects the graph ranges so that they all have the same size
213 QVector<SqpRange> correctedGraphRanges;
211 QVector<SqpRange> correctedGraphRanges;
214 for (auto range : graphRanges) {
212 for (auto range : graphRanges) {
215 auto dt = range.m_TEnd - range.m_TStart;
213 auto dt = range.m_TEnd - range.m_TStart;
216 auto diff = qAbs((maxDt - dt) / 2.0);
214 auto diff = qAbs((maxDt - dt) / 2.0);
217
215
218 SqpRange correctedRange;
216 SqpRange correctedRange;
219 correctedRange.m_TStart = range.m_TStart - diff;
217 correctedRange.m_TStart = range.m_TStart - diff;
220 correctedRange.m_TEnd = range.m_TEnd + diff;
218 correctedRange.m_TEnd = range.m_TEnd + diff;
221
219
222 correctedGraphRanges << correctedRange;
220 correctedGraphRanges << correctedRange;
223 }
221 }
224
222
225 return correctedGraphRanges;
223 return correctedGraphRanges;
226 }
224 }
227
225
228 void updateForGraphMode(CatalogueEventsWidget *catalogueEventWidget)
226 void updateForGraphMode(CatalogueEventsWidget *catalogueEventWidget)
229 {
227 {
230 auto selectedRows = catalogueEventWidget->ui->treeView->selectionModel()->selectedRows();
228 auto selectedRows = catalogueEventWidget->ui->treeView->selectionModel()->selectedRows();
231 if (selectedRows.count() != 1) {
229 if (selectedRows.count() != 1) {
232 qCWarning(LOG_CatalogueEventsWidget())
230 qCWarning(LOG_CatalogueEventsWidget())
233 << "updateGraphMode: not compatible with multiple events selected";
231 << "updateGraphMode: not compatible with multiple events selected";
234 return;
232 return;
235 }
233 }
236
234
237 if (!m_VisualizationWidget) {
235 if (!m_VisualizationWidget) {
238 qCWarning(LOG_CatalogueEventsWidget())
236 qCWarning(LOG_CatalogueEventsWidget())
239 << "updateGraphMode: visualization widget not found";
237 << "updateGraphMode: visualization widget not found";
240 return;
238 return;
241 }
239 }
242
240
243 auto event = m_Model->getEvent(selectedRows.first());
241 auto event = m_Model->getEvent(selectedRows.first());
244 if (!event) {
242 if (!event) {
245 // A event product is probably selected
243 // A event product is probably selected
246 qCInfo(LOG_CatalogueEventsWidget()) << "updateGraphMode: no events are selected";
244 qCInfo(LOG_CatalogueEventsWidget()) << "updateGraphMode: no events are selected";
247 return;
245 return;
248 }
246 }
249
247
250 auto tab = m_VisualizationWidget->currentTabWidget();
248 auto tab = m_VisualizationWidget->currentTabWidget();
251 if (!tab) {
249 if (!tab) {
252 qCWarning(LOG_CatalogueEventsWidget())
250 qCWarning(LOG_CatalogueEventsWidget())
253 << "updateGraphMode: no tab found in the visualization";
251 << "updateGraphMode: no tab found in the visualization";
254 return;
252 return;
255 }
253 }
256
254
257 auto zone = tab->getZoneWithName(m_ZoneForGraphMode);
255 auto zone = tab->getZoneWithName(m_ZoneForGraphMode);
258 if (!zone) {
256 if (!zone) {
259 qCWarning(LOG_CatalogueEventsWidget()) << "updateGraphMode: zone not found";
257 qCWarning(LOG_CatalogueEventsWidget()) << "updateGraphMode: zone not found";
260 return;
258 return;
261 }
259 }
262
260
263 // Closes the previous graph and delete the asociated variables
261 // Closes the previous graph and delete the asociated variables
264 for (auto graph : m_CustomGraphs) {
262 for (auto graph : m_CustomGraphs) {
265 graph->close();
263 graph->close();
266 auto variables = graph->variables().toVector();
264 auto variables = graph->variables().toVector();
267
265
268 QMetaObject::invokeMethod(&sqpApp->variableController(), "deleteVariables",
266 QMetaObject::invokeMethod(&sqpApp->variableController(), "deleteVariables",
269 Qt::QueuedConnection,
267 Qt::QueuedConnection,
270 Q_ARG(QVector<std::shared_ptr<Variable> >, variables));
268 Q_ARG(QVector<std::shared_ptr<Variable> >, variables));
271 }
269 }
272 m_CustomGraphs.clear();
270 m_CustomGraphs.clear();
273
271
274 // Closes the remaining graphs inside the zone
272 // Closes the remaining graphs inside the zone
275 zone->closeAllGraphs();
273 zone->closeAllGraphs();
276
274
277 // Calculates the range of each graph which will be created
275 // Calculates the range of each graph which will be created
278 auto graphRange = getGraphRanges(event);
276 auto graphRange = getGraphRanges(event);
279
277
280 // Loops through the event products and create the graph
278 // Loops through the event products and create the graph
281 auto itRange = graphRange.cbegin();
279 auto itRange = graphRange.cbegin();
282 for (auto eventProduct : event->getEventProducts()) {
280 for (auto eventProduct : event->getEventProducts()) {
283 auto productId = eventProduct.getProductId();
281 auto productId = eventProduct.getProductId();
284
282
285 auto range = *itRange;
283 auto range = *itRange;
286 ++itRange;
284 ++itRange;
287
285
288 SqpRange productRange;
286 SqpRange productRange;
289 productRange.m_TStart = eventProduct.getTStart();
287 productRange.m_TStart = eventProduct.getTStart();
290 productRange.m_TEnd = eventProduct.getTEnd();
288 productRange.m_TEnd = eventProduct.getTEnd();
291
289
292 auto context = new QObject{catalogueEventWidget};
290 auto context = new QObject{catalogueEventWidget};
293 QObject::connect(
291 QObject::connect(
294 &sqpApp->variableController(), &VariableController::variableAdded, context,
292 &sqpApp->variableController(), &VariableController::variableAdded, context,
295 [this, catalogueEventWidget, zone, context, event, range, productRange,
293 [this, catalogueEventWidget, zone, context, event, range, productRange,
296 productId](auto variable) {
294 productId](auto variable) {
297
295
298 if (variable->metadata().value(DataSourceItem::ID_DATA_KEY).toString()
296 if (variable->metadata().value(DataSourceItem::ID_DATA_KEY).toString()
299 == productId) {
297 == productId) {
300 auto graph = zone->createGraph(variable);
298 auto graph = zone->createGraph(variable);
301 graph->setAutoRangeOnVariableInitialization(false);
299 graph->setAutoRangeOnVariableInitialization(false);
302
300
303 auto selectionZone
301 auto selectionZone
304 = graph->addSelectionZone(event->getName(), productRange);
302 = graph->addSelectionZone(event->getName(), productRange);
305 emit catalogueEventWidget->selectionZoneAdded(event, productId,
303 emit catalogueEventWidget->selectionZoneAdded(event, productId,
306 selectionZone);
304 selectionZone);
307 m_CustomGraphs << graph;
305 m_CustomGraphs << graph;
308
306
309 graph->setGraphRange(range, true);
307 graph->setGraphRange(range, true);
310
308
311 // Removes the graph from the graph list if it is closed manually
309 // Removes the graph from the graph list if it is closed manually
312 QObject::connect(graph, &VisualizationGraphWidget::destroyed,
310 QObject::connect(graph, &VisualizationGraphWidget::destroyed,
313 [this, graph]() { m_CustomGraphs.removeAll(graph); });
311 [this, graph]() { m_CustomGraphs.removeAll(graph); });
314
312
315 delete context; // removes the connection
313 delete context; // removes the connection
316 }
314 }
317 },
315 },
318 Qt::QueuedConnection);
316 Qt::QueuedConnection);
319
317
320 QMetaObject::invokeMethod(&sqpApp->dataSourceController(),
318 QMetaObject::invokeMethod(&sqpApp->dataSourceController(),
321 "requestVariableFromProductIdKey", Qt::QueuedConnection,
319 "requestVariableFromProductIdKey", Qt::QueuedConnection,
322 Q_ARG(QString, productId));
320 Q_ARG(QString, productId));
323 }
321 }
324 }
322 }
325
323
326 void getSelectedItems(
324 void getSelectedItems(
327 QTreeView *treeView, QVector<std::shared_ptr<DBEvent> > &events,
325 QTreeView *treeView, QVector<std::shared_ptr<DBEvent> > &events,
328 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > &eventProducts)
326 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > &eventProducts)
329 {
327 {
330 for (auto rowIndex : treeView->selectionModel()->selectedRows()) {
328 for (auto rowIndex : treeView->selectionModel()->selectedRows()) {
331 auto itemType = m_Model->itemTypeOf(rowIndex);
329 auto itemType = m_Model->itemTypeOf(rowIndex);
332 if (itemType == CatalogueEventsModel::ItemType::Event) {
330 if (itemType == CatalogueEventsModel::ItemType::Event) {
333 events << m_Model->getEvent(rowIndex);
331 events << m_Model->getEvent(rowIndex);
334 }
332 }
335 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
333 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
336 eventProducts << qMakePair(m_Model->getParentEvent(rowIndex),
334 eventProducts << qMakePair(m_Model->getParentEvent(rowIndex),
337 m_Model->getEventProduct(rowIndex));
335 m_Model->getEventProduct(rowIndex));
338 }
336 }
339 }
337 }
340 }
338 }
341 };
339 };
342
340
343 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
341 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
344 : QWidget(parent),
342 : QWidget(parent),
345 ui(new Ui::CatalogueEventsWidget),
343 ui(new Ui::CatalogueEventsWidget),
346 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
344 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
347 {
345 {
348 ui->setupUi(this);
346 ui->setupUi(this);
349
347
350 impl->m_Model = new CatalogueEventsModel{this};
348 impl->m_Model = new CatalogueEventsModel{this};
351 ui->treeView->setModel(impl->m_Model);
349 ui->treeView->setModel(impl->m_Model);
352
350
353 ui->treeView->setSortingEnabled(true);
351 ui->treeView->setSortingEnabled(true);
354 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
352 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
355 ui->treeView->setDragEnabled(true);
353 ui->treeView->setDragEnabled(true);
356
354
355
357 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
356 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
358 if (checked) {
357 if (checked) {
359 ui->btnChart->setChecked(false);
358 ui->btnChart->setChecked(false);
360 impl->m_ZonesForTimeMode
359 impl->m_ZonesForTimeMode
361 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
360 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
362 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
361 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
363
362
364 impl->updateForTimeMode(ui->treeView);
363 impl->updateForTimeMode(ui->treeView);
365 }
364 }
366 });
365 });
367
366
368 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
367 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
369 if (checked) {
368 if (checked) {
370 ui->btnTime->setChecked(false);
369 ui->btnTime->setChecked(false);
371 impl->m_ZoneForGraphMode
370 impl->m_ZoneForGraphMode
372 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
371 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
373 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
372 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
374 .value(0);
373 .value(0);
375
374
376 impl->updateForGraphMode(this);
375 impl->updateForGraphMode(this);
377 }
376 }
378 });
377 });
379
378
380 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
379 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
381 QVector<std::shared_ptr<DBEvent> > events;
380 QVector<std::shared_ptr<DBEvent> > events;
382 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
381 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
383 impl->getSelectedItems(ui->treeView, events, eventProducts);
382 impl->getSelectedItems(ui->treeView, events, eventProducts);
384
383
385 if (!events.isEmpty() && eventProducts.isEmpty()) {
384 if (!events.isEmpty() && eventProducts.isEmpty()) {
386
385
387 if (QMessageBox::warning(this, tr("Remove Event(s)"),
386 auto canRemoveEvent
388 tr("The selected event(s) will be permanently removed "
387 = !this->isAllEventsDisplayed()
389 "from the repository!\nAre you sure you want to continue?"),
388 || (QMessageBox::warning(
390 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
389 this, tr("Remove Event(s)"),
391 == QMessageBox::Yes) {
390 tr("The selected event(s) will be permanently removed "
391 "from the repository!\nAre you sure you want to continue?"),
392 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
393 == QMessageBox::Yes);
392
394
395 if (canRemoveEvent) {
393 for (auto event : events) {
396 for (auto event : events) {
394 sqpApp->catalogueController().removeEvent(event);
397 if (this->isAllEventsDisplayed()) {
395 impl->removeEvent(event, ui->treeView);
398 sqpApp->catalogueController().removeEvent(event);
399 impl->removeEvent(event, ui->treeView);
400 }
401 else {
402 QVector<std::shared_ptr<DBCatalogue> > modifiedCatalogues;
403 for (auto catalogue : this->displayedCatalogues()) {
404 if (catalogue->removeEvent(event->getUniqId())) {
405 sqpApp->catalogueController().updateCatalogue(catalogue);
406 modifiedCatalogues << catalogue;
407 }
408 }
409 if (!modifiedCatalogues.empty()) {
410 emit eventCataloguesModified(modifiedCatalogues);
411 }
412 }
413 impl->m_Model->removeEvent(event);
396 }
414 }
397
415
416
398 emit this->eventsRemoved(events);
417 emit this->eventsRemoved(events);
399 }
418 }
400 }
419 }
401 });
420 });
402
421
403 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueEventsWidget::emitSelection);
422 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueEventsWidget::emitSelection);
404 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
423 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
405 &CatalogueEventsWidget::emitSelection);
424 &CatalogueEventsWidget::emitSelection);
406
425
407 ui->btnRemove->setEnabled(false); // Disabled by default when nothing is selected
426 ui->btnRemove->setEnabled(false); // Disabled by default when nothing is selected
408 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
427 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
409 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
428 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
410 ui->btnChart->setEnabled(isNotMultiSelection);
429 ui->btnChart->setEnabled(isNotMultiSelection);
411 ui->btnTime->setEnabled(isNotMultiSelection);
430 ui->btnTime->setEnabled(isNotMultiSelection);
412
431
413 if (isNotMultiSelection && ui->btnTime->isChecked()) {
432 if (isNotMultiSelection && ui->btnTime->isChecked()) {
414 impl->updateForTimeMode(ui->treeView);
433 impl->updateForTimeMode(ui->treeView);
415 }
434 }
416 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
435 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
417 impl->updateForGraphMode(this);
436 impl->updateForGraphMode(this);
418 }
437 }
419
438
420 QVector<std::shared_ptr<DBEvent> > events;
439 QVector<std::shared_ptr<DBEvent> > events;
421 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
440 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
422 impl->getSelectedItems(ui->treeView, events, eventProducts);
441 impl->getSelectedItems(ui->treeView, events, eventProducts);
423 ui->btnRemove->setEnabled(!events.isEmpty() && eventProducts.isEmpty());
442 ui->btnRemove->setEnabled(!events.isEmpty() && eventProducts.isEmpty());
424 });
443 });
425
444
426 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
445 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
427 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Tags,
446 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Tags,
428 QHeaderView::Stretch);
447 QHeaderView::Stretch);
429 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
448 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
430 QHeaderView::Fixed);
449 QHeaderView::ResizeToContents);
431 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
450 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
432 QHeaderView::Interactive);
451 QHeaderView::Interactive);
433 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
452 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::TStart,
434 VALIDATION_COLUMN_SIZE);
453 QHeaderView::ResizeToContents);
454 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::TEnd,
455 QHeaderView::ResizeToContents);
435 ui->treeView->header()->setSortIndicatorShown(true);
456 ui->treeView->header()->setSortIndicatorShown(true);
436
457
437 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
458 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
438 auto allEvents = impl->m_Model->events();
459 auto allEvents = impl->m_Model->events();
439 for (auto event : allEvents) {
460 for (auto event : allEvents) {
440 setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event));
461 setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event));
441 }
462 }
442 });
463 });
443
464
444 populateWithAllEvents();
465 populateWithAllEvents();
445 }
466 }
446
467
447 CatalogueEventsWidget::~CatalogueEventsWidget()
468 CatalogueEventsWidget::~CatalogueEventsWidget()
448 {
469 {
449 delete ui;
470 delete ui;
450 }
471 }
451
472
452 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
473 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
453 {
474 {
454 impl->m_VisualizationWidget = visualization;
475 impl->m_VisualizationWidget = visualization;
455 }
476 }
456
477
457 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
478 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
458 {
479 {
459 impl->addEvent(event, ui->treeView);
480 impl->addEvent(event, ui->treeView);
460 }
481 }
461
482
462 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
483 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
463 {
484 {
464 impl->m_Model->refreshEvent(event);
485 impl->m_Model->refreshEvent(event);
465
486
466 auto eventIndex = impl->m_Model->indexOf(event);
487 auto eventIndex = impl->m_Model->indexOf(event);
467 auto validationIndex
488 auto validationIndex
468 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
489 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
469
490
470 if (validationIndex.isValid()) {
491 if (validationIndex.isValid()) {
471 if (hasChanges) {
492 if (hasChanges) {
472 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
493 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
473 auto widget = CatalogueExplorerHelper::buildValidationWidget(
494 auto widget = CatalogueExplorerHelper::buildValidationWidget(
474 ui->treeView,
495 ui->treeView,
475 [this, event]() {
496 [this, event]() {
476 sqpApp->catalogueController().saveEvent(event);
497 sqpApp->catalogueController().saveEvent(event);
477 setEventChanges(event, false);
498 setEventChanges(event, false);
478 },
499 },
479 [this, event]() {
500 [this, event]() {
480 bool removed = false;
501 bool removed = false;
481 sqpApp->catalogueController().discardEvent(event, removed);
502 sqpApp->catalogueController().discardEvent(event, removed);
482 if (removed) {
503 if (removed) {
483 impl->m_Model->removeEvent(event);
504 impl->m_Model->removeEvent(event);
484 }
505 }
485 else {
506 else {
486 setEventChanges(event, false);
507 setEventChanges(event, false);
487 impl->m_Model->refreshEvent(event, true);
508 impl->m_Model->refreshEvent(event, true);
488 }
509 }
489 emitSelection();
510 emitSelection();
490 });
511 });
491 ui->treeView->setIndexWidget(validationIndex, widget);
512 ui->treeView->setIndexWidget(validationIndex, widget);
513 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
514 QHeaderView::ResizeToContents);
492 }
515 }
493 }
516 }
494 else {
517 else {
495 // Note: the widget is destroyed
518 // Note: the widget is destroyed
496 ui->treeView->setIndexWidget(validationIndex, nullptr);
519 ui->treeView->setIndexWidget(validationIndex, nullptr);
497 }
520 }
498 }
521 }
499 else {
522 else {
500 qCWarning(LOG_CatalogueEventsWidget())
523 qCWarning(LOG_CatalogueEventsWidget())
501 << "setEventChanges: the event is not displayed in the model.";
524 << "setEventChanges: the event is not displayed in the model.";
502 }
525 }
503 }
526 }
504
527
505 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
528 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
506 {
529 {
507 return impl->m_DisplayedCatalogues;
530 return impl->m_DisplayedCatalogues;
508 }
531 }
509
532
510 bool CatalogueEventsWidget::isAllEventsDisplayed() const
533 bool CatalogueEventsWidget::isAllEventsDisplayed() const
511 {
534 {
512 return impl->m_AllEventDisplayed;
535 return impl->m_AllEventDisplayed;
513 }
536 }
514
537
515 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
538 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
516 {
539 {
517 return impl->m_Model->indexOf(event).isValid();
540 return impl->m_Model->indexOf(event).isValid();
518 }
541 }
519
542
520 void CatalogueEventsWidget::refreshEvent(const std::shared_ptr<DBEvent> &event)
543 void CatalogueEventsWidget::refreshEvent(const std::shared_ptr<DBEvent> &event)
521 {
544 {
522 impl->m_Model->refreshEvent(event, true);
545 impl->m_Model->refreshEvent(event, true);
523 }
546 }
524
547
525 void CatalogueEventsWidget::populateWithCatalogues(
548 void CatalogueEventsWidget::populateWithCatalogues(
526 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
549 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
527 {
550 {
528 impl->m_DisplayedCatalogues = catalogues;
551 impl->m_DisplayedCatalogues = catalogues;
529 impl->m_AllEventDisplayed = false;
552 impl->m_AllEventDisplayed = false;
530
553
531 QSet<QUuid> eventIds;
554 QSet<QUuid> eventIds;
532 QVector<std::shared_ptr<DBEvent> > events;
555 QVector<std::shared_ptr<DBEvent> > events;
533
556
534 for (auto catalogue : catalogues) {
557 for (auto catalogue : catalogues) {
535 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
558 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
536 for (auto event : catalogueEvents) {
559 for (auto event : catalogueEvents) {
537 if (!eventIds.contains(event->getUniqId())) {
560 if (!eventIds.contains(event->getUniqId())) {
538 events << event;
561 events << event;
539 eventIds.insert(event->getUniqId());
562 eventIds.insert(event->getUniqId());
540 }
563 }
541 }
564 }
542 }
565 }
543
566
544 impl->setEvents(events, this);
567 impl->setEvents(events, this);
545 }
568 }
546
569
547 void CatalogueEventsWidget::populateWithAllEvents()
570 void CatalogueEventsWidget::populateWithAllEvents()
548 {
571 {
549 impl->m_DisplayedCatalogues.clear();
572 impl->m_DisplayedCatalogues.clear();
550 impl->m_AllEventDisplayed = true;
573 impl->m_AllEventDisplayed = true;
551
574
552 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
575 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
553
576
554 QVector<std::shared_ptr<DBEvent> > events;
577 QVector<std::shared_ptr<DBEvent> > events;
555 for (auto event : allEvents) {
578 for (auto event : allEvents) {
556 events << event;
579 events << event;
557 }
580 }
558
581
559 impl->setEvents(events, this);
582 impl->setEvents(events, this);
560 }
583 }
561
584
562 void CatalogueEventsWidget::clear()
585 void CatalogueEventsWidget::clear()
563 {
586 {
564 impl->m_DisplayedCatalogues.clear();
587 impl->m_DisplayedCatalogues.clear();
565 impl->m_AllEventDisplayed = false;
588 impl->m_AllEventDisplayed = false;
566 impl->setEvents({}, this);
589 impl->setEvents({}, this);
567 }
590 }
568
591
569 void CatalogueEventsWidget::refresh()
592 void CatalogueEventsWidget::refresh()
570 {
593 {
571 if (isAllEventsDisplayed()) {
594 if (isAllEventsDisplayed()) {
572 populateWithAllEvents();
595 populateWithAllEvents();
573 }
596 }
574 else if (!impl->m_DisplayedCatalogues.isEmpty()) {
597 else if (!impl->m_DisplayedCatalogues.isEmpty()) {
575 populateWithCatalogues(impl->m_DisplayedCatalogues);
598 populateWithCatalogues(impl->m_DisplayedCatalogues);
576 }
599 }
577 }
600 }
578
601
579 void CatalogueEventsWidget::emitSelection()
602 void CatalogueEventsWidget::emitSelection()
580 {
603 {
581 QVector<std::shared_ptr<DBEvent> > events;
604 QVector<std::shared_ptr<DBEvent> > events;
582 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
605 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
583 impl->getSelectedItems(ui->treeView, events, eventProducts);
606 impl->getSelectedItems(ui->treeView, events, eventProducts);
584
607
585 if (!events.isEmpty() && eventProducts.isEmpty()) {
608 if (!events.isEmpty() && eventProducts.isEmpty()) {
586 emit eventsSelected(events);
609 emit eventsSelected(events);
587 }
610 }
588 else if (events.isEmpty() && !eventProducts.isEmpty()) {
611 else if (events.isEmpty() && !eventProducts.isEmpty()) {
589 emit eventProductsSelected(eventProducts);
612 emit eventProductsSelected(eventProducts);
590 }
613 }
591 else {
614 else {
592 emit selectionCleared();
615 emit selectionCleared();
593 }
616 }
594 }
617 }
618
619
620 void CatalogueEventsWidget::keyPressEvent(QKeyEvent *event)
621 {
622 switch (event->key()) {
623 case Qt::Key_Delete: {
624 ui->btnRemove->click();
625 }
626 default:
627 break;
628 }
629 }
@@ -1,193 +1,203
1 #include "Catalogue/CatalogueExplorer.h"
1 #include "Catalogue/CatalogueExplorer.h"
2 #include "ui_CatalogueExplorer.h"
2 #include "ui_CatalogueExplorer.h"
3
3
4 #include <Catalogue/CatalogueActionManager.h>
4 #include <Catalogue/CatalogueActionManager.h>
5 #include <Catalogue/CatalogueController.h>
5 #include <Catalogue/CatalogueController.h>
6 #include <SqpApplication.h>
6 #include <SqpApplication.h>
7 #include <Visualization/VisualizationGraphWidget.h>
7 #include <Visualization/VisualizationGraphWidget.h>
8 #include <Visualization/VisualizationSelectionZoneItem.h>
8 #include <Visualization/VisualizationSelectionZoneItem.h>
9 #include <Visualization/VisualizationWidget.h>
9 #include <Visualization/VisualizationWidget.h>
10
10
11 #include <DBCatalogue.h>
11 #include <DBCatalogue.h>
12 #include <DBEvent.h>
12 #include <DBEvent.h>
13 #include <DBEventProduct.h>
13 #include <DBEventProduct.h>
14
14
15 #include <unordered_map>
15 #include <unordered_map>
16
16
17 struct CatalogueExplorer::CatalogueExplorerPrivate {
17 struct CatalogueExplorer::CatalogueExplorerPrivate {
18 CatalogueActionManager m_ActionManager;
18 CatalogueActionManager m_ActionManager;
19 std::unordered_map<std::shared_ptr<DBEvent>, QVector<VisualizationSelectionZoneItem *> >
19 std::unordered_map<std::shared_ptr<DBEvent>, QVector<VisualizationSelectionZoneItem *> >
20 m_SelectionZonesPerEvents;
20 m_SelectionZonesPerEvents;
21
21
22 QMetaObject::Connection m_Conn;
22 QMetaObject::Connection m_Conn;
23
23
24 CatalogueExplorerPrivate(CatalogueExplorer *catalogueExplorer)
24 CatalogueExplorerPrivate(CatalogueExplorer *catalogueExplorer)
25 : m_ActionManager(catalogueExplorer)
25 : m_ActionManager(catalogueExplorer)
26 {
26 {
27 }
27 }
28 };
28 };
29
29
30 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
30 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
31 : QDialog(parent, Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint),
31 : QDialog(parent, Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint),
32 ui(new Ui::CatalogueExplorer),
32 ui(new Ui::CatalogueExplorer),
33 impl{spimpl::make_unique_impl<CatalogueExplorerPrivate>(this)}
33 impl{spimpl::make_unique_impl<CatalogueExplorerPrivate>(this)}
34 {
34 {
35 ui->setupUi(this);
35 ui->setupUi(this);
36
36
37 impl->m_ActionManager.installSelectionZoneActions();
37 impl->m_ActionManager.installSelectionZoneActions();
38
38
39 // Updates events and inspector when something is selected in the catalogue widget
39 // Updates events and inspector when something is selected in the catalogue widget
40 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto catalogues) {
40 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto catalogues) {
41 if (catalogues.count() == 1) {
41 if (catalogues.count() == 1) {
42 ui->inspector->setCatalogue(catalogues.first());
42 ui->inspector->setCatalogue(catalogues.first());
43 }
43 }
44 else {
44 else {
45 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
45 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
46 }
46 }
47
47
48 ui->events->populateWithCatalogues(catalogues);
48 ui->events->populateWithCatalogues(catalogues);
49 });
49 });
50
50
51 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databases) {
51 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databases) {
52 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
52 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
53 });
53 });
54
54
55 connect(ui->catalogues, &CatalogueSideBarWidget::trashSelected, [this]() {
55 connect(ui->catalogues, &CatalogueSideBarWidget::trashSelected, [this]() {
56 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
56 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
57 ui->events->clear();
57 ui->events->clear();
58 });
58 });
59
59
60 connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected, [this]() {
60 connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected, [this]() {
61 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
61 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
62 ui->events->populateWithAllEvents();
62 ui->events->populateWithAllEvents();
63 });
63 });
64
64
65 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databaseList) {
65 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databaseList) {
66 QVector<std::shared_ptr<DBCatalogue> > catalogueList;
66 QVector<std::shared_ptr<DBCatalogue> > catalogueList;
67 for (auto database : databaseList) {
67 for (auto database : databaseList) {
68 catalogueList.append(ui->catalogues->getCatalogues(database));
68 catalogueList.append(ui->catalogues->getCatalogues(database));
69 }
69 }
70 ui->events->populateWithCatalogues(catalogueList);
70 ui->events->populateWithCatalogues(catalogueList);
71 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
71 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
72 });
72 });
73
73
74 connect(ui->catalogues, &CatalogueSideBarWidget::selectionCleared, [this]() {
74 connect(ui->catalogues, &CatalogueSideBarWidget::selectionCleared, [this]() {
75 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
75 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
76 ui->events->clear();
76 ui->events->clear();
77 });
77 });
78
78
79 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSaved, ui->events,
80 &CatalogueEventsWidget::refresh);
81
79 // Updates the inspectot when something is selected in the events
82 // Updates the inspectot when something is selected in the events
80 connect(ui->events, &CatalogueEventsWidget::eventsSelected, [this](auto events) {
83 connect(ui->events, &CatalogueEventsWidget::eventsSelected, [this](auto events) {
81 if (events.count() == 1) {
84 if (events.count() == 1) {
82 ui->inspector->setEvent(events.first());
85 ui->inspector->setEvent(events.first());
83 }
86 }
84 else {
87 else {
85 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
88 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
86 }
89 }
87 });
90 });
88
91
89 connect(ui->events, &CatalogueEventsWidget::eventProductsSelected, [this](auto eventProducts) {
92 connect(ui->events, &CatalogueEventsWidget::eventProductsSelected, [this](auto eventProducts) {
90 if (eventProducts.count() == 1) {
93 if (eventProducts.count() == 1) {
91 ui->inspector->setEventProduct(eventProducts.first().first,
94 ui->inspector->setEventProduct(eventProducts.first().first,
92 eventProducts.first().second);
95 eventProducts.first().second);
93 }
96 }
94 else {
97 else {
95 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
98 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
96 }
99 }
97 });
100 });
98
101
99 connect(ui->events, &CatalogueEventsWidget::selectionCleared,
102 connect(ui->events, &CatalogueEventsWidget::selectionCleared,
100 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
103 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
101
104
102 // Manage Selection Zones associated to events
105 // Manage Selection Zones associated to events
103 connect(ui->events, &CatalogueEventsWidget::selectionZoneAdded,
106 connect(ui->events, &CatalogueEventsWidget::selectionZoneAdded,
104 [this](auto event, auto productId, auto zone) {
107 [this](auto event, auto productId, auto zone) {
105 this->addSelectionZoneItem(event, productId, zone);
108 this->addSelectionZoneItem(event, productId, zone);
106 });
109 });
107
110
108 connect(ui->events, &CatalogueEventsWidget::eventsRemoved, [this](auto events) {
111 connect(ui->events, &CatalogueEventsWidget::eventsRemoved, [this](auto events) {
109 for (auto event : events) {
112 for (auto event : events) {
110 auto associatedSelectionZonesIt = impl->m_SelectionZonesPerEvents.find(event);
113 auto associatedSelectionZonesIt = impl->m_SelectionZonesPerEvents.find(event);
111 if (associatedSelectionZonesIt != impl->m_SelectionZonesPerEvents.cend()) {
114 if (associatedSelectionZonesIt != impl->m_SelectionZonesPerEvents.cend()) {
112 for (auto selectionZone : associatedSelectionZonesIt->second) {
115 for (auto selectionZone : associatedSelectionZonesIt->second) {
113 auto parentGraph = selectionZone->parentGraphWidget();
116 auto parentGraph = selectionZone->parentGraphWidget();
114 parentGraph->removeSelectionZone(selectionZone);
117 parentGraph->removeSelectionZone(selectionZone);
115 }
118 }
116
119
117 impl->m_SelectionZonesPerEvents.erase(event);
120 impl->m_SelectionZonesPerEvents.erase(event);
118 }
121 }
119 }
122 }
120 });
123 });
121
124
122 // Updates changes from the inspector
125 // Updates changes from the inspector
123 connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated, [this](auto catalogue) {
126 connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated, [this](auto catalogue) {
124 sqpApp->catalogueController().updateCatalogue(catalogue);
127 sqpApp->catalogueController().updateCatalogue(catalogue);
125 ui->catalogues->setCatalogueChanges(catalogue, true);
128 ui->catalogues->setCatalogueChanges(catalogue, true);
126 });
129 });
127
130
128 connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated, [this](auto event) {
131 connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated, [this](auto event) {
129 sqpApp->catalogueController().updateEvent(event);
132 sqpApp->catalogueController().updateEvent(event);
130 ui->events->setEventChanges(event, true);
133 ui->events->setEventChanges(event, true);
131 });
134 });
132
135
133 connect(ui->inspector, &CatalogueInspectorWidget::eventProductUpdated,
136 connect(ui->inspector, &CatalogueInspectorWidget::eventProductUpdated,
134 [this](auto event, auto eventProduct) {
137 [this](auto event, auto eventProduct) {
135 sqpApp->catalogueController().updateEventProduct(eventProduct);
138 sqpApp->catalogueController().updateEventProduct(eventProduct);
136 ui->events->setEventChanges(event, true);
139 ui->events->setEventChanges(event, true);
137 });
140 });
141
142 connect(ui->events, &CatalogueEventsWidget::eventCataloguesModified,
143 [this](const QVector<std::shared_ptr<DBCatalogue> > &catalogues) {
144 for (auto catalogue : catalogues) {
145 ui->catalogues->setCatalogueChanges(catalogue, true);
146 }
147 });
138 }
148 }
139
149
140 CatalogueExplorer::~CatalogueExplorer()
150 CatalogueExplorer::~CatalogueExplorer()
141 {
151 {
142 disconnect(impl->m_Conn);
152 disconnect(impl->m_Conn);
143 delete ui;
153 delete ui;
144 }
154 }
145
155
146 void CatalogueExplorer::setVisualizationWidget(VisualizationWidget *visualization)
156 void CatalogueExplorer::setVisualizationWidget(VisualizationWidget *visualization)
147 {
157 {
148 ui->events->setVisualizationWidget(visualization);
158 ui->events->setVisualizationWidget(visualization);
149 }
159 }
150
160
151 CatalogueEventsWidget &CatalogueExplorer::eventsWidget() const
161 CatalogueEventsWidget &CatalogueExplorer::eventsWidget() const
152 {
162 {
153 return *ui->events;
163 return *ui->events;
154 }
164 }
155
165
156 CatalogueSideBarWidget &CatalogueExplorer::sideBarWidget() const
166 CatalogueSideBarWidget &CatalogueExplorer::sideBarWidget() const
157 {
167 {
158 return *ui->catalogues;
168 return *ui->catalogues;
159 }
169 }
160
170
161 void CatalogueExplorer::clearSelectionZones()
171 void CatalogueExplorer::clearSelectionZones()
162 {
172 {
163 impl->m_SelectionZonesPerEvents.clear();
173 impl->m_SelectionZonesPerEvents.clear();
164 }
174 }
165
175
166 void CatalogueExplorer::addSelectionZoneItem(const std::shared_ptr<DBEvent> &event,
176 void CatalogueExplorer::addSelectionZoneItem(const std::shared_ptr<DBEvent> &event,
167 const QString &productId,
177 const QString &productId,
168 VisualizationSelectionZoneItem *selectionZone)
178 VisualizationSelectionZoneItem *selectionZone)
169 {
179 {
170 impl->m_SelectionZonesPerEvents[event] << selectionZone;
180 impl->m_SelectionZonesPerEvents[event] << selectionZone;
171 connect(selectionZone, &VisualizationSelectionZoneItem::rangeEdited,
181 connect(selectionZone, &VisualizationSelectionZoneItem::rangeEdited,
172 [event, productId, this](auto range) {
182 [event, productId, this](auto range) {
173 auto productList = event->getEventProducts();
183 auto productList = event->getEventProducts();
174 for (auto &product : productList) {
184 for (auto &product : productList) {
175 if (product.getProductId() == productId) {
185 if (product.getProductId() == productId) {
176 product.setTStart(range.m_TStart);
186 product.setTStart(range.m_TStart);
177 product.setTEnd(range.m_TEnd);
187 product.setTEnd(range.m_TEnd);
178 }
188 }
179 }
189 }
180 event->setEventProducts(productList);
190 event->setEventProducts(productList);
181 sqpApp->catalogueController().updateEvent(event);
191 sqpApp->catalogueController().updateEvent(event);
182 ui->events->refreshEvent(event);
192 ui->events->refreshEvent(event);
183 ui->events->setEventChanges(event, true);
193 ui->events->setEventChanges(event, true);
184 ui->inspector->refresh();
194 ui->inspector->refresh();
185 });
195 });
186
196
187 impl->m_Conn = connect(selectionZone, &VisualizationSelectionZoneItem::destroyed,
197 impl->m_Conn = connect(selectionZone, &VisualizationSelectionZoneItem::destroyed,
188 [event, selectionZone, this]() {
198 [event, selectionZone, this]() {
189 if (!impl->m_SelectionZonesPerEvents.empty()) {
199 if (!impl->m_SelectionZonesPerEvents.empty()) {
190 impl->m_SelectionZonesPerEvents[event].removeAll(selectionZone);
200 impl->m_SelectionZonesPerEvents[event].removeAll(selectionZone);
191 }
201 }
192 });
202 });
193 }
203 }
@@ -1,32 +1,30
1 #include "Catalogue/CatalogueExplorerHelper.h"
1 #include "Catalogue/CatalogueExplorerHelper.h"
2
2
3 #include <QBoxLayout>
3 #include <QBoxLayout>
4 #include <QToolButton>
4 #include <QToolButton>
5
5
6 const auto VALIDATION_BUTTON_ICON_SIZE = 12;
7
6
8 QWidget *CatalogueExplorerHelper::buildValidationWidget(QWidget *parent, std::function<void()> save,
7 QWidget *CatalogueExplorerHelper::buildValidationWidget(QWidget *parent, std::function<void()> save,
9 std::function<void()> discard)
8 std::function<void()> discard)
10 {
9 {
11 auto widget = new QWidget{parent};
10 auto widget = new QWidget{parent};
12
11
13 auto layout = new QHBoxLayout{widget};
12 auto layout = new QHBoxLayout{widget};
14 layout->setContentsMargins(0, 0, 0, 0);
15 layout->setSpacing(0);
16
13
17 auto btnValid = new QToolButton{widget};
14 auto btnValid = new QToolButton{widget};
18 btnValid->setIcon(QIcon{":/icones/save"});
15 btnValid->setIcon(QIcon{":/icones/save"});
19 btnValid->setIconSize(QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE});
20 btnValid->setAutoRaise(true);
16 btnValid->setAutoRaise(true);
21 QObject::connect(btnValid, &QToolButton::clicked, save);
17 QObject::connect(btnValid, &QToolButton::clicked, save);
22 layout->addWidget(btnValid);
18 layout->addWidget(btnValid);
23
19
24 auto btnDiscard = new QToolButton{widget};
20 auto btnDiscard = new QToolButton{widget};
25 btnDiscard->setIcon(QIcon{":/icones/discard"});
21 btnDiscard->setIcon(QIcon{":/icones/discard"});
26 btnDiscard->setIconSize(QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE});
27 btnDiscard->setAutoRaise(true);
22 btnDiscard->setAutoRaise(true);
28 QObject::connect(btnDiscard, &QToolButton::clicked, discard);
23 QObject::connect(btnDiscard, &QToolButton::clicked, discard);
29 layout->addWidget(btnDiscard);
24 layout->addWidget(btnDiscard);
30
25
26 layout->setContentsMargins(0, 0, 0, 0);
27 layout->setSpacing(0);
28
31 return widget;
29 return widget;
32 }
30 }
@@ -1,227 +1,236
1 #include "Catalogue/CatalogueInspectorWidget.h"
1 #include "Catalogue/CatalogueInspectorWidget.h"
2 #include "ui_CatalogueInspectorWidget.h"
2 #include "ui_CatalogueInspectorWidget.h"
3
3
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5 #include <DBCatalogue.h>
5 #include <DBCatalogue.h>
6 #include <DBEvent.h>
6 #include <DBEvent.h>
7 #include <DBEventProduct.h>
7 #include <DBEventProduct.h>
8 #include <DBTag.h>
8 #include <DBTag.h>
9
9
10 struct CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate {
10 struct CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate {
11 std::shared_ptr<DBCatalogue> m_DisplayedCatalogue = nullptr;
11 std::shared_ptr<DBCatalogue> m_DisplayedCatalogue = nullptr;
12 std::shared_ptr<DBEvent> m_DisplayedEvent = nullptr;
12 std::shared_ptr<DBEvent> m_DisplayedEvent = nullptr;
13 std::shared_ptr<DBEventProduct> m_DisplayedEventProduct = nullptr;
13 std::shared_ptr<DBEventProduct> m_DisplayedEventProduct = nullptr;
14
14
15 void connectCatalogueUpdateSignals(CatalogueInspectorWidget *inspector,
15 void connectCatalogueUpdateSignals(CatalogueInspectorWidget *inspector,
16 Ui::CatalogueInspectorWidget *ui);
16 Ui::CatalogueInspectorWidget *ui);
17 void connectEventUpdateSignals(CatalogueInspectorWidget *inspector,
17 void connectEventUpdateSignals(CatalogueInspectorWidget *inspector,
18 Ui::CatalogueInspectorWidget *ui);
18 Ui::CatalogueInspectorWidget *ui);
19 };
19 };
20
20
21 CatalogueInspectorWidget::CatalogueInspectorWidget(QWidget *parent)
21 CatalogueInspectorWidget::CatalogueInspectorWidget(QWidget *parent)
22 : QWidget(parent),
22 : QWidget(parent),
23 ui(new Ui::CatalogueInspectorWidget),
23 ui(new Ui::CatalogueInspectorWidget),
24 impl{spimpl::make_unique_impl<CatalogueInspectorWidgetPrivate>()}
24 impl{spimpl::make_unique_impl<CatalogueInspectorWidgetPrivate>()}
25 {
25 {
26 ui->setupUi(this);
26 ui->setupUi(this);
27 showPage(Page::Empty);
27 showPage(Page::Empty);
28
28
29 impl->connectCatalogueUpdateSignals(this, ui);
29 impl->connectCatalogueUpdateSignals(this, ui);
30 impl->connectEventUpdateSignals(this, ui);
30 impl->connectEventUpdateSignals(this, ui);
31
32 ui->dateTimeEventTStart->setDisplayFormat(DATETIME_FORMAT);
33 ui->dateTimeEventTEnd->setDisplayFormat(DATETIME_FORMAT);
31 }
34 }
32
35
33 CatalogueInspectorWidget::~CatalogueInspectorWidget()
36 CatalogueInspectorWidget::~CatalogueInspectorWidget()
34 {
37 {
35 delete ui;
38 delete ui;
36 }
39 }
37
40
38 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectCatalogueUpdateSignals(
41 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectCatalogueUpdateSignals(
39 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
42 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
40 {
43 {
41 connect(ui->leCatalogueName, &QLineEdit::editingFinished, [ui, inspector, this]() {
44 connect(ui->leCatalogueName, &QLineEdit::editingFinished, [ui, inspector, this]() {
42 if (ui->leCatalogueName->text() != m_DisplayedCatalogue->getName()) {
45 if (ui->leCatalogueName->text() != m_DisplayedCatalogue->getName()) {
43 m_DisplayedCatalogue->setName(ui->leCatalogueName->text());
46 m_DisplayedCatalogue->setName(ui->leCatalogueName->text());
44 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
47 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
45 }
48 }
46 });
49 });
47
50
48 connect(ui->leCatalogueAuthor, &QLineEdit::editingFinished, [ui, inspector, this]() {
51 connect(ui->leCatalogueAuthor, &QLineEdit::editingFinished, [ui, inspector, this]() {
49 if (ui->leCatalogueAuthor->text() != m_DisplayedCatalogue->getAuthor()) {
52 if (ui->leCatalogueAuthor->text() != m_DisplayedCatalogue->getAuthor()) {
50 m_DisplayedCatalogue->setAuthor(ui->leCatalogueAuthor->text());
53 m_DisplayedCatalogue->setAuthor(ui->leCatalogueAuthor->text());
51 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
54 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
52 }
55 }
53 });
56 });
54 }
57 }
55
58
56 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectEventUpdateSignals(
59 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectEventUpdateSignals(
57 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
60 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
58 {
61 {
59 connect(ui->leEventName, &QLineEdit::editingFinished, [ui, inspector, this]() {
62 connect(ui->leEventName, &QLineEdit::editingFinished, [ui, inspector, this]() {
60 if (ui->leEventName->text() != m_DisplayedEvent->getName()) {
63 if (ui->leEventName->text() != m_DisplayedEvent->getName()) {
61 m_DisplayedEvent->setName(ui->leEventName->text());
64 m_DisplayedEvent->setName(ui->leEventName->text());
62 emit inspector->eventUpdated(m_DisplayedEvent);
65 emit inspector->eventUpdated(m_DisplayedEvent);
63 }
66 }
64 });
67 });
65
68
66 connect(ui->leEventTags, &QLineEdit::editingFinished, [ui, inspector, this]() {
69 connect(ui->leEventTags, &QLineEdit::editingFinished, [ui, inspector, this]() {
67 auto tags = ui->leEventTags->text().split(QRegExp("\\s+"), QString::SkipEmptyParts);
70 auto tags = ui->leEventTags->text().split(QRegExp("\\s+"), QString::SkipEmptyParts);
68 std::list<QString> tagNames;
71 std::list<QString> tagNames;
69 for (auto tag : tags) {
72 for (auto tag : tags) {
70 tagNames.push_back(tag);
73 tagNames.push_back(tag);
71 }
74 }
72
75
73 if (m_DisplayedEvent->getTagsNames() != tagNames) {
76 if (m_DisplayedEvent->getTagsNames() != tagNames) {
74 m_DisplayedEvent->setTagsNames(tagNames);
77 m_DisplayedEvent->setTagsNames(tagNames);
75 emit inspector->eventUpdated(m_DisplayedEvent);
78 emit inspector->eventUpdated(m_DisplayedEvent);
76 }
79 }
77 });
80 });
78
81
79 connect(ui->leEventProduct, &QLineEdit::editingFinished, [ui, inspector, this]() {
82 connect(ui->leEventProduct, &QLineEdit::editingFinished, [ui, inspector, this]() {
80 if (ui->leEventProduct->text() != m_DisplayedEventProduct->getProductId()) {
83 if (ui->leEventProduct->text() != m_DisplayedEventProduct->getProductId()) {
81 auto oldProductId = m_DisplayedEventProduct->getProductId();
84 auto oldProductId = m_DisplayedEventProduct->getProductId();
82 m_DisplayedEventProduct->setProductId(ui->leEventProduct->text());
85 m_DisplayedEventProduct->setProductId(ui->leEventProduct->text());
83
86
84 auto eventProducts = m_DisplayedEvent->getEventProducts();
87 auto eventProducts = m_DisplayedEvent->getEventProducts();
85 for (auto &eventProduct : eventProducts) {
88 for (auto &eventProduct : eventProducts) {
86 if (eventProduct.getProductId() == oldProductId) {
89 if (eventProduct.getProductId() == oldProductId) {
87 eventProduct.setProductId(m_DisplayedEventProduct->getProductId());
90 eventProduct.setProductId(m_DisplayedEventProduct->getProductId());
88 }
91 }
89 }
92 }
90 m_DisplayedEvent->setEventProducts(eventProducts);
93 m_DisplayedEvent->setEventProducts(eventProducts);
91
94
92 emit inspector->eventUpdated(m_DisplayedEvent);
95 emit inspector->eventUpdated(m_DisplayedEvent);
93 }
96 }
94 });
97 });
95
98
96 connect(ui->dateTimeEventTStart, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
99 connect(ui->dateTimeEventTStart, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
97 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTStart->dateTime());
100 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTStart->dateTime());
98 if (time != m_DisplayedEventProduct->getTStart()) {
101 if (time != m_DisplayedEventProduct->getTStart()) {
99 m_DisplayedEventProduct->setTStart(time);
102 m_DisplayedEventProduct->setTStart(time);
100
103
101 auto eventProducts = m_DisplayedEvent->getEventProducts();
104 auto eventProducts = m_DisplayedEvent->getEventProducts();
102 for (auto &eventProduct : eventProducts) {
105 for (auto &eventProduct : eventProducts) {
103 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
106 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
104 eventProduct.setTStart(m_DisplayedEventProduct->getTStart());
107 eventProduct.setTStart(m_DisplayedEventProduct->getTStart());
105 }
108 }
106 }
109 }
107 m_DisplayedEvent->setEventProducts(eventProducts);
110 m_DisplayedEvent->setEventProducts(eventProducts);
108
111
109 emit inspector->eventUpdated(m_DisplayedEvent);
112 emit inspector->eventUpdated(m_DisplayedEvent);
110 }
113 }
111 });
114 });
112
115
113 connect(ui->dateTimeEventTEnd, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
116 connect(ui->dateTimeEventTEnd, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
114 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTEnd->dateTime());
117 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTEnd->dateTime());
115 if (time != m_DisplayedEventProduct->getTEnd()) {
118 if (time != m_DisplayedEventProduct->getTEnd()) {
116 m_DisplayedEventProduct->setTEnd(time);
119 m_DisplayedEventProduct->setTEnd(time);
117
120
118 auto eventProducts = m_DisplayedEvent->getEventProducts();
121 auto eventProducts = m_DisplayedEvent->getEventProducts();
119 for (auto &eventProduct : eventProducts) {
122 for (auto &eventProduct : eventProducts) {
120 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
123 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
121 eventProduct.setTEnd(m_DisplayedEventProduct->getTEnd());
124 eventProduct.setTEnd(m_DisplayedEventProduct->getTEnd());
122 }
125 }
123 }
126 }
124 m_DisplayedEvent->setEventProducts(eventProducts);
127 m_DisplayedEvent->setEventProducts(eventProducts);
125
128
126 emit inspector->eventUpdated(m_DisplayedEvent);
129 emit inspector->eventUpdated(m_DisplayedEvent);
127 }
130 }
128 });
131 });
129 }
132 }
130
133
131 void CatalogueInspectorWidget::showPage(CatalogueInspectorWidget::Page page)
134 void CatalogueInspectorWidget::showPage(CatalogueInspectorWidget::Page page)
132 {
135 {
133 ui->stackedWidget->setCurrentIndex(static_cast<int>(page));
136 ui->stackedWidget->setCurrentIndex(static_cast<int>(page));
134 }
137 }
135
138
136 CatalogueInspectorWidget::Page CatalogueInspectorWidget::currentPage() const
139 CatalogueInspectorWidget::Page CatalogueInspectorWidget::currentPage() const
137 {
140 {
138 return static_cast<Page>(ui->stackedWidget->currentIndex());
141 return static_cast<Page>(ui->stackedWidget->currentIndex());
139 }
142 }
140
143
141 void CatalogueInspectorWidget::setEvent(const std::shared_ptr<DBEvent> &event)
144 void CatalogueInspectorWidget::setEvent(const std::shared_ptr<DBEvent> &event)
142 {
145 {
143 impl->m_DisplayedEvent = event;
146 impl->m_DisplayedEvent = event;
144
147
145 blockSignals(true);
148 blockSignals(true);
146
149
147 showPage(Page::EventProperties);
150 showPage(Page::EventProperties);
148 ui->leEventName->setEnabled(true);
151 ui->leEventName->setEnabled(true);
149 ui->leEventName->setText(event->getName());
152 ui->leEventName->setText(event->getName());
150 ui->leEventProduct->setEnabled(false);
153 ui->leEventProduct->setEnabled(false);
151 ui->leEventProduct->setText(
154
152 QString::number(event->getEventProducts().size()).append(" product(s)"));
155 auto eventProducts = event->getEventProducts();
156 QStringList eventProductList;
157 for (auto evtProduct : eventProducts) {
158 eventProductList << evtProduct.getProductId();
159 }
160
161 ui->leEventProduct->setText(eventProductList.join(";"));
153
162
154 QString tagList;
163 QString tagList;
155 auto tags = event->getTagsNames();
164 auto tags = event->getTagsNames();
156 for (auto tag : tags) {
165 for (auto tag : tags) {
157 tagList += tag;
166 tagList += tag;
158 tagList += ' ';
167 tagList += ' ';
159 }
168 }
160
169
161 ui->leEventTags->setEnabled(true);
170 ui->leEventTags->setEnabled(true);
162 ui->leEventTags->setText(tagList);
171 ui->leEventTags->setText(tagList);
163
172
164 ui->dateTimeEventTStart->setEnabled(false);
173 ui->dateTimeEventTStart->setEnabled(false);
165 ui->dateTimeEventTEnd->setEnabled(false);
174 ui->dateTimeEventTEnd->setEnabled(false);
166
175
167 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(event->getTStart()));
176 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(event->getTStart()));
168 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(event->getTEnd()));
177 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(event->getTEnd()));
169
178
170 blockSignals(false);
179 blockSignals(false);
171 }
180 }
172
181
173 void CatalogueInspectorWidget::setEventProduct(const std::shared_ptr<DBEvent> &event,
182 void CatalogueInspectorWidget::setEventProduct(const std::shared_ptr<DBEvent> &event,
174 const std::shared_ptr<DBEventProduct> &eventProduct)
183 const std::shared_ptr<DBEventProduct> &eventProduct)
175 {
184 {
176
185
177 impl->m_DisplayedEvent = event;
186 impl->m_DisplayedEvent = event;
178 impl->m_DisplayedEventProduct = eventProduct;
187 impl->m_DisplayedEventProduct = eventProduct;
179
188
180 blockSignals(true);
189 blockSignals(true);
181
190
182 showPage(Page::EventProperties);
191 showPage(Page::EventProperties);
183 ui->leEventName->setEnabled(false);
192 ui->leEventName->setEnabled(false);
184 ui->leEventName->setText(event->getName());
193 ui->leEventName->setText(event->getName());
185 ui->leEventProduct->setEnabled(false);
194 ui->leEventProduct->setEnabled(false);
186 ui->leEventProduct->setText(eventProduct->getProductId());
195 ui->leEventProduct->setText(eventProduct->getProductId());
187
196
188 ui->leEventTags->setEnabled(false);
197 ui->leEventTags->setEnabled(false);
189 ui->leEventTags->clear();
198 ui->leEventTags->clear();
190
199
191 ui->dateTimeEventTStart->setEnabled(true);
200 ui->dateTimeEventTStart->setEnabled(true);
192 ui->dateTimeEventTEnd->setEnabled(true);
201 ui->dateTimeEventTEnd->setEnabled(true);
193
202
194 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(eventProduct->getTStart()));
203 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(eventProduct->getTStart()));
195 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(eventProduct->getTEnd()));
204 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(eventProduct->getTEnd()));
196
205
197 blockSignals(false);
206 blockSignals(false);
198 }
207 }
199
208
200 void CatalogueInspectorWidget::setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue)
209 void CatalogueInspectorWidget::setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue)
201 {
210 {
202 impl->m_DisplayedCatalogue = catalogue;
211 impl->m_DisplayedCatalogue = catalogue;
203
212
204 blockSignals(true);
213 blockSignals(true);
205
214
206 showPage(Page::CatalogueProperties);
215 showPage(Page::CatalogueProperties);
207 ui->leCatalogueName->setText(catalogue->getName());
216 ui->leCatalogueName->setText(catalogue->getName());
208 ui->leCatalogueAuthor->setText(catalogue->getAuthor());
217 ui->leCatalogueAuthor->setText(catalogue->getAuthor());
209
218
210 blockSignals(false);
219 blockSignals(false);
211 }
220 }
212
221
213 void CatalogueInspectorWidget::refresh()
222 void CatalogueInspectorWidget::refresh()
214 {
223 {
215 switch (static_cast<Page>(ui->stackedWidget->currentIndex())) {
224 switch (static_cast<Page>(ui->stackedWidget->currentIndex())) {
216 case Page::CatalogueProperties:
225 case Page::CatalogueProperties:
217 setCatalogue(impl->m_DisplayedCatalogue);
226 setCatalogue(impl->m_DisplayedCatalogue);
218 break;
227 break;
219 case Page::EventProperties: {
228 case Page::EventProperties: {
220 auto isEventShowed = ui->leEventName->isEnabled();
229 auto isEventShowed = ui->leEventName->isEnabled();
221 setEvent(impl->m_DisplayedEvent);
230 setEvent(impl->m_DisplayedEvent);
222 if (!isEventShowed && impl->m_DisplayedEvent) {
231 if (!isEventShowed && impl->m_DisplayedEvent) {
223 setEventProduct(impl->m_DisplayedEvent, impl->m_DisplayedEventProduct);
232 setEventProduct(impl->m_DisplayedEvent, impl->m_DisplayedEventProduct);
224 }
233 }
225 }
234 }
226 }
235 }
227 }
236 }
@@ -1,429 +1,447
1 #include "Catalogue/CatalogueSideBarWidget.h"
1 #include "Catalogue/CatalogueSideBarWidget.h"
2 #include "ui_CatalogueSideBarWidget.h"
2 #include "ui_CatalogueSideBarWidget.h"
3 #include <SqpApplication.h>
3 #include <SqpApplication.h>
4
4
5 #include <Catalogue/CatalogueController.h>
5 #include <Catalogue/CatalogueController.h>
6 #include <Catalogue/CatalogueExplorerHelper.h>
6 #include <Catalogue/CatalogueExplorerHelper.h>
7 #include <Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.h>
7 #include <Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.h>
8 #include <Catalogue/CatalogueTreeItems/CatalogueTreeItem.h>
8 #include <Catalogue/CatalogueTreeItems/CatalogueTreeItem.h>
9 #include <Catalogue/CatalogueTreeModel.h>
9 #include <Catalogue/CatalogueTreeModel.h>
10 #include <CatalogueDao.h>
10 #include <CatalogueDao.h>
11 #include <Common/MimeTypesDef.h>
11 #include <Common/MimeTypesDef.h>
12 #include <ComparaisonPredicate.h>
12 #include <ComparaisonPredicate.h>
13 #include <DBCatalogue.h>
13 #include <DBCatalogue.h>
14
14
15 #include <QKeyEvent>
15 #include <QMenu>
16 #include <QMenu>
16 #include <QMessageBox>
17 #include <QMessageBox>
17 #include <QMimeData>
18 #include <QMimeData>
18
19
19 Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
20 Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
20
21
21
22
22 constexpr auto ALL_EVENT_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 1;
23 constexpr auto ALL_EVENT_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 1;
23 constexpr auto TRASH_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 2;
24 constexpr auto TRASH_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 2;
24 constexpr auto CATALOGUE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 3;
25 constexpr auto CATALOGUE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 3;
25 constexpr auto DATABASE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 4;
26 constexpr auto DATABASE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 4;
26
27
27
28
28 struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
29 struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
29
30
30 CatalogueTreeModel *m_TreeModel = nullptr;
31 CatalogueTreeModel *m_TreeModel = nullptr;
31
32
32 void configureTreeWidget(QTreeView *treeView);
33 void configureTreeWidget(QTreeView *treeView);
33 QModelIndex addDatabaseItem(const QString &name);
34 QModelIndex addDatabaseItem(const QString &name);
34 CatalogueAbstractTreeItem *getDatabaseItem(const QString &name);
35 CatalogueAbstractTreeItem *getDatabaseItem(const QString &name);
35 CatalogueAbstractTreeItem *addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
36 CatalogueAbstractTreeItem *addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
36 const QModelIndex &databaseIndex);
37 const QModelIndex &databaseIndex);
37
38
38 CatalogueTreeItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue) const;
39 CatalogueTreeItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue) const;
39 void setHasChanges(bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget);
40 void setHasChanges(bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget);
40 bool hasChanges(const QModelIndex &index, QTreeView *treeView);
41 bool hasChanges(const QModelIndex &index, QTreeView *treeView);
41
42
42 int selectionType(QTreeView *treeView) const
43 int selectionType(QTreeView *treeView) const
43 {
44 {
44 auto selectedItems = treeView->selectionModel()->selectedRows();
45 auto selectedItems = treeView->selectionModel()->selectedRows();
45 if (selectedItems.isEmpty()) {
46 if (selectedItems.isEmpty()) {
46 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
47 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
47 }
48 }
48 else {
49 else {
49 auto firstIndex = selectedItems.first();
50 auto firstIndex = selectedItems.first();
50 auto firstItem = m_TreeModel->item(firstIndex);
51 auto firstItem = m_TreeModel->item(firstIndex);
51 if (!firstItem) {
52 if (!firstItem) {
52 Q_ASSERT(false);
53 Q_ASSERT(false);
53 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
54 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
54 }
55 }
55 auto selectionType = firstItem->type();
56 auto selectionType = firstItem->type();
56
57
57 for (auto itemIndex : selectedItems) {
58 for (auto itemIndex : selectedItems) {
58 auto item = m_TreeModel->item(itemIndex);
59 auto item = m_TreeModel->item(itemIndex);
59 if (!item || item->type() != selectionType) {
60 if (!item || item->type() != selectionType) {
60 // Incoherent multi selection
61 // Incoherent multi selection
61 selectionType = CatalogueAbstractTreeItem::DEFAULT_TYPE;
62 selectionType = CatalogueAbstractTreeItem::DEFAULT_TYPE;
62 break;
63 break;
63 }
64 }
64 }
65 }
65
66
66 return selectionType;
67 return selectionType;
67 }
68 }
68 }
69 }
69
70
70 QVector<std::shared_ptr<DBCatalogue> > selectedCatalogues(QTreeView *treeView) const
71 QVector<std::shared_ptr<DBCatalogue> > selectedCatalogues(QTreeView *treeView) const
71 {
72 {
72 QVector<std::shared_ptr<DBCatalogue> > catalogues;
73 QVector<std::shared_ptr<DBCatalogue> > catalogues;
73 auto selectedItems = treeView->selectionModel()->selectedRows();
74 auto selectedItems = treeView->selectionModel()->selectedRows();
74 for (auto itemIndex : selectedItems) {
75 for (auto itemIndex : selectedItems) {
75 auto item = m_TreeModel->item(itemIndex);
76 auto item = m_TreeModel->item(itemIndex);
76 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
77 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
77 catalogues.append(static_cast<CatalogueTreeItem *>(item)->catalogue());
78 catalogues.append(static_cast<CatalogueTreeItem *>(item)->catalogue());
78 }
79 }
79 }
80 }
80
81
81 return catalogues;
82 return catalogues;
82 }
83 }
83
84
84 QStringList selectedRepositories(QTreeView *treeView) const
85 QStringList selectedRepositories(QTreeView *treeView) const
85 {
86 {
86 QStringList repositories;
87 QStringList repositories;
87 auto selectedItems = treeView->selectionModel()->selectedRows();
88 auto selectedItems = treeView->selectionModel()->selectedRows();
88 for (auto itemIndex : selectedItems) {
89 for (auto itemIndex : selectedItems) {
89 auto item = m_TreeModel->item(itemIndex);
90 auto item = m_TreeModel->item(itemIndex);
90 if (item && item->type() == DATABASE_ITEM_TYPE) {
91 if (item && item->type() == DATABASE_ITEM_TYPE) {
91 repositories.append(item->text());
92 repositories.append(item->text());
92 }
93 }
93 }
94 }
94
95
95 return repositories;
96 return repositories;
96 }
97 }
97 };
98 };
98
99
99 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
100 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
100 : QWidget(parent),
101 : QWidget(parent),
101 ui(new Ui::CatalogueSideBarWidget),
102 ui(new Ui::CatalogueSideBarWidget),
102 impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
103 impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
103 {
104 {
104 ui->setupUi(this);
105 ui->setupUi(this);
105
106
106 impl->m_TreeModel = new CatalogueTreeModel(this);
107 impl->m_TreeModel = new CatalogueTreeModel(this);
107 ui->treeView->setModel(impl->m_TreeModel);
108 ui->treeView->setModel(impl->m_TreeModel);
108
109
109 impl->configureTreeWidget(ui->treeView);
110 impl->configureTreeWidget(ui->treeView);
110
111
111 ui->treeView->header()->setStretchLastSection(false);
112 ui->treeView->header()->setStretchLastSection(false);
112 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
113 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
113 ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
114 ui->treeView->header()->setSectionResizeMode((int)CatalogueTreeModel::Column::Name,
115 QHeaderView::Stretch);
114
116
115 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueSideBarWidget::emitSelection);
117 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueSideBarWidget::emitSelection);
116 connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, this,
118 connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, this,
117 &CatalogueSideBarWidget::emitSelection);
119 &CatalogueSideBarWidget::emitSelection);
118
120
119
121
120 connect(ui->btnAdd, &QToolButton::clicked, [this]() {
122 connect(ui->btnAdd, &QToolButton::clicked, [this]() {
121 auto catalogue = std::make_shared<DBCatalogue>();
123 auto catalogue = std::make_shared<DBCatalogue>();
122 catalogue->setName(QString("Cat"));
124 catalogue->setName(QString("Cat"));
123 sqpApp->catalogueController().addCatalogue(catalogue);
125 sqpApp->catalogueController().addCatalogue(catalogue);
124 auto item = this->addCatalogue(catalogue, REPOSITORY_DEFAULT);
126 auto item = this->addCatalogue(catalogue, REPOSITORY_DEFAULT);
125 this->setCatalogueChanges(catalogue, true);
127 this->setCatalogueChanges(catalogue, true);
126 ui->treeView->edit(impl->m_TreeModel->indexOf(item));
128 ui->treeView->edit(impl->m_TreeModel->indexOf(item));
127
129
128 });
130 });
129
131
130
132
131 connect(impl->m_TreeModel, &CatalogueTreeModel::itemDropped,
133 connect(impl->m_TreeModel, &CatalogueTreeModel::itemDropped,
132 [this](auto index, auto mimeData, auto action) {
134 [this](auto index, auto mimeData, auto action) {
133 auto item = impl->m_TreeModel->item(index);
135 auto item = impl->m_TreeModel->item(index);
134 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
136 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
135 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
137 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
136 this->setCatalogueChanges(catalogue, true);
138 this->setCatalogueChanges(catalogue, true);
137 }
139 }
138
140
139 if (action == Qt::MoveAction) {
141 if (action == Qt::MoveAction) {
140 /// Display a save button on source catalogues
142 /// Display a save button on source catalogues
141 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
143 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
142 mimeData->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
144 mimeData->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
143 for (auto catalogue : sourceCatalogues) {
145 for (auto catalogue : sourceCatalogues) {
144 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
146 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
145 this->setCatalogueChanges(catalogue, true);
147 this->setCatalogueChanges(catalogue, true);
146 }
148 }
147 }
149 }
148 }
150 }
149 });
151 });
150
152
151 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
153 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
152 QVector<QPair<std::shared_ptr<DBCatalogue>, CatalogueAbstractTreeItem *> >
154 QVector<QPair<std::shared_ptr<DBCatalogue>, CatalogueAbstractTreeItem *> >
153 cataloguesToItems;
155 cataloguesToItems;
154 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
156 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
155
157
156 for (auto index : selectedIndexes) {
158 for (auto index : selectedIndexes) {
157 auto item = impl->m_TreeModel->item(index);
159 auto item = impl->m_TreeModel->item(index);
158 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
160 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
159 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
161 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
160 cataloguesToItems << qMakePair(catalogue, item);
162 cataloguesToItems << qMakePair(catalogue, item);
161 }
163 }
162 }
164 }
163
165
164 if (!cataloguesToItems.isEmpty()) {
166 if (!cataloguesToItems.isEmpty()) {
165
167
166 if (QMessageBox::warning(this, tr("Remove Catalogue(s)"),
168 if (QMessageBox::warning(this, tr("Remove Catalogue(s)"),
167 tr("The selected catalogues(s) will be completly removed "
169 tr("The selected catalogues(s) will be completly removed "
168 "from the repository!\nAre you sure you want to continue?"),
170 "from the repository!\nAre you sure you want to continue?"),
169 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
171 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
170 == QMessageBox::Yes) {
172 == QMessageBox::Yes) {
171
173
172 for (auto catalogueToItem : cataloguesToItems) {
174 for (auto catalogueToItem : cataloguesToItems) {
173 sqpApp->catalogueController().removeCatalogue(catalogueToItem.first);
175 sqpApp->catalogueController().removeCatalogue(catalogueToItem.first);
174 impl->m_TreeModel->removeChildItem(
176 impl->m_TreeModel->removeChildItem(
175 catalogueToItem.second,
177 catalogueToItem.second,
176 impl->m_TreeModel->indexOf(catalogueToItem.second->parent()));
178 impl->m_TreeModel->indexOf(catalogueToItem.second->parent()));
177 }
179 }
180 emitSelection();
178 }
181 }
179 }
182 }
180 });
183 });
181
184
182 connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [this](auto index) {
185 connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [this](auto index) {
183 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
186 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
184 if (selectedIndexes.contains(index)) {
187 if (selectedIndexes.contains(index)) {
185 this->emitSelection();
188 this->emitSelection();
186 }
189 }
187 impl->setHasChanges(true, index, this);
190 impl->setHasChanges(true, index, this);
188 });
191 });
189
192
190 ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
193 ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
191 connect(ui->treeView, &QTreeView::customContextMenuRequested, this,
194 connect(ui->treeView, &QTreeView::customContextMenuRequested, this,
192 &CatalogueSideBarWidget::onContextMenuRequested);
195 &CatalogueSideBarWidget::onContextMenuRequested);
193 }
196 }
194
197
195 CatalogueSideBarWidget::~CatalogueSideBarWidget()
198 CatalogueSideBarWidget::~CatalogueSideBarWidget()
196 {
199 {
197 delete ui;
200 delete ui;
198 }
201 }
199
202
200 CatalogueAbstractTreeItem *
203 CatalogueAbstractTreeItem *
201 CatalogueSideBarWidget::addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
204 CatalogueSideBarWidget::addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
202 const QString &repository)
205 const QString &repository)
203 {
206 {
204 auto repositoryItem = impl->getDatabaseItem(repository);
207 auto repositoryItem = impl->getDatabaseItem(repository);
205 return impl->addCatalogueItem(catalogue, impl->m_TreeModel->indexOf(repositoryItem));
208 return impl->addCatalogueItem(catalogue, impl->m_TreeModel->indexOf(repositoryItem));
206 }
209 }
207
210
208 void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
211 void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
209 bool hasChanges)
212 bool hasChanges)
210 {
213 {
211 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
214 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
212 auto index = impl->m_TreeModel->indexOf(catalogueItem);
215 auto index = impl->m_TreeModel->indexOf(catalogueItem);
213 impl->setHasChanges(hasChanges, index, this);
216 impl->setHasChanges(hasChanges, index, this);
214 // catalogueItem->refresh();
217 // catalogueItem->refresh();
215 }
218 }
216 }
219 }
217
220
218 QVector<std::shared_ptr<DBCatalogue> >
221 QVector<std::shared_ptr<DBCatalogue> >
219 CatalogueSideBarWidget::getCatalogues(const QString &repository) const
222 CatalogueSideBarWidget::getCatalogues(const QString &repository) const
220 {
223 {
221 QVector<std::shared_ptr<DBCatalogue> > result;
224 QVector<std::shared_ptr<DBCatalogue> > result;
222 auto repositoryItem = impl->getDatabaseItem(repository);
225 auto repositoryItem = impl->getDatabaseItem(repository);
223 for (auto child : repositoryItem->children()) {
226 for (auto child : repositoryItem->children()) {
224 if (child->type() == CATALOGUE_ITEM_TYPE) {
227 if (child->type() == CATALOGUE_ITEM_TYPE) {
225 auto catalogueItem = static_cast<CatalogueTreeItem *>(child);
228 auto catalogueItem = static_cast<CatalogueTreeItem *>(child);
226 result << catalogueItem->catalogue();
229 result << catalogueItem->catalogue();
227 }
230 }
228 else {
231 else {
229 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogues: invalid structure";
232 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogues: invalid structure";
230 }
233 }
231 }
234 }
232
235
233 return result;
236 return result;
234 }
237 }
235
238
236 void CatalogueSideBarWidget::emitSelection()
239 void CatalogueSideBarWidget::emitSelection()
237 {
240 {
238 auto selectionType = impl->selectionType(ui->treeView);
241 auto selectionType = impl->selectionType(ui->treeView);
239
242
240 switch (selectionType) {
243 switch (selectionType) {
241 case CATALOGUE_ITEM_TYPE:
244 case CATALOGUE_ITEM_TYPE:
242 emit this->catalogueSelected(impl->selectedCatalogues(ui->treeView));
245 emit this->catalogueSelected(impl->selectedCatalogues(ui->treeView));
243 break;
246 break;
244 case DATABASE_ITEM_TYPE:
247 case DATABASE_ITEM_TYPE:
245 emit this->databaseSelected(impl->selectedRepositories(ui->treeView));
248 emit this->databaseSelected(impl->selectedRepositories(ui->treeView));
246 break;
249 break;
247 case ALL_EVENT_ITEM_TYPE:
250 case ALL_EVENT_ITEM_TYPE:
248 emit this->allEventsSelected();
251 emit this->allEventsSelected();
249 break;
252 break;
250 case TRASH_ITEM_TYPE:
253 case TRASH_ITEM_TYPE:
251 emit this->trashSelected();
254 emit this->trashSelected();
252 break;
255 break;
253 default:
256 default:
254 emit this->selectionCleared();
257 emit this->selectionCleared();
255 break;
258 break;
256 }
259 }
257 }
260 }
258
261
259 void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
262 void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
260 {
263 {
261 QMenu menu{this};
264 QMenu menu{this};
262
265
263 auto currentIndex = ui->treeView->currentIndex();
266 auto currentIndex = ui->treeView->currentIndex();
264 auto currentItem = impl->m_TreeModel->item(currentIndex);
267 auto currentItem = impl->m_TreeModel->item(currentIndex);
265 if (!currentItem) {
268 if (!currentItem) {
266 return;
269 return;
267 }
270 }
268
271
269 switch (currentItem->type()) {
272 switch (currentItem->type()) {
270 case CATALOGUE_ITEM_TYPE:
273 case CATALOGUE_ITEM_TYPE:
271 menu.addAction("Rename", [this, currentIndex]() { ui->treeView->edit(currentIndex); });
274 menu.addAction("Rename", [this, currentIndex]() { ui->treeView->edit(currentIndex); });
272 break;
275 break;
273 case DATABASE_ITEM_TYPE:
276 case DATABASE_ITEM_TYPE:
274 break;
277 break;
275 case ALL_EVENT_ITEM_TYPE:
278 case ALL_EVENT_ITEM_TYPE:
276 break;
279 break;
277 case TRASH_ITEM_TYPE:
280 case TRASH_ITEM_TYPE:
278 menu.addAction("Empty Trash", []() {
281 menu.addAction("Empty Trash", []() {
279 // TODO
282 // TODO
280 });
283 });
281 break;
284 break;
282 default:
285 default:
283 break;
286 break;
284 }
287 }
285
288
286 if (!menu.isEmpty()) {
289 if (!menu.isEmpty()) {
287 menu.exec(ui->treeView->mapToGlobal(pos));
290 menu.exec(ui->treeView->mapToGlobal(pos));
288 }
291 }
289 }
292 }
290
293
291 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(QTreeView *treeView)
294 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(QTreeView *treeView)
292 {
295 {
293 auto allEventsItem = new CatalogueTextTreeItem{QIcon{":/icones/allEvents.png"}, "All Events",
296 auto allEventsItem = new CatalogueTextTreeItem{QIcon{":/icones/allEvents.png"}, "All Events",
294 ALL_EVENT_ITEM_TYPE};
297 ALL_EVENT_ITEM_TYPE};
295 auto allEventIndex = m_TreeModel->addTopLevelItem(allEventsItem);
298 auto allEventIndex = m_TreeModel->addTopLevelItem(allEventsItem);
296 treeView->setCurrentIndex(allEventIndex);
299 treeView->setCurrentIndex(allEventIndex);
297
300
298 auto trashItem
301 auto trashItem
299 = new CatalogueTextTreeItem{QIcon{":/icones/trash.png"}, "Trash", TRASH_ITEM_TYPE};
302 = new CatalogueTextTreeItem{QIcon{":/icones/trash.png"}, "Trash", TRASH_ITEM_TYPE};
300 m_TreeModel->addTopLevelItem(trashItem);
303 m_TreeModel->addTopLevelItem(trashItem);
301
304
302 auto separator = new QFrame{treeView};
305 auto separator = new QFrame{treeView};
303 separator->setFrameShape(QFrame::HLine);
306 separator->setFrameShape(QFrame::HLine);
304 auto separatorItem
307 auto separatorItem
305 = new CatalogueTextTreeItem{QIcon{}, QString{}, CatalogueAbstractTreeItem::DEFAULT_TYPE};
308 = new CatalogueTextTreeItem{QIcon{}, QString{}, CatalogueAbstractTreeItem::DEFAULT_TYPE};
306 separatorItem->setEnabled(false);
309 separatorItem->setEnabled(false);
307 auto separatorIndex = m_TreeModel->addTopLevelItem(separatorItem);
310 auto separatorIndex = m_TreeModel->addTopLevelItem(separatorItem);
308 treeView->setIndexWidget(separatorIndex, separator);
311 treeView->setIndexWidget(separatorIndex, separator);
309
312
310 auto repositories = sqpApp->catalogueController().getRepositories();
313 auto repositories = sqpApp->catalogueController().getRepositories();
311 for (auto dbname : repositories) {
314 for (auto dbname : repositories) {
312 auto dbIndex = addDatabaseItem(dbname);
315 auto dbIndex = addDatabaseItem(dbname);
313 auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname);
316 auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname);
314 for (auto catalogue : catalogues) {
317 for (auto catalogue : catalogues) {
315 addCatalogueItem(catalogue, dbIndex);
318 addCatalogueItem(catalogue, dbIndex);
316 }
319 }
317 }
320 }
318
321
319 treeView->expandAll();
322 treeView->expandAll();
320 }
323 }
321
324
322 QModelIndex
325 QModelIndex
323 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name)
326 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name)
324 {
327 {
325 auto databaseItem
328 auto databaseItem
326 = new CatalogueTextTreeItem{QIcon{":/icones/database.png"}, {name}, DATABASE_ITEM_TYPE};
329 = new CatalogueTextTreeItem{QIcon{":/icones/database.png"}, {name}, DATABASE_ITEM_TYPE};
327 auto databaseIndex = m_TreeModel->addTopLevelItem(databaseItem);
330 auto databaseIndex = m_TreeModel->addTopLevelItem(databaseItem);
328
331
329 return databaseIndex;
332 return databaseIndex;
330 }
333 }
331
334
332 CatalogueAbstractTreeItem *
335 CatalogueAbstractTreeItem *
333 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name)
336 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name)
334 {
337 {
335 for (auto item : m_TreeModel->topLevelItems()) {
338 for (auto item : m_TreeModel->topLevelItems()) {
336 if (item->type() == DATABASE_ITEM_TYPE && item->text() == name) {
339 if (item->type() == DATABASE_ITEM_TYPE && item->text() == name) {
337 return item;
340 return item;
338 }
341 }
339 }
342 }
340
343
341 return nullptr;
344 return nullptr;
342 }
345 }
343
346
344 CatalogueAbstractTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
347 CatalogueAbstractTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
345 const std::shared_ptr<DBCatalogue> &catalogue, const QModelIndex &databaseIndex)
348 const std::shared_ptr<DBCatalogue> &catalogue, const QModelIndex &databaseIndex)
346 {
349 {
347 auto catalogueItem
350 auto catalogueItem
348 = new CatalogueTreeItem{catalogue, QIcon{":/icones/catalogue.png"}, CATALOGUE_ITEM_TYPE};
351 = new CatalogueTreeItem{catalogue, QIcon{":/icones/catalogue.png"}, CATALOGUE_ITEM_TYPE};
349 m_TreeModel->addChildItem(catalogueItem, databaseIndex);
352 m_TreeModel->addChildItem(catalogueItem, databaseIndex);
350
353
351 return catalogueItem;
354 return catalogueItem;
352 }
355 }
353
356
354 CatalogueTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
357 CatalogueTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
355 const std::shared_ptr<DBCatalogue> &catalogue) const
358 const std::shared_ptr<DBCatalogue> &catalogue) const
356 {
359 {
357 for (auto item : m_TreeModel->topLevelItems()) {
360 for (auto item : m_TreeModel->topLevelItems()) {
358 if (item->type() == DATABASE_ITEM_TYPE) {
361 if (item->type() == DATABASE_ITEM_TYPE) {
359 for (auto childItem : item->children()) {
362 for (auto childItem : item->children()) {
360 if (childItem->type() == CATALOGUE_ITEM_TYPE) {
363 if (childItem->type() == CATALOGUE_ITEM_TYPE) {
361 auto catalogueItem = static_cast<CatalogueTreeItem *>(childItem);
364 auto catalogueItem = static_cast<CatalogueTreeItem *>(childItem);
362 if (catalogueItem->catalogue()->getUniqId() == catalogue->getUniqId()) {
365 if (catalogueItem->catalogue()->getUniqId() == catalogue->getUniqId()) {
363 return catalogueItem;
366 return catalogueItem;
364 }
367 }
365 }
368 }
366 else {
369 else {
367 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
370 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
368 "structure. A database item should "
371 "structure. A database item should "
369 "only contain catalogues.";
372 "only contain catalogues.";
370 Q_ASSERT(false);
373 Q_ASSERT(false);
371 }
374 }
372 }
375 }
373 }
376 }
374 }
377 }
375
378
376 return nullptr;
379 return nullptr;
377 }
380 }
378
381
379 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(
382 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(
380 bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget)
383 bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget)
381 {
384 {
382 std::shared_ptr<DBCatalogue> catalogue = nullptr;
385 std::shared_ptr<DBCatalogue> catalogue = nullptr;
383 auto item = m_TreeModel->item(index);
386 auto item = m_TreeModel->item(index);
384 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
387 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
385 catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
388 catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
386 }
389 }
387
390
388 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
391 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
389 if (value) {
392 if (value) {
390 if (!hasChanges(validationIndex, sideBarWidget->ui->treeView)) {
393 if (!hasChanges(validationIndex, sideBarWidget->ui->treeView)) {
391 auto widget = CatalogueExplorerHelper::buildValidationWidget(
394 auto widget = CatalogueExplorerHelper::buildValidationWidget(
392 sideBarWidget->ui->treeView,
395 sideBarWidget->ui->treeView,
393 [this, validationIndex, sideBarWidget, catalogue]() {
396 [this, validationIndex, sideBarWidget, catalogue]() {
394 if (catalogue) {
397 if (catalogue) {
395 sqpApp->catalogueController().saveCatalogue(catalogue);
398 sqpApp->catalogueController().saveCatalogue(catalogue);
399 emit sideBarWidget->catalogueSaved(catalogue);
396 }
400 }
397 setHasChanges(false, validationIndex, sideBarWidget);
401 setHasChanges(false, validationIndex, sideBarWidget);
398 },
402 },
399 [this, validationIndex, sideBarWidget, catalogue, item]() {
403 [this, validationIndex, sideBarWidget, catalogue, item]() {
400 if (catalogue) {
404 if (catalogue) {
401 bool removed;
405 bool removed;
402 sqpApp->catalogueController().discardCatalogue(catalogue, removed);
406 sqpApp->catalogueController().discardCatalogue(catalogue, removed);
403
407
404 if (removed) {
408 if (removed) {
405 m_TreeModel->removeChildItem(item,
409 m_TreeModel->removeChildItem(item,
406 m_TreeModel->indexOf(item->parent()));
410 m_TreeModel->indexOf(item->parent()));
407 }
411 }
408 else {
412 else {
409 m_TreeModel->refresh(m_TreeModel->indexOf(item));
413 m_TreeModel->refresh(m_TreeModel->indexOf(item));
410 setHasChanges(false, validationIndex, sideBarWidget);
414 setHasChanges(false, validationIndex, sideBarWidget);
411 }
415 }
412 sideBarWidget->emitSelection();
416 sideBarWidget->emitSelection();
413 }
417 }
414 });
418 });
415 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, widget);
419 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, widget);
420 sideBarWidget->ui->treeView->header()->resizeSection(
421 (int)CatalogueTreeModel::Column::Validation, QHeaderView::ResizeToContents);
416 }
422 }
417 }
423 }
418 else {
424 else {
419 // Note: the widget is destroyed
425 // Note: the widget is destroyed
420 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, nullptr);
426 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, nullptr);
421 }
427 }
422 }
428 }
423
429
424 bool CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::hasChanges(const QModelIndex &index,
430 bool CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::hasChanges(const QModelIndex &index,
425 QTreeView *treeView)
431 QTreeView *treeView)
426 {
432 {
427 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
433 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
428 return treeView->indexWidget(validationIndex) != nullptr;
434 return treeView->indexWidget(validationIndex) != nullptr;
429 }
435 }
436
437
438 void CatalogueSideBarWidget::keyPressEvent(QKeyEvent *event)
439 {
440 switch (event->key()) {
441 case Qt::Key_Delete: {
442 ui->btnRemove->click();
443 }
444 default:
445 break;
446 }
447 }
@@ -1,129 +1,126
1 #include "Catalogue/CatalogueTreeItems/CatalogueTreeItem.h"
1 #include "Catalogue/CatalogueTreeItems/CatalogueTreeItem.h"
2 #include <Catalogue/CatalogueExplorerHelper.h>
2 #include <Catalogue/CatalogueExplorerHelper.h>
3
3
4 #include <Catalogue/CatalogueController.h>
4 #include <Catalogue/CatalogueController.h>
5 #include <Common/MimeTypesDef.h>
5 #include <Common/MimeTypesDef.h>
6 #include <QIcon>
6 #include <QIcon>
7 #include <QMimeData>
7 #include <QMimeData>
8 #include <SqpApplication.h>
8 #include <SqpApplication.h>
9
9
10 #include <memory>
10 #include <memory>
11
11
12 #include <DBCatalogue.h>
12 #include <DBCatalogue.h>
13
13
14 struct CatalogueTreeItem::CatalogueTreeItemPrivate {
14 struct CatalogueTreeItem::CatalogueTreeItemPrivate {
15
15
16 std::shared_ptr<DBCatalogue> m_Catalogue;
16 std::shared_ptr<DBCatalogue> m_Catalogue;
17 QIcon m_Icon;
17 QIcon m_Icon;
18
18
19 CatalogueTreeItemPrivate(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon)
19 CatalogueTreeItemPrivate(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon)
20 : m_Catalogue(catalogue), m_Icon(icon)
20 : m_Catalogue(catalogue), m_Icon(icon)
21 {
21 {
22 }
22 }
23 };
23 };
24
24
25
25
26 CatalogueTreeItem::CatalogueTreeItem(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon,
26 CatalogueTreeItem::CatalogueTreeItem(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon,
27 int type)
27 int type)
28 : CatalogueAbstractTreeItem(type),
28 : CatalogueAbstractTreeItem(type),
29 impl{spimpl::make_unique_impl<CatalogueTreeItemPrivate>(catalogue, icon)}
29 impl{spimpl::make_unique_impl<CatalogueTreeItemPrivate>(catalogue, icon)}
30 {
30 {
31 }
31 }
32
32
33 QVariant CatalogueTreeItem::data(int column, int role) const
33 QVariant CatalogueTreeItem::data(int column, int role) const
34 {
34 {
35 if (column == 0) {
35 if (column == 0) {
36 switch (role) {
36 switch (role) {
37 case Qt::EditRole: // fallthrough
37 case Qt::EditRole: // fallthrough
38 case Qt::DisplayRole:
38 case Qt::DisplayRole:
39 return impl->m_Catalogue->getName();
39 return impl->m_Catalogue->getName();
40 case Qt::DecorationRole:
40 case Qt::DecorationRole:
41 return impl->m_Icon;
41 return impl->m_Icon;
42 default:
42 default:
43 break;
43 break;
44 }
44 }
45 }
45 }
46
46
47 return QVariant();
47 return QVariant();
48 }
48 }
49
49
50 bool CatalogueTreeItem::setData(int column, int role, const QVariant &value)
50 bool CatalogueTreeItem::setData(int column, int role, const QVariant &value)
51 {
51 {
52 bool result = false;
52 bool result = false;
53
53
54 if (role == Qt::EditRole && column == 0) {
54 if (role == Qt::EditRole && column == 0) {
55 auto newName = value.toString();
55 auto newName = value.toString();
56 if (newName != impl->m_Catalogue->getName()) {
56 if (newName != impl->m_Catalogue->getName()) {
57 impl->m_Catalogue->setName(newName);
57 impl->m_Catalogue->setName(newName);
58 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
58 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
59 result = true;
59 result = true;
60 }
60 }
61 }
61 }
62
62
63 return result;
63 return result;
64 }
64 }
65
65
66 Qt::ItemFlags CatalogueTreeItem::flags(int column) const
66 Qt::ItemFlags CatalogueTreeItem::flags(int column) const
67 {
67 {
68 if (column == 0) {
68 if (column == 0) {
69 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable
69 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable
70 | Qt::ItemIsDropEnabled;
70 | Qt::ItemIsDropEnabled;
71 }
71 }
72 else {
72 else {
73 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
73 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
74 }
74 }
75 }
75 }
76
76
77 bool CatalogueTreeItem::canDropMimeData(const QMimeData *data, Qt::DropAction action)
77 bool CatalogueTreeItem::canDropMimeData(const QMimeData *data, Qt::DropAction action)
78 {
78 {
79 // Check that the event is not dropped on the same catalogue
79 // Check that the event is not dropped on the same catalogue
80 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
80 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
81 data->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
81 data->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
82 for (auto catalogue : sourceCatalogues) {
82 for (auto catalogue : sourceCatalogues) {
83 if (catalogue->getUniqId() == impl->m_Catalogue->getUniqId()) {
83 if (catalogue->getUniqId() == impl->m_Catalogue->getUniqId()) {
84 return false;
84 return false;
85 }
85 }
86 }
86 }
87
87
88 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
88 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
89 auto canDrop = data->hasFormat(MIME_TYPE_EVENT_LIST);
89 auto canDrop = data->hasFormat(MIME_TYPE_EVENT_LIST);
90
90
91 for (auto event : events) {
91 for (auto event : events) {
92 canDrop &= (event->getRepository() == impl->m_Catalogue->getRepository());
92 canDrop &= (event->getRepository() == impl->m_Catalogue->getRepository());
93 }
93 }
94
94
95 return canDrop;
95 return canDrop;
96 }
96 }
97
97
98 bool CatalogueTreeItem::dropMimeData(const QMimeData *data, Qt::DropAction action)
98 bool CatalogueTreeItem::dropMimeData(const QMimeData *data, Qt::DropAction action)
99 {
99 {
100 Q_ASSERT(canDropMimeData(data, action));
100 Q_ASSERT(canDropMimeData(data, action));
101 // Warning: Check that the events aren't already in the catalogue
101 // Warning: Check that the events aren't already in the catalogue
102 // No need to check check for the repository: inter-repository drop is forbidden in
102 // No need to check check for the repository: inter-repository drop is forbidden in
103 // canDropMimeData
103 // canDropMimeData
104
104
105 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
105 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
106 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
106 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
107 data->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
107 data->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
108
108
109 for (auto event : events) {
109 for (auto event : events) {
110
110
111 if (action == Qt::MoveAction) {
111 if (action == Qt::MoveAction) {
112 for (auto catalogue : sourceCatalogues) {
112 for (auto catalogue : sourceCatalogues) {
113 catalogue->removeEvent(event->getUniqId());
113 catalogue->removeEvent(event->getUniqId());
114 sqpApp->catalogueController().updateCatalogue(catalogue);
114 }
115 }
115 }
116 }
116
117
117 impl->m_Catalogue->addEvent(event->getUniqId());
118 impl->m_Catalogue->addEvent(event->getUniqId());
119 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
118 }
120 }
119
120 for (auto catalogue : sourceCatalogues) {
121 sqpApp->catalogueController().updateCatalogue(catalogue);
122 }
123 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
124 }
121 }
125
122
126 std::shared_ptr<DBCatalogue> CatalogueTreeItem::catalogue() const
123 std::shared_ptr<DBCatalogue> CatalogueTreeItem::catalogue() const
127 {
124 {
128 return impl->m_Catalogue;
125 return impl->m_Catalogue;
129 }
126 }
@@ -1,207 +1,205
1 #include "Visualization/AxisRenderingUtils.h"
1 #include "Visualization/AxisRenderingUtils.h"
2
2
3 #include <Data/ScalarSeries.h>
3 #include <Data/ScalarSeries.h>
4 #include <Data/SpectrogramSeries.h>
4 #include <Data/SpectrogramSeries.h>
5 #include <Data/VectorSeries.h>
5 #include <Data/VectorSeries.h>
6
6
7 #include <Variable/Variable.h>
7 #include <Variable/Variable.h>
8
8
9 #include <Visualization/SqpColorScale.h>
9 #include <Visualization/SqpColorScale.h>
10 #include <Visualization/qcustomplot.h>
10 #include <Visualization/qcustomplot.h>
11
11
12 Q_LOGGING_CATEGORY(LOG_AxisRenderingUtils, "AxisRenderingUtils")
12 Q_LOGGING_CATEGORY(LOG_AxisRenderingUtils, "AxisRenderingUtils")
13
13
14 namespace {
14 namespace {
15
15
16 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
17
18 /// Format for datetimes on a axis
16 /// Format for datetimes on a axis
19 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
17 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
20
18
21 const auto NUMBER_FORMAT = 'g';
19 const auto NUMBER_FORMAT = 'g';
22 const auto NUMBER_PRECISION = 9;
20 const auto NUMBER_PRECISION = 9;
23
21
24 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
22 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
25 /// non-time data
23 /// non-time data
26 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis, QCPAxis::ScaleType scaleType)
24 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis, QCPAxis::ScaleType scaleType)
27 {
25 {
28 if (isTimeAxis) {
26 if (isTimeAxis) {
29 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
27 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
30 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
28 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
31 dateTicker->setDateTimeSpec(Qt::UTC);
29 dateTicker->setDateTimeSpec(Qt::UTC);
32
30
33 return dateTicker;
31 return dateTicker;
34 }
32 }
35 else if (scaleType == QCPAxis::stLogarithmic) {
33 else if (scaleType == QCPAxis::stLogarithmic) {
36 return QSharedPointer<QCPAxisTickerLog>::create();
34 return QSharedPointer<QCPAxisTickerLog>::create();
37 }
35 }
38 else {
36 else {
39 // default ticker
37 // default ticker
40 return QSharedPointer<QCPAxisTicker>::create();
38 return QSharedPointer<QCPAxisTicker>::create();
41 }
39 }
42 }
40 }
43
41
44 /**
42 /**
45 * Sets properties of the axis passed as parameter
43 * Sets properties of the axis passed as parameter
46 * @param axis the axis to set
44 * @param axis the axis to set
47 * @param unit the unit to set for the axis
45 * @param unit the unit to set for the axis
48 * @param scaleType the scale type to set for the axis
46 * @param scaleType the scale type to set for the axis
49 */
47 */
50 void setAxisProperties(QCPAxis &axis, const Unit &unit,
48 void setAxisProperties(QCPAxis &axis, const Unit &unit,
51 QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
49 QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
52 {
50 {
53 // label (unit name)
51 // label (unit name)
54 axis.setLabel(unit.m_Name);
52 axis.setLabel(unit.m_Name);
55
53
56 // scale type
54 // scale type
57 axis.setScaleType(scaleType);
55 axis.setScaleType(scaleType);
58 if (scaleType == QCPAxis::stLogarithmic) {
56 if (scaleType == QCPAxis::stLogarithmic) {
59 // Scientific notation
57 // Scientific notation
60 axis.setNumberPrecision(0);
58 axis.setNumberPrecision(0);
61 axis.setNumberFormat("eb");
59 axis.setNumberFormat("eb");
62 }
60 }
63
61
64 // ticker (depending on the type of unit)
62 // ticker (depending on the type of unit)
65 axis.setTicker(axisTicker(unit.m_TimeUnit, scaleType));
63 axis.setTicker(axisTicker(unit.m_TimeUnit, scaleType));
66 }
64 }
67
65
68 /**
66 /**
69 * Delegate used to set axes properties
67 * Delegate used to set axes properties
70 */
68 */
71 template <typename T, typename Enabled = void>
69 template <typename T, typename Enabled = void>
72 struct AxisSetter {
70 struct AxisSetter {
73 static void setProperties(QCustomPlot &, SqpColorScale &)
71 static void setProperties(QCustomPlot &, SqpColorScale &)
74 {
72 {
75 // Default implementation does nothing
73 // Default implementation does nothing
76 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
74 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
77 }
75 }
78
76
79 static void setUnits(T &, QCustomPlot &, SqpColorScale &)
77 static void setUnits(T &, QCustomPlot &, SqpColorScale &)
80 {
78 {
81 // Default implementation does nothing
79 // Default implementation does nothing
82 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis units: unmanaged type of data";
80 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis units: unmanaged type of data";
83 }
81 }
84 };
82 };
85
83
86 /**
84 /**
87 * Specialization of AxisSetter for scalars and vectors
85 * Specialization of AxisSetter for scalars and vectors
88 * @sa ScalarSeries
86 * @sa ScalarSeries
89 * @sa VectorSeries
87 * @sa VectorSeries
90 */
88 */
91 template <typename T>
89 template <typename T>
92 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
90 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
93 or std::is_base_of<VectorSeries, T>::value> > {
91 or std::is_base_of<VectorSeries, T>::value> > {
94 static void setProperties(QCustomPlot &, SqpColorScale &)
92 static void setProperties(QCustomPlot &, SqpColorScale &)
95 {
93 {
96 // Nothing to do
94 // Nothing to do
97 }
95 }
98
96
99 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
97 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
100 {
98 {
101 dataSeries.lockRead();
99 dataSeries.lockRead();
102 auto xAxisUnit = dataSeries.xAxisUnit();
100 auto xAxisUnit = dataSeries.xAxisUnit();
103 auto valuesUnit = dataSeries.valuesUnit();
101 auto valuesUnit = dataSeries.valuesUnit();
104 dataSeries.unlock();
102 dataSeries.unlock();
105
103
106 setAxisProperties(*plot.xAxis, xAxisUnit);
104 setAxisProperties(*plot.xAxis, xAxisUnit);
107 setAxisProperties(*plot.yAxis, valuesUnit);
105 setAxisProperties(*plot.yAxis, valuesUnit);
108 }
106 }
109 };
107 };
110
108
111 /**
109 /**
112 * Specialization of AxisSetter for spectrograms
110 * Specialization of AxisSetter for spectrograms
113 * @sa SpectrogramSeries
111 * @sa SpectrogramSeries
114 */
112 */
115 template <typename T>
113 template <typename T>
116 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
114 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
117 static void setProperties(QCustomPlot &plot, SqpColorScale &colorScale)
115 static void setProperties(QCustomPlot &plot, SqpColorScale &colorScale)
118 {
116 {
119 // Displays color scale in plot
117 // Displays color scale in plot
120 plot.plotLayout()->insertRow(0);
118 plot.plotLayout()->insertRow(0);
121 plot.plotLayout()->addElement(0, 0, colorScale.m_Scale);
119 plot.plotLayout()->addElement(0, 0, colorScale.m_Scale);
122 colorScale.m_Scale->setType(QCPAxis::atTop);
120 colorScale.m_Scale->setType(QCPAxis::atTop);
123 colorScale.m_Scale->setMinimumMargins(QMargins{0, 0, 0, 0});
121 colorScale.m_Scale->setMinimumMargins(QMargins{0, 0, 0, 0});
124
122
125 // Aligns color scale with axes
123 // Aligns color scale with axes
126 auto marginGroups = plot.axisRect()->marginGroups();
124 auto marginGroups = plot.axisRect()->marginGroups();
127 for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it) {
125 for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it) {
128 colorScale.m_Scale->setMarginGroup(it.key(), it.value());
126 colorScale.m_Scale->setMarginGroup(it.key(), it.value());
129 }
127 }
130
128
131 // Set color scale properties
129 // Set color scale properties
132 colorScale.m_AutomaticThreshold = true;
130 colorScale.m_AutomaticThreshold = true;
133 }
131 }
134
132
135 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
133 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
136 {
134 {
137 dataSeries.lockRead();
135 dataSeries.lockRead();
138 auto xAxisUnit = dataSeries.xAxisUnit();
136 auto xAxisUnit = dataSeries.xAxisUnit();
139 auto yAxisUnit = dataSeries.yAxisUnit();
137 auto yAxisUnit = dataSeries.yAxisUnit();
140 auto valuesUnit = dataSeries.valuesUnit();
138 auto valuesUnit = dataSeries.valuesUnit();
141 dataSeries.unlock();
139 dataSeries.unlock();
142
140
143 setAxisProperties(*plot.xAxis, xAxisUnit);
141 setAxisProperties(*plot.xAxis, xAxisUnit);
144 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
142 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
145 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
143 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
146 }
144 }
147 };
145 };
148
146
149 /**
147 /**
150 * Default implementation of IAxisHelper, which takes data series to set axes properties
148 * Default implementation of IAxisHelper, which takes data series to set axes properties
151 * @tparam T the data series' type
149 * @tparam T the data series' type
152 */
150 */
153 template <typename T>
151 template <typename T>
154 struct AxisHelper : public IAxisHelper {
152 struct AxisHelper : public IAxisHelper {
155 explicit AxisHelper(std::shared_ptr<T> dataSeries) : m_DataSeries{dataSeries} {}
153 explicit AxisHelper(std::shared_ptr<T> dataSeries) : m_DataSeries{dataSeries} {}
156
154
157 void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
155 void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
158 {
156 {
159 AxisSetter<T>::setProperties(plot, colorScale);
157 AxisSetter<T>::setProperties(plot, colorScale);
160 }
158 }
161
159
162 void setUnits(QCustomPlot &plot, SqpColorScale &colorScale) override
160 void setUnits(QCustomPlot &plot, SqpColorScale &colorScale) override
163 {
161 {
164 if (m_DataSeries) {
162 if (m_DataSeries) {
165 AxisSetter<T>::setUnits(*m_DataSeries, plot, colorScale);
163 AxisSetter<T>::setUnits(*m_DataSeries, plot, colorScale);
166 }
164 }
167 else {
165 else {
168 qCCritical(LOG_AxisRenderingUtils()) << "Can't set units: inconsistency between the "
166 qCCritical(LOG_AxisRenderingUtils()) << "Can't set units: inconsistency between the "
169 "type of data series and the type supposed";
167 "type of data series and the type supposed";
170 }
168 }
171 }
169 }
172
170
173 std::shared_ptr<T> m_DataSeries;
171 std::shared_ptr<T> m_DataSeries;
174 };
172 };
175
173
176 } // namespace
174 } // namespace
177
175
178 QString formatValue(double value, const QCPAxis &axis)
176 QString formatValue(double value, const QCPAxis &axis)
179 {
177 {
180 // If the axis is a time axis, formats the value as a date
178 // If the axis is a time axis, formats the value as a date
181 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
179 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
182 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
180 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
183 }
181 }
184 else {
182 else {
185 return QString::number(value, NUMBER_FORMAT, NUMBER_PRECISION);
183 return QString::number(value, NUMBER_FORMAT, NUMBER_PRECISION);
186 }
184 }
187 }
185 }
188
186
189 std::unique_ptr<IAxisHelper> IAxisHelperFactory::create(const Variable &variable) noexcept
187 std::unique_ptr<IAxisHelper> IAxisHelperFactory::create(const Variable &variable) noexcept
190 {
188 {
191 switch (variable.type()) {
189 switch (variable.type()) {
192 case DataSeriesType::SCALAR:
190 case DataSeriesType::SCALAR:
193 return std::make_unique<AxisHelper<ScalarSeries> >(
191 return std::make_unique<AxisHelper<ScalarSeries> >(
194 std::dynamic_pointer_cast<ScalarSeries>(variable.dataSeries()));
192 std::dynamic_pointer_cast<ScalarSeries>(variable.dataSeries()));
195 case DataSeriesType::SPECTROGRAM:
193 case DataSeriesType::SPECTROGRAM:
196 return std::make_unique<AxisHelper<SpectrogramSeries> >(
194 return std::make_unique<AxisHelper<SpectrogramSeries> >(
197 std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()));
195 std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()));
198 case DataSeriesType::VECTOR:
196 case DataSeriesType::VECTOR:
199 return std::make_unique<AxisHelper<VectorSeries> >(
197 return std::make_unique<AxisHelper<VectorSeries> >(
200 std::dynamic_pointer_cast<VectorSeries>(variable.dataSeries()));
198 std::dynamic_pointer_cast<VectorSeries>(variable.dataSeries()));
201 default:
199 default:
202 // Creates default helper
200 // Creates default helper
203 break;
201 break;
204 }
202 }
205
203
206 return std::make_unique<AxisHelper<IDataSeries> >(nullptr);
204 return std::make_unique<AxisHelper<IDataSeries> >(nullptr);
207 }
205 }
@@ -1,69 +1,69
1 #include "Visualization/VisualizationMultiZoneSelectionDialog.h"
1 #include "Visualization/VisualizationMultiZoneSelectionDialog.h"
2 #include "ui_VisualizationMultiZoneSelectionDialog.h"
2 #include "ui_VisualizationMultiZoneSelectionDialog.h"
3
3
4 #include "Common/DateUtils.h"
4 #include "Common/DateUtils.h"
5 #include "Visualization/VisualizationSelectionZoneItem.h"
5 #include "Visualization/VisualizationSelectionZoneItem.h"
6
6
7 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss");
7 const auto DATETIME_FORMAT_S = QStringLiteral("yyyy/MM/dd hh:mm:ss");
8
8
9 struct VisualizationMultiZoneSelectionDialog::VisualizationMultiZoneSelectionDialogPrivate {
9 struct VisualizationMultiZoneSelectionDialog::VisualizationMultiZoneSelectionDialogPrivate {
10 QVector<VisualizationSelectionZoneItem *> m_Zones;
10 QVector<VisualizationSelectionZoneItem *> m_Zones;
11 };
11 };
12
12
13 VisualizationMultiZoneSelectionDialog::VisualizationMultiZoneSelectionDialog(QWidget *parent)
13 VisualizationMultiZoneSelectionDialog::VisualizationMultiZoneSelectionDialog(QWidget *parent)
14 : QDialog(parent, Qt::Tool),
14 : QDialog(parent, Qt::Tool),
15 ui(new Ui::VisualizationMultiZoneSelectionDialog),
15 ui(new Ui::VisualizationMultiZoneSelectionDialog),
16 impl{spimpl::make_unique_impl<VisualizationMultiZoneSelectionDialogPrivate>()}
16 impl{spimpl::make_unique_impl<VisualizationMultiZoneSelectionDialogPrivate>()}
17 {
17 {
18 ui->setupUi(this);
18 ui->setupUi(this);
19
19
20 connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
20 connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
21 &VisualizationMultiZoneSelectionDialog::accept);
21 &VisualizationMultiZoneSelectionDialog::accept);
22 connect(ui->buttonBox, &QDialogButtonBox::rejected, this,
22 connect(ui->buttonBox, &QDialogButtonBox::rejected, this,
23 &VisualizationMultiZoneSelectionDialog::reject);
23 &VisualizationMultiZoneSelectionDialog::reject);
24 }
24 }
25
25
26 VisualizationMultiZoneSelectionDialog::~VisualizationMultiZoneSelectionDialog()
26 VisualizationMultiZoneSelectionDialog::~VisualizationMultiZoneSelectionDialog()
27 {
27 {
28 delete ui;
28 delete ui;
29 }
29 }
30
30
31 void VisualizationMultiZoneSelectionDialog::setZones(
31 void VisualizationMultiZoneSelectionDialog::setZones(
32 const QVector<VisualizationSelectionZoneItem *> &zones)
32 const QVector<VisualizationSelectionZoneItem *> &zones)
33 {
33 {
34 impl->m_Zones = zones;
34 impl->m_Zones = zones;
35
35
36 // Sorts the zones to display them in temporal order
36 // Sorts the zones to display them in temporal order
37 std::sort(impl->m_Zones.begin(), impl->m_Zones.end(), [](auto zone1, auto zone2) {
37 std::sort(impl->m_Zones.begin(), impl->m_Zones.end(), [](auto zone1, auto zone2) {
38 return zone1->range().m_TStart < zone2->range().m_TStart;
38 return zone1->range().m_TStart < zone2->range().m_TStart;
39 });
39 });
40
40
41 // Adds the zones in the listwidget
41 // Adds the zones in the listwidget
42 for (auto zone : impl->m_Zones) {
42 for (auto zone : impl->m_Zones) {
43 auto name = zone->name();
43 auto name = zone->name();
44 if (!name.isEmpty()) {
44 if (!name.isEmpty()) {
45 name += tr(": ");
45 name += tr(": ");
46 }
46 }
47
47
48 auto range = zone->range();
48 auto range = zone->range();
49 name += DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT);
49 name += DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT_S);
50 name += " - ";
50 name += " - ";
51 name += DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT);
51 name += DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT_S);
52
52
53 auto item = new QListWidgetItem(name, ui->listWidget);
53 auto item = new QListWidgetItem(name, ui->listWidget);
54 item->setSelected(zone->selected());
54 item->setSelected(zone->selected());
55 }
55 }
56 }
56 }
57
57
58 QMap<VisualizationSelectionZoneItem *, bool>
58 QMap<VisualizationSelectionZoneItem *, bool>
59 VisualizationMultiZoneSelectionDialog::selectedZones() const
59 VisualizationMultiZoneSelectionDialog::selectedZones() const
60 {
60 {
61 QMap<VisualizationSelectionZoneItem *, bool> selectedZones;
61 QMap<VisualizationSelectionZoneItem *, bool> selectedZones;
62
62
63 for (auto i = 0; i < ui->listWidget->count(); ++i) {
63 for (auto i = 0; i < ui->listWidget->count(); ++i) {
64 auto item = ui->listWidget->item(i);
64 auto item = ui->listWidget->item(i);
65 selectedZones[impl->m_Zones[i]] = item->isSelected();
65 selectedZones[impl->m_Zones[i]] = item->isSelected();
66 }
66 }
67
67
68 return selectedZones;
68 return selectedZones;
69 }
69 }
@@ -1,658 +1,658
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/VisualizationWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
8
8
9 #include "Common/MimeTypesDef.h"
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
10 #include "Common/VisualizationDef.h"
11
11
12 #include <Data/SqpRange.h>
12 #include <Data/SqpRange.h>
13 #include <DataSource/DataSourceController.h>
13 #include <DataSource/DataSourceController.h>
14 #include <Time/TimeController.h>
14 #include <Time/TimeController.h>
15 #include <Variable/Variable.h>
15 #include <Variable/Variable.h>
16 #include <Variable/VariableController.h>
16 #include <Variable/VariableController.h>
17
17
18 #include <Visualization/operations/FindVariableOperation.h>
18 #include <Visualization/operations/FindVariableOperation.h>
19
19
20 #include <DragAndDrop/DragDropGuiController.h>
20 #include <DragAndDrop/DragDropGuiController.h>
21 #include <QUuid>
21 #include <QUuid>
22 #include <SqpApplication.h>
22 #include <SqpApplication.h>
23 #include <cmath>
23 #include <cmath>
24
24
25 #include <QLayout>
25 #include <QLayout>
26
26
27 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
28
28
29 namespace {
29 namespace {
30
30
31 /**
31 /**
32 * Applies a function to all graphs of the zone represented by its layout
32 * Applies a function to all graphs of the zone represented by its layout
33 * @param layout the layout that contains graphs
33 * @param layout the layout that contains graphs
34 * @param fun the function to apply to each graph
34 * @param fun the function to apply to each graph
35 */
35 */
36 template <typename Fun>
36 template <typename Fun>
37 void processGraphs(QLayout &layout, Fun fun)
37 void processGraphs(QLayout &layout, Fun fun)
38 {
38 {
39 for (auto i = 0; i < layout.count(); ++i) {
39 for (auto i = 0; i < layout.count(); ++i) {
40 if (auto item = layout.itemAt(i)) {
40 if (auto item = layout.itemAt(i)) {
41 if (auto visualizationGraphWidget
41 if (auto visualizationGraphWidget
42 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
42 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
43 fun(*visualizationGraphWidget);
43 fun(*visualizationGraphWidget);
44 }
44 }
45 }
45 }
46 }
46 }
47 }
47 }
48
48
49 /// Generates a default name for a new graph, according to the number of graphs already displayed in
49 /// Generates a default name for a new graph, according to the number of graphs already displayed in
50 /// the zone
50 /// the zone
51 QString defaultGraphName(QLayout &layout)
51 QString defaultGraphName(QLayout &layout)
52 {
52 {
53 QSet<QString> existingNames;
53 QSet<QString> existingNames;
54 processGraphs(
54 processGraphs(
55 layout, [&existingNames](auto &graphWidget) { existingNames.insert(graphWidget.name()); });
55 layout, [&existingNames](auto &graphWidget) { existingNames.insert(graphWidget.name()); });
56
56
57 int zoneNum = 1;
57 int zoneNum = 1;
58 QString name;
58 QString name;
59 do {
59 do {
60 name = QObject::tr("Graph ").append(QString::number(zoneNum));
60 name = QObject::tr("Graph ").append(QString::number(zoneNum));
61 ++zoneNum;
61 ++zoneNum;
62 } while (existingNames.contains(name));
62 } while (existingNames.contains(name));
63
63
64 return name;
64 return name;
65 }
65 }
66
66
67 } // namespace
67 } // namespace
68
68
69 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
69 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
70
70
71 explicit VisualizationZoneWidgetPrivate()
71 explicit VisualizationZoneWidgetPrivate()
72 : m_SynchronisationGroupId{QUuid::createUuid()},
72 : m_SynchronisationGroupId{QUuid::createUuid()},
73 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
73 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
74 {
74 {
75 }
75 }
76 QUuid m_SynchronisationGroupId;
76 QUuid m_SynchronisationGroupId;
77 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
77 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
78
78
79 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
79 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
80 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
80 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
81 VisualizationZoneWidget *zoneWidget);
81 VisualizationZoneWidget *zoneWidget);
82 void dropProducts(const QVariantList &productsData, int index,
82 void dropProducts(const QVariantList &productsData, int index,
83 VisualizationZoneWidget *zoneWidget);
83 VisualizationZoneWidget *zoneWidget);
84 };
84 };
85
85
86 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
86 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
87 : VisualizationDragWidget{parent},
87 : VisualizationDragWidget{parent},
88 ui{new Ui::VisualizationZoneWidget},
88 ui{new Ui::VisualizationZoneWidget},
89 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
89 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
90 {
90 {
91 ui->setupUi(this);
91 ui->setupUi(this);
92
92
93 ui->zoneNameLabel->setText(name);
93 ui->zoneNameLabel->setText(name);
94
94
95 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
95 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
96 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
96 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
97 VisualizationDragDropContainer::DropBehavior::Inserted);
97 VisualizationDragDropContainer::DropBehavior::Inserted);
98 ui->dragDropContainer->setMimeType(
98 ui->dragDropContainer->setMimeType(
99 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
99 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
100 ui->dragDropContainer->setMimeType(
100 ui->dragDropContainer->setMimeType(
101 MIME_TYPE_PRODUCT_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
101 MIME_TYPE_PRODUCT_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
102 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
102 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
103 VisualizationDragDropContainer::DropBehavior::Merged);
103 VisualizationDragDropContainer::DropBehavior::Merged);
104 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
104 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
105 VisualizationDragDropContainer::DropBehavior::Forbidden);
105 VisualizationDragDropContainer::DropBehavior::Forbidden);
106 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
106 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
107 VisualizationDragDropContainer::DropBehavior::Forbidden);
107 VisualizationDragDropContainer::DropBehavior::Forbidden);
108 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
108 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
109 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
109 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
110 ui->dragDropContainer);
110 ui->dragDropContainer);
111 });
111 });
112
112
113 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
113 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
114 if (!mimeData) {
114 if (!mimeData) {
115 return false;
115 return false;
116 }
116 }
117
117
118 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
118 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
119 auto variables = sqpApp->variableController().variablesForMimeData(
119 auto variables = sqpApp->variableController().variablesForMimeData(
120 mimeData->data(MIME_TYPE_VARIABLE_LIST));
120 mimeData->data(MIME_TYPE_VARIABLE_LIST));
121
121
122 if (variables.count() != 1) {
122 if (variables.count() != 1) {
123 return false;
123 return false;
124 }
124 }
125 auto variable = variables.first();
125 auto variable = variables.first();
126
126
127 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
127 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
128 return graphWidget->canDrop(*variable);
128 return graphWidget->canDrop(*variable);
129 }
129 }
130 }
130 }
131
131
132 return true;
132 return true;
133 };
133 };
134 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
134 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
135
135
136 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
136 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
137 &VisualizationZoneWidget::dropMimeData);
137 &VisualizationZoneWidget::dropMimeData);
138 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
138 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
139 &VisualizationZoneWidget::dropMimeDataOnGraph);
139 &VisualizationZoneWidget::dropMimeDataOnGraph);
140
140
141 // 'Close' options : widget is deleted when closed
141 // 'Close' options : widget is deleted when closed
142 setAttribute(Qt::WA_DeleteOnClose);
142 setAttribute(Qt::WA_DeleteOnClose);
143 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
143 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
144 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
144 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
145
145
146 // Synchronisation id
146 // Synchronisation id
147 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
147 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
148 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
148 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
149 }
149 }
150
150
151 VisualizationZoneWidget::~VisualizationZoneWidget()
151 VisualizationZoneWidget::~VisualizationZoneWidget()
152 {
152 {
153 delete ui;
153 delete ui;
154 }
154 }
155
155
156 void VisualizationZoneWidget::setZoneRange(const SqpRange &range)
156 void VisualizationZoneWidget::setZoneRange(const SqpRange &range)
157 {
157 {
158 if (auto graph = firstGraph()) {
158 if (auto graph = firstGraph()) {
159 graph->setGraphRange(range);
159 graph->setGraphRange(range);
160 }
160 }
161 else {
161 else {
162 qCWarning(LOG_VisualizationZoneWidget())
162 qCWarning(LOG_VisualizationZoneWidget())
163 << tr("setZoneRange:Cannot set the range of an empty zone.");
163 << tr("setZoneRange:Cannot set the range of an empty zone.");
164 }
164 }
165 }
165 }
166
166
167 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
167 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
168 {
168 {
169 // Synchronize new graph with others in the zone
169 // Synchronize new graph with others in the zone
170 impl->m_Synchronizer->addGraph(*graphWidget);
170 impl->m_Synchronizer->addGraph(*graphWidget);
171
171
172 ui->dragDropContainer->addDragWidget(graphWidget);
172 ui->dragDropContainer->addDragWidget(graphWidget);
173 }
173 }
174
174
175 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
175 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
176 {
176 {
177 // Synchronize new graph with others in the zone
177 // Synchronize new graph with others in the zone
178 impl->m_Synchronizer->addGraph(*graphWidget);
178 impl->m_Synchronizer->addGraph(*graphWidget);
179
179
180 ui->dragDropContainer->insertDragWidget(index, graphWidget);
180 ui->dragDropContainer->insertDragWidget(index, graphWidget);
181 }
181 }
182
182
183 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
183 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
184 {
184 {
185 return createGraph(variable, -1);
185 return createGraph(variable, -1);
186 }
186 }
187
187
188 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
188 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
189 int index)
189 int index)
190 {
190 {
191 auto graphWidget
191 auto graphWidget
192 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
192 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
193
193
194
194
195 // Set graph properties
195 // Set graph properties
196 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
196 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
197 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
197 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
198
198
199
199
200 // Lambda to synchronize zone widget
200 // Lambda to synchronize zone widget
201 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
201 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
202 const SqpRange &oldGraphRange) {
202 const SqpRange &oldGraphRange) {
203
203
204 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
204 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
205 auto frameLayout = ui->dragDropContainer->layout();
205 auto frameLayout = ui->dragDropContainer->layout();
206 for (auto i = 0; i < frameLayout->count(); ++i) {
206 for (auto i = 0; i < frameLayout->count(); ++i) {
207 auto graphChild
207 auto graphChild
208 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
208 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
209 if (graphChild && (graphChild != graphWidget)) {
209 if (graphChild && (graphChild != graphWidget)) {
210
210
211 auto graphChildRange = graphChild->graphRange();
211 auto graphChildRange = graphChild->graphRange();
212 switch (zoomType) {
212 switch (zoomType) {
213 case AcquisitionZoomType::ZoomIn: {
213 case AcquisitionZoomType::ZoomIn: {
214 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
214 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
215 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
215 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
216 graphChildRange.m_TStart += deltaLeft;
216 graphChildRange.m_TStart += deltaLeft;
217 graphChildRange.m_TEnd -= deltaRight;
217 graphChildRange.m_TEnd -= deltaRight;
218 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
218 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
219 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
219 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
220 << deltaLeft;
220 << deltaLeft;
221 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
221 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
222 << deltaRight;
222 << deltaRight;
223 qCDebug(LOG_VisualizationZoneWidget())
223 qCDebug(LOG_VisualizationZoneWidget())
224 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
224 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
225
225
226 break;
226 break;
227 }
227 }
228
228
229 case AcquisitionZoomType::ZoomOut: {
229 case AcquisitionZoomType::ZoomOut: {
230 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
230 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
231 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
231 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
232 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
232 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
233 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
233 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
234 << deltaLeft;
234 << deltaLeft;
235 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
235 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
236 << deltaRight;
236 << deltaRight;
237 qCDebug(LOG_VisualizationZoneWidget())
237 qCDebug(LOG_VisualizationZoneWidget())
238 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
238 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
239 graphChildRange.m_TStart -= deltaLeft;
239 graphChildRange.m_TStart -= deltaLeft;
240 graphChildRange.m_TEnd += deltaRight;
240 graphChildRange.m_TEnd += deltaRight;
241 break;
241 break;
242 }
242 }
243 case AcquisitionZoomType::PanRight: {
243 case AcquisitionZoomType::PanRight: {
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
245 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
245 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
246 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
246 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
247 graphChildRange.m_TStart += deltaLeft;
247 graphChildRange.m_TStart += deltaLeft;
248 graphChildRange.m_TEnd += deltaRight;
248 graphChildRange.m_TEnd += deltaRight;
249 qCDebug(LOG_VisualizationZoneWidget())
249 qCDebug(LOG_VisualizationZoneWidget())
250 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
250 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
251 break;
251 break;
252 }
252 }
253 case AcquisitionZoomType::PanLeft: {
253 case AcquisitionZoomType::PanLeft: {
254 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
254 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
255 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
255 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
256 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
256 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
257 graphChildRange.m_TStart -= deltaLeft;
257 graphChildRange.m_TStart -= deltaLeft;
258 graphChildRange.m_TEnd -= deltaRight;
258 graphChildRange.m_TEnd -= deltaRight;
259 break;
259 break;
260 }
260 }
261 case AcquisitionZoomType::Unknown: {
261 case AcquisitionZoomType::Unknown: {
262 qCDebug(LOG_VisualizationZoneWidget())
262 qCDebug(LOG_VisualizationZoneWidget())
263 << tr("Impossible to synchronize: zoom type unknown");
263 << tr("Impossible to synchronize: zoom type unknown");
264 break;
264 break;
265 }
265 }
266 default:
266 default:
267 qCCritical(LOG_VisualizationZoneWidget())
267 qCCritical(LOG_VisualizationZoneWidget())
268 << tr("Impossible to synchronize: zoom type not take into account");
268 << tr("Impossible to synchronize: zoom type not take into account");
269 // No action
269 // No action
270 break;
270 break;
271 }
271 }
272 graphChild->setFlags(GraphFlag::DisableAll);
272 graphChild->setFlags(GraphFlag::DisableAll);
273 qCDebug(LOG_VisualizationZoneWidget())
273 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
274 << tr("TORM: Range before: ") << graphChild->graphRange();
274 << graphChild->graphRange();
275 qCDebug(LOG_VisualizationZoneWidget())
275 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
276 << tr("TORM: Range after : ") << graphChildRange;
276 << graphChildRange;
277 qCDebug(LOG_VisualizationZoneWidget())
277 qCDebug(LOG_VisualizationZoneWidget())
278 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
278 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
279 graphChild->setGraphRange(graphChildRange);
279 graphChild->setGraphRange(graphChildRange);
280 graphChild->setFlags(GraphFlag::EnableAll);
280 graphChild->setFlags(GraphFlag::EnableAll);
281 }
281 }
282 }
282 }
283 };
283 };
284
284
285 // connection for synchronization
285 // connection for synchronization
286 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
286 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
287 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
287 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
288 &VisualizationZoneWidget::onVariableAdded);
288 &VisualizationZoneWidget::onVariableAdded);
289 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
289 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
290 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
290 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
291
291
292 auto range = SqpRange{};
292 auto range = SqpRange{};
293 if (auto firstGraph = this->firstGraph()) {
293 if (auto firstGraph = this->firstGraph()) {
294 // Case of a new graph in a existant zone
294 // Case of a new graph in a existant zone
295 range = firstGraph->graphRange();
295 range = firstGraph->graphRange();
296 }
296 }
297 else {
297 else {
298 // Case of a new graph as the first of the zone
298 // Case of a new graph as the first of the zone
299 range = variable->range();
299 range = variable->range();
300 }
300 }
301
301
302 this->insertGraph(index, graphWidget);
302 this->insertGraph(index, graphWidget);
303
303
304 graphWidget->addVariable(variable, range);
304 graphWidget->addVariable(variable, range);
305 graphWidget->setYRange(variable);
305 graphWidget->setYRange(variable);
306
306
307 return graphWidget;
307 return graphWidget;
308 }
308 }
309
309
310 VisualizationGraphWidget *
310 VisualizationGraphWidget *
311 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
311 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
312 {
312 {
313 if (variables.isEmpty()) {
313 if (variables.isEmpty()) {
314 return nullptr;
314 return nullptr;
315 }
315 }
316
316
317 auto graphWidget = createGraph(variables.first(), index);
317 auto graphWidget = createGraph(variables.first(), index);
318 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
318 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
319 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
319 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
320 }
320 }
321
321
322 return graphWidget;
322 return graphWidget;
323 }
323 }
324
324
325 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
325 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
326 {
326 {
327 VisualizationGraphWidget *firstGraph = nullptr;
327 VisualizationGraphWidget *firstGraph = nullptr;
328 auto layout = ui->dragDropContainer->layout();
328 auto layout = ui->dragDropContainer->layout();
329 if (layout->count() > 0) {
329 if (layout->count() > 0) {
330 if (auto visualizationGraphWidget
330 if (auto visualizationGraphWidget
331 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
331 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
332 firstGraph = visualizationGraphWidget;
332 firstGraph = visualizationGraphWidget;
333 }
333 }
334 }
334 }
335
335
336 return firstGraph;
336 return firstGraph;
337 }
337 }
338
338
339 void VisualizationZoneWidget::closeAllGraphs()
339 void VisualizationZoneWidget::closeAllGraphs()
340 {
340 {
341 processGraphs(*ui->dragDropContainer->layout(),
341 processGraphs(*ui->dragDropContainer->layout(),
342 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
342 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
343 }
343 }
344
344
345 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
345 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
346 {
346 {
347 if (visitor) {
347 if (visitor) {
348 visitor->visitEnter(this);
348 visitor->visitEnter(this);
349
349
350 // Apply visitor to graph children: widgets different from graphs are not visited (no
350 // Apply visitor to graph children: widgets different from graphs are not visited (no
351 // action)
351 // action)
352 processGraphs(
352 processGraphs(
353 *ui->dragDropContainer->layout(),
353 *ui->dragDropContainer->layout(),
354 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
354 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
355
355
356 visitor->visitLeave(this);
356 visitor->visitLeave(this);
357 }
357 }
358 else {
358 else {
359 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
359 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
360 }
360 }
361 }
361 }
362
362
363 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
363 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
364 {
364 {
365 // A tab can always accomodate a variable
365 // A tab can always accomodate a variable
366 Q_UNUSED(variable);
366 Q_UNUSED(variable);
367 return true;
367 return true;
368 }
368 }
369
369
370 bool VisualizationZoneWidget::contains(const Variable &variable) const
370 bool VisualizationZoneWidget::contains(const Variable &variable) const
371 {
371 {
372 Q_UNUSED(variable);
372 Q_UNUSED(variable);
373 return false;
373 return false;
374 }
374 }
375
375
376 QString VisualizationZoneWidget::name() const
376 QString VisualizationZoneWidget::name() const
377 {
377 {
378 return ui->zoneNameLabel->text();
378 return ui->zoneNameLabel->text();
379 }
379 }
380
380
381 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
381 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
382 {
382 {
383 Q_UNUSED(position);
383 Q_UNUSED(position);
384
384
385 auto mimeData = new QMimeData;
385 auto mimeData = new QMimeData;
386 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
386 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
387
387
388 if (auto firstGraph = this->firstGraph()) {
388 if (auto firstGraph = this->firstGraph()) {
389 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
389 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
390 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
390 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
391 }
391 }
392
392
393 return mimeData;
393 return mimeData;
394 }
394 }
395
395
396 bool VisualizationZoneWidget::isDragAllowed() const
396 bool VisualizationZoneWidget::isDragAllowed() const
397 {
397 {
398 return true;
398 return true;
399 }
399 }
400
400
401 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
401 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
402 const QPointF &plotPosition,
402 const QPointF &plotPosition,
403 VisualizationGraphWidget *graphWidget)
403 VisualizationGraphWidget *graphWidget)
404 {
404 {
405 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
405 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
406 VisualizationGraphWidget &processedGraph) {
406 VisualizationGraphWidget &processedGraph) {
407
407
408 switch (sqpApp->plotsCursorMode()) {
408 switch (sqpApp->plotsCursorMode()) {
409 case SqpApplication::PlotsCursorMode::Vertical:
409 case SqpApplication::PlotsCursorMode::Vertical:
410 processedGraph.removeHorizontalCursor();
410 processedGraph.removeHorizontalCursor();
411 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
411 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
412 break;
412 break;
413 case SqpApplication::PlotsCursorMode::Temporal:
413 case SqpApplication::PlotsCursorMode::Temporal:
414 processedGraph.addVerticalCursor(plotPosition.x());
414 processedGraph.addVerticalCursor(plotPosition.x());
415 processedGraph.removeHorizontalCursor();
415 processedGraph.removeHorizontalCursor();
416 break;
416 break;
417 case SqpApplication::PlotsCursorMode::Horizontal:
417 case SqpApplication::PlotsCursorMode::Horizontal:
418 processedGraph.removeVerticalCursor();
418 processedGraph.removeVerticalCursor();
419 if (&processedGraph == graphWidget) {
419 if (&processedGraph == graphWidget) {
420 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
420 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
421 }
421 }
422 else {
422 else {
423 processedGraph.removeHorizontalCursor();
423 processedGraph.removeHorizontalCursor();
424 }
424 }
425 break;
425 break;
426 case SqpApplication::PlotsCursorMode::Cross:
426 case SqpApplication::PlotsCursorMode::Cross:
427 if (&processedGraph == graphWidget) {
427 if (&processedGraph == graphWidget) {
428 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
428 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
429 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
429 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
430 }
430 }
431 else {
431 else {
432 processedGraph.removeHorizontalCursor();
432 processedGraph.removeHorizontalCursor();
433 processedGraph.removeVerticalCursor();
433 processedGraph.removeVerticalCursor();
434 }
434 }
435 break;
435 break;
436 case SqpApplication::PlotsCursorMode::NoCursor:
436 case SqpApplication::PlotsCursorMode::NoCursor:
437 processedGraph.removeHorizontalCursor();
437 processedGraph.removeHorizontalCursor();
438 processedGraph.removeVerticalCursor();
438 processedGraph.removeVerticalCursor();
439 break;
439 break;
440 }
440 }
441
441
442
442
443 });
443 });
444 }
444 }
445
445
446 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
446 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
447 {
447 {
448 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
448 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
449 processedGraph.removeHorizontalCursor();
449 processedGraph.removeHorizontalCursor();
450 processedGraph.removeVerticalCursor();
450 processedGraph.removeVerticalCursor();
451 });
451 });
452 }
452 }
453
453
454 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
454 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
455 {
455 {
456 // Closes graphs in the zone
456 // Closes graphs in the zone
457 processGraphs(*ui->dragDropContainer->layout(),
457 processGraphs(*ui->dragDropContainer->layout(),
458 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
458 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
459
459
460 // Delete synchronization group from variable controller
460 // Delete synchronization group from variable controller
461 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
461 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
462 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
462 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
463
463
464 QWidget::closeEvent(event);
464 QWidget::closeEvent(event);
465 }
465 }
466
466
467 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
467 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
468 {
468 {
469 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
469 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
470 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
470 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
471 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
471 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
472 }
472 }
473
473
474 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
474 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
475 {
475 {
476 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
476 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
477 Q_ARG(std::shared_ptr<Variable>, variable),
477 Q_ARG(std::shared_ptr<Variable>, variable),
478 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
478 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
479 }
479 }
480
480
481 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
481 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
482 {
482 {
483 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
483 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
484 impl->dropGraph(index, this);
484 impl->dropGraph(index, this);
485 }
485 }
486 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
486 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
487 auto variables = sqpApp->variableController().variablesForMimeData(
487 auto variables = sqpApp->variableController().variablesForMimeData(
488 mimeData->data(MIME_TYPE_VARIABLE_LIST));
488 mimeData->data(MIME_TYPE_VARIABLE_LIST));
489 impl->dropVariables(variables, index, this);
489 impl->dropVariables(variables, index, this);
490 }
490 }
491 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
491 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
492 auto products = sqpApp->dataSourceController().productsDataForMimeData(
492 auto products = sqpApp->dataSourceController().productsDataForMimeData(
493 mimeData->data(MIME_TYPE_PRODUCT_LIST));
493 mimeData->data(MIME_TYPE_PRODUCT_LIST));
494 impl->dropProducts(products, index, this);
494 impl->dropProducts(products, index, this);
495 }
495 }
496 else {
496 else {
497 qCWarning(LOG_VisualizationZoneWidget())
497 qCWarning(LOG_VisualizationZoneWidget())
498 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
498 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
499 }
499 }
500 }
500 }
501
501
502 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
502 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
503 const QMimeData *mimeData)
503 const QMimeData *mimeData)
504 {
504 {
505 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
505 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
506 if (!graphWidget) {
506 if (!graphWidget) {
507 qCWarning(LOG_VisualizationZoneWidget())
507 qCWarning(LOG_VisualizationZoneWidget())
508 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
508 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
509 "drop aborted");
509 "drop aborted");
510 Q_ASSERT(false);
510 Q_ASSERT(false);
511 return;
511 return;
512 }
512 }
513
513
514 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
514 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
515 auto variables = sqpApp->variableController().variablesForMimeData(
515 auto variables = sqpApp->variableController().variablesForMimeData(
516 mimeData->data(MIME_TYPE_VARIABLE_LIST));
516 mimeData->data(MIME_TYPE_VARIABLE_LIST));
517 for (const auto &var : variables) {
517 for (const auto &var : variables) {
518 graphWidget->addVariable(var, graphWidget->graphRange());
518 graphWidget->addVariable(var, graphWidget->graphRange());
519 }
519 }
520 }
520 }
521 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
521 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
522 auto products = sqpApp->dataSourceController().productsDataForMimeData(
522 auto products = sqpApp->dataSourceController().productsDataForMimeData(
523 mimeData->data(MIME_TYPE_PRODUCT_LIST));
523 mimeData->data(MIME_TYPE_PRODUCT_LIST));
524
524
525 auto context = new QObject{this};
525 auto context = new QObject{this};
526 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
526 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
527 [this, graphWidget, context](auto variable) {
527 [this, graphWidget, context](auto variable) {
528 graphWidget->addVariable(variable, graphWidget->graphRange());
528 graphWidget->addVariable(variable, graphWidget->graphRange());
529 delete context; // removes the connection
529 delete context; // removes the connection
530 },
530 },
531 Qt::QueuedConnection);
531 Qt::QueuedConnection);
532
532
533 auto productData = products.first().toHash();
533 auto productData = products.first().toHash();
534 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
534 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
535 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
535 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
536 }
536 }
537 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
537 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
538 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
538 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
539 graphWidget->setGraphRange(range);
539 graphWidget->setGraphRange(range);
540 }
540 }
541 else {
541 else {
542 qCWarning(LOG_VisualizationZoneWidget())
542 qCWarning(LOG_VisualizationZoneWidget())
543 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
543 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
544 }
544 }
545 }
545 }
546
546
547 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
547 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
548 int index, VisualizationZoneWidget *zoneWidget)
548 int index, VisualizationZoneWidget *zoneWidget)
549 {
549 {
550 auto &helper = sqpApp->dragDropGuiController();
550 auto &helper = sqpApp->dragDropGuiController();
551
551
552 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
552 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
553 if (!graphWidget) {
553 if (!graphWidget) {
554 qCWarning(LOG_VisualizationZoneWidget())
554 qCWarning(LOG_VisualizationZoneWidget())
555 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
555 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
556 "found or invalid.");
556 "found or invalid.");
557 Q_ASSERT(false);
557 Q_ASSERT(false);
558 return;
558 return;
559 }
559 }
560
560
561 auto parentDragDropContainer
561 auto parentDragDropContainer
562 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
562 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
563 if (!parentDragDropContainer) {
563 if (!parentDragDropContainer) {
564 qCWarning(LOG_VisualizationZoneWidget())
564 qCWarning(LOG_VisualizationZoneWidget())
565 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
565 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
566 "the dropped graph is not found.");
566 "the dropped graph is not found.");
567 Q_ASSERT(false);
567 Q_ASSERT(false);
568 return;
568 return;
569 }
569 }
570
570
571 const auto &variables = graphWidget->variables();
571 const auto &variables = graphWidget->variables();
572
572
573 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
573 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
574 // The drop didn't occur in the same zone
574 // The drop didn't occur in the same zone
575
575
576 // Abort the requests for the variables (if any)
576 // Abort the requests for the variables (if any)
577 // Commented, because it's not sure if it's needed or not
577 // Commented, because it's not sure if it's needed or not
578 // for (const auto& var : variables)
578 // for (const auto& var : variables)
579 //{
579 //{
580 // sqpApp->variableController().onAbortProgressRequested(var);
580 // sqpApp->variableController().onAbortProgressRequested(var);
581 //}
581 //}
582
582
583 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
583 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
584 auto nbGraph = parentDragDropContainer->countDragWidget();
584 auto nbGraph = parentDragDropContainer->countDragWidget();
585 if (nbGraph == 1) {
585 if (nbGraph == 1) {
586 // This is the only graph in the previous zone, close the zone
586 // This is the only graph in the previous zone, close the zone
587 helper.delayedCloseWidget(previousParentZoneWidget);
587 helper.delayedCloseWidget(previousParentZoneWidget);
588 }
588 }
589 else {
589 else {
590 // Close the graph
590 // Close the graph
591 helper.delayedCloseWidget(graphWidget);
591 helper.delayedCloseWidget(graphWidget);
592 }
592 }
593
593
594 // Creates the new graph in the zone
594 // Creates the new graph in the zone
595 auto newGraphWidget = zoneWidget->createGraph(variables, index);
595 auto newGraphWidget = zoneWidget->createGraph(variables, index);
596 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
596 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
597 }
597 }
598 else {
598 else {
599 // The drop occurred in the same zone or the graph is empty
599 // The drop occurred in the same zone or the graph is empty
600 // Simple move of the graph, no variable operation associated
600 // Simple move of the graph, no variable operation associated
601 parentDragDropContainer->layout()->removeWidget(graphWidget);
601 parentDragDropContainer->layout()->removeWidget(graphWidget);
602
602
603 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
603 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
604 // The graph is empty and dropped in a different zone.
604 // The graph is empty and dropped in a different zone.
605 // Take the range of the first graph in the zone (if existing).
605 // Take the range of the first graph in the zone (if existing).
606 auto layout = zoneWidget->ui->dragDropContainer->layout();
606 auto layout = zoneWidget->ui->dragDropContainer->layout();
607 if (layout->count() > 0) {
607 if (layout->count() > 0) {
608 if (auto visualizationGraphWidget
608 if (auto visualizationGraphWidget
609 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
609 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
610 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
610 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
611 }
611 }
612 }
612 }
613 }
613 }
614
614
615 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
615 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
616 }
616 }
617 }
617 }
618
618
619 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
619 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
620 const QList<std::shared_ptr<Variable> > &variables, int index,
620 const QList<std::shared_ptr<Variable> > &variables, int index,
621 VisualizationZoneWidget *zoneWidget)
621 VisualizationZoneWidget *zoneWidget)
622 {
622 {
623 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
623 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
624 // compatible variable here
624 // compatible variable here
625 if (variables.count() > 1) {
625 if (variables.count() > 1) {
626 qCWarning(LOG_VisualizationZoneWidget())
626 qCWarning(LOG_VisualizationZoneWidget())
627 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
627 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
628 "aborted.");
628 "aborted.");
629 return;
629 return;
630 }
630 }
631
631
632 zoneWidget->createGraph(variables, index);
632 zoneWidget->createGraph(variables, index);
633 }
633 }
634
634
635 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProducts(
635 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProducts(
636 const QVariantList &productsData, int index, VisualizationZoneWidget *zoneWidget)
636 const QVariantList &productsData, int index, VisualizationZoneWidget *zoneWidget)
637 {
637 {
638 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
638 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
639 // compatible variable here
639 // compatible variable here
640 if (productsData.count() != 1) {
640 if (productsData.count() != 1) {
641 qCWarning(LOG_VisualizationZoneWidget())
641 qCWarning(LOG_VisualizationZoneWidget())
642 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
642 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
643 "aborted.");
643 "aborted.");
644 return;
644 return;
645 }
645 }
646
646
647 auto context = new QObject{zoneWidget};
647 auto context = new QObject{zoneWidget};
648 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
648 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
649 [this, index, zoneWidget, context](auto variable) {
649 [this, index, zoneWidget, context](auto variable) {
650 zoneWidget->createGraph(variable, index);
650 zoneWidget->createGraph(variable, index);
651 delete context; // removes the connection
651 delete context; // removes the connection
652 },
652 },
653 Qt::QueuedConnection);
653 Qt::QueuedConnection);
654
654
655 auto productData = productsData.first().toHash();
655 auto productData = productsData.first().toHash();
656 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
656 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
657 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
657 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
658 }
658 }
@@ -1,145 +1,144
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>CatalogueEventsWidget</class>
3 <class>CatalogueEventsWidget</class>
4 <widget class="QWidget" name="CatalogueEventsWidget">
4 <widget class="QWidget" name="CatalogueEventsWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>566</width>
9 <width>566</width>
10 <height>258</height>
10 <height>258</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="windowTitle">
13 <property name="windowTitle">
14 <string>Form</string>
14 <string>Form</string>
15 </property>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout">
16 <layout class="QVBoxLayout" name="verticalLayout">
17 <property name="leftMargin">
17 <property name="leftMargin">
18 <number>0</number>
18 <number>0</number>
19 </property>
19 </property>
20 <property name="topMargin">
20 <property name="topMargin">
21 <number>0</number>
21 <number>0</number>
22 </property>
22 </property>
23 <property name="rightMargin">
23 <property name="rightMargin">
24 <number>0</number>
24 <number>0</number>
25 </property>
25 </property>
26 <property name="bottomMargin">
26 <property name="bottomMargin">
27 <number>0</number>
27 <number>0</number>
28 </property>
28 </property>
29 <item>
29 <item>
30 <layout class="QHBoxLayout" name="horizontalLayout">
30 <layout class="QHBoxLayout" name="horizontalLayout">
31 <item>
31 <item>
32 <widget class="QToolButton" name="btnAdd">
32 <widget class="QToolButton" name="btnAdd">
33 <property name="enabled">
33 <property name="enabled">
34 <bool>false</bool>
34 <bool>false</bool>
35 </property>
35 </property>
36 <property name="text">
36 <property name="text">
37 <string>+</string>
37 <string>+</string>
38 </property>
38 </property>
39 <property name="icon">
39 <property name="icon">
40 <iconset resource="../../resources/sqpguiresources.qrc">
40 <iconset resource="../../resources/sqpguiresources.qrc">
41 <normaloff>:/icones/add.png</normaloff>:/icones/add.png</iconset>
41 <normaloff>:/icones/add.png</normaloff>:/icones/add.png</iconset>
42 </property>
42 </property>
43 <property name="autoRaise">
43 <property name="autoRaise">
44 <bool>true</bool>
44 <bool>true</bool>
45 </property>
45 </property>
46 </widget>
46 </widget>
47 </item>
47 </item>
48 <item>
48 <item>
49 <widget class="QToolButton" name="btnRemove">
49 <widget class="QToolButton" name="btnRemove">
50 <property name="text">
50 <property name="text">
51 <string> - </string>
51 <string> - </string>
52 </property>
52 </property>
53 <property name="icon">
53 <property name="icon">
54 <iconset resource="../../resources/sqpguiresources.qrc">
54 <iconset resource="../../resources/sqpguiresources.qrc">
55 <normaloff>:/icones/remove.png</normaloff>:/icones/remove.png</iconset>
55 <normaloff>:/icones/remove.png</normaloff>:/icones/remove.png</iconset>
56 </property>
56 </property>
57 <property name="autoRaise">
57 <property name="autoRaise">
58 <bool>true</bool>
58 <bool>true</bool>
59 </property>
59 </property>
60 </widget>
60 </widget>
61 </item>
61 </item>
62 <item>
62 <item>
63 <widget class="Line" name="line">
63 <widget class="Line" name="line">
64 <property name="orientation">
64 <property name="orientation">
65 <enum>Qt::Vertical</enum>
65 <enum>Qt::Vertical</enum>
66 </property>
66 </property>
67 </widget>
67 </widget>
68 </item>
68 </item>
69 <item>
69 <item>
70 <widget class="QToolButton" name="btnTime">
70 <widget class="QToolButton" name="btnTime">
71 <property name="text">
71 <property name="text">
72 <string>T</string>
72 <string>T</string>
73 </property>
73 </property>
74 <property name="icon">
74 <property name="icon">
75 <iconset resource="../../resources/sqpguiresources.qrc">
75 <iconset resource="../../resources/sqpguiresources.qrc">
76 <normaloff>:/icones/time.png</normaloff>:/icones/time.png</iconset>
76 <normaloff>:/icones/time.png</normaloff>:/icones/time.png</iconset>
77 </property>
77 </property>
78 <property name="checkable">
78 <property name="checkable">
79 <bool>true</bool>
79 <bool>true</bool>
80 </property>
80 </property>
81 <property name="autoRaise">
81 <property name="autoRaise">
82 <bool>true</bool>
82 <bool>true</bool>
83 </property>
83 </property>
84 </widget>
84 </widget>
85 </item>
85 </item>
86 <item>
86 <item>
87 <widget class="QToolButton" name="btnChart">
87 <widget class="QToolButton" name="btnChart">
88 <property name="text">
88 <property name="text">
89 <string>G</string>
89 <string>G</string>
90 </property>
90 </property>
91 <property name="icon">
91 <property name="icon">
92 <iconset resource="../../resources/sqpguiresources.qrc">
92 <iconset resource="../../resources/sqpguiresources.qrc">
93 <normaloff>:/icones/chart.png</normaloff>:/icones/chart.png</iconset>
93 <normaloff>:/icones/chart.png</normaloff>:/icones/chart.png</iconset>
94 </property>
94 </property>
95 <property name="checkable">
95 <property name="checkable">
96 <bool>true</bool>
96 <bool>true</bool>
97 </property>
97 </property>
98 <property name="autoRaise">
98 <property name="autoRaise">
99 <bool>true</bool>
99 <bool>true</bool>
100 </property>
100 </property>
101 </widget>
101 </widget>
102 </item>
102 </item>
103 <item>
103 <item>
104 <widget class="Line" name="line_2">
104 <widget class="Line" name="line_2">
105 <property name="orientation">
105 <property name="orientation">
106 <enum>Qt::Vertical</enum>
106 <enum>Qt::Vertical</enum>
107 </property>
107 </property>
108 </widget>
108 </widget>
109 </item>
109 </item>
110 <item>
110 <item>
111 <widget class="QLineEdit" name="lineEdit">
111 <widget class="QLineEdit" name="lineEdit">
112 <property name="enabled">
112 <property name="enabled">
113 <bool>false</bool>
113 <bool>false</bool>
114 </property>
114 </property>
115 </widget>
115 </widget>
116 </item>
116 </item>
117 </layout>
117 </layout>
118 </item>
118 </item>
119 <item>
119 <item>
120 <widget class="QTreeView" name="treeView">
120 <widget class="QTreeView" name="treeView">
121 <property name="dragEnabled">
121 <property name="dragEnabled">
122 <bool>true</bool>
122 <bool>true</bool>
123 </property>
123 </property>
124 <property name="dragDropMode">
124 <property name="dragDropMode">
125 <enum>QAbstractItemView::DragDrop</enum>
125 <enum>QAbstractItemView::DragDrop</enum>
126 </property>
126 </property>
127 <property name="selectionMode">
127 <property name="selectionMode">
128 <enum>QAbstractItemView::ExtendedSelection</enum>
128 <enum>QAbstractItemView::ExtendedSelection</enum>
129 </property>
129 </property>
130 <property name="selectionBehavior">
130 <property name="selectionBehavior">
131 <enum>QAbstractItemView::SelectRows</enum>
131 <enum>QAbstractItemView::SelectRows</enum>
132 </property>
132 </property>
133 <attribute name="headerStretchLastSection">
133 <attribute name="headerStretchLastSection">
134 <bool>false</bool>
134 <bool>false</bool>
135 </attribute>
135 </attribute>
136 </widget>
136 </widget>
137 </item>
137 </item>
138 </layout>
138 </layout>
139 </widget>
139 </widget>
140 <resources>
140 <resources>
141 <include location="../../resources/sqpguiresources.qrc"/>
141 <include location="../../resources/sqpguiresources.qrc"/>
142 <include location="../../resources/sqpguiresources.qrc"/>
143 </resources>
142 </resources>
144 <connections/>
143 <connections/>
145 </ui>
144 </ui>
General Comments 0
You need to be logged in to leave comments. Login now