##// END OF EJS Templates
Merge branch 'feature/CataloguePart6' into develop
trabillard -
r1363:faf6baef791f merge
parent child
Show More
@@ -1,86 +1,93
1 #ifndef SCIQLOP_CATALOGUECONTROLLER_H
1 #ifndef SCIQLOP_CATALOGUECONTROLLER_H
2 #define SCIQLOP_CATALOGUECONTROLLER_H
2 #define SCIQLOP_CATALOGUECONTROLLER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QObject>
9 #include <QObject>
10 #include <QUuid>
10 #include <QUuid>
11
11
12 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
13
13
14 #include <memory>
14 #include <memory>
15
15
16 class DBCatalogue;
16 class DBCatalogue;
17 class DBEvent;
17 class DBEvent;
18 class DBEventProduct;
18 class DBEventProduct;
19
19
20 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueController)
20 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueController)
21
21
22 class DataSourceItem;
22 class DataSourceItem;
23 class Variable;
23 class Variable;
24
24
25 /**
25 /**
26 * @brief The CatalogueController class aims to handle catalogues and event using the CatalogueAPI
26 * @brief The CatalogueController class aims to handle catalogues and event using the CatalogueAPI
27 * library.
27 * library.
28 */
28 */
29 class SCIQLOP_CORE_EXPORT CatalogueController : public QObject {
29 class SCIQLOP_CORE_EXPORT CatalogueController : public QObject {
30 Q_OBJECT
30 Q_OBJECT
31 public:
31 public:
32 explicit CatalogueController(QObject *parent = 0);
32 explicit CatalogueController(QObject *parent = 0);
33 virtual ~CatalogueController();
33 virtual ~CatalogueController();
34
34
35 // DB
35 // DB
36 QStringList getRepositories() const;
36 QStringList getRepositories() const;
37 void addDB(const QString &dbPath);
37 void addDB(const QString &dbPath);
38 void saveDB(const QString &destinationPath, const QString &repository);
38 void saveDB(const QString &destinationPath, const QString &repository);
39
39
40 // Event
40 // Event
41 /// retrieveEvents with empty repository retrieve them from the default repository
41 /// retrieveEvents with empty repository retrieve them from the default repository
42 std::list<std::shared_ptr<DBEvent> > retrieveEvents(const QString &repository) const;
42 std::list<std::shared_ptr<DBEvent> > retrieveEvents(const QString &repository) const;
43 std::list<std::shared_ptr<DBEvent> > retrieveAllEvents() const;
43 std::list<std::shared_ptr<DBEvent> > retrieveAllEvents() const;
44
44
45 void addEvent(std::shared_ptr<DBEvent> event);
45 void addEvent(std::shared_ptr<DBEvent> event);
46 void updateEvent(std::shared_ptr<DBEvent> event);
46 void updateEvent(std::shared_ptr<DBEvent> event);
47 void updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct);
47 void updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct);
48 void removeEvent(std::shared_ptr<DBEvent> event);
48 void removeEvent(std::shared_ptr<DBEvent> event);
49 // void trashEvent(std::shared_ptr<DBEvent> event);
49 // void trashEvent(std::shared_ptr<DBEvent> event);
50 // void restore(std::shared_ptr<DBEvent> event);
50 // void restore(std::shared_ptr<DBEvent> event);
51 void saveEvent(std::shared_ptr<DBEvent> event);
51 void saveEvent(std::shared_ptr<DBEvent> event);
52 void discardEvent(std::shared_ptr<DBEvent> event, bool &removed);
52 void discardEvent(std::shared_ptr<DBEvent> event, bool &removed);
53 bool eventHasChanges(std::shared_ptr<DBEvent> event) const;
53 bool eventHasChanges(std::shared_ptr<DBEvent> event) const;
54
54
55 // Catalogue
55 // Catalogue
56 std::list<std::shared_ptr<DBEvent> >
56 std::list<std::shared_ptr<DBEvent> >
57 retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const;
57 retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const;
58
58
59 /// retrieveEvents with empty repository retrieve them from the default repository
59 /// retrieveEvents with empty repository retrieve them from the default repository
60 std::list<std::shared_ptr<DBCatalogue> > retrieveCatalogues(const QString &repository
60 std::list<std::shared_ptr<DBCatalogue> > retrieveCatalogues(const QString &repository
61 = QString()) const;
61 = QString()) const;
62 void addCatalogue(std::shared_ptr<DBCatalogue> catalogue);
62 void addCatalogue(std::shared_ptr<DBCatalogue> catalogue);
63 void updateCatalogue(std::shared_ptr<DBCatalogue> catalogue);
63 void updateCatalogue(std::shared_ptr<DBCatalogue> catalogue);
64 void removeCatalogue(std::shared_ptr<DBCatalogue> catalogue);
64 void removeCatalogue(std::shared_ptr<DBCatalogue> catalogue);
65 void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue);
65 void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue);
66 void discardCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool &removed);
66 void discardCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool &removed);
67
67
68 void saveAll();
68 void saveAll();
69 bool hasChanges() const;
69 bool hasChanges() const;
70
70
71 /// Returns the MIME data associated to a list of variables
71 /// Returns the MIME data associated to a list of variables
72 QByteArray mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const;
72 QByteArray mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const;
73
73
74 /// Returns the list of variables contained in a MIME data
74 /// Returns the list of variables contained in a MIME data
75 QVector<std::shared_ptr<DBEvent> > eventsForMimeData(const QByteArray &mimeData) const;
75 QVector<std::shared_ptr<DBEvent> > eventsForMimeData(const QByteArray &mimeData) const;
76
76
77 /// Returns the MIME data associated to a list of variables
78 QByteArray
79 mimeDataForCatalogues(const QVector<std::shared_ptr<DBCatalogue> > &catalogues) const;
80
81 /// Returns the list of variables contained in a MIME data
82 QVector<std::shared_ptr<DBCatalogue> > cataloguesForMimeData(const QByteArray &mimeData) const;
83
77 public slots:
84 public slots:
78 /// Manage init/end of the controller
85 /// Manage init/end of the controller
79 void initialize();
86 void initialize();
80
87
81 private:
88 private:
82 class CatalogueControllerPrivate;
89 class CatalogueControllerPrivate;
83 spimpl::unique_impl_ptr<CatalogueControllerPrivate> impl;
90 spimpl::unique_impl_ptr<CatalogueControllerPrivate> impl;
84 };
91 };
85
92
86 #endif // SCIQLOP_CATALOGUECONTROLLER_H
93 #endif // SCIQLOP_CATALOGUECONTROLLER_H
@@ -1,21 +1,22
1 #ifndef SCIQLOP_MIMETYPESDEF_H
1 #ifndef SCIQLOP_MIMETYPESDEF_H
2 #define SCIQLOP_MIMETYPESDEF_H
2 #define SCIQLOP_MIMETYPESDEF_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <QString>
6 #include <QString>
7
7
8 // ////////////////// //
8 // ////////////////// //
9 // SciQlop Mime Types //
9 // SciQlop Mime Types //
10 // ////////////////// //
10 // ////////////////// //
11
11
12 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_GRAPH;
12 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_GRAPH;
13 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_ZONE;
13 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_ZONE;
14 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_VARIABLE_LIST;
14 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_VARIABLE_LIST;
15 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_PRODUCT_LIST;
15 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_PRODUCT_LIST;
16 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_TIME_RANGE;
16 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_TIME_RANGE;
17 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_SELECTION_ZONE;
17 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_SELECTION_ZONE;
18 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_EVENT_LIST;
18 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_EVENT_LIST;
19 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_SOURCE_CATALOGUE_LIST;
19
20
20
21
21 #endif // SCIQLOP_MIMETYPESDEF_H
22 #endif // SCIQLOP_MIMETYPESDEF_H
@@ -1,526 +1,566
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 }
293 }
294
294
295 void CatalogueController::discardCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool &removed)
295 void CatalogueController::discardCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool &removed)
296 {
296 {
297 auto syncPred
297 auto syncPred
298 = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::SYNC);
298 = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::SYNC);
299 auto workPred
299 auto workPred
300 = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::WORK);
300 = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::WORK);
301
301
302 auto syncCatalogue = impl->m_CatalogueDao.getCatalogue(syncPred);
302 auto syncCatalogue = impl->m_CatalogueDao.getCatalogue(syncPred);
303 if (!syncCatalogue.getUniqId().isNull()) {
303 if (!syncCatalogue.getUniqId().isNull()) {
304 removed = false;
304 removed = false;
305 impl->m_CatalogueDao.copyCatalogue(
305 impl->m_CatalogueDao.copyCatalogue(
306 syncCatalogue, impl->toWorkRepository(catalogue->getRepository()), true);
306 syncCatalogue, impl->toWorkRepository(catalogue->getRepository()), true);
307
307
308 auto workCatalogue = impl->m_CatalogueDao.getCatalogue(workPred);
308 auto workCatalogue = impl->m_CatalogueDao.getCatalogue(workPred);
309 *catalogue = workCatalogue;
309 *catalogue = workCatalogue;
310 impl->m_KeysWithChanges.remove(impl->catalogueUniqueKey(catalogue));
310 impl->m_KeysWithChanges.remove(impl->catalogueUniqueKey(catalogue));
311 }
311 }
312 else {
312 else {
313 removed = true;
313 removed = true;
314 // Since the element wasn't in sync repository. Discard it means remove it
314 // Since the element wasn't in sync repository. Discard it means remove it
315 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
315 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
316 impl->m_CatalogueDao.removeCatalogue(*catalogue);
316 impl->m_CatalogueDao.removeCatalogue(*catalogue);
317 }
317 }
318 }
318 }
319
319
320 void CatalogueController::saveAll()
320 void CatalogueController::saveAll()
321 {
321 {
322 for (auto repository : impl->m_RepositoryList) {
322 for (auto repository : impl->m_RepositoryList) {
323 // Save Event
323 // Save Event
324 auto events = this->retrieveEvents(repository);
324 auto events = this->retrieveEvents(repository);
325 for (auto event : events) {
325 for (auto event : events) {
326 impl->saveEvent(event, false);
326 impl->saveEvent(event, false);
327 }
327 }
328
328
329 // Save Catalogue
329 // Save Catalogue
330 auto catalogues = this->retrieveCatalogues(repository);
330 auto catalogues = this->retrieveCatalogues(repository);
331 for (auto catalogue : catalogues) {
331 for (auto catalogue : catalogues) {
332 impl->saveCatalogue(catalogue, false);
332 impl->saveCatalogue(catalogue, false);
333 }
333 }
334 }
334 }
335
335
336 impl->savAllDB();
336 impl->savAllDB();
337 impl->m_KeysWithChanges.clear();
337 impl->m_KeysWithChanges.clear();
338 }
338 }
339
339
340 bool CatalogueController::hasChanges() const
340 bool CatalogueController::hasChanges() const
341 {
341 {
342 return !impl->m_KeysWithChanges.isEmpty();
342 return !impl->m_KeysWithChanges.isEmpty();
343 }
343 }
344
344
345 QByteArray
345 QByteArray
346 CatalogueController::mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const
346 CatalogueController::mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const
347 {
347 {
348 auto encodedData = QByteArray{};
348 auto encodedData = QByteArray{};
349
349
350 QMap<QString, QVariantList> idsPerRepository;
350 QMap<QString, QVariantList> idsPerRepository;
351 for (auto event : events) {
351 for (auto event : events) {
352 idsPerRepository[event->getRepository()] << event->getUniqId();
352 idsPerRepository[event->getRepository()] << event->getUniqId();
353 }
353 }
354
354
355 QDataStream stream{&encodedData, QIODevice::WriteOnly};
355 QDataStream stream{&encodedData, QIODevice::WriteOnly};
356 stream << idsPerRepository;
356 stream << idsPerRepository;
357
357
358 return encodedData;
358 return encodedData;
359 }
359 }
360
360
361 QVector<std::shared_ptr<DBEvent> >
361 QVector<std::shared_ptr<DBEvent> >
362 CatalogueController::eventsForMimeData(const QByteArray &mimeData) const
362 CatalogueController::eventsForMimeData(const QByteArray &mimeData) const
363 {
363 {
364 auto events = QVector<std::shared_ptr<DBEvent> >{};
364 auto events = QVector<std::shared_ptr<DBEvent> >{};
365 QDataStream stream{mimeData};
365 QDataStream stream{mimeData};
366
366
367 QMap<QString, QVariantList> idsPerRepository;
367 QMap<QString, QVariantList> idsPerRepository;
368 stream >> idsPerRepository;
368 stream >> idsPerRepository;
369
369
370 for (auto it = idsPerRepository.cbegin(); it != idsPerRepository.cend(); ++it) {
370 for (auto it = idsPerRepository.cbegin(); it != idsPerRepository.cend(); ++it) {
371 auto repository = it.key();
371 auto repository = it.key();
372 auto allRepositoryEvent = retrieveEvents(repository);
372 auto allRepositoryEvent = retrieveEvents(repository);
373 for (auto uuid : it.value()) {
373 for (auto uuid : it.value()) {
374 for (auto repositoryEvent : allRepositoryEvent) {
374 for (auto repositoryEvent : allRepositoryEvent) {
375 if (uuid.toUuid() == repositoryEvent->getUniqId()) {
375 if (uuid.toUuid() == repositoryEvent->getUniqId()) {
376 events << repositoryEvent;
376 events << repositoryEvent;
377 }
377 }
378 }
378 }
379 }
379 }
380 }
380 }
381
381
382 return events;
382 return events;
383 }
383 }
384
384
385 QByteArray CatalogueController::mimeDataForCatalogues(
386 const QVector<std::shared_ptr<DBCatalogue> > &catalogues) const
387 {
388 auto encodedData = QByteArray{};
389
390 QMap<QString, QVariantList> idsPerRepository;
391 for (auto catalogue : catalogues) {
392 idsPerRepository[catalogue->getRepository()] << catalogue->getUniqId();
393 }
394
395 QDataStream stream{&encodedData, QIODevice::WriteOnly};
396 stream << idsPerRepository;
397
398 return encodedData;
399 }
400
401 QVector<std::shared_ptr<DBCatalogue> >
402 CatalogueController::cataloguesForMimeData(const QByteArray &mimeData) const
403 {
404 auto catalogues = QVector<std::shared_ptr<DBCatalogue> >{};
405 QDataStream stream{mimeData};
406
407 QMap<QString, QVariantList> idsPerRepository;
408 stream >> idsPerRepository;
409
410 for (auto it = idsPerRepository.cbegin(); it != idsPerRepository.cend(); ++it) {
411 auto repository = it.key();
412 auto allRepositoryCatalogues = retrieveCatalogues(repository);
413 for (auto uuid : it.value()) {
414 for (auto repositoryCatalogues : allRepositoryCatalogues) {
415 if (uuid.toUuid() == repositoryCatalogues->getUniqId()) {
416 catalogues << repositoryCatalogues;
417 }
418 }
419 }
420 }
421
422 return catalogues;
423 }
424
385 void CatalogueController::initialize()
425 void CatalogueController::initialize()
386 {
426 {
387 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init")
427 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init")
388 << QThread::currentThread();
428 << QThread::currentThread();
389
429
390 impl->m_CatalogueDao.initialize();
430 impl->m_CatalogueDao.initialize();
391 auto defaultRepositoryLocation
431 auto defaultRepositoryLocation
392 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
432 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
393
433
394 QDir defaultRepositoryLocationDir;
434 QDir defaultRepositoryLocationDir;
395 if (defaultRepositoryLocationDir.mkpath(defaultRepositoryLocation)) {
435 if (defaultRepositoryLocationDir.mkpath(defaultRepositoryLocation)) {
396 defaultRepositoryLocationDir.cd(defaultRepositoryLocation);
436 defaultRepositoryLocationDir.cd(defaultRepositoryLocation);
397 auto defaultRepository = defaultRepositoryLocationDir.absoluteFilePath(REPOSITORY_DEFAULT);
437 auto defaultRepository = defaultRepositoryLocationDir.absoluteFilePath(REPOSITORY_DEFAULT);
398
438
399 qCInfo(LOG_CatalogueController()) << tr("Persistant data loading from: ")
439 qCInfo(LOG_CatalogueController()) << tr("Persistant data loading from: ")
400 << defaultRepository;
440 << defaultRepository;
401
441
402 QDir dbDir(defaultRepository);
442 QDir dbDir(defaultRepository);
403 impl->m_RepositoryList << REPOSITORY_DEFAULT;
443 impl->m_RepositoryList << REPOSITORY_DEFAULT;
404 if (dbDir.exists()) {
444 if (dbDir.exists()) {
405 auto dirName = dbDir.dirName();
445 auto dirName = dbDir.dirName();
406
446
407 if (impl->m_CatalogueDao.addDB(defaultRepository, dirName)) {
447 if (impl->m_CatalogueDao.addDB(defaultRepository, dirName)) {
408 impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName));
448 impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName));
409 }
449 }
410 }
450 }
411 else {
451 else {
412 qCInfo(LOG_CatalogueController()) << tr("Initialisation of Default repository detected")
452 qCInfo(LOG_CatalogueController()) << tr("Initialisation of Default repository detected")
413 << defaultRepository;
453 << defaultRepository;
414 }
454 }
415 }
455 }
416 else {
456 else {
417 qCWarning(LOG_CatalogueController())
457 qCWarning(LOG_CatalogueController())
418 << tr("Cannot load the persistent default repository from ")
458 << tr("Cannot load the persistent default repository from ")
419 << defaultRepositoryLocation;
459 << defaultRepositoryLocation;
420 }
460 }
421
461
422 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init END");
462 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init END");
423 }
463 }
424
464
425 QString CatalogueController::CatalogueControllerPrivate::eventUniqueKey(
465 QString CatalogueController::CatalogueControllerPrivate::eventUniqueKey(
426 const std::shared_ptr<DBEvent> &event) const
466 const std::shared_ptr<DBEvent> &event) const
427 {
467 {
428 return event->getUniqId().toString().append(event->getRepository());
468 return event->getUniqId().toString().append(event->getRepository());
429 }
469 }
430
470
431 QString CatalogueController::CatalogueControllerPrivate::catalogueUniqueKey(
471 QString CatalogueController::CatalogueControllerPrivate::catalogueUniqueKey(
432 const std::shared_ptr<DBCatalogue> &catalogue) const
472 const std::shared_ptr<DBCatalogue> &catalogue) const
433 {
473 {
434 return catalogue->getUniqId().toString().append(catalogue->getRepository());
474 return catalogue->getUniqId().toString().append(catalogue->getRepository());
435 }
475 }
436
476
437 void CatalogueController::CatalogueControllerPrivate::copyDBtoDB(const QString &dbFrom,
477 void CatalogueController::CatalogueControllerPrivate::copyDBtoDB(const QString &dbFrom,
438 const QString &dbTo)
478 const QString &dbTo)
439 {
479 {
440 // auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
480 // auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
441 auto catalogues = m_CatalogueDao.getCatalogues(dbFrom);
481 auto catalogues = m_CatalogueDao.getCatalogues(dbFrom);
442 auto events = m_CatalogueDao.getEvents(dbFrom);
482 auto events = m_CatalogueDao.getEvents(dbFrom);
443 for (auto catalogue : catalogues) {
483 for (auto catalogue : catalogues) {
444 m_CatalogueDao.copyCatalogue(catalogue, dbTo, true);
484 m_CatalogueDao.copyCatalogue(catalogue, dbTo, true);
445 }
485 }
446
486
447 for (auto event : events) {
487 for (auto event : events) {
448 m_CatalogueDao.copyEvent(event, dbTo, true);
488 m_CatalogueDao.copyEvent(event, dbTo, true);
449 }
489 }
450 }
490 }
451
491
452 QString CatalogueController::CatalogueControllerPrivate::toWorkRepository(QString repository)
492 QString CatalogueController::CatalogueControllerPrivate::toWorkRepository(QString repository)
453 {
493 {
454 auto syncRepository = toSyncRepository(repository);
494 auto syncRepository = toSyncRepository(repository);
455
495
456 return QString("%1%2").arg(syncRepository, REPOSITORY_WORK_SUFFIX);
496 return QString("%1%2").arg(syncRepository, REPOSITORY_WORK_SUFFIX);
457 }
497 }
458
498
459 QString CatalogueController::CatalogueControllerPrivate::toSyncRepository(QString repository)
499 QString CatalogueController::CatalogueControllerPrivate::toSyncRepository(QString repository)
460 {
500 {
461 auto syncRepository = repository;
501 auto syncRepository = repository;
462 if (repository.endsWith(REPOSITORY_WORK_SUFFIX)) {
502 if (repository.endsWith(REPOSITORY_WORK_SUFFIX)) {
463 syncRepository.remove(REPOSITORY_WORK_SUFFIX);
503 syncRepository.remove(REPOSITORY_WORK_SUFFIX);
464 }
504 }
465 else if (repository.endsWith(REPOSITORY_TRASH_SUFFIX)) {
505 else if (repository.endsWith(REPOSITORY_TRASH_SUFFIX)) {
466 syncRepository.remove(REPOSITORY_TRASH_SUFFIX);
506 syncRepository.remove(REPOSITORY_TRASH_SUFFIX);
467 }
507 }
468 return syncRepository;
508 return syncRepository;
469 }
509 }
470
510
471 void CatalogueController::CatalogueControllerPrivate::savAllDB()
511 void CatalogueController::CatalogueControllerPrivate::savAllDB()
472 {
512 {
473 for (auto repository : m_RepositoryList) {
513 for (auto repository : m_RepositoryList) {
474 auto defaultRepositoryLocation
514 auto defaultRepositoryLocation
475 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
515 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
476 m_CatalogueDao.saveDB(defaultRepositoryLocation, repository);
516 m_CatalogueDao.saveDB(defaultRepositoryLocation, repository);
477 }
517 }
478 }
518 }
479
519
480 void CatalogueController::CatalogueControllerPrivate::saveEvent(std::shared_ptr<DBEvent> event,
520 void CatalogueController::CatalogueControllerPrivate::saveEvent(std::shared_ptr<DBEvent> event,
481 bool persist)
521 bool persist)
482 {
522 {
483 m_CatalogueDao.copyEvent(*event, toSyncRepository(event->getRepository()), true);
523 m_CatalogueDao.copyEvent(*event, toSyncRepository(event->getRepository()), true);
484 if (persist) {
524 if (persist) {
485 savAllDB();
525 savAllDB();
486 }
526 }
487 }
527 }
488
528
489 void CatalogueController::CatalogueControllerPrivate::saveCatalogue(
529 void CatalogueController::CatalogueControllerPrivate::saveCatalogue(
490 std::shared_ptr<DBCatalogue> catalogue, bool persist)
530 std::shared_ptr<DBCatalogue> catalogue, bool persist)
491 {
531 {
492 m_CatalogueDao.copyCatalogue(*catalogue, toSyncRepository(catalogue->getRepository()), true);
532 m_CatalogueDao.copyCatalogue(*catalogue, toSyncRepository(catalogue->getRepository()), true);
493 if (persist) {
533 if (persist) {
494 savAllDB();
534 savAllDB();
495 }
535 }
496 }
536 }
497
537
498 std::shared_ptr<IRequestPredicate> CatalogueController::CatalogueControllerPrivate::createFinder(
538 std::shared_ptr<IRequestPredicate> CatalogueController::CatalogueControllerPrivate::createFinder(
499 const QUuid &uniqId, const QString &repository, DBType type)
539 const QUuid &uniqId, const QString &repository, DBType type)
500 {
540 {
501 // update catalogue parameter
541 // update catalogue parameter
502 auto uniqIdPredicate = std::make_shared<ComparaisonPredicate>(QString{"uniqId"}, uniqId,
542 auto uniqIdPredicate = std::make_shared<ComparaisonPredicate>(QString{"uniqId"}, uniqId,
503 ComparaisonOperation::EQUALEQUAL);
543 ComparaisonOperation::EQUALEQUAL);
504
544
505 auto repositoryType = repository;
545 auto repositoryType = repository;
506 switch (type) {
546 switch (type) {
507 case DBType::SYNC:
547 case DBType::SYNC:
508 repositoryType = toSyncRepository(repositoryType);
548 repositoryType = toSyncRepository(repositoryType);
509 break;
549 break;
510 case DBType::WORK:
550 case DBType::WORK:
511 repositoryType = toWorkRepository(repositoryType);
551 repositoryType = toWorkRepository(repositoryType);
512 break;
552 break;
513 case DBType::TRASH:
553 case DBType::TRASH:
514 default:
554 default:
515 break;
555 break;
516 }
556 }
517
557
518 auto repositoryPredicate = std::make_shared<ComparaisonPredicate>(
558 auto repositoryPredicate = std::make_shared<ComparaisonPredicate>(
519 QString{"repository"}, repositoryType, ComparaisonOperation::EQUALEQUAL);
559 QString{"repository"}, repositoryType, ComparaisonOperation::EQUALEQUAL);
520
560
521 auto finderPred = std::make_shared<CompoundPredicate>(CompoundOperation::AND);
561 auto finderPred = std::make_shared<CompoundPredicate>(CompoundOperation::AND);
522 finderPred->AddRequestPredicate(uniqIdPredicate);
562 finderPred->AddRequestPredicate(uniqIdPredicate);
523 finderPred->AddRequestPredicate(repositoryPredicate);
563 finderPred->AddRequestPredicate(repositoryPredicate);
524
564
525 return finderPred;
565 return finderPred;
526 }
566 }
@@ -1,9 +1,10
1 #include "Common/MimeTypesDef.h"
1 #include "Common/MimeTypesDef.h"
2
2
3 const QString MIME_TYPE_GRAPH = QStringLiteral("sciqlop/graph");
3 const QString MIME_TYPE_GRAPH = QStringLiteral("sciqlop/graph");
4 const QString MIME_TYPE_ZONE = QStringLiteral("sciqlop/zone");
4 const QString MIME_TYPE_ZONE = QStringLiteral("sciqlop/zone");
5 const QString MIME_TYPE_VARIABLE_LIST = QStringLiteral("sciqlop/var-list");
5 const QString MIME_TYPE_VARIABLE_LIST = QStringLiteral("sciqlop/var-list");
6 const QString MIME_TYPE_PRODUCT_LIST = QStringLiteral("sciqlop/product-list");
6 const QString MIME_TYPE_PRODUCT_LIST = QStringLiteral("sciqlop/product-list");
7 const QString MIME_TYPE_TIME_RANGE = QStringLiteral("sciqlop/time-range");
7 const QString MIME_TYPE_TIME_RANGE = QStringLiteral("sciqlop/time-range");
8 const QString MIME_TYPE_SELECTION_ZONE = QStringLiteral("sciqlop/selection-zone");
8 const QString MIME_TYPE_SELECTION_ZONE = QStringLiteral("sciqlop/selection-zone");
9 const QString MIME_TYPE_EVENT_LIST = QStringLiteral("sciqlop/event-list");
9 const QString MIME_TYPE_EVENT_LIST = QStringLiteral("sciqlop/event-list");
10 const QString MIME_TYPE_SOURCE_CATALOGUE_LIST = QStringLiteral("sciqlop/source-catalogue-list");
@@ -1,68 +1,70
1 #ifndef SCIQLOP_CATALOGUEEVENTSMODEL_H
1 #ifndef SCIQLOP_CATALOGUEEVENTSMODEL_H
2 #define SCIQLOP_CATALOGUEEVENTSMODEL_H
2 #define SCIQLOP_CATALOGUEEVENTSMODEL_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QAbstractItemModel>
5 #include <QAbstractItemModel>
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <unordered_set>
7 #include <unordered_set>
8
8
9 class DBCatalogue;
9 class DBEvent;
10 class DBEvent;
10 class DBEventProduct;
11 class DBEventProduct;
11
12
12 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueEventsModel)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueEventsModel)
13
14
14 class CatalogueEventsModel : public QAbstractItemModel {
15 class CatalogueEventsModel : public QAbstractItemModel {
15 Q_OBJECT
16 Q_OBJECT
16
17
17 signals:
18 signals:
18 void modelSorted();
19 void modelSorted();
19
20
20 public:
21 public:
21 CatalogueEventsModel(QObject *parent = nullptr);
22 CatalogueEventsModel(QObject *parent = nullptr);
22
23
23 enum class Column { Name, TStart, TEnd, Tags, Product, Validation, NbColumn };
24 enum class Column { Name, TStart, TEnd, Tags, Product, Validation, NbColumn };
24
25
26 void setSourceCatalogues(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
25 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events);
27 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events);
26 void addEvent(const std::shared_ptr<DBEvent> &event);
28 void addEvent(const std::shared_ptr<DBEvent> &event);
27 void removeEvent(const std::shared_ptr<DBEvent> &event);
29 void removeEvent(const std::shared_ptr<DBEvent> &event);
28 QVector<std::shared_ptr<DBEvent> > events() const;
30 QVector<std::shared_ptr<DBEvent> > events() const;
29
31
30 enum class ItemType { Root, Event, EventProduct };
32 enum class ItemType { Root, Event, EventProduct };
31 ItemType itemTypeOf(const QModelIndex &index) const;
33 ItemType itemTypeOf(const QModelIndex &index) const;
32 std::shared_ptr<DBEvent> getEvent(const QModelIndex &index) const;
34 std::shared_ptr<DBEvent> getEvent(const QModelIndex &index) const;
33 std::shared_ptr<DBEvent> getParentEvent(const QModelIndex &index) const;
35 std::shared_ptr<DBEvent> getParentEvent(const QModelIndex &index) const;
34 std::shared_ptr<DBEventProduct> getEventProduct(const QModelIndex &index) const;
36 std::shared_ptr<DBEventProduct> getEventProduct(const QModelIndex &index) const;
35
37
36 /// Refresh the data for the specified event
38 /// Refresh the data for the specified event
37 void refreshEvent(const std::shared_ptr<DBEvent> &event, bool refreshEventProducts = false);
39 void refreshEvent(const std::shared_ptr<DBEvent> &event, bool refreshEventProducts = false);
38
40
39 /// Returns a QModelIndex which represent the specified event
41 /// Returns a QModelIndex which represent the specified event
40 QModelIndex indexOf(const std::shared_ptr<DBEvent> &event) const;
42 QModelIndex indexOf(const std::shared_ptr<DBEvent> &event) const;
41
43
42 /// Marks a change flag on the specified event to allow sorting on the validation column
44 /// Marks a change flag on the specified event to allow sorting on the validation column
43 void setEventHasChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges);
45 void setEventHasChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges);
44
46
45 /// Returns true if the specified event has unsaved changes
47 /// Returns true if the specified event has unsaved changes
46 bool eventsHasChanges(const std::shared_ptr<DBEvent> &event) const;
48 bool eventsHasChanges(const std::shared_ptr<DBEvent> &event) const;
47
49
48 // Model
50 // Model
49 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
51 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
50 QModelIndex parent(const QModelIndex &index) const;
52 QModelIndex parent(const QModelIndex &index) const;
51 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
53 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
52 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
54 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
53 Qt::ItemFlags flags(const QModelIndex &index) const override;
55 Qt::ItemFlags flags(const QModelIndex &index) const override;
54 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
56 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
55 QVariant headerData(int section, Qt::Orientation orientation,
57 QVariant headerData(int section, Qt::Orientation orientation,
56 int role = Qt::DisplayRole) const override;
58 int role = Qt::DisplayRole) const override;
57 void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
59 void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
58
60
59 Qt::DropActions supportedDragActions() const override;
61 Qt::DropActions supportedDragActions() const override;
60 QStringList mimeTypes() const override;
62 QStringList mimeTypes() const override;
61 QMimeData *mimeData(const QModelIndexList &indexes) const override;
63 QMimeData *mimeData(const QModelIndexList &indexes) const override;
62
64
63 private:
65 private:
64 class CatalogueEventsModelPrivate;
66 class CatalogueEventsModelPrivate;
65 spimpl::unique_impl_ptr<CatalogueEventsModelPrivate> impl;
67 spimpl::unique_impl_ptr<CatalogueEventsModelPrivate> impl;
66 };
68 };
67
69
68 #endif // SCIQLOP_CATALOGUEEVENTSMODEL_H
70 #endif // SCIQLOP_CATALOGUEEVENTSMODEL_H
@@ -1,59 +1,59
1 #ifndef SCIQLOP_CATALOGUETREEMODEL_H
1 #ifndef SCIQLOP_CATALOGUETREEMODEL_H
2 #define SCIQLOP_CATALOGUETREEMODEL_H
2 #define SCIQLOP_CATALOGUETREEMODEL_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QAbstractItemModel>
5 #include <QAbstractItemModel>
6
6
7 class CatalogueAbstractTreeItem;
7 class CatalogueAbstractTreeItem;
8
8
9 /**
9 /**
10 * @brief Model to display catalogue items based on QTreeWidgetItem
10 * @brief Model to display catalogue items based on QTreeWidgetItem
11 * @warning Do not use the method QTreeWidgetItem::treeWidget for an item added to this model or the
11 * @warning Do not use the method QTreeWidgetItem::treeWidget for an item added to this model or the
12 * application will crash
12 * application will crash
13 */
13 */
14 class CatalogueTreeModel : public QAbstractItemModel {
14 class CatalogueTreeModel : public QAbstractItemModel {
15 Q_OBJECT
15 Q_OBJECT
16
16
17 signals:
17 signals:
18 void itemRenamed(const QModelIndex &index);
18 void itemRenamed(const QModelIndex &index);
19 void itemDropped(const QModelIndex &parentIndex);
19 void itemDropped(const QModelIndex &parentIndex, const QMimeData *data, Qt::DropAction action);
20
20
21 public:
21 public:
22 CatalogueTreeModel(QObject *parent = nullptr);
22 CatalogueTreeModel(QObject *parent = nullptr);
23
23
24 enum class Column { Name, Validation, Count };
24 enum class Column { Name, Validation, Count };
25
25
26 QModelIndex addTopLevelItem(CatalogueAbstractTreeItem *item);
26 QModelIndex addTopLevelItem(CatalogueAbstractTreeItem *item);
27 QVector<CatalogueAbstractTreeItem *> topLevelItems() const;
27 QVector<CatalogueAbstractTreeItem *> topLevelItems() const;
28
28
29 void addChildItem(CatalogueAbstractTreeItem *child, const QModelIndex &parentIndex);
29 void addChildItem(CatalogueAbstractTreeItem *child, const QModelIndex &parentIndex);
30 void removeChildItem(CatalogueAbstractTreeItem *child, const QModelIndex &parentIndex);
30 void removeChildItem(CatalogueAbstractTreeItem *child, const QModelIndex &parentIndex);
31 /// Refresh the data for the specified index
31 /// Refresh the data for the specified index
32 void refresh(const QModelIndex &index);
32 void refresh(const QModelIndex &index);
33
33
34 CatalogueAbstractTreeItem *item(const QModelIndex &index) const;
34 CatalogueAbstractTreeItem *item(const QModelIndex &index) const;
35 QModelIndex indexOf(CatalogueAbstractTreeItem *item, int column = 0) const;
35 QModelIndex indexOf(CatalogueAbstractTreeItem *item, int column = 0) const;
36
36
37 // model
37 // model
38 QModelIndex index(int row, int column,
38 QModelIndex index(int row, int column,
39 const QModelIndex &parent = QModelIndex()) const override;
39 const QModelIndex &parent = QModelIndex()) const override;
40 QModelIndex parent(const QModelIndex &index) const override;
40 QModelIndex parent(const QModelIndex &index) const override;
41 int rowCount(const QModelIndex &parent) const override;
41 int rowCount(const QModelIndex &parent) const override;
42 int columnCount(const QModelIndex &parent) const override;
42 int columnCount(const QModelIndex &parent) const override;
43 Qt::ItemFlags flags(const QModelIndex &index) const override;
43 Qt::ItemFlags flags(const QModelIndex &index) const override;
44 QVariant data(const QModelIndex &index, int role) const override;
44 QVariant data(const QModelIndex &index, int role) const override;
45 bool setData(const QModelIndex &index, const QVariant &value, int role) override;
45 bool setData(const QModelIndex &index, const QVariant &value, int role) override;
46
46
47 bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
47 bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
48 const QModelIndex &parent) const override;
48 const QModelIndex &parent) const override;
49 bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
49 bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
50 const QModelIndex &parent) override;
50 const QModelIndex &parent) override;
51 Qt::DropActions supportedDropActions() const;
51 Qt::DropActions supportedDropActions() const;
52 QStringList mimeTypes() const;
52 QStringList mimeTypes() const;
53
53
54 private:
54 private:
55 class CatalogueTreeModelPrivate;
55 class CatalogueTreeModelPrivate;
56 spimpl::unique_impl_ptr<CatalogueTreeModelPrivate> impl;
56 spimpl::unique_impl_ptr<CatalogueTreeModelPrivate> impl;
57 };
57 };
58
58
59 #endif // CATALOGUETREEMODEL_H
59 #endif // CATALOGUETREEMODEL_H
@@ -1,103 +1,106
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
3
3
4 #include "Data/SqpRange.h"
4 #include "Data/SqpRange.h"
5 #include "Visualization/IVisualizationWidget.h"
5 #include "Visualization/IVisualizationWidget.h"
6 #include "Visualization/VisualizationDragWidget.h"
6 #include "Visualization/VisualizationDragWidget.h"
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QWidget>
9 #include <QWidget>
10
10
11 #include <memory>
11 #include <memory>
12
12
13 #include <Common/spimpl.h>
13 #include <Common/spimpl.h>
14
14
15 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
15 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
16
16
17 namespace Ui {
17 namespace Ui {
18 class VisualizationZoneWidget;
18 class VisualizationZoneWidget;
19 } // namespace Ui
19 } // namespace Ui
20
20
21 class Variable;
21 class Variable;
22 class VisualizationGraphWidget;
22 class VisualizationGraphWidget;
23
23
24 class VisualizationZoneWidget : public VisualizationDragWidget, public IVisualizationWidget {
24 class VisualizationZoneWidget : public VisualizationDragWidget, public IVisualizationWidget {
25 Q_OBJECT
25 Q_OBJECT
26
26
27 public:
27 public:
28 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
28 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
29 virtual ~VisualizationZoneWidget();
29 virtual ~VisualizationZoneWidget();
30
30
31 /// Sets the range of the zone, only works if there is at least one graph in the zone
31 /// Sets the range of the zone, only works if there is at least one graph in the zone
32 /// Note: calibrations between graphs are lost.
32 /// Note: calibrations between graphs are lost.
33 void setZoneRange(const SqpRange &range);
33 void setZoneRange(const SqpRange &range);
34
34
35 /// Adds a graph widget
35 /// Adds a graph widget
36 void addGraph(VisualizationGraphWidget *graphWidget);
36 void addGraph(VisualizationGraphWidget *graphWidget);
37
37
38 /// Inserts a graph widget
38 /// Inserts a graph widget
39 void insertGraph(int index, VisualizationGraphWidget *graphWidget);
39 void insertGraph(int index, VisualizationGraphWidget *graphWidget);
40
40
41 /**
41 /**
42 * Creates a graph using a variable. The variable will be displayed in the new graph.
42 * Creates a graph using a variable. The variable will be displayed in the new graph.
43 * The graph is added at the end.
43 * The graph is added at the end.
44 * @param variable the variable for which to create the graph
44 * @param variable the variable for which to create the graph
45 * @return the pointer to the created graph
45 * @return the pointer to the created graph
46 */
46 */
47 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
47 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
48
48
49 /**
49 /**
50 * Creates a graph using a variable. The variable will be displayed in the new graph.
50 * Creates a graph using a variable. The variable will be displayed in the new graph.
51 * The graph is inserted at the specified index.
51 * The graph is inserted at the specified index.
52 * @param variable the variable for which to create the graph
52 * @param variable the variable for which to create the graph
53 * @param index The index where the graph should be inserted in the layout
53 * @param index The index where the graph should be inserted in the layout
54 * @return the pointer to the created graph
54 * @return the pointer to the created graph
55 */
55 */
56 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable, int index);
56 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable, int index);
57
57
58 /**
58 /**
59 * Creates a graph using a list of variables. The variables will be displayed in the new graph.
59 * Creates a graph using a list of variables. The variables will be displayed in the new graph.
60 * The graph is inserted at the specified index.
60 * The graph is inserted at the specified index.
61 * @param variables List of variables to be added to the graph
61 * @param variables List of variables to be added to the graph
62 * @param index The index where the graph should be inserted in the layout
62 * @param index The index where the graph should be inserted in the layout
63 * @return the pointer to the created graph
63 * @return the pointer to the created graph
64 */
64 */
65 VisualizationGraphWidget *createGraph(const QList<std::shared_ptr<Variable> > variables,
65 VisualizationGraphWidget *createGraph(const QList<std::shared_ptr<Variable> > variables,
66 int index);
66 int index);
67
67
68 /// Returns the first graph in the zone or nullptr if there is no graph inside
68 /// Returns the first graph in the zone or nullptr if there is no graph inside
69 VisualizationGraphWidget *firstGraph() const;
69 VisualizationGraphWidget *firstGraph() const;
70
70
71 /// Closes all graphes inside the zone
72 void closeAllGraphs();
73
71 // IVisualizationWidget interface
74 // IVisualizationWidget interface
72 void accept(IVisualizationWidgetVisitor *visitor) override;
75 void accept(IVisualizationWidgetVisitor *visitor) override;
73 bool canDrop(const Variable &variable) const override;
76 bool canDrop(const Variable &variable) const override;
74 bool contains(const Variable &variable) const override;
77 bool contains(const Variable &variable) const override;
75 QString name() const override;
78 QString name() const override;
76
79
77 // VisualisationDragWidget
80 // VisualisationDragWidget
78 QMimeData *mimeData(const QPoint &position) const override;
81 QMimeData *mimeData(const QPoint &position) const override;
79 bool isDragAllowed() const override;
82 bool isDragAllowed() const override;
80
83
81 void notifyMouseMoveInGraph(const QPointF &graphPosition, const QPointF &plotPosition,
84 void notifyMouseMoveInGraph(const QPointF &graphPosition, const QPointF &plotPosition,
82 VisualizationGraphWidget *graphWidget);
85 VisualizationGraphWidget *graphWidget);
83 void notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget);
86 void notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget);
84
87
85 protected:
88 protected:
86 void closeEvent(QCloseEvent *event) override;
89 void closeEvent(QCloseEvent *event) override;
87
90
88 private:
91 private:
89 Ui::VisualizationZoneWidget *ui;
92 Ui::VisualizationZoneWidget *ui;
90
93
91 class VisualizationZoneWidgetPrivate;
94 class VisualizationZoneWidgetPrivate;
92 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
95 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
93
96
94 private slots:
97 private slots:
95 void onVariableAdded(std::shared_ptr<Variable> variable);
98 void onVariableAdded(std::shared_ptr<Variable> variable);
96 /// Slot called when a variable is about to be removed from a graph contained in the zone
99 /// Slot called when a variable is about to be removed from a graph contained in the zone
97 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
100 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
98
101
99 void dropMimeData(int index, const QMimeData *mimeData);
102 void dropMimeData(int index, const QMimeData *mimeData);
100 void dropMimeDataOnGraph(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
103 void dropMimeDataOnGraph(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
101 };
104 };
102
105
103 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
106 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -1,147 +1,145
1 #include "Catalogue/CatalogueActionManager.h"
1 #include "Catalogue/CatalogueActionManager.h"
2
2
3 #include <Actions/ActionsGuiController.h>
3 #include <Actions/ActionsGuiController.h>
4 #include <Catalogue/CatalogueController.h>
4 #include <Catalogue/CatalogueController.h>
5 #include <DataSource/DataSourceItem.h>
5 #include <DataSource/DataSourceItem.h>
6 #include <SqpApplication.h>
6 #include <SqpApplication.h>
7 #include <Variable/Variable.h>
7 #include <Variable/Variable.h>
8 #include <Visualization/VisualizationGraphWidget.h>
8 #include <Visualization/VisualizationGraphWidget.h>
9 #include <Visualization/VisualizationSelectionZoneItem.h>
9 #include <Visualization/VisualizationSelectionZoneItem.h>
10
10
11 #include <Catalogue/CatalogueEventsWidget.h>
11 #include <Catalogue/CatalogueEventsWidget.h>
12 #include <Catalogue/CatalogueExplorer.h>
12 #include <Catalogue/CatalogueExplorer.h>
13 #include <Catalogue/CatalogueSideBarWidget.h>
13 #include <Catalogue/CatalogueSideBarWidget.h>
14 #include <Catalogue/CreateEventDialog.h>
14 #include <Catalogue/CreateEventDialog.h>
15
15
16 #include <CatalogueDao.h>
16 #include <CatalogueDao.h>
17 #include <DBCatalogue.h>
17 #include <DBCatalogue.h>
18 #include <DBEvent.h>
18 #include <DBEvent.h>
19 #include <DBEventProduct.h>
19 #include <DBEventProduct.h>
20
20
21 #include <QBoxLayout>
21 #include <QBoxLayout>
22 #include <QComboBox>
22 #include <QComboBox>
23 #include <QDialog>
23 #include <QDialog>
24 #include <QDialogButtonBox>
24 #include <QDialogButtonBox>
25 #include <QLineEdit>
25 #include <QLineEdit>
26 #include <memory>
26 #include <memory>
27
27
28 struct CatalogueActionManager::CatalogueActionManagerPrivate {
28 struct CatalogueActionManager::CatalogueActionManagerPrivate {
29
29
30 CatalogueExplorer *m_CatalogueExplorer = nullptr;
30 CatalogueExplorer *m_CatalogueExplorer = nullptr;
31
31
32 CatalogueActionManagerPrivate(CatalogueExplorer *catalogueExplorer)
32 CatalogueActionManagerPrivate(CatalogueExplorer *catalogueExplorer)
33 : m_CatalogueExplorer(catalogueExplorer)
33 : m_CatalogueExplorer(catalogueExplorer)
34 {
34 {
35 }
35 }
36
36
37 void createEventFromZones(const QString &eventName,
37 void createEventFromZones(const QString &eventName,
38 const QVector<VisualizationSelectionZoneItem *> &zones,
38 const QVector<VisualizationSelectionZoneItem *> &zones,
39 const std::shared_ptr<DBCatalogue> &catalogue = nullptr)
39 const std::shared_ptr<DBCatalogue> &catalogue = nullptr)
40 {
40 {
41 auto event = std::make_shared<DBEvent>();
41 auto event = std::make_shared<DBEvent>();
42 event->setName(eventName);
42 event->setName(eventName);
43
43
44 std::list<DBEventProduct> productList;
44 std::list<DBEventProduct> productList;
45 for (auto zone : zones) {
45 for (auto zone : zones) {
46 auto graph = zone->parentGraphWidget();
46 auto graph = zone->parentGraphWidget();
47 for (auto var : graph->variables()) {
47 for (auto var : graph->variables()) {
48 auto eventProduct = std::make_shared<DBEventProduct>();
48 auto eventProduct = std::make_shared<DBEventProduct>();
49 eventProduct->setEvent(*event);
49 eventProduct->setEvent(*event);
50
50
51 auto productId
51 auto productId
52 = var->metadata().value(DataSourceItem::ID_DATA_KEY, "UnknownID").toString();
52 = var->metadata().value(DataSourceItem::ID_DATA_KEY, "UnknownID").toString();
53
53
54 auto zoneRange = zone->range();
54 auto zoneRange = zone->range();
55 eventProduct->setTStart(zoneRange.m_TStart);
55 eventProduct->setTStart(zoneRange.m_TStart);
56 eventProduct->setTEnd(zoneRange.m_TEnd);
56 eventProduct->setTEnd(zoneRange.m_TEnd);
57
57
58 eventProduct->setProductId(productId);
58 eventProduct->setProductId(productId);
59
59
60 productList.push_back(*eventProduct);
60 productList.push_back(*eventProduct);
61
62 m_CatalogueExplorer->addSelectionZoneItem(event, productId, zone);
63 }
61 }
64 }
62 }
65
63
66 event->setEventProducts(productList);
64 event->setEventProducts(productList);
67
65
68 sqpApp->catalogueController().addEvent(event);
66 sqpApp->catalogueController().addEvent(event);
69
67
70
68
71 if (catalogue) {
69 if (catalogue) {
72 catalogue->addEvent(event->getUniqId());
70 catalogue->addEvent(event->getUniqId());
73 sqpApp->catalogueController().updateCatalogue(catalogue);
71 sqpApp->catalogueController().updateCatalogue(catalogue);
74 m_CatalogueExplorer->sideBarWidget().setCatalogueChanges(catalogue, true);
72 m_CatalogueExplorer->sideBarWidget().setCatalogueChanges(catalogue, true);
75 if (m_CatalogueExplorer->eventsWidget().displayedCatalogues().contains(catalogue)) {
73 if (m_CatalogueExplorer->eventsWidget().displayedCatalogues().contains(catalogue)) {
76 m_CatalogueExplorer->eventsWidget().addEvent(event);
74 m_CatalogueExplorer->eventsWidget().addEvent(event);
77 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
75 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
78 }
76 }
79 }
77 }
80 else if (m_CatalogueExplorer->eventsWidget().isAllEventsDisplayed()) {
78 else if (m_CatalogueExplorer->eventsWidget().isAllEventsDisplayed()) {
81 m_CatalogueExplorer->eventsWidget().addEvent(event);
79 m_CatalogueExplorer->eventsWidget().addEvent(event);
82 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
80 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
83 }
81 }
84 }
82 }
85 };
83 };
86
84
87 CatalogueActionManager::CatalogueActionManager(CatalogueExplorer *catalogueExplorer)
85 CatalogueActionManager::CatalogueActionManager(CatalogueExplorer *catalogueExplorer)
88 : impl{spimpl::make_unique_impl<CatalogueActionManagerPrivate>(catalogueExplorer)}
86 : impl{spimpl::make_unique_impl<CatalogueActionManagerPrivate>(catalogueExplorer)}
89 {
87 {
90 }
88 }
91
89
92 void CatalogueActionManager::installSelectionZoneActions()
90 void CatalogueActionManager::installSelectionZoneActions()
93 {
91 {
94 auto &actionController = sqpApp->actionsGuiController();
92 auto &actionController = sqpApp->actionsGuiController();
95
93
96 auto createEventEnableFuntion = [](auto zones) {
94 auto createEventEnableFuntion = [](auto zones) {
97
95
98 // Checks that all variables in the zones doesn't refer to the same product
96 // Checks that all variables in the zones doesn't refer to the same product
99 QSet<QString> usedDatasource;
97 QSet<QString> usedDatasource;
100 for (auto zone : zones) {
98 for (auto zone : zones) {
101 auto graph = zone->parentGraphWidget();
99 auto graph = zone->parentGraphWidget();
102 auto variables = graph->variables();
100 auto variables = graph->variables();
103
101
104 for (auto var : variables) {
102 for (auto var : variables) {
105 auto datasourceId = var->metadata().value(DataSourceItem::ID_DATA_KEY).toString();
103 auto datasourceId = var->metadata().value(DataSourceItem::ID_DATA_KEY).toString();
106 if (!usedDatasource.contains(datasourceId)) {
104 if (!usedDatasource.contains(datasourceId)) {
107 usedDatasource.insert(datasourceId);
105 usedDatasource.insert(datasourceId);
108 }
106 }
109 else {
107 else {
110 return false;
108 return false;
111 }
109 }
112 }
110 }
113 }
111 }
114
112
115 return true;
113 return true;
116 };
114 };
117
115
118 auto createEventAction = actionController.addSectionZoneAction(
116 auto createEventAction = actionController.addSectionZoneAction(
119 {QObject::tr("Catalogues")}, QObject::tr("New Event..."), [this](auto zones) {
117 {QObject::tr("Catalogues")}, QObject::tr("New Event..."), [this](auto zones) {
120 CreateEventDialog dialog(
118 CreateEventDialog dialog(
121 impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT));
119 impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT));
122 dialog.hideCatalogueChoice();
120 dialog.hideCatalogueChoice();
123 if (dialog.exec() == QDialog::Accepted) {
121 if (dialog.exec() == QDialog::Accepted) {
124 impl->createEventFromZones(dialog.eventName(), zones);
122 impl->createEventFromZones(dialog.eventName(), zones);
125 }
123 }
126 });
124 });
127 createEventAction->setEnableFunction(createEventEnableFuntion);
125 createEventAction->setEnableFunction(createEventEnableFuntion);
128
126
129 auto createEventInCatalogueAction = actionController.addSectionZoneAction(
127 auto createEventInCatalogueAction = actionController.addSectionZoneAction(
130 {QObject::tr("Catalogues")}, QObject::tr("New Event in Catalogue..."), [this](auto zones) {
128 {QObject::tr("Catalogues")}, QObject::tr("New Event in Catalogue..."), [this](auto zones) {
131 CreateEventDialog dialog(
129 CreateEventDialog dialog(
132 impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT));
130 impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT));
133 if (dialog.exec() == QDialog::Accepted) {
131 if (dialog.exec() == QDialog::Accepted) {
134 auto selectedCatalogue = dialog.selectedCatalogue();
132 auto selectedCatalogue = dialog.selectedCatalogue();
135 if (!selectedCatalogue) {
133 if (!selectedCatalogue) {
136 selectedCatalogue = std::make_shared<DBCatalogue>();
134 selectedCatalogue = std::make_shared<DBCatalogue>();
137 selectedCatalogue->setName(dialog.catalogueName());
135 selectedCatalogue->setName(dialog.catalogueName());
138 sqpApp->catalogueController().addCatalogue(selectedCatalogue);
136 sqpApp->catalogueController().addCatalogue(selectedCatalogue);
139 impl->m_CatalogueExplorer->sideBarWidget().addCatalogue(selectedCatalogue,
137 impl->m_CatalogueExplorer->sideBarWidget().addCatalogue(selectedCatalogue,
140 REPOSITORY_DEFAULT);
138 REPOSITORY_DEFAULT);
141 }
139 }
142
140
143 impl->createEventFromZones(dialog.eventName(), zones, selectedCatalogue);
141 impl->createEventFromZones(dialog.eventName(), zones, selectedCatalogue);
144 }
142 }
145 });
143 });
146 createEventInCatalogueAction->setEnableFunction(createEventEnableFuntion);
144 createEventInCatalogueAction->setEnableFunction(createEventEnableFuntion);
147 }
145 }
@@ -1,461 +1,472
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
28
28 QStringList columnNames()
29 QStringList columnNames()
29 {
30 {
30 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"),
31 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"),
31 tr("Tags"), tr("Product"), tr("")};
32 tr("Tags"), tr("Product"), tr("")};
32 }
33 }
33
34
34 QVariant sortData(int col, const std::shared_ptr<DBEvent> &event) const
35 QVariant sortData(int col, const std::shared_ptr<DBEvent> &event) const
35 {
36 {
36 if (col == (int)CatalogueEventsModel::Column::Validation) {
37 if (col == (int)CatalogueEventsModel::Column::Validation) {
37 auto hasChanges = sqpApp->catalogueController().eventHasChanges(event);
38 auto hasChanges = sqpApp->catalogueController().eventHasChanges(event);
38 return hasChanges ? true : QVariant();
39 return hasChanges ? true : QVariant();
39 }
40 }
40
41
41 return eventData(col, event);
42 return eventData(col, event);
42 }
43 }
43
44
44 QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
45 QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
45 {
46 {
46 switch (static_cast<Column>(col)) {
47 switch (static_cast<Column>(col)) {
47 case CatalogueEventsModel::Column::Name:
48 case CatalogueEventsModel::Column::Name:
48 return event->getName();
49 return event->getName();
49 case CatalogueEventsModel::Column::TStart:
50 case CatalogueEventsModel::Column::TStart:
50 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart())
51 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart())
51 : QVariant{};
52 : QVariant{};
52 case CatalogueEventsModel::Column::TEnd:
53 case CatalogueEventsModel::Column::TEnd:
53 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd())
54 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd())
54 : QVariant{};
55 : QVariant{};
55 case CatalogueEventsModel::Column::Product:
56 case CatalogueEventsModel::Column::Product:
56 return QString::number(nbEventProducts(event)) + " product(s)";
57 return QString::number(nbEventProducts(event)) + " product(s)";
57 case CatalogueEventsModel::Column::Tags: {
58 case CatalogueEventsModel::Column::Tags: {
58 QString tagList;
59 QString tagList;
59 auto tags = event->getTags();
60 auto tags = event->getTags();
60 for (auto tag : tags) {
61 for (auto tag : tags) {
61 tagList += tag.getName();
62 tagList += tag.getName();
62 tagList += ' ';
63 tagList += ' ';
63 }
64 }
64
65
65 return tagList;
66 return tagList;
66 }
67 }
67 case CatalogueEventsModel::Column::Validation:
68 case CatalogueEventsModel::Column::Validation:
68 return QVariant();
69 return QVariant();
69 default:
70 default:
70 break;
71 break;
71 }
72 }
72
73
73 Q_ASSERT(false);
74 Q_ASSERT(false);
74 return QStringLiteral("Unknown Data");
75 return QStringLiteral("Unknown Data");
75 }
76 }
76
77
77 void parseEventProduct(const std::shared_ptr<DBEvent> &event)
78 void parseEventProduct(const std::shared_ptr<DBEvent> &event)
78 {
79 {
79 for (auto product : event->getEventProducts()) {
80 for (auto product : event->getEventProducts()) {
80 m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
81 m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
81 }
82 }
82 }
83 }
83
84
84 int nbEventProducts(const std::shared_ptr<DBEvent> &event) const
85 int nbEventProducts(const std::shared_ptr<DBEvent> &event) const
85 {
86 {
86 auto eventProductsIt = m_EventProducts.find(event.get());
87 auto eventProductsIt = m_EventProducts.find(event.get());
87 if (eventProductsIt != m_EventProducts.cend()) {
88 if (eventProductsIt != m_EventProducts.cend()) {
88 return m_EventProducts.at(event.get()).count();
89 return m_EventProducts.at(event.get()).count();
89 }
90 }
90 else {
91 else {
91 return 0;
92 return 0;
92 }
93 }
93 }
94 }
94
95
95 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
96 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
96 {
97 {
97 switch (static_cast<Column>(col)) {
98 switch (static_cast<Column>(col)) {
98 case CatalogueEventsModel::Column::Name:
99 case CatalogueEventsModel::Column::Name:
99 return eventProduct->getProductId();
100 return eventProduct->getProductId();
100 case CatalogueEventsModel::Column::TStart:
101 case CatalogueEventsModel::Column::TStart:
101 return DateUtils::dateTime(eventProduct->getTStart());
102 return DateUtils::dateTime(eventProduct->getTStart());
102 case CatalogueEventsModel::Column::TEnd:
103 case CatalogueEventsModel::Column::TEnd:
103 return DateUtils::dateTime(eventProduct->getTEnd());
104 return DateUtils::dateTime(eventProduct->getTEnd());
104 case CatalogueEventsModel::Column::Product:
105 case CatalogueEventsModel::Column::Product:
105 return eventProduct->getProductId();
106 return eventProduct->getProductId();
106 case CatalogueEventsModel::Column::Tags:
107 case CatalogueEventsModel::Column::Tags:
107 return QString();
108 return QString();
108 case CatalogueEventsModel::Column::Validation:
109 case CatalogueEventsModel::Column::Validation:
109 return QVariant();
110 return QVariant();
110 default:
111 default:
111 break;
112 break;
112 }
113 }
113
114
114 Q_ASSERT(false);
115 Q_ASSERT(false);
115 return QStringLiteral("Unknown Data");
116 return QStringLiteral("Unknown Data");
116 }
117 }
117
118
118 void refreshChildrenOfIndex(CatalogueEventsModel *model, const QModelIndex &index) const
119 void refreshChildrenOfIndex(CatalogueEventsModel *model, const QModelIndex &index) const
119 {
120 {
120 auto childCount = model->rowCount(index);
121 auto childCount = model->rowCount(index);
121 auto colCount = model->columnCount();
122 auto colCount = model->columnCount();
122 emit model->dataChanged(model->index(0, 0, index),
123 emit model->dataChanged(model->index(0, 0, index),
123 model->index(childCount, colCount, index));
124 model->index(childCount, colCount, index));
124 }
125 }
125 };
126 };
126
127
127 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
128 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
128 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
129 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
129 {
130 {
130 }
131 }
131
132
133 void CatalogueEventsModel::setSourceCatalogues(
134 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
135 {
136 impl->m_SourceCatalogue = catalogues;
137 }
138
132 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
139 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
133 {
140 {
134 beginResetModel();
141 beginResetModel();
135
142
136 impl->m_Events = events;
143 impl->m_Events = events;
137 impl->m_EventProducts.clear();
144 impl->m_EventProducts.clear();
138 for (auto event : events) {
145 for (auto event : events) {
139 impl->parseEventProduct(event);
146 impl->parseEventProduct(event);
140 }
147 }
141
148
142 endResetModel();
149 endResetModel();
143 }
150 }
144
151
145 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
152 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
146 {
153 {
147 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
154 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
148 return impl->m_Events.value(index.row());
155 return impl->m_Events.value(index.row());
149 }
156 }
150 else {
157 else {
151 return nullptr;
158 return nullptr;
152 }
159 }
153 }
160 }
154
161
155 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
162 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
156 {
163 {
157 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
164 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
158 return getEvent(index.parent());
165 return getEvent(index.parent());
159 }
166 }
160 else {
167 else {
161 return nullptr;
168 return nullptr;
162 }
169 }
163 }
170 }
164
171
165 std::shared_ptr<DBEventProduct>
172 std::shared_ptr<DBEventProduct>
166 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
173 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
167 {
174 {
168 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
175 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
169 auto event = static_cast<DBEvent *>(index.internalPointer());
176 auto event = static_cast<DBEvent *>(index.internalPointer());
170 return impl->m_EventProducts.at(event).value(index.row());
177 return impl->m_EventProducts.at(event).value(index.row());
171 }
178 }
172 else {
179 else {
173 return nullptr;
180 return nullptr;
174 }
181 }
175 }
182 }
176
183
177 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
184 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
178 {
185 {
179 beginInsertRows(QModelIndex(), impl->m_Events.count(), impl->m_Events.count());
186 beginInsertRows(QModelIndex(), impl->m_Events.count(), impl->m_Events.count());
180 impl->m_Events.append(event);
187 impl->m_Events.append(event);
181 impl->parseEventProduct(event);
188 impl->parseEventProduct(event);
182 endInsertRows();
189 endInsertRows();
183
190
184 // Also refreshes its children event products
191 // Also refreshes its children event products
185 auto eventIndex = index(impl->m_Events.count(), 0);
192 auto eventIndex = index(impl->m_Events.count(), 0);
186 impl->refreshChildrenOfIndex(this, eventIndex);
193 impl->refreshChildrenOfIndex(this, eventIndex);
187 }
194 }
188
195
189 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
196 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
190 {
197 {
191 auto index = impl->m_Events.indexOf(event);
198 auto index = impl->m_Events.indexOf(event);
192 if (index >= 0) {
199 if (index >= 0) {
193 beginRemoveRows(QModelIndex(), index, index);
200 beginRemoveRows(QModelIndex(), index, index);
194 impl->m_Events.removeAt(index);
201 impl->m_Events.removeAt(index);
195 impl->m_EventProducts.erase(event.get());
202 impl->m_EventProducts.erase(event.get());
196 endRemoveRows();
203 endRemoveRows();
197 }
204 }
198 }
205 }
199
206
200 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
207 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
201 {
208 {
202 return impl->m_Events;
209 return impl->m_Events;
203 }
210 }
204
211
205 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event,
212 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event,
206 bool refreshEventProducts)
213 bool refreshEventProducts)
207 {
214 {
208 auto eventIndex = indexOf(event);
215 auto eventIndex = indexOf(event);
209 if (eventIndex.isValid()) {
216 if (eventIndex.isValid()) {
210
217
211 if (refreshEventProducts) {
218 if (refreshEventProducts) {
212 // Reparse the associated event products
219 // Reparse the associated event products
213
220
214 auto nbEventProducts = impl->nbEventProducts(event);
221 auto nbEventProducts = impl->nbEventProducts(event);
215 auto newNbOfEventProducts = event->getEventProducts().size();
222 auto newNbOfEventProducts = event->getEventProducts().size();
216 if (newNbOfEventProducts < nbEventProducts) {
223 if (newNbOfEventProducts < nbEventProducts) {
217 beginRemoveRows(eventIndex, newNbOfEventProducts, nbEventProducts - 1);
224 beginRemoveRows(eventIndex, newNbOfEventProducts, nbEventProducts - 1);
218 impl->m_EventProducts.erase(event.get());
225 impl->m_EventProducts.erase(event.get());
219 impl->parseEventProduct(event);
226 impl->parseEventProduct(event);
220 endRemoveRows();
227 endRemoveRows();
221 }
228 }
222 else if (newNbOfEventProducts > nbEventProducts) {
229 else if (newNbOfEventProducts > nbEventProducts) {
223 beginInsertRows(eventIndex, nbEventProducts, newNbOfEventProducts - 1);
230 beginInsertRows(eventIndex, nbEventProducts, newNbOfEventProducts - 1);
224 impl->m_EventProducts.erase(event.get());
231 impl->m_EventProducts.erase(event.get());
225 impl->parseEventProduct(event);
232 impl->parseEventProduct(event);
226 endInsertRows();
233 endInsertRows();
227 }
234 }
228 else { // newNbOfEventProducts == nbEventProducts
235 else { // newNbOfEventProducts == nbEventProducts
229 impl->m_EventProducts.erase(event.get());
236 impl->m_EventProducts.erase(event.get());
230 impl->parseEventProduct(event);
237 impl->parseEventProduct(event);
231 }
238 }
232 }
239 }
233
240
234 // Refreshes the event line
241 // Refreshes the event line
235 auto colCount = columnCount();
242 auto colCount = columnCount();
236 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
243 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
237
244
238 // Also refreshes its children event products
245 // Also refreshes its children event products
239 impl->refreshChildrenOfIndex(this, eventIndex);
246 impl->refreshChildrenOfIndex(this, eventIndex);
240 }
247 }
241 else {
248 else {
242 qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
249 qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
243 }
250 }
244 }
251 }
245
252
246 QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
253 QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
247 {
254 {
248 auto row = impl->m_Events.indexOf(event);
255 auto row = impl->m_Events.indexOf(event);
249 if (row >= 0) {
256 if (row >= 0) {
250 return index(row, 0);
257 return index(row, 0);
251 }
258 }
252
259
253 return QModelIndex();
260 return QModelIndex();
254 }
261 }
255
262
256 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
263 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
257 {
264 {
258 if (!hasIndex(row, column, parent)) {
265 if (!hasIndex(row, column, parent)) {
259 return QModelIndex();
266 return QModelIndex();
260 }
267 }
261
268
262 switch (itemTypeOf(parent)) {
269 switch (itemTypeOf(parent)) {
263 case CatalogueEventsModel::ItemType::Root:
270 case CatalogueEventsModel::ItemType::Root:
264 return createIndex(row, column);
271 return createIndex(row, column);
265 case CatalogueEventsModel::ItemType::Event: {
272 case CatalogueEventsModel::ItemType::Event: {
266 auto event = getEvent(parent);
273 auto event = getEvent(parent);
267 return createIndex(row, column, event.get());
274 return createIndex(row, column, event.get());
268 }
275 }
269 case CatalogueEventsModel::ItemType::EventProduct:
276 case CatalogueEventsModel::ItemType::EventProduct:
270 break;
277 break;
271 default:
278 default:
272 break;
279 break;
273 }
280 }
274
281
275 return QModelIndex();
282 return QModelIndex();
276 }
283 }
277
284
278 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
285 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
279 {
286 {
280 switch (itemTypeOf(index)) {
287 switch (itemTypeOf(index)) {
281 case CatalogueEventsModel::ItemType::EventProduct: {
288 case CatalogueEventsModel::ItemType::EventProduct: {
282 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
289 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
283 auto it
290 auto it
284 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
291 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
285 [parentEvent](auto event) { return event.get() == parentEvent; });
292 [parentEvent](auto event) { return event.get() == parentEvent; });
286
293
287 if (it != impl->m_Events.cend()) {
294 if (it != impl->m_Events.cend()) {
288 return createIndex(it - impl->m_Events.cbegin(), 0);
295 return createIndex(it - impl->m_Events.cbegin(), 0);
289 }
296 }
290 else {
297 else {
291 return QModelIndex();
298 return QModelIndex();
292 }
299 }
293 }
300 }
294 case CatalogueEventsModel::ItemType::Root:
301 case CatalogueEventsModel::ItemType::Root:
295 break;
302 break;
296 case CatalogueEventsModel::ItemType::Event:
303 case CatalogueEventsModel::ItemType::Event:
297 break;
304 break;
298 default:
305 default:
299 break;
306 break;
300 }
307 }
301
308
302 return QModelIndex();
309 return QModelIndex();
303 }
310 }
304
311
305 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
312 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
306 {
313 {
307 if (parent.column() > 0) {
314 if (parent.column() > 0) {
308 return 0;
315 return 0;
309 }
316 }
310
317
311 switch (itemTypeOf(parent)) {
318 switch (itemTypeOf(parent)) {
312 case CatalogueEventsModel::ItemType::Root:
319 case CatalogueEventsModel::ItemType::Root:
313 return impl->m_Events.count();
320 return impl->m_Events.count();
314 case CatalogueEventsModel::ItemType::Event: {
321 case CatalogueEventsModel::ItemType::Event: {
315 auto event = getEvent(parent);
322 auto event = getEvent(parent);
316 return impl->m_EventProducts[event.get()].count();
323 return impl->m_EventProducts[event.get()].count();
317 }
324 }
318 case CatalogueEventsModel::ItemType::EventProduct:
325 case CatalogueEventsModel::ItemType::EventProduct:
319 break;
326 break;
320 default:
327 default:
321 break;
328 break;
322 }
329 }
323
330
324 return 0;
331 return 0;
325 }
332 }
326
333
327 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
334 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
328 {
335 {
329 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
336 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
330 }
337 }
331
338
332 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
339 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
333 {
340 {
334 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
341 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
335 }
342 }
336
343
337 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
344 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
338 {
345 {
339 if (index.isValid()) {
346 if (index.isValid()) {
340
347
341 auto type = itemTypeOf(index);
348 auto type = itemTypeOf(index);
342 if (type == CatalogueEventsModel::ItemType::Event) {
349 if (type == CatalogueEventsModel::ItemType::Event) {
343 auto event = getEvent(index);
350 auto event = getEvent(index);
344 switch (role) {
351 switch (role) {
345 case Qt::DisplayRole:
352 case Qt::DisplayRole:
346 return impl->eventData(index.column(), event);
353 return impl->eventData(index.column(), event);
347 break;
354 break;
348 }
355 }
349 }
356 }
350 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
357 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
351 auto product = getEventProduct(index);
358 auto product = getEventProduct(index);
352 switch (role) {
359 switch (role) {
353 case Qt::DisplayRole:
360 case Qt::DisplayRole:
354 return impl->eventProductData(index.column(), product);
361 return impl->eventProductData(index.column(), product);
355 break;
362 break;
356 }
363 }
357 }
364 }
358 }
365 }
359
366
360 return QVariant{};
367 return QVariant{};
361 }
368 }
362
369
363 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
370 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
364 {
371 {
365 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
372 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
366 return impl->columnNames().value(section);
373 return impl->columnNames().value(section);
367 }
374 }
368
375
369 return QVariant();
376 return QVariant();
370 }
377 }
371
378
372 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
379 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
373 {
380 {
374 beginResetModel();
381 beginResetModel();
375 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
382 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
376 [this, column, order](auto e1, auto e2) {
383 [this, column, order](auto e1, auto e2) {
377 auto data1 = impl->sortData(column, e1);
384 auto data1 = impl->sortData(column, e1);
378 auto data2 = impl->sortData(column, e2);
385 auto data2 = impl->sortData(column, e2);
379
386
380 auto result = data1.toString() < data2.toString();
387 auto result = data1.toString() < data2.toString();
381
388
382 return order == Qt::AscendingOrder ? result : !result;
389 return order == Qt::AscendingOrder ? result : !result;
383 });
390 });
384
391
385 endResetModel();
392 endResetModel();
386 emit modelSorted();
393 emit modelSorted();
387 }
394 }
388
395
389 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
396 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
390 {
397 {
391 return Qt::CopyAction;
398 return Qt::CopyAction | Qt::MoveAction;
392 }
399 }
393
400
394 QStringList CatalogueEventsModel::mimeTypes() const
401 QStringList CatalogueEventsModel::mimeTypes() const
395 {
402 {
396 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_TIME_RANGE};
403 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_SOURCE_CATALOGUE_LIST, MIME_TYPE_TIME_RANGE};
397 }
404 }
398
405
399 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
406 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
400 {
407 {
401 auto mimeData = new QMimeData;
408 auto mimeData = new QMimeData;
402
409
403 bool isFirst = true;
410 bool isFirst = true;
404
411
405 QVector<std::shared_ptr<DBEvent> > eventList;
412 QVector<std::shared_ptr<DBEvent> > eventList;
406 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
413 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
407
414
408 SqpRange firstTimeRange;
415 SqpRange firstTimeRange;
409 for (const auto &index : indexes) {
416 for (const auto &index : indexes) {
410 if (index.column() == 0) { // only the first column
417 if (index.column() == 0) { // only the first column
411
418
412 auto type = itemTypeOf(index);
419 auto type = itemTypeOf(index);
413 if (type == ItemType::Event) {
420 if (type == ItemType::Event) {
414 auto event = getEvent(index);
421 auto event = getEvent(index);
415 eventList << event;
422 eventList << event;
416
423
417 if (isFirst) {
424 if (isFirst) {
418 isFirst = false;
425 isFirst = false;
419 firstTimeRange.m_TStart = event->getTStart();
426 firstTimeRange.m_TStart = event->getTStart();
420 firstTimeRange.m_TEnd = event->getTEnd();
427 firstTimeRange.m_TEnd = event->getTEnd();
421 }
428 }
422 }
429 }
423 else if (type == ItemType::EventProduct) {
430 else if (type == ItemType::EventProduct) {
424 auto product = getEventProduct(index);
431 auto product = getEventProduct(index);
425 eventProductList << product;
432 eventProductList << product;
426
433
427 if (isFirst) {
434 if (isFirst) {
428 isFirst = false;
435 isFirst = false;
429 firstTimeRange.m_TStart = product->getTStart();
436 firstTimeRange.m_TStart = product->getTStart();
430 firstTimeRange.m_TEnd = product->getTEnd();
437 firstTimeRange.m_TEnd = product->getTEnd();
431 }
438 }
432 }
439 }
433 }
440 }
434 }
441 }
435
442
436 if (!eventList.isEmpty() && eventProductList.isEmpty()) {
443 if (!eventList.isEmpty() && eventProductList.isEmpty()) {
437 auto eventsEncodedData = sqpApp->catalogueController().mimeDataForEvents(eventList);
444 auto eventsEncodedData = sqpApp->catalogueController().mimeDataForEvents(eventList);
438 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
445 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
446
447 auto sourceCataloguesEncodedData
448 = sqpApp->catalogueController().mimeDataForCatalogues(impl->m_SourceCatalogue);
449 mimeData->setData(MIME_TYPE_SOURCE_CATALOGUE_LIST, sourceCataloguesEncodedData);
439 }
450 }
440
451
441 if (eventList.count() + eventProductList.count() == 1) {
452 if (eventList.count() + eventProductList.count() == 1) {
442 // No time range MIME data if multiple events are dragged
453 // No time range MIME data if multiple events are dragged
443 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
454 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
444 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
455 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
445 }
456 }
446
457
447 return mimeData;
458 return mimeData;
448 }
459 }
449
460
450 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
461 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
451 {
462 {
452 if (!index.isValid()) {
463 if (!index.isValid()) {
453 return ItemType::Root;
464 return ItemType::Root;
454 }
465 }
455 else if (index.internalPointer() == nullptr) {
466 else if (index.internalPointer() == nullptr) {
456 return ItemType::Event;
467 return ItemType::Event;
457 }
468 }
458 else {
469 else {
459 return ItemType::EventProduct;
470 return ItemType::EventProduct;
460 }
471 }
461 }
472 }
@@ -1,590 +1,594
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 <QListWidget>
22 #include <QListWidget>
23 #include <QMessageBox>
23 #include <QMessageBox>
24
24
25 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
25 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
26
26
27 /// Fixed size of the validation column
27 /// Fixed size of the validation column
28 const auto VALIDATION_COLUMN_SIZE = 35;
28 const auto VALIDATION_COLUMN_SIZE = 35;
29
29
30 /// Percentage added to the range of a event when it is displayed
30 /// Percentage added to the range of a event when it is displayed
31 const auto EVENT_RANGE_MARGE = 30; // in %
31 const auto EVENT_RANGE_MARGE = 30; // in %
32
32
33 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
33 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
34
34
35 CatalogueEventsModel *m_Model = nullptr;
35 CatalogueEventsModel *m_Model = nullptr;
36 QStringList m_ZonesForTimeMode;
36 QStringList m_ZonesForTimeMode;
37 QString m_ZoneForGraphMode;
37 QString m_ZoneForGraphMode;
38 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
38 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
39 bool m_AllEventDisplayed = false;
39 bool m_AllEventDisplayed = false;
40 QVector<VisualizationGraphWidget *> m_CustomGraphs;
40 QVector<VisualizationGraphWidget *> m_CustomGraphs;
41
41
42 VisualizationWidget *m_VisualizationWidget = nullptr;
42 VisualizationWidget *m_VisualizationWidget = nullptr;
43
43
44 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget)
44 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget)
45 {
45 {
46 widget->ui->treeView->setSortingEnabled(false);
46 widget->ui->treeView->setSortingEnabled(false);
47 m_Model->setSourceCatalogues(m_DisplayedCatalogues);
47 m_Model->setEvents(events);
48 m_Model->setEvents(events);
48 widget->ui->treeView->setSortingEnabled(true);
49 widget->ui->treeView->setSortingEnabled(true);
49
50
50 for (auto event : events) {
51 for (auto event : events) {
51 if (sqpApp->catalogueController().eventHasChanges(event)) {
52 if (sqpApp->catalogueController().eventHasChanges(event)) {
52 auto index = m_Model->indexOf(event);
53 auto index = m_Model->indexOf(event);
53 widget->setEventChanges(event, true);
54 widget->setEventChanges(event, true);
54 }
55 }
55 }
56 }
56 }
57 }
57
58
58 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
59 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
59 {
60 {
60 treeView->setSortingEnabled(false);
61 treeView->setSortingEnabled(false);
61 m_Model->addEvent(event);
62 m_Model->addEvent(event);
62 treeView->setSortingEnabled(true);
63 treeView->setSortingEnabled(true);
63 }
64 }
64
65
65 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
66 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
66 {
67 {
67 treeView->setSortingEnabled(false);
68 treeView->setSortingEnabled(false);
68 m_Model->removeEvent(event);
69 m_Model->removeEvent(event);
69 treeView->setSortingEnabled(true);
70 treeView->setSortingEnabled(true);
70 }
71 }
71
72
72 QStringList getAvailableVisualizationZoneList() const
73 QStringList getAvailableVisualizationZoneList() const
73 {
74 {
74 if (m_VisualizationWidget) {
75 if (m_VisualizationWidget) {
75 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
76 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
76 return tab->availableZoneWidgets();
77 return tab->availableZoneWidgets();
77 }
78 }
78 }
79 }
79
80
80 return QStringList{};
81 return QStringList{};
81 }
82 }
82
83
83 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
84 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
84 bool allowMultiSelection, const QPoint &location)
85 bool allowMultiSelection, const QPoint &location)
85 {
86 {
86 auto availableZones = getAvailableVisualizationZoneList();
87 auto availableZones = getAvailableVisualizationZoneList();
87 if (availableZones.isEmpty()) {
88 if (availableZones.isEmpty()) {
88 return QStringList{};
89 return QStringList{};
89 }
90 }
90
91
91 QDialog d(parent, Qt::Tool);
92 QDialog d(parent, Qt::Tool);
92 d.setWindowTitle("Choose a zone");
93 d.setWindowTitle("Choose a zone");
93 auto layout = new QVBoxLayout{&d};
94 auto layout = new QVBoxLayout{&d};
94 layout->setContentsMargins(0, 0, 0, 0);
95 layout->setContentsMargins(0, 0, 0, 0);
95 auto listWidget = new QListWidget{&d};
96 auto listWidget = new QListWidget{&d};
96 layout->addWidget(listWidget);
97 layout->addWidget(listWidget);
97
98
98 QSet<QListWidgetItem *> checkedItems;
99 QSet<QListWidgetItem *> checkedItems;
99 for (auto zone : availableZones) {
100 for (auto zone : availableZones) {
100 auto item = new QListWidgetItem{zone};
101 auto item = new QListWidgetItem{zone};
101 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
102 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
102 if (selectedZones.contains(zone)) {
103 if (selectedZones.contains(zone)) {
103 item->setCheckState(Qt::Checked);
104 item->setCheckState(Qt::Checked);
104 checkedItems << item;
105 checkedItems << item;
105 }
106 }
106 else {
107 else {
107 item->setCheckState(Qt::Unchecked);
108 item->setCheckState(Qt::Unchecked);
108 }
109 }
109
110
110 listWidget->addItem(item);
111 listWidget->addItem(item);
111 }
112 }
112
113
113 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
114 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
114 layout->addWidget(buttonBox);
115 layout->addWidget(buttonBox);
115
116
116 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
117 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
117 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
118 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
118
119
119 QObject::connect(listWidget, &QListWidget::itemChanged,
120 QObject::connect(listWidget, &QListWidget::itemChanged,
120 [&checkedItems, allowMultiSelection, listWidget](auto item) {
121 [&checkedItems, allowMultiSelection, listWidget](auto item) {
121 if (item->checkState() == Qt::Checked) {
122 if (item->checkState() == Qt::Checked) {
122 if (!allowMultiSelection) {
123 if (!allowMultiSelection) {
123 for (auto checkedItem : checkedItems) {
124 for (auto checkedItem : checkedItems) {
124 listWidget->blockSignals(true);
125 listWidget->blockSignals(true);
125 checkedItem->setCheckState(Qt::Unchecked);
126 checkedItem->setCheckState(Qt::Unchecked);
126 listWidget->blockSignals(false);
127 listWidget->blockSignals(false);
127 }
128 }
128
129
129 checkedItems.clear();
130 checkedItems.clear();
130 }
131 }
131 checkedItems << item;
132 checkedItems << item;
132 }
133 }
133 else {
134 else {
134 checkedItems.remove(item);
135 checkedItems.remove(item);
135 }
136 }
136 });
137 });
137
138
138 QStringList result;
139 QStringList result;
139
140
140 d.setMinimumWidth(120);
141 d.setMinimumWidth(120);
141 d.resize(d.minimumSizeHint());
142 d.resize(d.minimumSizeHint());
142 d.move(location);
143 d.move(location);
143 if (d.exec() == QDialog::Accepted) {
144 if (d.exec() == QDialog::Accepted) {
144 for (auto item : checkedItems) {
145 for (auto item : checkedItems) {
145 result += item->text();
146 result += item->text();
146 }
147 }
147 }
148 }
148 else {
149 else {
149 result = selectedZones;
150 result = selectedZones;
150 }
151 }
151
152
152 return result;
153 return result;
153 }
154 }
154
155
155 void updateForTimeMode(QTreeView *treeView)
156 void updateForTimeMode(QTreeView *treeView)
156 {
157 {
157 auto selectedRows = treeView->selectionModel()->selectedRows();
158 auto selectedRows = treeView->selectionModel()->selectedRows();
158
159
159 if (selectedRows.count() == 1) {
160 if (selectedRows.count() == 1) {
160 auto event = m_Model->getEvent(selectedRows.first());
161 auto event = m_Model->getEvent(selectedRows.first());
161 if (event) {
162 if (event) {
162 if (m_VisualizationWidget) {
163 if (m_VisualizationWidget) {
163 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
164 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
164
165
165 for (auto zoneName : m_ZonesForTimeMode) {
166 for (auto zoneName : m_ZonesForTimeMode) {
166 if (auto zone = tab->getZoneWithName(zoneName)) {
167 if (auto zone = tab->getZoneWithName(zoneName)) {
167 SqpRange eventRange;
168 SqpRange eventRange;
168 eventRange.m_TStart = event->getTStart();
169 eventRange.m_TStart = event->getTStart();
169 eventRange.m_TEnd = event->getTEnd();
170 eventRange.m_TEnd = event->getTEnd();
170 zone->setZoneRange(eventRange);
171 zone->setZoneRange(eventRange);
171 }
172 }
172 }
173 }
173 }
174 }
174 else {
175 else {
175 qCWarning(LOG_CatalogueEventsWidget())
176 qCWarning(LOG_CatalogueEventsWidget())
176 << "updateTimeZone: no tab found in the visualization";
177 << "updateTimeZone: no tab found in the visualization";
177 }
178 }
178 }
179 }
179 else {
180 else {
180 qCWarning(LOG_CatalogueEventsWidget())
181 qCWarning(LOG_CatalogueEventsWidget())
181 << "updateTimeZone: visualization widget not found";
182 << "updateTimeZone: visualization widget not found";
182 }
183 }
183 }
184 }
184 }
185 }
185 else {
186 else {
186 qCWarning(LOG_CatalogueEventsWidget())
187 qCWarning(LOG_CatalogueEventsWidget())
187 << "updateTimeZone: not compatible with multiple events selected";
188 << "updateTimeZone: not compatible with multiple events selected";
188 }
189 }
189 }
190 }
190
191
191 QVector<SqpRange> getGraphRanges(const std::shared_ptr<DBEvent> &event)
192 QVector<SqpRange> getGraphRanges(const std::shared_ptr<DBEvent> &event)
192 {
193 {
193 // Retrieves the range of each product and the maximum size
194 // Retrieves the range of each product and the maximum size
194 QVector<SqpRange> graphRanges;
195 QVector<SqpRange> graphRanges;
195 double maxDt = 0;
196 double maxDt = 0;
196 for (auto eventProduct : event->getEventProducts()) {
197 for (auto eventProduct : event->getEventProducts()) {
197 SqpRange eventRange;
198 SqpRange eventRange;
198 eventRange.m_TStart = eventProduct.getTStart();
199 eventRange.m_TStart = eventProduct.getTStart();
199 eventRange.m_TEnd = eventProduct.getTEnd();
200 eventRange.m_TEnd = eventProduct.getTEnd();
200 graphRanges << eventRange;
201 graphRanges << eventRange;
201
202
202 auto dt = eventRange.m_TEnd - eventRange.m_TStart;
203 auto dt = eventRange.m_TEnd - eventRange.m_TStart;
203 if (dt > maxDt) {
204 if (dt > maxDt) {
204 maxDt = dt;
205 maxDt = dt;
205 }
206 }
206 }
207 }
207
208
208 // Adds the marge
209 // Adds the marge
209 maxDt *= (100.0 + EVENT_RANGE_MARGE) / 100.0;
210 maxDt *= (100.0 + EVENT_RANGE_MARGE) / 100.0;
210
211
211 // Corrects the graph ranges so that they all have the same size
212 // Corrects the graph ranges so that they all have the same size
212 QVector<SqpRange> correctedGraphRanges;
213 QVector<SqpRange> correctedGraphRanges;
213 for (auto range : graphRanges) {
214 for (auto range : graphRanges) {
214 auto dt = range.m_TEnd - range.m_TStart;
215 auto dt = range.m_TEnd - range.m_TStart;
215 auto diff = qAbs((maxDt - dt) / 2.0);
216 auto diff = qAbs((maxDt - dt) / 2.0);
216
217
217 SqpRange correctedRange;
218 SqpRange correctedRange;
218 correctedRange.m_TStart = range.m_TStart - diff;
219 correctedRange.m_TStart = range.m_TStart - diff;
219 correctedRange.m_TEnd = range.m_TEnd + diff;
220 correctedRange.m_TEnd = range.m_TEnd + diff;
220
221
221 correctedGraphRanges << correctedRange;
222 correctedGraphRanges << correctedRange;
222 }
223 }
223
224
224 return correctedGraphRanges;
225 return correctedGraphRanges;
225 }
226 }
226
227
227 void updateForGraphMode(CatalogueEventsWidget *catalogueEventWidget)
228 void updateForGraphMode(CatalogueEventsWidget *catalogueEventWidget)
228 {
229 {
229 auto selectedRows = catalogueEventWidget->ui->treeView->selectionModel()->selectedRows();
230 auto selectedRows = catalogueEventWidget->ui->treeView->selectionModel()->selectedRows();
230 if (selectedRows.count() != 1) {
231 if (selectedRows.count() != 1) {
231 qCWarning(LOG_CatalogueEventsWidget())
232 qCWarning(LOG_CatalogueEventsWidget())
232 << "updateGraphMode: not compatible with multiple events selected";
233 << "updateGraphMode: not compatible with multiple events selected";
233 return;
234 return;
234 }
235 }
235
236
236 if (!m_VisualizationWidget) {
237 if (!m_VisualizationWidget) {
237 qCWarning(LOG_CatalogueEventsWidget())
238 qCWarning(LOG_CatalogueEventsWidget())
238 << "updateGraphMode: visualization widget not found";
239 << "updateGraphMode: visualization widget not found";
239 return;
240 return;
240 }
241 }
241
242
242 auto event = m_Model->getEvent(selectedRows.first());
243 auto event = m_Model->getEvent(selectedRows.first());
243 if (!event) {
244 if (!event) {
244 // A event product is probably selected
245 // A event product is probably selected
245 qCInfo(LOG_CatalogueEventsWidget()) << "updateGraphMode: no events are selected";
246 qCInfo(LOG_CatalogueEventsWidget()) << "updateGraphMode: no events are selected";
246 return;
247 return;
247 }
248 }
248
249
249 auto tab = m_VisualizationWidget->currentTabWidget();
250 auto tab = m_VisualizationWidget->currentTabWidget();
250 if (!tab) {
251 if (!tab) {
251 qCWarning(LOG_CatalogueEventsWidget())
252 qCWarning(LOG_CatalogueEventsWidget())
252 << "updateGraphMode: no tab found in the visualization";
253 << "updateGraphMode: no tab found in the visualization";
253 return;
254 return;
254 }
255 }
255
256
256 auto zone = tab->getZoneWithName(m_ZoneForGraphMode);
257 auto zone = tab->getZoneWithName(m_ZoneForGraphMode);
257 if (!zone) {
258 if (!zone) {
258 qCWarning(LOG_CatalogueEventsWidget()) << "updateGraphMode: zone not found";
259 qCWarning(LOG_CatalogueEventsWidget()) << "updateGraphMode: zone not found";
259 return;
260 return;
260 }
261 }
261
262
262 // Close the previous graph and delete the asociated variables
263 // Closes the previous graph and delete the asociated variables
263 for (auto graph : m_CustomGraphs) {
264 for (auto graph : m_CustomGraphs) {
264 graph->close();
265 graph->close();
265 auto variables = graph->variables().toVector();
266 auto variables = graph->variables().toVector();
266
267
267 QMetaObject::invokeMethod(&sqpApp->variableController(), "deleteVariables",
268 QMetaObject::invokeMethod(&sqpApp->variableController(), "deleteVariables",
268 Qt::QueuedConnection,
269 Qt::QueuedConnection,
269 Q_ARG(QVector<std::shared_ptr<Variable> >, variables));
270 Q_ARG(QVector<std::shared_ptr<Variable> >, variables));
270 }
271 }
271 m_CustomGraphs.clear();
272 m_CustomGraphs.clear();
272
273
274 // Closes the remaining graphs inside the zone
275 zone->closeAllGraphs();
276
273 // Calculates the range of each graph which will be created
277 // Calculates the range of each graph which will be created
274 auto graphRange = getGraphRanges(event);
278 auto graphRange = getGraphRanges(event);
275
279
276 // Loops through the event products and create the graph
280 // Loops through the event products and create the graph
277 auto itRange = graphRange.cbegin();
281 auto itRange = graphRange.cbegin();
278 for (auto eventProduct : event->getEventProducts()) {
282 for (auto eventProduct : event->getEventProducts()) {
279 auto productId = eventProduct.getProductId();
283 auto productId = eventProduct.getProductId();
280
284
281 auto range = *itRange;
285 auto range = *itRange;
282 ++itRange;
286 ++itRange;
283
287
284 SqpRange productRange;
288 SqpRange productRange;
285 productRange.m_TStart = eventProduct.getTStart();
289 productRange.m_TStart = eventProduct.getTStart();
286 productRange.m_TEnd = eventProduct.getTEnd();
290 productRange.m_TEnd = eventProduct.getTEnd();
287
291
288 auto context = new QObject{catalogueEventWidget};
292 auto context = new QObject{catalogueEventWidget};
289 QObject::connect(
293 QObject::connect(
290 &sqpApp->variableController(), &VariableController::variableAdded, context,
294 &sqpApp->variableController(), &VariableController::variableAdded, context,
291 [this, catalogueEventWidget, zone, context, event, range, productRange,
295 [this, catalogueEventWidget, zone, context, event, range, productRange,
292 productId](auto variable) {
296 productId](auto variable) {
293
297
294 if (variable->metadata().value(DataSourceItem::ID_DATA_KEY).toString()
298 if (variable->metadata().value(DataSourceItem::ID_DATA_KEY).toString()
295 == productId) {
299 == productId) {
296 auto graph = zone->createGraph(variable);
300 auto graph = zone->createGraph(variable);
297 graph->setAutoRangeOnVariableInitialization(false);
301 graph->setAutoRangeOnVariableInitialization(false);
298
302
299 auto selectionZone
303 auto selectionZone
300 = graph->addSelectionZone(event->getName(), productRange);
304 = graph->addSelectionZone(event->getName(), productRange);
301 emit catalogueEventWidget->selectionZoneAdded(event, productId,
305 emit catalogueEventWidget->selectionZoneAdded(event, productId,
302 selectionZone);
306 selectionZone);
303 m_CustomGraphs << graph;
307 m_CustomGraphs << graph;
304
308
305 graph->setGraphRange(range, true);
309 graph->setGraphRange(range, true);
306
310
307 // Removes the graph from the graph list if it is closed manually
311 // Removes the graph from the graph list if it is closed manually
308 QObject::connect(graph, &VisualizationGraphWidget::destroyed,
312 QObject::connect(graph, &VisualizationGraphWidget::destroyed,
309 [this, graph]() { m_CustomGraphs.removeAll(graph); });
313 [this, graph]() { m_CustomGraphs.removeAll(graph); });
310
314
311 delete context; // removes the connection
315 delete context; // removes the connection
312 }
316 }
313 },
317 },
314 Qt::QueuedConnection);
318 Qt::QueuedConnection);
315
319
316 QMetaObject::invokeMethod(&sqpApp->dataSourceController(),
320 QMetaObject::invokeMethod(&sqpApp->dataSourceController(),
317 "requestVariableFromProductIdKey", Qt::QueuedConnection,
321 "requestVariableFromProductIdKey", Qt::QueuedConnection,
318 Q_ARG(QString, productId));
322 Q_ARG(QString, productId));
319 }
323 }
320 }
324 }
321
325
322 void getSelectedItems(
326 void getSelectedItems(
323 QTreeView *treeView, QVector<std::shared_ptr<DBEvent> > &events,
327 QTreeView *treeView, QVector<std::shared_ptr<DBEvent> > &events,
324 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > &eventProducts)
328 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > &eventProducts)
325 {
329 {
326 for (auto rowIndex : treeView->selectionModel()->selectedRows()) {
330 for (auto rowIndex : treeView->selectionModel()->selectedRows()) {
327 auto itemType = m_Model->itemTypeOf(rowIndex);
331 auto itemType = m_Model->itemTypeOf(rowIndex);
328 if (itemType == CatalogueEventsModel::ItemType::Event) {
332 if (itemType == CatalogueEventsModel::ItemType::Event) {
329 events << m_Model->getEvent(rowIndex);
333 events << m_Model->getEvent(rowIndex);
330 }
334 }
331 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
335 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
332 eventProducts << qMakePair(m_Model->getParentEvent(rowIndex),
336 eventProducts << qMakePair(m_Model->getParentEvent(rowIndex),
333 m_Model->getEventProduct(rowIndex));
337 m_Model->getEventProduct(rowIndex));
334 }
338 }
335 }
339 }
336 }
340 }
337 };
341 };
338
342
339 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
343 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
340 : QWidget(parent),
344 : QWidget(parent),
341 ui(new Ui::CatalogueEventsWidget),
345 ui(new Ui::CatalogueEventsWidget),
342 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
346 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
343 {
347 {
344 ui->setupUi(this);
348 ui->setupUi(this);
345
349
346 impl->m_Model = new CatalogueEventsModel{this};
350 impl->m_Model = new CatalogueEventsModel{this};
347 ui->treeView->setModel(impl->m_Model);
351 ui->treeView->setModel(impl->m_Model);
348
352
349 ui->treeView->setSortingEnabled(true);
353 ui->treeView->setSortingEnabled(true);
350 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
354 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
351 ui->treeView->setDragEnabled(true);
355 ui->treeView->setDragEnabled(true);
352
356
353 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
357 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
354 if (checked) {
358 if (checked) {
355 ui->btnChart->setChecked(false);
359 ui->btnChart->setChecked(false);
356 impl->m_ZonesForTimeMode
360 impl->m_ZonesForTimeMode
357 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
361 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
358 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
362 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
359
363
360 impl->updateForTimeMode(ui->treeView);
364 impl->updateForTimeMode(ui->treeView);
361 }
365 }
362 });
366 });
363
367
364 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
368 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
365 if (checked) {
369 if (checked) {
366 ui->btnTime->setChecked(false);
370 ui->btnTime->setChecked(false);
367 impl->m_ZoneForGraphMode
371 impl->m_ZoneForGraphMode
368 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
372 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
369 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
373 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
370 .value(0);
374 .value(0);
371
375
372 impl->updateForGraphMode(this);
376 impl->updateForGraphMode(this);
373 }
377 }
374 });
378 });
375
379
376 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
380 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
377 QVector<std::shared_ptr<DBEvent> > events;
381 QVector<std::shared_ptr<DBEvent> > events;
378 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
382 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
379 impl->getSelectedItems(ui->treeView, events, eventProducts);
383 impl->getSelectedItems(ui->treeView, events, eventProducts);
380
384
381 if (!events.isEmpty() && eventProducts.isEmpty()) {
385 if (!events.isEmpty() && eventProducts.isEmpty()) {
382
386
383 if (QMessageBox::warning(this, tr("Remove Event(s)"),
387 if (QMessageBox::warning(this, tr("Remove Event(s)"),
384 tr("The selected event(s) will be permanently removed "
388 tr("The selected event(s) will be permanently removed "
385 "from the repository!\nAre you sure you want to continue?"),
389 "from the repository!\nAre you sure you want to continue?"),
386 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
390 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
387 == QMessageBox::Yes) {
391 == QMessageBox::Yes) {
388
392
389 for (auto event : events) {
393 for (auto event : events) {
390 sqpApp->catalogueController().removeEvent(event);
394 sqpApp->catalogueController().removeEvent(event);
391 impl->removeEvent(event, ui->treeView);
395 impl->removeEvent(event, ui->treeView);
392 }
396 }
393
397
394 emit this->eventsRemoved(events);
398 emit this->eventsRemoved(events);
395 }
399 }
396 }
400 }
397 });
401 });
398
402
399 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueEventsWidget::emitSelection);
403 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueEventsWidget::emitSelection);
400 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
404 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
401 &CatalogueEventsWidget::emitSelection);
405 &CatalogueEventsWidget::emitSelection);
402
406
403 ui->btnRemove->setEnabled(false); // Disabled by default when nothing is selected
407 ui->btnRemove->setEnabled(false); // Disabled by default when nothing is selected
404 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
408 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
405 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
409 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
406 ui->btnChart->setEnabled(isNotMultiSelection);
410 ui->btnChart->setEnabled(isNotMultiSelection);
407 ui->btnTime->setEnabled(isNotMultiSelection);
411 ui->btnTime->setEnabled(isNotMultiSelection);
408
412
409 if (isNotMultiSelection && ui->btnTime->isChecked()) {
413 if (isNotMultiSelection && ui->btnTime->isChecked()) {
410 impl->updateForTimeMode(ui->treeView);
414 impl->updateForTimeMode(ui->treeView);
411 }
415 }
412 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
416 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
413 impl->updateForGraphMode(this);
417 impl->updateForGraphMode(this);
414 }
418 }
415
419
416 QVector<std::shared_ptr<DBEvent> > events;
420 QVector<std::shared_ptr<DBEvent> > events;
417 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
421 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
418 impl->getSelectedItems(ui->treeView, events, eventProducts);
422 impl->getSelectedItems(ui->treeView, events, eventProducts);
419 ui->btnRemove->setEnabled(!events.isEmpty() && eventProducts.isEmpty());
423 ui->btnRemove->setEnabled(!events.isEmpty() && eventProducts.isEmpty());
420 });
424 });
421
425
422 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
426 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
423 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Tags,
427 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Tags,
424 QHeaderView::Stretch);
428 QHeaderView::Stretch);
425 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
429 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
426 QHeaderView::Fixed);
430 QHeaderView::Fixed);
427 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
431 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
428 QHeaderView::Interactive);
432 QHeaderView::Interactive);
429 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
433 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
430 VALIDATION_COLUMN_SIZE);
434 VALIDATION_COLUMN_SIZE);
431 ui->treeView->header()->setSortIndicatorShown(true);
435 ui->treeView->header()->setSortIndicatorShown(true);
432
436
433 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
437 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
434 auto allEvents = impl->m_Model->events();
438 auto allEvents = impl->m_Model->events();
435 for (auto event : allEvents) {
439 for (auto event : allEvents) {
436 setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event));
440 setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event));
437 }
441 }
438 });
442 });
439
443
440 populateWithAllEvents();
444 populateWithAllEvents();
441 }
445 }
442
446
443 CatalogueEventsWidget::~CatalogueEventsWidget()
447 CatalogueEventsWidget::~CatalogueEventsWidget()
444 {
448 {
445 delete ui;
449 delete ui;
446 }
450 }
447
451
448 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
452 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
449 {
453 {
450 impl->m_VisualizationWidget = visualization;
454 impl->m_VisualizationWidget = visualization;
451 }
455 }
452
456
453 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
457 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
454 {
458 {
455 impl->addEvent(event, ui->treeView);
459 impl->addEvent(event, ui->treeView);
456 }
460 }
457
461
458 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
462 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
459 {
463 {
460 impl->m_Model->refreshEvent(event);
464 impl->m_Model->refreshEvent(event);
461
465
462 auto eventIndex = impl->m_Model->indexOf(event);
466 auto eventIndex = impl->m_Model->indexOf(event);
463 auto validationIndex
467 auto validationIndex
464 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
468 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
465
469
466 if (validationIndex.isValid()) {
470 if (validationIndex.isValid()) {
467 if (hasChanges) {
471 if (hasChanges) {
468 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
472 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
469 auto widget = CatalogueExplorerHelper::buildValidationWidget(
473 auto widget = CatalogueExplorerHelper::buildValidationWidget(
470 ui->treeView,
474 ui->treeView,
471 [this, event]() {
475 [this, event]() {
472 sqpApp->catalogueController().saveEvent(event);
476 sqpApp->catalogueController().saveEvent(event);
473 setEventChanges(event, false);
477 setEventChanges(event, false);
474 },
478 },
475 [this, event]() {
479 [this, event]() {
476 bool removed = false;
480 bool removed = false;
477 sqpApp->catalogueController().discardEvent(event, removed);
481 sqpApp->catalogueController().discardEvent(event, removed);
478 if (removed) {
482 if (removed) {
479 impl->m_Model->removeEvent(event);
483 impl->m_Model->removeEvent(event);
480 }
484 }
481 else {
485 else {
482 setEventChanges(event, false);
486 setEventChanges(event, false);
483 impl->m_Model->refreshEvent(event, true);
487 impl->m_Model->refreshEvent(event, true);
484 }
488 }
485 emitSelection();
489 emitSelection();
486 });
490 });
487 ui->treeView->setIndexWidget(validationIndex, widget);
491 ui->treeView->setIndexWidget(validationIndex, widget);
488 }
492 }
489 }
493 }
490 else {
494 else {
491 // Note: the widget is destroyed
495 // Note: the widget is destroyed
492 ui->treeView->setIndexWidget(validationIndex, nullptr);
496 ui->treeView->setIndexWidget(validationIndex, nullptr);
493 }
497 }
494 }
498 }
495 else {
499 else {
496 qCWarning(LOG_CatalogueEventsWidget())
500 qCWarning(LOG_CatalogueEventsWidget())
497 << "setEventChanges: the event is not displayed in the model.";
501 << "setEventChanges: the event is not displayed in the model.";
498 }
502 }
499 }
503 }
500
504
501 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
505 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
502 {
506 {
503 return impl->m_DisplayedCatalogues;
507 return impl->m_DisplayedCatalogues;
504 }
508 }
505
509
506 bool CatalogueEventsWidget::isAllEventsDisplayed() const
510 bool CatalogueEventsWidget::isAllEventsDisplayed() const
507 {
511 {
508 return impl->m_AllEventDisplayed;
512 return impl->m_AllEventDisplayed;
509 }
513 }
510
514
511 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
515 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
512 {
516 {
513 return impl->m_Model->indexOf(event).isValid();
517 return impl->m_Model->indexOf(event).isValid();
514 }
518 }
515
519
516 void CatalogueEventsWidget::refreshEvent(const std::shared_ptr<DBEvent> &event)
520 void CatalogueEventsWidget::refreshEvent(const std::shared_ptr<DBEvent> &event)
517 {
521 {
518 impl->m_Model->refreshEvent(event, true);
522 impl->m_Model->refreshEvent(event, true);
519 }
523 }
520
524
521 void CatalogueEventsWidget::populateWithCatalogues(
525 void CatalogueEventsWidget::populateWithCatalogues(
522 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
526 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
523 {
527 {
524 impl->m_DisplayedCatalogues = catalogues;
528 impl->m_DisplayedCatalogues = catalogues;
525 impl->m_AllEventDisplayed = false;
529 impl->m_AllEventDisplayed = false;
526
530
527 QSet<QUuid> eventIds;
531 QSet<QUuid> eventIds;
528 QVector<std::shared_ptr<DBEvent> > events;
532 QVector<std::shared_ptr<DBEvent> > events;
529
533
530 for (auto catalogue : catalogues) {
534 for (auto catalogue : catalogues) {
531 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
535 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
532 for (auto event : catalogueEvents) {
536 for (auto event : catalogueEvents) {
533 if (!eventIds.contains(event->getUniqId())) {
537 if (!eventIds.contains(event->getUniqId())) {
534 events << event;
538 events << event;
535 eventIds.insert(event->getUniqId());
539 eventIds.insert(event->getUniqId());
536 }
540 }
537 }
541 }
538 }
542 }
539
543
540 impl->setEvents(events, this);
544 impl->setEvents(events, this);
541 }
545 }
542
546
543 void CatalogueEventsWidget::populateWithAllEvents()
547 void CatalogueEventsWidget::populateWithAllEvents()
544 {
548 {
545 impl->m_DisplayedCatalogues.clear();
549 impl->m_DisplayedCatalogues.clear();
546 impl->m_AllEventDisplayed = true;
550 impl->m_AllEventDisplayed = true;
547
551
548 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
552 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
549
553
550 QVector<std::shared_ptr<DBEvent> > events;
554 QVector<std::shared_ptr<DBEvent> > events;
551 for (auto event : allEvents) {
555 for (auto event : allEvents) {
552 events << event;
556 events << event;
553 }
557 }
554
558
555 impl->setEvents(events, this);
559 impl->setEvents(events, this);
556 }
560 }
557
561
558 void CatalogueEventsWidget::clear()
562 void CatalogueEventsWidget::clear()
559 {
563 {
560 impl->m_DisplayedCatalogues.clear();
564 impl->m_DisplayedCatalogues.clear();
561 impl->m_AllEventDisplayed = false;
565 impl->m_AllEventDisplayed = false;
562 impl->setEvents({}, this);
566 impl->setEvents({}, this);
563 }
567 }
564
568
565 void CatalogueEventsWidget::refresh()
569 void CatalogueEventsWidget::refresh()
566 {
570 {
567 if (isAllEventsDisplayed()) {
571 if (isAllEventsDisplayed()) {
568 populateWithAllEvents();
572 populateWithAllEvents();
569 }
573 }
570 else if (!impl->m_DisplayedCatalogues.isEmpty()) {
574 else if (!impl->m_DisplayedCatalogues.isEmpty()) {
571 populateWithCatalogues(impl->m_DisplayedCatalogues);
575 populateWithCatalogues(impl->m_DisplayedCatalogues);
572 }
576 }
573 }
577 }
574
578
575 void CatalogueEventsWidget::emitSelection()
579 void CatalogueEventsWidget::emitSelection()
576 {
580 {
577 QVector<std::shared_ptr<DBEvent> > events;
581 QVector<std::shared_ptr<DBEvent> > events;
578 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
582 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
579 impl->getSelectedItems(ui->treeView, events, eventProducts);
583 impl->getSelectedItems(ui->treeView, events, eventProducts);
580
584
581 if (!events.isEmpty() && eventProducts.isEmpty()) {
585 if (!events.isEmpty() && eventProducts.isEmpty()) {
582 emit eventsSelected(events);
586 emit eventsSelected(events);
583 }
587 }
584 else if (events.isEmpty() && !eventProducts.isEmpty()) {
588 else if (events.isEmpty() && !eventProducts.isEmpty()) {
585 emit eventProductsSelected(eventProducts);
589 emit eventProductsSelected(eventProducts);
586 }
590 }
587 else {
591 else {
588 emit selectionCleared();
592 emit selectionCleared();
589 }
593 }
590 }
594 }
@@ -1,414 +1,429
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 <ComparaisonPredicate.h>
12 #include <ComparaisonPredicate.h>
12 #include <DBCatalogue.h>
13 #include <DBCatalogue.h>
13
14
14 #include <QMenu>
15 #include <QMenu>
15 #include <QMessageBox>
16 #include <QMessageBox>
17 #include <QMimeData>
16
18
17 Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
19 Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
18
20
19
21
20 constexpr auto ALL_EVENT_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 1;
22 constexpr auto ALL_EVENT_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 1;
21 constexpr auto TRASH_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 2;
23 constexpr auto TRASH_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 2;
22 constexpr auto CATALOGUE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 3;
24 constexpr auto CATALOGUE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 3;
23 constexpr auto DATABASE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 4;
25 constexpr auto DATABASE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 4;
24
26
25
27
26 struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
28 struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
27
29
28 CatalogueTreeModel *m_TreeModel = nullptr;
30 CatalogueTreeModel *m_TreeModel = nullptr;
29
31
30 void configureTreeWidget(QTreeView *treeView);
32 void configureTreeWidget(QTreeView *treeView);
31 QModelIndex addDatabaseItem(const QString &name);
33 QModelIndex addDatabaseItem(const QString &name);
32 CatalogueAbstractTreeItem *getDatabaseItem(const QString &name);
34 CatalogueAbstractTreeItem *getDatabaseItem(const QString &name);
33 CatalogueAbstractTreeItem *addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
35 CatalogueAbstractTreeItem *addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
34 const QModelIndex &databaseIndex);
36 const QModelIndex &databaseIndex);
35
37
36 CatalogueTreeItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue) const;
38 CatalogueTreeItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue) const;
37 void setHasChanges(bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget);
39 void setHasChanges(bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget);
38 bool hasChanges(const QModelIndex &index, QTreeView *treeView);
40 bool hasChanges(const QModelIndex &index, QTreeView *treeView);
39
41
40 int selectionType(QTreeView *treeView) const
42 int selectionType(QTreeView *treeView) const
41 {
43 {
42 auto selectedItems = treeView->selectionModel()->selectedRows();
44 auto selectedItems = treeView->selectionModel()->selectedRows();
43 if (selectedItems.isEmpty()) {
45 if (selectedItems.isEmpty()) {
44 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
46 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
45 }
47 }
46 else {
48 else {
47 auto firstIndex = selectedItems.first();
49 auto firstIndex = selectedItems.first();
48 auto firstItem = m_TreeModel->item(firstIndex);
50 auto firstItem = m_TreeModel->item(firstIndex);
49 if (!firstItem) {
51 if (!firstItem) {
50 Q_ASSERT(false);
52 Q_ASSERT(false);
51 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
53 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
52 }
54 }
53 auto selectionType = firstItem->type();
55 auto selectionType = firstItem->type();
54
56
55 for (auto itemIndex : selectedItems) {
57 for (auto itemIndex : selectedItems) {
56 auto item = m_TreeModel->item(itemIndex);
58 auto item = m_TreeModel->item(itemIndex);
57 if (!item || item->type() != selectionType) {
59 if (!item || item->type() != selectionType) {
58 // Incoherent multi selection
60 // Incoherent multi selection
59 selectionType = CatalogueAbstractTreeItem::DEFAULT_TYPE;
61 selectionType = CatalogueAbstractTreeItem::DEFAULT_TYPE;
60 break;
62 break;
61 }
63 }
62 }
64 }
63
65
64 return selectionType;
66 return selectionType;
65 }
67 }
66 }
68 }
67
69
68 QVector<std::shared_ptr<DBCatalogue> > selectedCatalogues(QTreeView *treeView) const
70 QVector<std::shared_ptr<DBCatalogue> > selectedCatalogues(QTreeView *treeView) const
69 {
71 {
70 QVector<std::shared_ptr<DBCatalogue> > catalogues;
72 QVector<std::shared_ptr<DBCatalogue> > catalogues;
71 auto selectedItems = treeView->selectionModel()->selectedRows();
73 auto selectedItems = treeView->selectionModel()->selectedRows();
72 for (auto itemIndex : selectedItems) {
74 for (auto itemIndex : selectedItems) {
73 auto item = m_TreeModel->item(itemIndex);
75 auto item = m_TreeModel->item(itemIndex);
74 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
76 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
75 catalogues.append(static_cast<CatalogueTreeItem *>(item)->catalogue());
77 catalogues.append(static_cast<CatalogueTreeItem *>(item)->catalogue());
76 }
78 }
77 }
79 }
78
80
79 return catalogues;
81 return catalogues;
80 }
82 }
81
83
82 QStringList selectedRepositories(QTreeView *treeView) const
84 QStringList selectedRepositories(QTreeView *treeView) const
83 {
85 {
84 QStringList repositories;
86 QStringList repositories;
85 auto selectedItems = treeView->selectionModel()->selectedRows();
87 auto selectedItems = treeView->selectionModel()->selectedRows();
86 for (auto itemIndex : selectedItems) {
88 for (auto itemIndex : selectedItems) {
87 auto item = m_TreeModel->item(itemIndex);
89 auto item = m_TreeModel->item(itemIndex);
88 if (item && item->type() == DATABASE_ITEM_TYPE) {
90 if (item && item->type() == DATABASE_ITEM_TYPE) {
89 repositories.append(item->text());
91 repositories.append(item->text());
90 }
92 }
91 }
93 }
92
94
93 return repositories;
95 return repositories;
94 }
96 }
95 };
97 };
96
98
97 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
99 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
98 : QWidget(parent),
100 : QWidget(parent),
99 ui(new Ui::CatalogueSideBarWidget),
101 ui(new Ui::CatalogueSideBarWidget),
100 impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
102 impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
101 {
103 {
102 ui->setupUi(this);
104 ui->setupUi(this);
103
105
104 impl->m_TreeModel = new CatalogueTreeModel(this);
106 impl->m_TreeModel = new CatalogueTreeModel(this);
105 ui->treeView->setModel(impl->m_TreeModel);
107 ui->treeView->setModel(impl->m_TreeModel);
106
108
107 impl->configureTreeWidget(ui->treeView);
109 impl->configureTreeWidget(ui->treeView);
108
110
109 ui->treeView->header()->setStretchLastSection(false);
111 ui->treeView->header()->setStretchLastSection(false);
110 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
112 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
111 ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
113 ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
112
114
113 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueSideBarWidget::emitSelection);
115 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueSideBarWidget::emitSelection);
114 connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, this,
116 connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, this,
115 &CatalogueSideBarWidget::emitSelection);
117 &CatalogueSideBarWidget::emitSelection);
116
118
117
119
118 connect(ui->btnAdd, &QToolButton::clicked, [this]() {
120 connect(ui->btnAdd, &QToolButton::clicked, [this]() {
119 auto catalogue = std::make_shared<DBCatalogue>();
121 auto catalogue = std::make_shared<DBCatalogue>();
120 catalogue->setName(QString("Cat"));
122 catalogue->setName(QString("Cat"));
121 sqpApp->catalogueController().addCatalogue(catalogue);
123 sqpApp->catalogueController().addCatalogue(catalogue);
122 auto item = this->addCatalogue(catalogue, REPOSITORY_DEFAULT);
124 auto item = this->addCatalogue(catalogue, REPOSITORY_DEFAULT);
123 this->setCatalogueChanges(catalogue, true);
125 this->setCatalogueChanges(catalogue, true);
124 ui->treeView->edit(impl->m_TreeModel->indexOf(item));
126 ui->treeView->edit(impl->m_TreeModel->indexOf(item));
125
127
126 });
128 });
127
129
128
130
129 connect(impl->m_TreeModel, &CatalogueTreeModel::itemDropped, [this](auto index) {
131 connect(impl->m_TreeModel, &CatalogueTreeModel::itemDropped,
132 [this](auto index, auto mimeData, auto action) {
130 auto item = impl->m_TreeModel->item(index);
133 auto item = impl->m_TreeModel->item(index);
131 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
134 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
132 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
135 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
133 this->setCatalogueChanges(catalogue, true);
136 this->setCatalogueChanges(catalogue, true);
134 }
137 }
138
139 if (action == Qt::MoveAction) {
140 /// Display a save button on source catalogues
141 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
142 mimeData->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
143 for (auto catalogue : sourceCatalogues) {
144 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
145 this->setCatalogueChanges(catalogue, true);
146 }
147 }
148 }
135 });
149 });
150
136 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
151 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
137 QVector<QPair<std::shared_ptr<DBCatalogue>, CatalogueAbstractTreeItem *> >
152 QVector<QPair<std::shared_ptr<DBCatalogue>, CatalogueAbstractTreeItem *> >
138 cataloguesToItems;
153 cataloguesToItems;
139 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
154 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
140
155
141 for (auto index : selectedIndexes) {
156 for (auto index : selectedIndexes) {
142 auto item = impl->m_TreeModel->item(index);
157 auto item = impl->m_TreeModel->item(index);
143 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
158 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
144 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
159 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
145 cataloguesToItems << qMakePair(catalogue, item);
160 cataloguesToItems << qMakePair(catalogue, item);
146 }
161 }
147 }
162 }
148
163
149 if (!cataloguesToItems.isEmpty()) {
164 if (!cataloguesToItems.isEmpty()) {
150
165
151 if (QMessageBox::warning(this, tr("Remove Catalogue(s)"),
166 if (QMessageBox::warning(this, tr("Remove Catalogue(s)"),
152 tr("The selected catalogues(s) will be completly removed "
167 tr("The selected catalogues(s) will be completly removed "
153 "from the repository!\nAre you sure you want to continue?"),
168 "from the repository!\nAre you sure you want to continue?"),
154 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
169 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
155 == QMessageBox::Yes) {
170 == QMessageBox::Yes) {
156
171
157 for (auto catalogueToItem : cataloguesToItems) {
172 for (auto catalogueToItem : cataloguesToItems) {
158 sqpApp->catalogueController().removeCatalogue(catalogueToItem.first);
173 sqpApp->catalogueController().removeCatalogue(catalogueToItem.first);
159 impl->m_TreeModel->removeChildItem(
174 impl->m_TreeModel->removeChildItem(
160 catalogueToItem.second,
175 catalogueToItem.second,
161 impl->m_TreeModel->indexOf(catalogueToItem.second->parent()));
176 impl->m_TreeModel->indexOf(catalogueToItem.second->parent()));
162 }
177 }
163 }
178 }
164 }
179 }
165 });
180 });
166
181
167 connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [this](auto index) {
182 connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [this](auto index) {
168 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
183 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
169 if (selectedIndexes.contains(index)) {
184 if (selectedIndexes.contains(index)) {
170 this->emitSelection();
185 this->emitSelection();
171 }
186 }
172 impl->setHasChanges(true, index, this);
187 impl->setHasChanges(true, index, this);
173 });
188 });
174
189
175 ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
190 ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
176 connect(ui->treeView, &QTreeView::customContextMenuRequested, this,
191 connect(ui->treeView, &QTreeView::customContextMenuRequested, this,
177 &CatalogueSideBarWidget::onContextMenuRequested);
192 &CatalogueSideBarWidget::onContextMenuRequested);
178 }
193 }
179
194
180 CatalogueSideBarWidget::~CatalogueSideBarWidget()
195 CatalogueSideBarWidget::~CatalogueSideBarWidget()
181 {
196 {
182 delete ui;
197 delete ui;
183 }
198 }
184
199
185 CatalogueAbstractTreeItem *
200 CatalogueAbstractTreeItem *
186 CatalogueSideBarWidget::addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
201 CatalogueSideBarWidget::addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
187 const QString &repository)
202 const QString &repository)
188 {
203 {
189 auto repositoryItem = impl->getDatabaseItem(repository);
204 auto repositoryItem = impl->getDatabaseItem(repository);
190 return impl->addCatalogueItem(catalogue, impl->m_TreeModel->indexOf(repositoryItem));
205 return impl->addCatalogueItem(catalogue, impl->m_TreeModel->indexOf(repositoryItem));
191 }
206 }
192
207
193 void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
208 void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
194 bool hasChanges)
209 bool hasChanges)
195 {
210 {
196 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
211 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
197 auto index = impl->m_TreeModel->indexOf(catalogueItem);
212 auto index = impl->m_TreeModel->indexOf(catalogueItem);
198 impl->setHasChanges(hasChanges, index, this);
213 impl->setHasChanges(hasChanges, index, this);
199 // catalogueItem->refresh();
214 // catalogueItem->refresh();
200 }
215 }
201 }
216 }
202
217
203 QVector<std::shared_ptr<DBCatalogue> >
218 QVector<std::shared_ptr<DBCatalogue> >
204 CatalogueSideBarWidget::getCatalogues(const QString &repository) const
219 CatalogueSideBarWidget::getCatalogues(const QString &repository) const
205 {
220 {
206 QVector<std::shared_ptr<DBCatalogue> > result;
221 QVector<std::shared_ptr<DBCatalogue> > result;
207 auto repositoryItem = impl->getDatabaseItem(repository);
222 auto repositoryItem = impl->getDatabaseItem(repository);
208 for (auto child : repositoryItem->children()) {
223 for (auto child : repositoryItem->children()) {
209 if (child->type() == CATALOGUE_ITEM_TYPE) {
224 if (child->type() == CATALOGUE_ITEM_TYPE) {
210 auto catalogueItem = static_cast<CatalogueTreeItem *>(child);
225 auto catalogueItem = static_cast<CatalogueTreeItem *>(child);
211 result << catalogueItem->catalogue();
226 result << catalogueItem->catalogue();
212 }
227 }
213 else {
228 else {
214 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogues: invalid structure";
229 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogues: invalid structure";
215 }
230 }
216 }
231 }
217
232
218 return result;
233 return result;
219 }
234 }
220
235
221 void CatalogueSideBarWidget::emitSelection()
236 void CatalogueSideBarWidget::emitSelection()
222 {
237 {
223 auto selectionType = impl->selectionType(ui->treeView);
238 auto selectionType = impl->selectionType(ui->treeView);
224
239
225 switch (selectionType) {
240 switch (selectionType) {
226 case CATALOGUE_ITEM_TYPE:
241 case CATALOGUE_ITEM_TYPE:
227 emit this->catalogueSelected(impl->selectedCatalogues(ui->treeView));
242 emit this->catalogueSelected(impl->selectedCatalogues(ui->treeView));
228 break;
243 break;
229 case DATABASE_ITEM_TYPE:
244 case DATABASE_ITEM_TYPE:
230 emit this->databaseSelected(impl->selectedRepositories(ui->treeView));
245 emit this->databaseSelected(impl->selectedRepositories(ui->treeView));
231 break;
246 break;
232 case ALL_EVENT_ITEM_TYPE:
247 case ALL_EVENT_ITEM_TYPE:
233 emit this->allEventsSelected();
248 emit this->allEventsSelected();
234 break;
249 break;
235 case TRASH_ITEM_TYPE:
250 case TRASH_ITEM_TYPE:
236 emit this->trashSelected();
251 emit this->trashSelected();
237 break;
252 break;
238 default:
253 default:
239 emit this->selectionCleared();
254 emit this->selectionCleared();
240 break;
255 break;
241 }
256 }
242 }
257 }
243
258
244 void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
259 void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
245 {
260 {
246 QMenu menu{this};
261 QMenu menu{this};
247
262
248 auto currentIndex = ui->treeView->currentIndex();
263 auto currentIndex = ui->treeView->currentIndex();
249 auto currentItem = impl->m_TreeModel->item(currentIndex);
264 auto currentItem = impl->m_TreeModel->item(currentIndex);
250 if (!currentItem) {
265 if (!currentItem) {
251 return;
266 return;
252 }
267 }
253
268
254 switch (currentItem->type()) {
269 switch (currentItem->type()) {
255 case CATALOGUE_ITEM_TYPE:
270 case CATALOGUE_ITEM_TYPE:
256 menu.addAction("Rename", [this, currentIndex]() { ui->treeView->edit(currentIndex); });
271 menu.addAction("Rename", [this, currentIndex]() { ui->treeView->edit(currentIndex); });
257 break;
272 break;
258 case DATABASE_ITEM_TYPE:
273 case DATABASE_ITEM_TYPE:
259 break;
274 break;
260 case ALL_EVENT_ITEM_TYPE:
275 case ALL_EVENT_ITEM_TYPE:
261 break;
276 break;
262 case TRASH_ITEM_TYPE:
277 case TRASH_ITEM_TYPE:
263 menu.addAction("Empty Trash", []() {
278 menu.addAction("Empty Trash", []() {
264 // TODO
279 // TODO
265 });
280 });
266 break;
281 break;
267 default:
282 default:
268 break;
283 break;
269 }
284 }
270
285
271 if (!menu.isEmpty()) {
286 if (!menu.isEmpty()) {
272 menu.exec(ui->treeView->mapToGlobal(pos));
287 menu.exec(ui->treeView->mapToGlobal(pos));
273 }
288 }
274 }
289 }
275
290
276 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(QTreeView *treeView)
291 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(QTreeView *treeView)
277 {
292 {
278 auto allEventsItem = new CatalogueTextTreeItem{QIcon{":/icones/allEvents.png"}, "All Events",
293 auto allEventsItem = new CatalogueTextTreeItem{QIcon{":/icones/allEvents.png"}, "All Events",
279 ALL_EVENT_ITEM_TYPE};
294 ALL_EVENT_ITEM_TYPE};
280 auto allEventIndex = m_TreeModel->addTopLevelItem(allEventsItem);
295 auto allEventIndex = m_TreeModel->addTopLevelItem(allEventsItem);
281 treeView->setCurrentIndex(allEventIndex);
296 treeView->setCurrentIndex(allEventIndex);
282
297
283 auto trashItem
298 auto trashItem
284 = new CatalogueTextTreeItem{QIcon{":/icones/trash.png"}, "Trash", TRASH_ITEM_TYPE};
299 = new CatalogueTextTreeItem{QIcon{":/icones/trash.png"}, "Trash", TRASH_ITEM_TYPE};
285 m_TreeModel->addTopLevelItem(trashItem);
300 m_TreeModel->addTopLevelItem(trashItem);
286
301
287 auto separator = new QFrame{treeView};
302 auto separator = new QFrame{treeView};
288 separator->setFrameShape(QFrame::HLine);
303 separator->setFrameShape(QFrame::HLine);
289 auto separatorItem
304 auto separatorItem
290 = new CatalogueTextTreeItem{QIcon{}, QString{}, CatalogueAbstractTreeItem::DEFAULT_TYPE};
305 = new CatalogueTextTreeItem{QIcon{}, QString{}, CatalogueAbstractTreeItem::DEFAULT_TYPE};
291 separatorItem->setEnabled(false);
306 separatorItem->setEnabled(false);
292 auto separatorIndex = m_TreeModel->addTopLevelItem(separatorItem);
307 auto separatorIndex = m_TreeModel->addTopLevelItem(separatorItem);
293 treeView->setIndexWidget(separatorIndex, separator);
308 treeView->setIndexWidget(separatorIndex, separator);
294
309
295 auto repositories = sqpApp->catalogueController().getRepositories();
310 auto repositories = sqpApp->catalogueController().getRepositories();
296 for (auto dbname : repositories) {
311 for (auto dbname : repositories) {
297 auto dbIndex = addDatabaseItem(dbname);
312 auto dbIndex = addDatabaseItem(dbname);
298 auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname);
313 auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname);
299 for (auto catalogue : catalogues) {
314 for (auto catalogue : catalogues) {
300 addCatalogueItem(catalogue, dbIndex);
315 addCatalogueItem(catalogue, dbIndex);
301 }
316 }
302 }
317 }
303
318
304 treeView->expandAll();
319 treeView->expandAll();
305 }
320 }
306
321
307 QModelIndex
322 QModelIndex
308 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name)
323 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name)
309 {
324 {
310 auto databaseItem
325 auto databaseItem
311 = new CatalogueTextTreeItem{QIcon{":/icones/database.png"}, {name}, DATABASE_ITEM_TYPE};
326 = new CatalogueTextTreeItem{QIcon{":/icones/database.png"}, {name}, DATABASE_ITEM_TYPE};
312 auto databaseIndex = m_TreeModel->addTopLevelItem(databaseItem);
327 auto databaseIndex = m_TreeModel->addTopLevelItem(databaseItem);
313
328
314 return databaseIndex;
329 return databaseIndex;
315 }
330 }
316
331
317 CatalogueAbstractTreeItem *
332 CatalogueAbstractTreeItem *
318 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name)
333 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name)
319 {
334 {
320 for (auto item : m_TreeModel->topLevelItems()) {
335 for (auto item : m_TreeModel->topLevelItems()) {
321 if (item->type() == DATABASE_ITEM_TYPE && item->text() == name) {
336 if (item->type() == DATABASE_ITEM_TYPE && item->text() == name) {
322 return item;
337 return item;
323 }
338 }
324 }
339 }
325
340
326 return nullptr;
341 return nullptr;
327 }
342 }
328
343
329 CatalogueAbstractTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
344 CatalogueAbstractTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
330 const std::shared_ptr<DBCatalogue> &catalogue, const QModelIndex &databaseIndex)
345 const std::shared_ptr<DBCatalogue> &catalogue, const QModelIndex &databaseIndex)
331 {
346 {
332 auto catalogueItem
347 auto catalogueItem
333 = new CatalogueTreeItem{catalogue, QIcon{":/icones/catalogue.png"}, CATALOGUE_ITEM_TYPE};
348 = new CatalogueTreeItem{catalogue, QIcon{":/icones/catalogue.png"}, CATALOGUE_ITEM_TYPE};
334 m_TreeModel->addChildItem(catalogueItem, databaseIndex);
349 m_TreeModel->addChildItem(catalogueItem, databaseIndex);
335
350
336 return catalogueItem;
351 return catalogueItem;
337 }
352 }
338
353
339 CatalogueTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
354 CatalogueTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
340 const std::shared_ptr<DBCatalogue> &catalogue) const
355 const std::shared_ptr<DBCatalogue> &catalogue) const
341 {
356 {
342 for (auto item : m_TreeModel->topLevelItems()) {
357 for (auto item : m_TreeModel->topLevelItems()) {
343 if (item->type() == DATABASE_ITEM_TYPE) {
358 if (item->type() == DATABASE_ITEM_TYPE) {
344 for (auto childItem : item->children()) {
359 for (auto childItem : item->children()) {
345 if (childItem->type() == CATALOGUE_ITEM_TYPE) {
360 if (childItem->type() == CATALOGUE_ITEM_TYPE) {
346 auto catalogueItem = static_cast<CatalogueTreeItem *>(childItem);
361 auto catalogueItem = static_cast<CatalogueTreeItem *>(childItem);
347 if (catalogueItem->catalogue() == catalogue) {
362 if (catalogueItem->catalogue()->getUniqId() == catalogue->getUniqId()) {
348 return catalogueItem;
363 return catalogueItem;
349 }
364 }
350 }
365 }
351 else {
366 else {
352 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
367 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
353 "structure. A database item should "
368 "structure. A database item should "
354 "only contain catalogues.";
369 "only contain catalogues.";
355 Q_ASSERT(false);
370 Q_ASSERT(false);
356 }
371 }
357 }
372 }
358 }
373 }
359 }
374 }
360
375
361 return nullptr;
376 return nullptr;
362 }
377 }
363
378
364 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(
379 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(
365 bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget)
380 bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget)
366 {
381 {
367 std::shared_ptr<DBCatalogue> catalogue = nullptr;
382 std::shared_ptr<DBCatalogue> catalogue = nullptr;
368 auto item = m_TreeModel->item(index);
383 auto item = m_TreeModel->item(index);
369 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
384 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
370 catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
385 catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
371 }
386 }
372
387
373 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
388 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
374 if (value) {
389 if (value) {
375 if (!hasChanges(validationIndex, sideBarWidget->ui->treeView)) {
390 if (!hasChanges(validationIndex, sideBarWidget->ui->treeView)) {
376 auto widget = CatalogueExplorerHelper::buildValidationWidget(
391 auto widget = CatalogueExplorerHelper::buildValidationWidget(
377 sideBarWidget->ui->treeView,
392 sideBarWidget->ui->treeView,
378 [this, validationIndex, sideBarWidget, catalogue]() {
393 [this, validationIndex, sideBarWidget, catalogue]() {
379 if (catalogue) {
394 if (catalogue) {
380 sqpApp->catalogueController().saveCatalogue(catalogue);
395 sqpApp->catalogueController().saveCatalogue(catalogue);
381 }
396 }
382 setHasChanges(false, validationIndex, sideBarWidget);
397 setHasChanges(false, validationIndex, sideBarWidget);
383 },
398 },
384 [this, validationIndex, sideBarWidget, catalogue, item]() {
399 [this, validationIndex, sideBarWidget, catalogue, item]() {
385 if (catalogue) {
400 if (catalogue) {
386 bool removed;
401 bool removed;
387 sqpApp->catalogueController().discardCatalogue(catalogue, removed);
402 sqpApp->catalogueController().discardCatalogue(catalogue, removed);
388
403
389 if (removed) {
404 if (removed) {
390 m_TreeModel->removeChildItem(item,
405 m_TreeModel->removeChildItem(item,
391 m_TreeModel->indexOf(item->parent()));
406 m_TreeModel->indexOf(item->parent()));
392 }
407 }
393 else {
408 else {
394 m_TreeModel->refresh(m_TreeModel->indexOf(item));
409 m_TreeModel->refresh(m_TreeModel->indexOf(item));
395 setHasChanges(false, validationIndex, sideBarWidget);
410 setHasChanges(false, validationIndex, sideBarWidget);
396 }
411 }
397 sideBarWidget->emitSelection();
412 sideBarWidget->emitSelection();
398 }
413 }
399 });
414 });
400 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, widget);
415 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, widget);
401 }
416 }
402 }
417 }
403 else {
418 else {
404 // Note: the widget is destroyed
419 // Note: the widget is destroyed
405 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, nullptr);
420 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, nullptr);
406 }
421 }
407 }
422 }
408
423
409 bool CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::hasChanges(const QModelIndex &index,
424 bool CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::hasChanges(const QModelIndex &index,
410 QTreeView *treeView)
425 QTreeView *treeView)
411 {
426 {
412 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
427 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
413 return treeView->indexWidget(validationIndex) != nullptr;
428 return treeView->indexWidget(validationIndex) != nullptr;
414 }
429 }
@@ -1,105 +1,129
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
80 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
81 data->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
82 for (auto catalogue : sourceCatalogues) {
83 if (catalogue->getUniqId() == impl->m_Catalogue->getUniqId()) {
84 return false;
85 }
86 }
87
79 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
88 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
80 auto canDrop = data->hasFormat(MIME_TYPE_EVENT_LIST);
89 auto canDrop = data->hasFormat(MIME_TYPE_EVENT_LIST);
81
90
82 for (auto event : events) {
91 for (auto event : events) {
83 canDrop &= (event->getRepository() == impl->m_Catalogue->getRepository());
92 canDrop &= (event->getRepository() == impl->m_Catalogue->getRepository());
84 }
93 }
94
85 return canDrop;
95 return canDrop;
86 }
96 }
87
97
88 bool CatalogueTreeItem::dropMimeData(const QMimeData *data, Qt::DropAction action)
98 bool CatalogueTreeItem::dropMimeData(const QMimeData *data, Qt::DropAction action)
89 {
99 {
90 Q_ASSERT(canDropMimeData(data, action));
100 Q_ASSERT(canDropMimeData(data, action));
91 // Warning: Check that the events aren't already in the catalogue
101 // Warning: Check that the events aren't already in the catalogue
92 // Also check for the repository !!!
102 // No need to check check for the repository: inter-repository drop is forbidden in
103 // canDropMimeData
93
104
94 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(
107 data->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
95
108
96 for (auto event : events) {
109 for (auto event : events) {
110
111 if (action == Qt::MoveAction) {
112 for (auto catalogue : sourceCatalogues) {
113 catalogue->removeEvent(event->getUniqId());
114 }
115 }
116
97 impl->m_Catalogue->addEvent(event->getUniqId());
117 impl->m_Catalogue->addEvent(event->getUniqId());
98 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
99 }
118 }
119
120 for (auto catalogue : sourceCatalogues) {
121 sqpApp->catalogueController().updateCatalogue(catalogue);
122 }
123 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
100 }
124 }
101
125
102 std::shared_ptr<DBCatalogue> CatalogueTreeItem::catalogue() const
126 std::shared_ptr<DBCatalogue> CatalogueTreeItem::catalogue() const
103 {
127 {
104 return impl->m_Catalogue;
128 return impl->m_Catalogue;
105 }
129 }
@@ -1,218 +1,219
1 #include "Catalogue/CatalogueTreeModel.h"
1 #include "Catalogue/CatalogueTreeModel.h"
2 #include <Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h>
2 #include <Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h>
3
3
4 #include <QMimeData>
4 #include <QMimeData>
5 #include <memory>
5 #include <memory>
6
6
7 #include <Common/MimeTypesDef.h>
7 #include <Common/MimeTypesDef.h>
8
8
9 struct CatalogueTreeModel::CatalogueTreeModelPrivate {
9 struct CatalogueTreeModel::CatalogueTreeModelPrivate {
10 std::unique_ptr<CatalogueAbstractTreeItem> m_RootItem = nullptr;
10 std::unique_ptr<CatalogueAbstractTreeItem> m_RootItem = nullptr;
11
11
12 CatalogueTreeModelPrivate() : m_RootItem{std::make_unique<CatalogueAbstractTreeItem>()} {}
12 CatalogueTreeModelPrivate() : m_RootItem{std::make_unique<CatalogueAbstractTreeItem>()} {}
13 };
13 };
14
14
15 CatalogueTreeModel::CatalogueTreeModel(QObject *parent)
15 CatalogueTreeModel::CatalogueTreeModel(QObject *parent)
16 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueTreeModelPrivate>()}
16 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueTreeModelPrivate>()}
17 {
17 {
18 }
18 }
19
19
20 QModelIndex CatalogueTreeModel::addTopLevelItem(CatalogueAbstractTreeItem *item)
20 QModelIndex CatalogueTreeModel::addTopLevelItem(CatalogueAbstractTreeItem *item)
21 {
21 {
22 auto nbTopLevelItems = impl->m_RootItem->children().count();
22 auto nbTopLevelItems = impl->m_RootItem->children().count();
23 beginInsertRows(QModelIndex(), nbTopLevelItems, nbTopLevelItems);
23 beginInsertRows(QModelIndex(), nbTopLevelItems, nbTopLevelItems);
24 impl->m_RootItem->addChild(item);
24 impl->m_RootItem->addChild(item);
25 endInsertRows();
25 endInsertRows();
26
26
27 emit dataChanged(QModelIndex(), QModelIndex());
27 emit dataChanged(QModelIndex(), QModelIndex());
28
28
29 return index(nbTopLevelItems, 0);
29 return index(nbTopLevelItems, 0);
30 }
30 }
31
31
32 QVector<CatalogueAbstractTreeItem *> CatalogueTreeModel::topLevelItems() const
32 QVector<CatalogueAbstractTreeItem *> CatalogueTreeModel::topLevelItems() const
33 {
33 {
34 return impl->m_RootItem->children();
34 return impl->m_RootItem->children();
35 }
35 }
36
36
37 void CatalogueTreeModel::addChildItem(CatalogueAbstractTreeItem *child,
37 void CatalogueTreeModel::addChildItem(CatalogueAbstractTreeItem *child,
38 const QModelIndex &parentIndex)
38 const QModelIndex &parentIndex)
39 {
39 {
40 auto parentItem = item(parentIndex);
40 auto parentItem = item(parentIndex);
41 int c = parentItem->children().count();
41 int c = parentItem->children().count();
42 beginInsertRows(parentIndex, c, c);
42 beginInsertRows(parentIndex, c, c);
43 parentItem->addChild(child);
43 parentItem->addChild(child);
44 endInsertRows();
44 endInsertRows();
45
45
46 emit dataChanged(parentIndex, parentIndex);
46 emit dataChanged(parentIndex, parentIndex);
47 }
47 }
48
48
49 void CatalogueTreeModel::removeChildItem(CatalogueAbstractTreeItem *child,
49 void CatalogueTreeModel::removeChildItem(CatalogueAbstractTreeItem *child,
50 const QModelIndex &parentIndex)
50 const QModelIndex &parentIndex)
51 {
51 {
52 auto parentItem = item(parentIndex);
52 auto parentItem = item(parentIndex);
53 int i = parentItem->children().indexOf(child);
53 int i = parentItem->children().indexOf(child);
54 beginRemoveRows(parentIndex, i, i);
54 beginRemoveRows(parentIndex, i, i);
55 parentItem->removeChild(child);
55 parentItem->removeChild(child);
56 endRemoveRows();
56 endRemoveRows();
57
57
58 emit dataChanged(parentIndex, parentIndex);
58 emit dataChanged(parentIndex, parentIndex);
59 }
59 }
60
60
61 void CatalogueTreeModel::refresh(const QModelIndex &index)
61 void CatalogueTreeModel::refresh(const QModelIndex &index)
62 {
62 {
63 emit dataChanged(index, index);
63 emit dataChanged(index, index);
64 }
64 }
65
65
66 CatalogueAbstractTreeItem *CatalogueTreeModel::item(const QModelIndex &index) const
66 CatalogueAbstractTreeItem *CatalogueTreeModel::item(const QModelIndex &index) const
67 {
67 {
68 return static_cast<CatalogueAbstractTreeItem *>(index.internalPointer());
68 return static_cast<CatalogueAbstractTreeItem *>(index.internalPointer());
69 }
69 }
70
70
71 QModelIndex CatalogueTreeModel::indexOf(CatalogueAbstractTreeItem *item, int column) const
71 QModelIndex CatalogueTreeModel::indexOf(CatalogueAbstractTreeItem *item, int column) const
72 {
72 {
73 auto parentItem = item->parent();
73 auto parentItem = item->parent();
74 if (!parentItem) {
74 if (!parentItem) {
75 return QModelIndex();
75 return QModelIndex();
76 }
76 }
77
77
78 auto row = parentItem->children().indexOf(item);
78 auto row = parentItem->children().indexOf(item);
79 return createIndex(row, column, item);
79 return createIndex(row, column, item);
80 }
80 }
81
81
82 QModelIndex CatalogueTreeModel::index(int row, int column, const QModelIndex &parent) const
82 QModelIndex CatalogueTreeModel::index(int row, int column, const QModelIndex &parent) const
83 {
83 {
84 if (column > 0) {
84 if (column > 0) {
85 int a = 0;
85 int a = 0;
86 }
86 }
87
87
88 if (!hasIndex(row, column, parent)) {
88 if (!hasIndex(row, column, parent)) {
89 return QModelIndex();
89 return QModelIndex();
90 }
90 }
91
91
92 CatalogueAbstractTreeItem *parentItem = nullptr;
92 CatalogueAbstractTreeItem *parentItem = nullptr;
93
93
94 if (!parent.isValid()) {
94 if (!parent.isValid()) {
95 parentItem = impl->m_RootItem.get();
95 parentItem = impl->m_RootItem.get();
96 }
96 }
97 else {
97 else {
98 parentItem = item(parent);
98 parentItem = item(parent);
99 }
99 }
100
100
101 auto childItem = parentItem->children().value(row);
101 auto childItem = parentItem->children().value(row);
102 if (childItem) {
102 if (childItem) {
103 return createIndex(row, column, childItem);
103 return createIndex(row, column, childItem);
104 }
104 }
105
105
106 return QModelIndex();
106 return QModelIndex();
107 }
107 }
108
108
109
109
110 QModelIndex CatalogueTreeModel::parent(const QModelIndex &index) const
110 QModelIndex CatalogueTreeModel::parent(const QModelIndex &index) const
111 {
111 {
112 if (!index.isValid()) {
112 if (!index.isValid()) {
113 return QModelIndex();
113 return QModelIndex();
114 }
114 }
115
115
116 auto childItem = item(index);
116 auto childItem = item(index);
117 auto parentItem = childItem->parent();
117 auto parentItem = childItem->parent();
118
118
119 if (parentItem == nullptr || parentItem->parent() == nullptr) {
119 if (parentItem == nullptr || parentItem->parent() == nullptr) {
120 return QModelIndex();
120 return QModelIndex();
121 }
121 }
122
122
123 auto row = parentItem->parent()->children().indexOf(parentItem);
123 auto row = parentItem->parent()->children().indexOf(parentItem);
124 return createIndex(row, 0, parentItem);
124 return createIndex(row, 0, parentItem);
125 }
125 }
126
126
127 int CatalogueTreeModel::rowCount(const QModelIndex &parent) const
127 int CatalogueTreeModel::rowCount(const QModelIndex &parent) const
128 {
128 {
129 CatalogueAbstractTreeItem *parentItem = nullptr;
129 CatalogueAbstractTreeItem *parentItem = nullptr;
130
130
131 if (!parent.isValid()) {
131 if (!parent.isValid()) {
132 parentItem = impl->m_RootItem.get();
132 parentItem = impl->m_RootItem.get();
133 }
133 }
134 else {
134 else {
135 parentItem = item(parent);
135 parentItem = item(parent);
136 }
136 }
137
137
138 return parentItem->children().count();
138 return parentItem->children().count();
139 }
139 }
140
140
141 int CatalogueTreeModel::columnCount(const QModelIndex &parent) const
141 int CatalogueTreeModel::columnCount(const QModelIndex &parent) const
142 {
142 {
143 return (int)Column::Count;
143 return (int)Column::Count;
144 }
144 }
145
145
146 Qt::ItemFlags CatalogueTreeModel::flags(const QModelIndex &index) const
146 Qt::ItemFlags CatalogueTreeModel::flags(const QModelIndex &index) const
147 {
147 {
148 auto treeItem = item(index);
148 auto treeItem = item(index);
149 if (treeItem) {
149 if (treeItem) {
150 return treeItem->flags(index.column());
150 return treeItem->flags(index.column());
151 }
151 }
152
152
153 return Qt::NoItemFlags;
153 return Qt::NoItemFlags;
154 }
154 }
155
155
156 QVariant CatalogueTreeModel::data(const QModelIndex &index, int role) const
156 QVariant CatalogueTreeModel::data(const QModelIndex &index, int role) const
157 {
157 {
158 auto treeItem = item(index);
158 auto treeItem = item(index);
159 if (treeItem) {
159 if (treeItem) {
160 return treeItem->data(index.column(), role);
160 return treeItem->data(index.column(), role);
161 }
161 }
162
162
163 return QModelIndex();
163 return QModelIndex();
164 }
164 }
165
165
166 bool CatalogueTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
166 bool CatalogueTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
167 {
167 {
168 auto treeItem = item(index);
168 auto treeItem = item(index);
169 if (treeItem) {
169 if (treeItem) {
170 auto result = treeItem->setData(index.column(), role, value);
170 auto result = treeItem->setData(index.column(), role, value);
171
171
172 if (result && index.column() == (int)Column::Name) {
172 if (result && index.column() == (int)Column::Name) {
173 emit itemRenamed(index);
173 emit itemRenamed(index);
174 }
174 }
175
175
176 return result;
176 return result;
177 }
177 }
178
178
179 return false;
179 return false;
180 }
180 }
181
181 bool CatalogueTreeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
182 bool CatalogueTreeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
182 int column, const QModelIndex &parent) const
183 int column, const QModelIndex &parent) const
183 {
184 {
184 auto draggedIndex = parent;
185 auto draggedIndex = parent;
185 auto draggedItem = item(draggedIndex);
186 auto draggedItem = item(draggedIndex);
186 if (draggedItem) {
187 if (draggedItem) {
187 return draggedItem->canDropMimeData(data, action);
188 return draggedItem->canDropMimeData(data, action);
188 }
189 }
189
190
190 return false;
191 return false;
191 }
192 }
192
193
193 bool CatalogueTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row,
194 bool CatalogueTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row,
194 int column, const QModelIndex &parent)
195 int column, const QModelIndex &parent)
195 {
196 {
196 bool result = false;
197 bool result = false;
197
198
198 auto draggedIndex = parent;
199 auto draggedIndex = parent;
199 auto draggedItem = item(draggedIndex);
200 auto draggedItem = item(draggedIndex);
200 if (draggedItem) {
201 if (draggedItem) {
201 result = draggedItem->dropMimeData(data, action);
202 result = draggedItem->dropMimeData(data, action);
202 if (result) {
203 if (result) {
203 emit itemDropped(draggedIndex);
204 emit itemDropped(draggedIndex, data, action);
204 }
205 }
205 }
206 }
206
207
207 return result;
208 return result;
208 }
209 }
209
210
210 Qt::DropActions CatalogueTreeModel::supportedDropActions() const
211 Qt::DropActions CatalogueTreeModel::supportedDropActions() const
211 {
212 {
212 return Qt::CopyAction | Qt::MoveAction;
213 return Qt::CopyAction | Qt::MoveAction;
213 }
214 }
214
215
215 QStringList CatalogueTreeModel::mimeTypes() const
216 QStringList CatalogueTreeModel::mimeTypes() const
216 {
217 {
217 return {MIME_TYPE_EVENT_LIST};
218 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_SOURCE_CATALOGUE_LIST};
218 }
219 }
@@ -1,652 +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())
274 << tr("TORM: Range before: ") << graphChild->graphRange();
274 << tr("TORM: Range before: ") << graphChild->graphRange();
275 qCDebug(LOG_VisualizationZoneWidget())
275 qCDebug(LOG_VisualizationZoneWidget())
276 << tr("TORM: Range after : ") << graphChildRange;
276 << tr("TORM: Range after : ") << 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()
340 {
341 processGraphs(*ui->dragDropContainer->layout(),
342 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
343 }
344
339 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
345 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
340 {
346 {
341 if (visitor) {
347 if (visitor) {
342 visitor->visitEnter(this);
348 visitor->visitEnter(this);
343
349
344 // 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
345 // action)
351 // action)
346 processGraphs(
352 processGraphs(
347 *ui->dragDropContainer->layout(),
353 *ui->dragDropContainer->layout(),
348 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
354 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
349
355
350 visitor->visitLeave(this);
356 visitor->visitLeave(this);
351 }
357 }
352 else {
358 else {
353 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");
354 }
360 }
355 }
361 }
356
362
357 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
363 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
358 {
364 {
359 // A tab can always accomodate a variable
365 // A tab can always accomodate a variable
360 Q_UNUSED(variable);
366 Q_UNUSED(variable);
361 return true;
367 return true;
362 }
368 }
363
369
364 bool VisualizationZoneWidget::contains(const Variable &variable) const
370 bool VisualizationZoneWidget::contains(const Variable &variable) const
365 {
371 {
366 Q_UNUSED(variable);
372 Q_UNUSED(variable);
367 return false;
373 return false;
368 }
374 }
369
375
370 QString VisualizationZoneWidget::name() const
376 QString VisualizationZoneWidget::name() const
371 {
377 {
372 return ui->zoneNameLabel->text();
378 return ui->zoneNameLabel->text();
373 }
379 }
374
380
375 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
381 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
376 {
382 {
377 Q_UNUSED(position);
383 Q_UNUSED(position);
378
384
379 auto mimeData = new QMimeData;
385 auto mimeData = new QMimeData;
380 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
386 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
381
387
382 if (auto firstGraph = this->firstGraph()) {
388 if (auto firstGraph = this->firstGraph()) {
383 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
389 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
384 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
390 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
385 }
391 }
386
392
387 return mimeData;
393 return mimeData;
388 }
394 }
389
395
390 bool VisualizationZoneWidget::isDragAllowed() const
396 bool VisualizationZoneWidget::isDragAllowed() const
391 {
397 {
392 return true;
398 return true;
393 }
399 }
394
400
395 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
401 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
396 const QPointF &plotPosition,
402 const QPointF &plotPosition,
397 VisualizationGraphWidget *graphWidget)
403 VisualizationGraphWidget *graphWidget)
398 {
404 {
399 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
405 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
400 VisualizationGraphWidget &processedGraph) {
406 VisualizationGraphWidget &processedGraph) {
401
407
402 switch (sqpApp->plotsCursorMode()) {
408 switch (sqpApp->plotsCursorMode()) {
403 case SqpApplication::PlotsCursorMode::Vertical:
409 case SqpApplication::PlotsCursorMode::Vertical:
404 processedGraph.removeHorizontalCursor();
410 processedGraph.removeHorizontalCursor();
405 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
411 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
406 break;
412 break;
407 case SqpApplication::PlotsCursorMode::Temporal:
413 case SqpApplication::PlotsCursorMode::Temporal:
408 processedGraph.addVerticalCursor(plotPosition.x());
414 processedGraph.addVerticalCursor(plotPosition.x());
409 processedGraph.removeHorizontalCursor();
415 processedGraph.removeHorizontalCursor();
410 break;
416 break;
411 case SqpApplication::PlotsCursorMode::Horizontal:
417 case SqpApplication::PlotsCursorMode::Horizontal:
412 processedGraph.removeVerticalCursor();
418 processedGraph.removeVerticalCursor();
413 if (&processedGraph == graphWidget) {
419 if (&processedGraph == graphWidget) {
414 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
420 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
415 }
421 }
416 else {
422 else {
417 processedGraph.removeHorizontalCursor();
423 processedGraph.removeHorizontalCursor();
418 }
424 }
419 break;
425 break;
420 case SqpApplication::PlotsCursorMode::Cross:
426 case SqpApplication::PlotsCursorMode::Cross:
421 if (&processedGraph == graphWidget) {
427 if (&processedGraph == graphWidget) {
422 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
428 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
423 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
429 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
424 }
430 }
425 else {
431 else {
426 processedGraph.removeHorizontalCursor();
432 processedGraph.removeHorizontalCursor();
427 processedGraph.removeVerticalCursor();
433 processedGraph.removeVerticalCursor();
428 }
434 }
429 break;
435 break;
430 case SqpApplication::PlotsCursorMode::NoCursor:
436 case SqpApplication::PlotsCursorMode::NoCursor:
431 processedGraph.removeHorizontalCursor();
437 processedGraph.removeHorizontalCursor();
432 processedGraph.removeVerticalCursor();
438 processedGraph.removeVerticalCursor();
433 break;
439 break;
434 }
440 }
435
441
436
442
437 });
443 });
438 }
444 }
439
445
440 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
446 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
441 {
447 {
442 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
448 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
443 processedGraph.removeHorizontalCursor();
449 processedGraph.removeHorizontalCursor();
444 processedGraph.removeVerticalCursor();
450 processedGraph.removeVerticalCursor();
445 });
451 });
446 }
452 }
447
453
448 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
454 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
449 {
455 {
450 // Closes graphs in the zone
456 // Closes graphs in the zone
451 processGraphs(*ui->dragDropContainer->layout(),
457 processGraphs(*ui->dragDropContainer->layout(),
452 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
458 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
453
459
454 // Delete synchronization group from variable controller
460 // Delete synchronization group from variable controller
455 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
461 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
456 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
462 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
457
463
458 QWidget::closeEvent(event);
464 QWidget::closeEvent(event);
459 }
465 }
460
466
461 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
467 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
462 {
468 {
463 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
469 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
464 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
470 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
465 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
471 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
466 }
472 }
467
473
468 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
474 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
469 {
475 {
470 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
476 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
471 Q_ARG(std::shared_ptr<Variable>, variable),
477 Q_ARG(std::shared_ptr<Variable>, variable),
472 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
478 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
473 }
479 }
474
480
475 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
481 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
476 {
482 {
477 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
483 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
478 impl->dropGraph(index, this);
484 impl->dropGraph(index, this);
479 }
485 }
480 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
486 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
481 auto variables = sqpApp->variableController().variablesForMimeData(
487 auto variables = sqpApp->variableController().variablesForMimeData(
482 mimeData->data(MIME_TYPE_VARIABLE_LIST));
488 mimeData->data(MIME_TYPE_VARIABLE_LIST));
483 impl->dropVariables(variables, index, this);
489 impl->dropVariables(variables, index, this);
484 }
490 }
485 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
491 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
486 auto products = sqpApp->dataSourceController().productsDataForMimeData(
492 auto products = sqpApp->dataSourceController().productsDataForMimeData(
487 mimeData->data(MIME_TYPE_PRODUCT_LIST));
493 mimeData->data(MIME_TYPE_PRODUCT_LIST));
488 impl->dropProducts(products, index, this);
494 impl->dropProducts(products, index, this);
489 }
495 }
490 else {
496 else {
491 qCWarning(LOG_VisualizationZoneWidget())
497 qCWarning(LOG_VisualizationZoneWidget())
492 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
498 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
493 }
499 }
494 }
500 }
495
501
496 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
502 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
497 const QMimeData *mimeData)
503 const QMimeData *mimeData)
498 {
504 {
499 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
505 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
500 if (!graphWidget) {
506 if (!graphWidget) {
501 qCWarning(LOG_VisualizationZoneWidget())
507 qCWarning(LOG_VisualizationZoneWidget())
502 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
508 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
503 "drop aborted");
509 "drop aborted");
504 Q_ASSERT(false);
510 Q_ASSERT(false);
505 return;
511 return;
506 }
512 }
507
513
508 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
514 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
509 auto variables = sqpApp->variableController().variablesForMimeData(
515 auto variables = sqpApp->variableController().variablesForMimeData(
510 mimeData->data(MIME_TYPE_VARIABLE_LIST));
516 mimeData->data(MIME_TYPE_VARIABLE_LIST));
511 for (const auto &var : variables) {
517 for (const auto &var : variables) {
512 graphWidget->addVariable(var, graphWidget->graphRange());
518 graphWidget->addVariable(var, graphWidget->graphRange());
513 }
519 }
514 }
520 }
515 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
521 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
516 auto products = sqpApp->dataSourceController().productsDataForMimeData(
522 auto products = sqpApp->dataSourceController().productsDataForMimeData(
517 mimeData->data(MIME_TYPE_PRODUCT_LIST));
523 mimeData->data(MIME_TYPE_PRODUCT_LIST));
518
524
519 auto context = new QObject{this};
525 auto context = new QObject{this};
520 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
526 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
521 [this, graphWidget, context](auto variable) {
527 [this, graphWidget, context](auto variable) {
522 graphWidget->addVariable(variable, graphWidget->graphRange());
528 graphWidget->addVariable(variable, graphWidget->graphRange());
523 delete context; // removes the connection
529 delete context; // removes the connection
524 },
530 },
525 Qt::QueuedConnection);
531 Qt::QueuedConnection);
526
532
527 auto productData = products.first().toHash();
533 auto productData = products.first().toHash();
528 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
534 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
529 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
535 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
530 }
536 }
531 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
537 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
532 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
538 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
533 graphWidget->setGraphRange(range);
539 graphWidget->setGraphRange(range);
534 }
540 }
535 else {
541 else {
536 qCWarning(LOG_VisualizationZoneWidget())
542 qCWarning(LOG_VisualizationZoneWidget())
537 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
543 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
538 }
544 }
539 }
545 }
540
546
541 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
547 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
542 int index, VisualizationZoneWidget *zoneWidget)
548 int index, VisualizationZoneWidget *zoneWidget)
543 {
549 {
544 auto &helper = sqpApp->dragDropGuiController();
550 auto &helper = sqpApp->dragDropGuiController();
545
551
546 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
552 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
547 if (!graphWidget) {
553 if (!graphWidget) {
548 qCWarning(LOG_VisualizationZoneWidget())
554 qCWarning(LOG_VisualizationZoneWidget())
549 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
555 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
550 "found or invalid.");
556 "found or invalid.");
551 Q_ASSERT(false);
557 Q_ASSERT(false);
552 return;
558 return;
553 }
559 }
554
560
555 auto parentDragDropContainer
561 auto parentDragDropContainer
556 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
562 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
557 if (!parentDragDropContainer) {
563 if (!parentDragDropContainer) {
558 qCWarning(LOG_VisualizationZoneWidget())
564 qCWarning(LOG_VisualizationZoneWidget())
559 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
565 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
560 "the dropped graph is not found.");
566 "the dropped graph is not found.");
561 Q_ASSERT(false);
567 Q_ASSERT(false);
562 return;
568 return;
563 }
569 }
564
570
565 const auto &variables = graphWidget->variables();
571 const auto &variables = graphWidget->variables();
566
572
567 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
573 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
568 // The drop didn't occur in the same zone
574 // The drop didn't occur in the same zone
569
575
570 // Abort the requests for the variables (if any)
576 // Abort the requests for the variables (if any)
571 // 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
572 // for (const auto& var : variables)
578 // for (const auto& var : variables)
573 //{
579 //{
574 // sqpApp->variableController().onAbortProgressRequested(var);
580 // sqpApp->variableController().onAbortProgressRequested(var);
575 //}
581 //}
576
582
577 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
583 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
578 auto nbGraph = parentDragDropContainer->countDragWidget();
584 auto nbGraph = parentDragDropContainer->countDragWidget();
579 if (nbGraph == 1) {
585 if (nbGraph == 1) {
580 // 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
581 helper.delayedCloseWidget(previousParentZoneWidget);
587 helper.delayedCloseWidget(previousParentZoneWidget);
582 }
588 }
583 else {
589 else {
584 // Close the graph
590 // Close the graph
585 helper.delayedCloseWidget(graphWidget);
591 helper.delayedCloseWidget(graphWidget);
586 }
592 }
587
593
588 // Creates the new graph in the zone
594 // Creates the new graph in the zone
589 auto newGraphWidget = zoneWidget->createGraph(variables, index);
595 auto newGraphWidget = zoneWidget->createGraph(variables, index);
590 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
596 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
591 }
597 }
592 else {
598 else {
593 // 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
594 // Simple move of the graph, no variable operation associated
600 // Simple move of the graph, no variable operation associated
595 parentDragDropContainer->layout()->removeWidget(graphWidget);
601 parentDragDropContainer->layout()->removeWidget(graphWidget);
596
602
597 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
603 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
598 // The graph is empty and dropped in a different zone.
604 // The graph is empty and dropped in a different zone.
599 // 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).
600 auto layout = zoneWidget->ui->dragDropContainer->layout();
606 auto layout = zoneWidget->ui->dragDropContainer->layout();
601 if (layout->count() > 0) {
607 if (layout->count() > 0) {
602 if (auto visualizationGraphWidget
608 if (auto visualizationGraphWidget
603 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
609 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
604 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
610 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
605 }
611 }
606 }
612 }
607 }
613 }
608
614
609 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
615 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
610 }
616 }
611 }
617 }
612
618
613 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
619 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
614 const QList<std::shared_ptr<Variable> > &variables, int index,
620 const QList<std::shared_ptr<Variable> > &variables, int index,
615 VisualizationZoneWidget *zoneWidget)
621 VisualizationZoneWidget *zoneWidget)
616 {
622 {
617 // 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
618 // compatible variable here
624 // compatible variable here
619 if (variables.count() > 1) {
625 if (variables.count() > 1) {
620 qCWarning(LOG_VisualizationZoneWidget())
626 qCWarning(LOG_VisualizationZoneWidget())
621 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
627 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
622 "aborted.");
628 "aborted.");
623 return;
629 return;
624 }
630 }
625
631
626 zoneWidget->createGraph(variables, index);
632 zoneWidget->createGraph(variables, index);
627 }
633 }
628
634
629 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProducts(
635 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProducts(
630 const QVariantList &productsData, int index, VisualizationZoneWidget *zoneWidget)
636 const QVariantList &productsData, int index, VisualizationZoneWidget *zoneWidget)
631 {
637 {
632 // 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
633 // compatible variable here
639 // compatible variable here
634 if (productsData.count() != 1) {
640 if (productsData.count() != 1) {
635 qCWarning(LOG_VisualizationZoneWidget())
641 qCWarning(LOG_VisualizationZoneWidget())
636 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
642 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
637 "aborted.");
643 "aborted.");
638 return;
644 return;
639 }
645 }
640
646
641 auto context = new QObject{zoneWidget};
647 auto context = new QObject{zoneWidget};
642 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
648 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
643 [this, index, zoneWidget, context](auto variable) {
649 [this, index, zoneWidget, context](auto variable) {
644 zoneWidget->createGraph(variable, index);
650 zoneWidget->createGraph(variable, index);
645 delete context; // removes the connection
651 delete context; // removes the connection
646 },
652 },
647 Qt::QueuedConnection);
653 Qt::QueuedConnection);
648
654
649 auto productData = productsData.first().toHash();
655 auto productData = productsData.first().toHash();
650 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
656 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
651 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
657 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
652 }
658 }
General Comments 0
You need to be logged in to leave comments. Login now