##// END OF EJS Templates
Drop of events on a catalogue
trabillard -
r1285:964109cb8b70
parent child
Show More
@@ -1,77 +1,83
1 #ifndef SCIQLOP_CATALOGUECONTROLLER_H
1 #ifndef SCIQLOP_CATALOGUECONTROLLER_H
2 #define SCIQLOP_CATALOGUECONTROLLER_H
2 #define SCIQLOP_CATALOGUECONTROLLER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QObject>
9 #include <QObject>
10 #include <QUuid>
10 #include <QUuid>
11
11
12 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
13
13
14 #include <memory>
14 #include <memory>
15
15
16 class DBCatalogue;
16 class DBCatalogue;
17 class DBEvent;
17 class DBEvent;
18 class DBEventProduct;
18 class DBEventProduct;
19
19
20 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueController)
20 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueController)
21
21
22 class DataSourceItem;
22 class DataSourceItem;
23 class Variable;
23 class Variable;
24
24
25 /**
25 /**
26 * @brief The CatalogueController class aims to handle catalogues and event using the CatalogueAPI
26 * @brief The CatalogueController class aims to handle catalogues and event using the CatalogueAPI
27 * library.
27 * library.
28 */
28 */
29 class SCIQLOP_CORE_EXPORT CatalogueController : public QObject {
29 class SCIQLOP_CORE_EXPORT CatalogueController : public QObject {
30 Q_OBJECT
30 Q_OBJECT
31 public:
31 public:
32 explicit CatalogueController(QObject *parent = 0);
32 explicit CatalogueController(QObject *parent = 0);
33 virtual ~CatalogueController();
33 virtual ~CatalogueController();
34
34
35 // DB
35 // DB
36 QStringList getRepositories() const;
36 QStringList getRepositories() const;
37 void addDB(const QString &dbPath);
37 void addDB(const QString &dbPath);
38 void saveDB(const QString &destinationPath, const QString &repository);
38 void saveDB(const QString &destinationPath, const QString &repository);
39
39
40 // Event
40 // Event
41 /// retrieveEvents with empty repository retrieve them from the default repository
41 /// retrieveEvents with empty repository retrieve them from the default repository
42 std::list<std::shared_ptr<DBEvent> > retrieveEvents(const QString &repository) const;
42 std::list<std::shared_ptr<DBEvent> > retrieveEvents(const QString &repository) const;
43 std::list<std::shared_ptr<DBEvent> > retrieveAllEvents() const;
43 std::list<std::shared_ptr<DBEvent> > retrieveAllEvents() const;
44 std::list<std::shared_ptr<DBEvent> >
44 std::list<std::shared_ptr<DBEvent> >
45 retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const;
45 retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const;
46 void addEvent(std::shared_ptr<DBEvent> event);
46 void addEvent(std::shared_ptr<DBEvent> event);
47 void updateEvent(std::shared_ptr<DBEvent> event);
47 void updateEvent(std::shared_ptr<DBEvent> event);
48 void updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct);
48 void updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct);
49 void removeEvent(std::shared_ptr<DBEvent> event);
49 void removeEvent(std::shared_ptr<DBEvent> event);
50 // void trashEvent(std::shared_ptr<DBEvent> event);
50 // void trashEvent(std::shared_ptr<DBEvent> event);
51 // void restore(QUuid eventId);
51 // void restore(QUuid eventId);
52 void saveEvent(std::shared_ptr<DBEvent> event);
52 void saveEvent(std::shared_ptr<DBEvent> event);
53
53
54 // Catalogue
54 // Catalogue
55 // bool createCatalogue(const QString &name, QVector<QUuid> eventList);
55 // bool createCatalogue(const QString &name, QVector<QUuid> eventList);
56 /// retrieveEvents with empty repository retrieve them from the default repository
56 /// retrieveEvents with empty repository retrieve them from the default repository
57 std::list<std::shared_ptr<DBCatalogue> > retrieveCatalogues(const QString &repository
57 std::list<std::shared_ptr<DBCatalogue> > retrieveCatalogues(const QString &repository
58 = QString()) const;
58 = QString()) const;
59 void updateCatalogue(std::shared_ptr<DBCatalogue> catalogue);
59 void updateCatalogue(std::shared_ptr<DBCatalogue> catalogue);
60 void removeCatalogue(std::shared_ptr<DBCatalogue> catalogue);
60 void removeCatalogue(std::shared_ptr<DBCatalogue> catalogue);
61 void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue);
61 void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue);
62
62
63 void saveAll();
63 void saveAll();
64
64
65 /// Returns the MIME data associated to a list of variables
66 QByteArray mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const;
67
68 /// Returns the list of variables contained in a MIME data
69 QVector<std::shared_ptr<DBEvent> > eventsForMimeData(const QByteArray &mimeData) const;
70
65 public slots:
71 public slots:
66 /// Manage init/end of the controller
72 /// Manage init/end of the controller
67 void initialize();
73 void initialize();
68 void finalize();
74 void finalize();
69
75
70 private:
76 private:
71 void waitForFinish();
77 void waitForFinish();
72
78
73 class CatalogueControllerPrivate;
79 class CatalogueControllerPrivate;
74 spimpl::unique_impl_ptr<CatalogueControllerPrivate> impl;
80 spimpl::unique_impl_ptr<CatalogueControllerPrivate> impl;
75 };
81 };
76
82
77 #endif // SCIQLOP_CATALOGUECONTROLLER_H
83 #endif // SCIQLOP_CATALOGUECONTROLLER_H
@@ -1,334 +1,375
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 <QMutex>
16 #include <QMutex>
16 #include <QThread>
17 #include <QThread>
17
18
18 #include <QDir>
19 #include <QDir>
19 #include <QStandardPaths>
20 #include <QStandardPaths>
20
21
21 Q_LOGGING_CATEGORY(LOG_CatalogueController, "CatalogueController")
22 Q_LOGGING_CATEGORY(LOG_CatalogueController, "CatalogueController")
22
23
23 namespace {
24 namespace {
24
25
25 static QString REPOSITORY_WORK_SUFFIX = QString{"_work"};
26 static QString REPOSITORY_WORK_SUFFIX = QString{"_work"};
26 static QString REPOSITORY_TRASH_SUFFIX = QString{"_trash"};
27 static QString REPOSITORY_TRASH_SUFFIX = QString{"_trash"};
27 }
28 }
28
29
29 class CatalogueController::CatalogueControllerPrivate {
30 class CatalogueController::CatalogueControllerPrivate {
30
31
31 public:
32 public:
32 explicit CatalogueControllerPrivate(CatalogueController *parent) : m_Q{parent} {}
33 explicit CatalogueControllerPrivate(CatalogueController *parent) : m_Q{parent} {}
33
34
34 QMutex m_WorkingMutex;
35 QMutex m_WorkingMutex;
35 CatalogueDao m_CatalogueDao;
36 CatalogueDao m_CatalogueDao;
36
37
37 QStringList m_RepositoryList;
38 QStringList m_RepositoryList;
38 CatalogueController *m_Q;
39 CatalogueController *m_Q;
39
40
40 void copyDBtoDB(const QString &dbFrom, const QString &dbTo);
41 void copyDBtoDB(const QString &dbFrom, const QString &dbTo);
41 QString toWorkRepository(QString repository);
42 QString toWorkRepository(QString repository);
42 QString toSyncRepository(QString repository);
43 QString toSyncRepository(QString repository);
43 void savAllDB();
44 void savAllDB();
44
45
45 void saveEvent(std::shared_ptr<DBEvent> event, bool persist = true);
46 void saveEvent(std::shared_ptr<DBEvent> event, bool persist = true);
46 void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool persist = true);
47 void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool persist = true);
47 };
48 };
48
49
49 CatalogueController::CatalogueController(QObject *parent)
50 CatalogueController::CatalogueController(QObject *parent)
50 : impl{spimpl::make_unique_impl<CatalogueControllerPrivate>(this)}
51 : impl{spimpl::make_unique_impl<CatalogueControllerPrivate>(this)}
51 {
52 {
52 qCDebug(LOG_CatalogueController()) << tr("CatalogueController construction")
53 qCDebug(LOG_CatalogueController()) << tr("CatalogueController construction")
53 << QThread::currentThread();
54 << QThread::currentThread();
54 }
55 }
55
56
56 CatalogueController::~CatalogueController()
57 CatalogueController::~CatalogueController()
57 {
58 {
58 qCDebug(LOG_CatalogueController()) << tr("CatalogueController destruction")
59 qCDebug(LOG_CatalogueController()) << tr("CatalogueController destruction")
59 << QThread::currentThread();
60 << QThread::currentThread();
60 this->waitForFinish();
61 this->waitForFinish();
61 }
62 }
62
63
63 QStringList CatalogueController::getRepositories() const
64 QStringList CatalogueController::getRepositories() const
64 {
65 {
65 return impl->m_RepositoryList;
66 return impl->m_RepositoryList;
66 }
67 }
67
68
68 void CatalogueController::addDB(const QString &dbPath)
69 void CatalogueController::addDB(const QString &dbPath)
69 {
70 {
70 QDir dbDir(dbPath);
71 QDir dbDir(dbPath);
71 if (dbDir.exists()) {
72 if (dbDir.exists()) {
72 auto dirName = dbDir.dirName();
73 auto dirName = dbDir.dirName();
73
74
74 if (std::find(impl->m_RepositoryList.cbegin(), impl->m_RepositoryList.cend(), dirName)
75 if (std::find(impl->m_RepositoryList.cbegin(), impl->m_RepositoryList.cend(), dirName)
75 != impl->m_RepositoryList.cend()) {
76 != impl->m_RepositoryList.cend()) {
76 qCCritical(LOG_CatalogueController())
77 qCCritical(LOG_CatalogueController())
77 << tr("Impossible to addDB that is already loaded");
78 << tr("Impossible to addDB that is already loaded");
78 }
79 }
79
80
80 if (!impl->m_CatalogueDao.addDB(dbPath, dirName)) {
81 if (!impl->m_CatalogueDao.addDB(dbPath, dirName)) {
81 qCCritical(LOG_CatalogueController())
82 qCCritical(LOG_CatalogueController())
82 << tr("Impossible to addDB %1 from %2 ").arg(dirName, dbPath);
83 << tr("Impossible to addDB %1 from %2 ").arg(dirName, dbPath);
83 }
84 }
84 else {
85 else {
85 impl->m_RepositoryList << dirName;
86 impl->m_RepositoryList << dirName;
86 impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName));
87 impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName));
87 }
88 }
88 }
89 }
89 else {
90 else {
90 qCCritical(LOG_CatalogueController()) << tr("Impossible to addDB that not exists: ")
91 qCCritical(LOG_CatalogueController()) << tr("Impossible to addDB that not exists: ")
91 << dbPath;
92 << dbPath;
92 }
93 }
93 }
94 }
94
95
95 void CatalogueController::saveDB(const QString &destinationPath, const QString &repository)
96 void CatalogueController::saveDB(const QString &destinationPath, const QString &repository)
96 {
97 {
97 if (!impl->m_CatalogueDao.saveDB(destinationPath, repository)) {
98 if (!impl->m_CatalogueDao.saveDB(destinationPath, repository)) {
98 qCCritical(LOG_CatalogueController())
99 qCCritical(LOG_CatalogueController())
99 << tr("Impossible to saveDB %1 from %2 ").arg(repository, destinationPath);
100 << tr("Impossible to saveDB %1 from %2 ").arg(repository, destinationPath);
100 }
101 }
101 }
102 }
102
103
103 std::list<std::shared_ptr<DBEvent> >
104 std::list<std::shared_ptr<DBEvent> >
104 CatalogueController::retrieveEvents(const QString &repository) const
105 CatalogueController::retrieveEvents(const QString &repository) const
105 {
106 {
106 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
107 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
107
108
108 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
109 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
109 auto events = impl->m_CatalogueDao.getEvents(impl->toWorkRepository(dbDireName));
110 auto events = impl->m_CatalogueDao.getEvents(impl->toWorkRepository(dbDireName));
110 for (auto event : events) {
111 for (auto event : events) {
111 eventsShared.push_back(std::make_shared<DBEvent>(event));
112 eventsShared.push_back(std::make_shared<DBEvent>(event));
112 }
113 }
113 return eventsShared;
114 return eventsShared;
114 }
115 }
115
116
116 std::list<std::shared_ptr<DBEvent> > CatalogueController::retrieveAllEvents() const
117 std::list<std::shared_ptr<DBEvent> > CatalogueController::retrieveAllEvents() const
117 {
118 {
118 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
119 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
119 for (auto repository : impl->m_RepositoryList) {
120 for (auto repository : impl->m_RepositoryList) {
120 eventsShared.splice(eventsShared.end(), retrieveEvents(repository));
121 eventsShared.splice(eventsShared.end(), retrieveEvents(repository));
121 }
122 }
122
123
123 return eventsShared;
124 return eventsShared;
124 }
125 }
125
126
126 std::list<std::shared_ptr<DBEvent> >
127 std::list<std::shared_ptr<DBEvent> >
127 CatalogueController::retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const
128 CatalogueController::retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const
128 {
129 {
129 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
130 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
130 auto events = impl->m_CatalogueDao.getCatalogueEvents(*catalogue);
131 auto events = impl->m_CatalogueDao.getCatalogueEvents(*catalogue);
131 for (auto event : events) {
132 for (auto event : events) {
132 eventsShared.push_back(std::make_shared<DBEvent>(event));
133 eventsShared.push_back(std::make_shared<DBEvent>(event));
133 }
134 }
134 return eventsShared;
135 return eventsShared;
135 }
136 }
136
137
137 void CatalogueController::updateEvent(std::shared_ptr<DBEvent> event)
138 void CatalogueController::updateEvent(std::shared_ptr<DBEvent> event)
138 {
139 {
139 event->setRepository(impl->toWorkRepository(event->getRepository()));
140 event->setRepository(impl->toWorkRepository(event->getRepository()));
140
141
141 impl->m_CatalogueDao.updateEvent(*event);
142 impl->m_CatalogueDao.updateEvent(*event);
142 }
143 }
143
144
144 void CatalogueController::updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct)
145 void CatalogueController::updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct)
145 {
146 {
146 impl->m_CatalogueDao.updateEventProduct(*eventProduct);
147 impl->m_CatalogueDao.updateEventProduct(*eventProduct);
147 }
148 }
148
149
149 void CatalogueController::removeEvent(std::shared_ptr<DBEvent> event)
150 void CatalogueController::removeEvent(std::shared_ptr<DBEvent> event)
150 {
151 {
151 // Remove it from both repository and repository_work
152 // Remove it from both repository and repository_work
152 event->setRepository(impl->toWorkRepository(event->getRepository()));
153 event->setRepository(impl->toWorkRepository(event->getRepository()));
153 impl->m_CatalogueDao.removeEvent(*event);
154 impl->m_CatalogueDao.removeEvent(*event);
154 event->setRepository(impl->toSyncRepository(event->getRepository()));
155 event->setRepository(impl->toSyncRepository(event->getRepository()));
155 impl->m_CatalogueDao.removeEvent(*event);
156 impl->m_CatalogueDao.removeEvent(*event);
156 }
157 }
157
158
158 void CatalogueController::addEvent(std::shared_ptr<DBEvent> event)
159 void CatalogueController::addEvent(std::shared_ptr<DBEvent> event)
159 {
160 {
160 event->setRepository(impl->toWorkRepository(event->getRepository()));
161 event->setRepository(impl->toWorkRepository(event->getRepository()));
161
162
162 auto eventTemp = *event;
163 auto eventTemp = *event;
163 impl->m_CatalogueDao.addEvent(eventTemp);
164 impl->m_CatalogueDao.addEvent(eventTemp);
164
165
165 // Call update is necessary at the creation of add Event if it has some tags or some event
166 // Call update is necessary at the creation of add Event if it has some tags or some event
166 // products
167 // products
167 if (!event->getEventProducts().empty() || !event->getTags().empty()) {
168 if (!event->getEventProducts().empty() || !event->getTags().empty()) {
168
169
169 auto eventProductsTemp = eventTemp.getEventProducts();
170 auto eventProductsTemp = eventTemp.getEventProducts();
170 auto eventProductTempUpdated = std::list<DBEventProduct>{};
171 auto eventProductTempUpdated = std::list<DBEventProduct>{};
171 for (auto eventProductTemp : eventProductsTemp) {
172 for (auto eventProductTemp : eventProductsTemp) {
172 eventProductTemp.setEvent(eventTemp);
173 eventProductTemp.setEvent(eventTemp);
173 eventProductTempUpdated.push_back(eventProductTemp);
174 eventProductTempUpdated.push_back(eventProductTemp);
174 }
175 }
175 eventTemp.setEventProducts(eventProductTempUpdated);
176 eventTemp.setEventProducts(eventProductTempUpdated);
176
177
177 impl->m_CatalogueDao.updateEvent(eventTemp);
178 impl->m_CatalogueDao.updateEvent(eventTemp);
178 }
179 }
179 }
180 }
180
181
181 void CatalogueController::saveEvent(std::shared_ptr<DBEvent> event)
182 void CatalogueController::saveEvent(std::shared_ptr<DBEvent> event)
182 {
183 {
183 impl->saveEvent(event, true);
184 impl->saveEvent(event, true);
184 }
185 }
185
186
186 std::list<std::shared_ptr<DBCatalogue> >
187 std::list<std::shared_ptr<DBCatalogue> >
187 CatalogueController::retrieveCatalogues(const QString &repository) const
188 CatalogueController::retrieveCatalogues(const QString &repository) const
188 {
189 {
189 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
190 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
190
191
191 auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
192 auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
192 auto catalogues = impl->m_CatalogueDao.getCatalogues(impl->toWorkRepository(dbDireName));
193 auto catalogues = impl->m_CatalogueDao.getCatalogues(impl->toWorkRepository(dbDireName));
193 for (auto catalogue : catalogues) {
194 for (auto catalogue : catalogues) {
194 cataloguesShared.push_back(std::make_shared<DBCatalogue>(catalogue));
195 cataloguesShared.push_back(std::make_shared<DBCatalogue>(catalogue));
195 }
196 }
196 return cataloguesShared;
197 return cataloguesShared;
197 }
198 }
198
199
199 void CatalogueController::updateCatalogue(std::shared_ptr<DBCatalogue> catalogue)
200 void CatalogueController::updateCatalogue(std::shared_ptr<DBCatalogue> catalogue)
200 {
201 {
201 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
202 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
202
203
203 impl->m_CatalogueDao.updateCatalogue(*catalogue);
204 impl->m_CatalogueDao.updateCatalogue(*catalogue);
204 }
205 }
205
206
206 void CatalogueController::removeCatalogue(std::shared_ptr<DBCatalogue> catalogue)
207 void CatalogueController::removeCatalogue(std::shared_ptr<DBCatalogue> catalogue)
207 {
208 {
208 // Remove it from both repository and repository_work
209 // Remove it from both repository and repository_work
209 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
210 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
210 impl->m_CatalogueDao.removeCatalogue(*catalogue);
211 impl->m_CatalogueDao.removeCatalogue(*catalogue);
211 catalogue->setRepository(impl->toSyncRepository(catalogue->getRepository()));
212 catalogue->setRepository(impl->toSyncRepository(catalogue->getRepository()));
212 impl->m_CatalogueDao.removeCatalogue(*catalogue);
213 impl->m_CatalogueDao.removeCatalogue(*catalogue);
213 }
214 }
214
215
215 void CatalogueController::saveCatalogue(std::shared_ptr<DBCatalogue> catalogue)
216 void CatalogueController::saveCatalogue(std::shared_ptr<DBCatalogue> catalogue)
216 {
217 {
217 impl->saveCatalogue(catalogue, true);
218 impl->saveCatalogue(catalogue, true);
218 }
219 }
219
220
220 void CatalogueController::saveAll()
221 void CatalogueController::saveAll()
221 {
222 {
222 for (auto repository : impl->m_RepositoryList) {
223 for (auto repository : impl->m_RepositoryList) {
223 // Save Event
224 // Save Event
224 auto events = this->retrieveEvents(repository);
225 auto events = this->retrieveEvents(repository);
225 for (auto event : events) {
226 for (auto event : events) {
226 impl->saveEvent(event, false);
227 impl->saveEvent(event, false);
227 }
228 }
228
229
229 // Save Catalogue
230 // Save Catalogue
230 auto catalogues = this->retrieveCatalogues(repository);
231 auto catalogues = this->retrieveCatalogues(repository);
231 for (auto catalogue : catalogues) {
232 for (auto catalogue : catalogues) {
232 impl->saveCatalogue(catalogue, false);
233 impl->saveCatalogue(catalogue, false);
233 }
234 }
234 }
235 }
235
236
236 impl->savAllDB();
237 impl->savAllDB();
237 }
238 }
238
239
240 QByteArray
241 CatalogueController::mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const
242 {
243 auto encodedData = QByteArray{};
244
245 QMap<QString, QVariantList> idsPerRepository;
246 for (auto event : events) {
247 idsPerRepository[event->getRepository()] << event->getUniqId();
248 }
249
250 QDataStream stream{&encodedData, QIODevice::WriteOnly};
251 stream << idsPerRepository;
252
253 return encodedData;
254 }
255
256 QVector<std::shared_ptr<DBEvent> >
257 CatalogueController::eventsForMimeData(const QByteArray &mimeData) const
258 {
259 auto events = QVector<std::shared_ptr<DBEvent> >{};
260 QDataStream stream{mimeData};
261
262 QMap<QString, QVariantList> idsPerRepository;
263 stream >> idsPerRepository;
264
265 for (auto it = idsPerRepository.cbegin(); it != idsPerRepository.cend(); ++it) {
266 auto repository = it.key();
267 auto allRepositoryEvent = retrieveEvents(repository);
268 for (auto uuid : it.value()) {
269 for (auto repositoryEvent : allRepositoryEvent) {
270 if (uuid.toUuid() == repositoryEvent->getUniqId()) {
271 events << repositoryEvent;
272 }
273 }
274 }
275 }
276
277 return events;
278 }
279
239 void CatalogueController::initialize()
280 void CatalogueController::initialize()
240 {
281 {
241 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init")
282 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init")
242 << QThread::currentThread();
283 << QThread::currentThread();
243 impl->m_WorkingMutex.lock();
284 impl->m_WorkingMutex.lock();
244 impl->m_CatalogueDao.initialize();
285 impl->m_CatalogueDao.initialize();
245 auto defaultRepositoryLocation
286 auto defaultRepositoryLocation
246 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
287 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
247
288
248 QDir defaultRepositoryLocationDir;
289 QDir defaultRepositoryLocationDir;
249 if (defaultRepositoryLocationDir.mkpath(defaultRepositoryLocation)) {
290 if (defaultRepositoryLocationDir.mkpath(defaultRepositoryLocation)) {
250 defaultRepositoryLocationDir.cd(defaultRepositoryLocation);
291 defaultRepositoryLocationDir.cd(defaultRepositoryLocation);
251 auto defaultRepository = defaultRepositoryLocationDir.absoluteFilePath(REPOSITORY_DEFAULT);
292 auto defaultRepository = defaultRepositoryLocationDir.absoluteFilePath(REPOSITORY_DEFAULT);
252 qCInfo(LOG_CatalogueController()) << tr("Persistant data loading from: ")
293 qCInfo(LOG_CatalogueController()) << tr("Persistant data loading from: ")
253 << defaultRepository;
294 << defaultRepository;
254 this->addDB(defaultRepository);
295 this->addDB(defaultRepository);
255 }
296 }
256 else {
297 else {
257 qCWarning(LOG_CatalogueController())
298 qCWarning(LOG_CatalogueController())
258 << tr("Cannot load the persistent default repository from ")
299 << tr("Cannot load the persistent default repository from ")
259 << defaultRepositoryLocation;
300 << defaultRepositoryLocation;
260 }
301 }
261
302
262 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init END");
303 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init END");
263 }
304 }
264
305
265 void CatalogueController::finalize()
306 void CatalogueController::finalize()
266 {
307 {
267 impl->m_WorkingMutex.unlock();
308 impl->m_WorkingMutex.unlock();
268 }
309 }
269
310
270 void CatalogueController::waitForFinish()
311 void CatalogueController::waitForFinish()
271 {
312 {
272 QMutexLocker locker{&impl->m_WorkingMutex};
313 QMutexLocker locker{&impl->m_WorkingMutex};
273 }
314 }
274
315
275 void CatalogueController::CatalogueControllerPrivate::copyDBtoDB(const QString &dbFrom,
316 void CatalogueController::CatalogueControllerPrivate::copyDBtoDB(const QString &dbFrom,
276 const QString &dbTo)
317 const QString &dbTo)
277 {
318 {
278 // auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
319 // auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
279 auto catalogues = m_CatalogueDao.getCatalogues(dbFrom);
320 auto catalogues = m_CatalogueDao.getCatalogues(dbFrom);
280 auto events = m_CatalogueDao.getEvents(dbFrom);
321 auto events = m_CatalogueDao.getEvents(dbFrom);
281 for (auto catalogue : catalogues) {
322 for (auto catalogue : catalogues) {
282 m_CatalogueDao.copyCatalogue(catalogue, dbTo, true);
323 m_CatalogueDao.copyCatalogue(catalogue, dbTo, true);
283 }
324 }
284
325
285 for (auto event : events) {
326 for (auto event : events) {
286 m_CatalogueDao.copyEvent(event, dbTo, true);
327 m_CatalogueDao.copyEvent(event, dbTo, true);
287 }
328 }
288 }
329 }
289
330
290 QString CatalogueController::CatalogueControllerPrivate::toWorkRepository(QString repository)
331 QString CatalogueController::CatalogueControllerPrivate::toWorkRepository(QString repository)
291 {
332 {
292 auto syncRepository = toSyncRepository(repository);
333 auto syncRepository = toSyncRepository(repository);
293
334
294 return QString("%1%2").arg(syncRepository, REPOSITORY_WORK_SUFFIX);
335 return QString("%1%2").arg(syncRepository, REPOSITORY_WORK_SUFFIX);
295 }
336 }
296
337
297 QString CatalogueController::CatalogueControllerPrivate::toSyncRepository(QString repository)
338 QString CatalogueController::CatalogueControllerPrivate::toSyncRepository(QString repository)
298 {
339 {
299 auto syncRepository = repository;
340 auto syncRepository = repository;
300 if (repository.endsWith(REPOSITORY_WORK_SUFFIX)) {
341 if (repository.endsWith(REPOSITORY_WORK_SUFFIX)) {
301 syncRepository.remove(REPOSITORY_WORK_SUFFIX);
342 syncRepository.remove(REPOSITORY_WORK_SUFFIX);
302 }
343 }
303 else if (repository.endsWith(REPOSITORY_TRASH_SUFFIX)) {
344 else if (repository.endsWith(REPOSITORY_TRASH_SUFFIX)) {
304 syncRepository.remove(REPOSITORY_TRASH_SUFFIX);
345 syncRepository.remove(REPOSITORY_TRASH_SUFFIX);
305 }
346 }
306 return syncRepository;
347 return syncRepository;
307 }
348 }
308
349
309 void CatalogueController::CatalogueControllerPrivate::savAllDB()
350 void CatalogueController::CatalogueControllerPrivate::savAllDB()
310 {
351 {
311 for (auto repository : m_RepositoryList) {
352 for (auto repository : m_RepositoryList) {
312 auto defaultRepositoryLocation
353 auto defaultRepositoryLocation
313 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
354 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
314 m_CatalogueDao.saveDB(defaultRepositoryLocation, repository);
355 m_CatalogueDao.saveDB(defaultRepositoryLocation, repository);
315 }
356 }
316 }
357 }
317
358
318 void CatalogueController::CatalogueControllerPrivate::saveEvent(std::shared_ptr<DBEvent> event,
359 void CatalogueController::CatalogueControllerPrivate::saveEvent(std::shared_ptr<DBEvent> event,
319 bool persist)
360 bool persist)
320 {
361 {
321 m_CatalogueDao.copyEvent(*event, toSyncRepository(event->getRepository()), true);
362 m_CatalogueDao.copyEvent(*event, toSyncRepository(event->getRepository()), true);
322 if (persist) {
363 if (persist) {
323 savAllDB();
364 savAllDB();
324 }
365 }
325 }
366 }
326
367
327 void CatalogueController::CatalogueControllerPrivate::saveCatalogue(
368 void CatalogueController::CatalogueControllerPrivate::saveCatalogue(
328 std::shared_ptr<DBCatalogue> catalogue, bool persist)
369 std::shared_ptr<DBCatalogue> catalogue, bool persist)
329 {
370 {
330 m_CatalogueDao.copyCatalogue(*catalogue, toSyncRepository(catalogue->getRepository()), true);
371 m_CatalogueDao.copyCatalogue(*catalogue, toSyncRepository(catalogue->getRepository()), true);
331 if (persist) {
372 if (persist) {
332 savAllDB();
373 savAllDB();
333 }
374 }
334 }
375 }
@@ -1,34 +1,35
1 #ifndef SCIQLOP_CATALOGUEABSTRACTTREEITEM_H
1 #ifndef SCIQLOP_CATALOGUEABSTRACTTREEITEM_H
2 #define SCIQLOP_CATALOGUEABSTRACTTREEITEM_H
2 #define SCIQLOP_CATALOGUEABSTRACTTREEITEM_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QVariant>
5 #include <QVariant>
6 #include <QVector>
6 #include <QVector>
7
7
8 class QMimeData;
8 class QMimeData;
9
9
10 class CatalogueAbstractTreeItem {
10 class CatalogueAbstractTreeItem {
11 public:
11 public:
12 constexpr static const int DEFAULT_TYPE = -1;
12 constexpr static const int DEFAULT_TYPE = -1;
13
13
14 CatalogueAbstractTreeItem(int type = DEFAULT_TYPE);
14 CatalogueAbstractTreeItem(int type = DEFAULT_TYPE);
15 virtual ~CatalogueAbstractTreeItem();
15 virtual ~CatalogueAbstractTreeItem();
16
16
17 void addChild(CatalogueAbstractTreeItem *child);
17 void addChild(CatalogueAbstractTreeItem *child);
18 QVector<CatalogueAbstractTreeItem *> children() const;
18 QVector<CatalogueAbstractTreeItem *> children() const;
19 CatalogueAbstractTreeItem *parent() const;
19 CatalogueAbstractTreeItem *parent() const;
20
20
21 int type() const;
21 int type() const;
22 QString text(int column = 0) const;
22 QString text(int column = 0) const;
23
23
24 virtual QVariant data(int column, int role) const;
24 virtual QVariant data(int column, int role) const;
25 virtual Qt::ItemFlags flags(int column) const;
25 virtual Qt::ItemFlags flags(int column) const;
26 virtual bool setData(int column, int role, const QVariant &value);
26 virtual bool setData(int column, int role, const QVariant &value);
27 virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action);
27 virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action);
28 virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action);
28
29
29 private:
30 private:
30 class CatalogueAbstractTreeItemPrivate;
31 class CatalogueAbstractTreeItemPrivate;
31 spimpl::unique_impl_ptr<CatalogueAbstractTreeItemPrivate> impl;
32 spimpl::unique_impl_ptr<CatalogueAbstractTreeItemPrivate> impl;
32 };
33 };
33
34
34 #endif // SCIQLOP_CATALOGUEABSTRACTTREEITEM_H
35 #endif // SCIQLOP_CATALOGUEABSTRACTTREEITEM_H
@@ -1,27 +1,28
1 #ifndef SCIQLOP_CATALOGUETREEITEM_H
1 #ifndef SCIQLOP_CATALOGUETREEITEM_H
2 #define SCIQLOP_CATALOGUETREEITEM_H
2 #define SCIQLOP_CATALOGUETREEITEM_H
3
3
4 #include <Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h>
4 #include <Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h>
5 #include <Common/spimpl.h>
5 #include <Common/spimpl.h>
6
6
7 class DBCatalogue;
7 class DBCatalogue;
8
8
9
9
10 class CatalogueTreeItem : public CatalogueAbstractTreeItem {
10 class CatalogueTreeItem : public CatalogueAbstractTreeItem {
11 public:
11 public:
12 CatalogueTreeItem(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon, int type);
12 CatalogueTreeItem(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon, int type);
13
13
14 QVariant data(int column, int role) const override;
14 QVariant data(int column, int role) const override;
15 bool setData(int column, int role, const QVariant &value) override;
15 bool setData(int column, int role, const QVariant &value) override;
16 Qt::ItemFlags flags(int column) const override;
16 Qt::ItemFlags flags(int column) const override;
17 bool canDropMimeData(const QMimeData *data, Qt::DropAction action) override;
17 bool canDropMimeData(const QMimeData *data, Qt::DropAction action) override;
18 bool dropMimeData(const QMimeData *data, Qt::DropAction action) override;
18
19
19 /// Returns the catalogue represented by the item
20 /// Returns the catalogue represented by the item
20 std::shared_ptr<DBCatalogue> catalogue() const;
21 std::shared_ptr<DBCatalogue> catalogue() const;
21
22
22 private:
23 private:
23 class CatalogueTreeItemPrivate;
24 class CatalogueTreeItemPrivate;
24 spimpl::unique_impl_ptr<CatalogueTreeItemPrivate> impl;
25 spimpl::unique_impl_ptr<CatalogueTreeItemPrivate> impl;
25 };
26 };
26
27
27 #endif // SCIQLOP_CATALOGUETREEITEM_H
28 #endif // SCIQLOP_CATALOGUETREEITEM_H
@@ -1,55 +1,56
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
20
20 public:
21 public:
21 CatalogueTreeModel(QObject *parent = nullptr);
22 CatalogueTreeModel(QObject *parent = nullptr);
22
23
23 enum class Column { Name, Validation, Count };
24 enum class Column { Name, Validation, Count };
24
25
25 QModelIndex addTopLevelItem(CatalogueAbstractTreeItem *item);
26 QModelIndex addTopLevelItem(CatalogueAbstractTreeItem *item);
26 QVector<CatalogueAbstractTreeItem *> topLevelItems() const;
27 QVector<CatalogueAbstractTreeItem *> topLevelItems() const;
27
28
28 void addChildItem(CatalogueAbstractTreeItem *child, const QModelIndex &parentIndex);
29 void addChildItem(CatalogueAbstractTreeItem *child, const QModelIndex &parentIndex);
29
30
30 CatalogueAbstractTreeItem *item(const QModelIndex &index) const;
31 CatalogueAbstractTreeItem *item(const QModelIndex &index) const;
31 QModelIndex indexOf(CatalogueAbstractTreeItem *item, int column = 0) const;
32 QModelIndex indexOf(CatalogueAbstractTreeItem *item, int column = 0) const;
32
33
33 // model
34 // model
34 QModelIndex index(int row, int column,
35 QModelIndex index(int row, int column,
35 const QModelIndex &parent = QModelIndex()) const override;
36 const QModelIndex &parent = QModelIndex()) const override;
36 QModelIndex parent(const QModelIndex &index) const override;
37 QModelIndex parent(const QModelIndex &index) const override;
37 int rowCount(const QModelIndex &parent) const override;
38 int rowCount(const QModelIndex &parent) const override;
38 int columnCount(const QModelIndex &parent) const override;
39 int columnCount(const QModelIndex &parent) const override;
39 Qt::ItemFlags flags(const QModelIndex &index) const override;
40 Qt::ItemFlags flags(const QModelIndex &index) const override;
40 QVariant data(const QModelIndex &index, int role) const override;
41 QVariant data(const QModelIndex &index, int role) const override;
41 bool setData(const QModelIndex &index, const QVariant &value, int role) override;
42 bool setData(const QModelIndex &index, const QVariant &value, int role) override;
42
43
43 bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
44 bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
44 const QModelIndex &parent) const override;
45 const QModelIndex &parent) const override;
45 bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
46 bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
46 const QModelIndex &parent) override;
47 const QModelIndex &parent) override;
47 Qt::DropActions supportedDropActions() const;
48 Qt::DropActions supportedDropActions() const;
48 QStringList mimeTypes() const;
49 QStringList mimeTypes() const;
49
50
50 private:
51 private:
51 class CatalogueTreeModelPrivate;
52 class CatalogueTreeModelPrivate;
52 spimpl::unique_impl_ptr<CatalogueTreeModelPrivate> impl;
53 spimpl::unique_impl_ptr<CatalogueTreeModelPrivate> impl;
53 };
54 };
54
55
55 #endif // CATALOGUETREEMODEL_H
56 #endif // CATALOGUETREEMODEL_H
@@ -1,442 +1,444
1 #include "Catalogue/CatalogueEventsModel.h"
1 #include "Catalogue/CatalogueEventsModel.h"
2
2
3 #include <Catalogue/CatalogueController.h>
3 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
4 #include <Common/MimeTypesDef.h>
5 #include <Common/MimeTypesDef.h>
5 #include <DBEvent.h>
6 #include <DBEvent.h>
6 #include <DBEventProduct.h>
7 #include <DBEventProduct.h>
7 #include <DBTag.h>
8 #include <DBTag.h>
8 #include <Data/SqpRange.h>
9 #include <Data/SqpRange.h>
9 #include <SqpApplication.h>
10 #include <SqpApplication.h>
10 #include <Time/TimeController.h>
11 #include <Time/TimeController.h>
11
12
12 #include <list>
13 #include <list>
13 #include <unordered_map>
14 #include <unordered_map>
14
15
15 #include <QHash>
16 #include <QHash>
16 #include <QMimeData>
17 #include <QMimeData>
17
18
18 Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
19 Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
19
20
20 const auto EVENT_ITEM_TYPE = 1;
21 const auto EVENT_ITEM_TYPE = 1;
21 const auto EVENT_PRODUCT_ITEM_TYPE = 2;
22 const auto EVENT_PRODUCT_ITEM_TYPE = 2;
22
23
23 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
24 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
24 QVector<std::shared_ptr<DBEvent> > m_Events;
25 QVector<std::shared_ptr<DBEvent> > m_Events;
25 std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
26 std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
26 std::unordered_set<std::shared_ptr<DBEvent> > m_EventsWithChanges;
27 std::unordered_set<std::shared_ptr<DBEvent> > m_EventsWithChanges;
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 return m_EventsWithChanges.find(event) != m_EventsWithChanges.cend() ? true
38 return m_EventsWithChanges.find(event) != m_EventsWithChanges.cend() ? true
38 : QVariant();
39 : 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
119
119 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
120 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
120 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
121 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
121 {
122 {
122 }
123 }
123
124
124 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
125 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
125 {
126 {
126 beginResetModel();
127 beginResetModel();
127
128
128 impl->m_Events = events;
129 impl->m_Events = events;
129 impl->m_EventProducts.clear();
130 impl->m_EventProducts.clear();
130 impl->m_EventsWithChanges.clear();
131 impl->m_EventsWithChanges.clear();
131 for (auto event : events) {
132 for (auto event : events) {
132 impl->parseEventProduct(event);
133 impl->parseEventProduct(event);
133 }
134 }
134
135
135 endResetModel();
136 endResetModel();
136 }
137 }
137
138
138 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
139 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
139 {
140 {
140 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
141 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
141 return impl->m_Events.value(index.row());
142 return impl->m_Events.value(index.row());
142 }
143 }
143 else {
144 else {
144 return nullptr;
145 return nullptr;
145 }
146 }
146 }
147 }
147
148
148 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
149 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
149 {
150 {
150 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
151 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
151 return getEvent(index.parent());
152 return getEvent(index.parent());
152 }
153 }
153 else {
154 else {
154 return nullptr;
155 return nullptr;
155 }
156 }
156 }
157 }
157
158
158 std::shared_ptr<DBEventProduct>
159 std::shared_ptr<DBEventProduct>
159 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
160 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
160 {
161 {
161 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
162 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
162 auto event = static_cast<DBEvent *>(index.internalPointer());
163 auto event = static_cast<DBEvent *>(index.internalPointer());
163 return impl->m_EventProducts.at(event).value(index.row());
164 return impl->m_EventProducts.at(event).value(index.row());
164 }
165 }
165 else {
166 else {
166 return nullptr;
167 return nullptr;
167 }
168 }
168 }
169 }
169
170
170 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
171 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
171 {
172 {
172 beginInsertRows(QModelIndex(), impl->m_Events.count() - 1, impl->m_Events.count() - 1);
173 beginInsertRows(QModelIndex(), impl->m_Events.count() - 1, impl->m_Events.count() - 1);
173 impl->m_Events.append(event);
174 impl->m_Events.append(event);
174 impl->parseEventProduct(event);
175 impl->parseEventProduct(event);
175 endInsertRows();
176 endInsertRows();
176 }
177 }
177
178
178 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
179 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
179 {
180 {
180 auto index = impl->m_Events.indexOf(event);
181 auto index = impl->m_Events.indexOf(event);
181 if (index >= 0) {
182 if (index >= 0) {
182 beginRemoveRows(QModelIndex(), index, index);
183 beginRemoveRows(QModelIndex(), index, index);
183 impl->m_Events.removeAt(index);
184 impl->m_Events.removeAt(index);
184 impl->m_EventProducts.erase(event.get());
185 impl->m_EventProducts.erase(event.get());
185 impl->m_EventsWithChanges.erase(event);
186 impl->m_EventsWithChanges.erase(event);
186 endRemoveRows();
187 endRemoveRows();
187 }
188 }
188 }
189 }
189
190
190 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
191 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
191 {
192 {
192 return impl->m_Events;
193 return impl->m_Events;
193 }
194 }
194
195
195 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event)
196 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event)
196 {
197 {
197 auto eventIndex = indexOf(event);
198 auto eventIndex = indexOf(event);
198 if (eventIndex.isValid()) {
199 if (eventIndex.isValid()) {
199
200
200 // Refreshes the event line
201 // Refreshes the event line
201 auto colCount = columnCount();
202 auto colCount = columnCount();
202 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
203 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
203
204
204 // Also refreshes its children event products
205 // Also refreshes its children event products
205 auto childCount = rowCount(eventIndex);
206 auto childCount = rowCount(eventIndex);
206 emit dataChanged(index(0, 0, eventIndex), index(childCount, colCount, eventIndex));
207 emit dataChanged(index(0, 0, eventIndex), index(childCount, colCount, eventIndex));
207 }
208 }
208 else {
209 else {
209 qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
210 qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
210 }
211 }
211 }
212 }
212
213
213 QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
214 QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
214 {
215 {
215 auto row = impl->m_Events.indexOf(event);
216 auto row = impl->m_Events.indexOf(event);
216 if (row >= 0) {
217 if (row >= 0) {
217 return index(row, 0);
218 return index(row, 0);
218 }
219 }
219
220
220 return QModelIndex();
221 return QModelIndex();
221 }
222 }
222
223
223 void CatalogueEventsModel::setEventHasChanges(const std::shared_ptr<DBEvent> &event,
224 void CatalogueEventsModel::setEventHasChanges(const std::shared_ptr<DBEvent> &event,
224 bool hasChanges)
225 bool hasChanges)
225 {
226 {
226 if (hasChanges) {
227 if (hasChanges) {
227 impl->m_EventsWithChanges.insert(event);
228 impl->m_EventsWithChanges.insert(event);
228 }
229 }
229 else {
230 else {
230 impl->m_EventsWithChanges.erase(event);
231 impl->m_EventsWithChanges.erase(event);
231 }
232 }
232 }
233 }
233
234
234 bool CatalogueEventsModel::eventsHasChanges(const std::shared_ptr<DBEvent> &event) const
235 bool CatalogueEventsModel::eventsHasChanges(const std::shared_ptr<DBEvent> &event) const
235 {
236 {
236 return impl->m_EventsWithChanges.find(event) != impl->m_EventsWithChanges.cend();
237 return impl->m_EventsWithChanges.find(event) != impl->m_EventsWithChanges.cend();
237 }
238 }
238
239
239 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
240 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
240 {
241 {
241 if (!hasIndex(row, column, parent)) {
242 if (!hasIndex(row, column, parent)) {
242 return QModelIndex();
243 return QModelIndex();
243 }
244 }
244
245
245 switch (itemTypeOf(parent)) {
246 switch (itemTypeOf(parent)) {
246 case CatalogueEventsModel::ItemType::Root:
247 case CatalogueEventsModel::ItemType::Root:
247 return createIndex(row, column);
248 return createIndex(row, column);
248 case CatalogueEventsModel::ItemType::Event: {
249 case CatalogueEventsModel::ItemType::Event: {
249 auto event = getEvent(parent);
250 auto event = getEvent(parent);
250 return createIndex(row, column, event.get());
251 return createIndex(row, column, event.get());
251 }
252 }
252 case CatalogueEventsModel::ItemType::EventProduct:
253 case CatalogueEventsModel::ItemType::EventProduct:
253 break;
254 break;
254 default:
255 default:
255 break;
256 break;
256 }
257 }
257
258
258 return QModelIndex();
259 return QModelIndex();
259 }
260 }
260
261
261 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
262 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
262 {
263 {
263 switch (itemTypeOf(index)) {
264 switch (itemTypeOf(index)) {
264 case CatalogueEventsModel::ItemType::EventProduct: {
265 case CatalogueEventsModel::ItemType::EventProduct: {
265 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
266 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
266 auto it
267 auto it
267 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
268 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
268 [parentEvent](auto event) { return event.get() == parentEvent; });
269 [parentEvent](auto event) { return event.get() == parentEvent; });
269
270
270 if (it != impl->m_Events.cend()) {
271 if (it != impl->m_Events.cend()) {
271 return createIndex(it - impl->m_Events.cbegin(), 0);
272 return createIndex(it - impl->m_Events.cbegin(), 0);
272 }
273 }
273 else {
274 else {
274 return QModelIndex();
275 return QModelIndex();
275 }
276 }
276 }
277 }
277 case CatalogueEventsModel::ItemType::Root:
278 case CatalogueEventsModel::ItemType::Root:
278 break;
279 break;
279 case CatalogueEventsModel::ItemType::Event:
280 case CatalogueEventsModel::ItemType::Event:
280 break;
281 break;
281 default:
282 default:
282 break;
283 break;
283 }
284 }
284
285
285 return QModelIndex();
286 return QModelIndex();
286 }
287 }
287
288
288 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
289 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
289 {
290 {
290 if (parent.column() > 0) {
291 if (parent.column() > 0) {
291 return 0;
292 return 0;
292 }
293 }
293
294
294 switch (itemTypeOf(parent)) {
295 switch (itemTypeOf(parent)) {
295 case CatalogueEventsModel::ItemType::Root:
296 case CatalogueEventsModel::ItemType::Root:
296 return impl->m_Events.count();
297 return impl->m_Events.count();
297 case CatalogueEventsModel::ItemType::Event: {
298 case CatalogueEventsModel::ItemType::Event: {
298 auto event = getEvent(parent);
299 auto event = getEvent(parent);
299 return impl->m_EventProducts[event.get()].count();
300 return impl->m_EventProducts[event.get()].count();
300 }
301 }
301 case CatalogueEventsModel::ItemType::EventProduct:
302 case CatalogueEventsModel::ItemType::EventProduct:
302 break;
303 break;
303 default:
304 default:
304 break;
305 break;
305 }
306 }
306
307
307 return 0;
308 return 0;
308 }
309 }
309
310
310 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
311 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
311 {
312 {
312 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
313 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
313 }
314 }
314
315
315 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
316 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
316 {
317 {
317 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
318 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
318 }
319 }
319
320
320 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
321 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
321 {
322 {
322 if (index.isValid()) {
323 if (index.isValid()) {
323
324
324 auto type = itemTypeOf(index);
325 auto type = itemTypeOf(index);
325 if (type == CatalogueEventsModel::ItemType::Event) {
326 if (type == CatalogueEventsModel::ItemType::Event) {
326 auto event = getEvent(index);
327 auto event = getEvent(index);
327 switch (role) {
328 switch (role) {
328 case Qt::DisplayRole:
329 case Qt::DisplayRole:
329 return impl->eventData(index.column(), event);
330 return impl->eventData(index.column(), event);
330 break;
331 break;
331 }
332 }
332 }
333 }
333 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
334 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
334 auto product = getEventProduct(index);
335 auto product = getEventProduct(index);
335 switch (role) {
336 switch (role) {
336 case Qt::DisplayRole:
337 case Qt::DisplayRole:
337 return impl->eventProductData(index.column(), product);
338 return impl->eventProductData(index.column(), product);
338 break;
339 break;
339 }
340 }
340 }
341 }
341 }
342 }
342
343
343 return QVariant{};
344 return QVariant{};
344 }
345 }
345
346
346 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
347 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
347 {
348 {
348 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
349 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
349 return impl->columnNames().value(section);
350 return impl->columnNames().value(section);
350 }
351 }
351
352
352 return QVariant();
353 return QVariant();
353 }
354 }
354
355
355 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
356 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
356 {
357 {
357 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
358 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
358 [this, column, order](auto e1, auto e2) {
359 [this, column, order](auto e1, auto e2) {
359 auto data1 = impl->sortData(column, e1);
360 auto data1 = impl->sortData(column, e1);
360 auto data2 = impl->sortData(column, e2);
361 auto data2 = impl->sortData(column, e2);
361
362
362 auto result = data1.toString() < data2.toString();
363 auto result = data1.toString() < data2.toString();
363
364
364 return order == Qt::AscendingOrder ? result : !result;
365 return order == Qt::AscendingOrder ? result : !result;
365 });
366 });
366
367
367 emit dataChanged(QModelIndex(), QModelIndex());
368 emit dataChanged(QModelIndex(), QModelIndex());
368 emit modelSorted();
369 emit modelSorted();
369 }
370 }
370
371
371 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
372 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
372 {
373 {
373 return Qt::CopyAction | Qt::MoveAction;
374 return Qt::CopyAction;
374 }
375 }
375
376
376 QStringList CatalogueEventsModel::mimeTypes() const
377 QStringList CatalogueEventsModel::mimeTypes() const
377 {
378 {
378 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_TIME_RANGE};
379 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_TIME_RANGE};
379 }
380 }
380
381
381 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
382 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
382 {
383 {
383 auto mimeData = new QMimeData;
384 auto mimeData = new QMimeData;
384
385
385 bool isFirst = true;
386 bool isFirst = true;
386
387
387 QVector<std::shared_ptr<DBEvent> > eventList;
388 QVector<std::shared_ptr<DBEvent> > eventList;
388 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
389 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
389
390
390 SqpRange firstTimeRange;
391 SqpRange firstTimeRange;
391 for (const auto &index : indexes) {
392 for (const auto &index : indexes) {
392 if (index.column() == 0) { // only the first column
393 if (index.column() == 0) { // only the first column
393
394
394 auto type = itemTypeOf(index);
395 auto type = itemTypeOf(index);
395 if (type == ItemType::Event) {
396 if (type == ItemType::Event) {
396 auto event = getEvent(index);
397 auto event = getEvent(index);
397 eventList << event;
398 eventList << event;
398
399
399 if (isFirst) {
400 if (isFirst) {
400 isFirst = false;
401 isFirst = false;
401 firstTimeRange.m_TStart = event->getTStart();
402 firstTimeRange.m_TStart = event->getTStart();
402 firstTimeRange.m_TEnd = event->getTEnd();
403 firstTimeRange.m_TEnd = event->getTEnd();
403 }
404 }
404 }
405 }
405 else if (type == ItemType::EventProduct) {
406 else if (type == ItemType::EventProduct) {
406 auto product = getEventProduct(index);
407 auto product = getEventProduct(index);
407 eventProductList << product;
408 eventProductList << product;
408
409
409 if (isFirst) {
410 if (isFirst) {
410 isFirst = false;
411 isFirst = false;
411 firstTimeRange.m_TStart = product->getTStart();
412 firstTimeRange.m_TStart = product->getTStart();
412 firstTimeRange.m_TEnd = product->getTEnd();
413 firstTimeRange.m_TEnd = product->getTEnd();
413 }
414 }
414 }
415 }
415 }
416 }
416 }
417 }
417
418
418 auto eventsEncodedData
419 if (!eventList.isEmpty() && eventProductList.isEmpty()) {
419 = QByteArray{}; // sqpApp->catalogueController().->mimeDataForEvents(eventList); //TODO
420 auto eventsEncodedData = sqpApp->catalogueController().mimeDataForEvents(eventList);
420 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
421 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
422 }
421
423
422 if (eventList.count() + eventProductList.count() == 1) {
424 if (eventList.count() + eventProductList.count() == 1) {
423 // No time range MIME data if multiple events are dragged
425 // No time range MIME data if multiple events are dragged
424 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
426 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
425 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
427 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
426 }
428 }
427
429
428 return mimeData;
430 return mimeData;
429 }
431 }
430
432
431 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
433 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
432 {
434 {
433 if (!index.isValid()) {
435 if (!index.isValid()) {
434 return ItemType::Root;
436 return ItemType::Root;
435 }
437 }
436 else if (index.internalPointer() == nullptr) {
438 else if (index.internalPointer() == nullptr) {
437 return ItemType::Event;
439 return ItemType::Event;
438 }
440 }
439 else {
441 else {
440 return ItemType::EventProduct;
442 return ItemType::EventProduct;
441 }
443 }
442 }
444 }
@@ -1,295 +1,313
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 <ComparaisonPredicate.h>
11 #include <ComparaisonPredicate.h>
12 #include <DBCatalogue.h>
12 #include <DBCatalogue.h>
13
13
14 #include <QMenu>
14 #include <QMenu>
15
15
16 Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
16 Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
17
17
18
18
19 constexpr auto ALL_EVENT_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 1;
19 constexpr auto ALL_EVENT_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 1;
20 constexpr auto TRASH_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 2;
20 constexpr auto TRASH_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 2;
21 constexpr auto CATALOGUE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 3;
21 constexpr auto CATALOGUE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 3;
22 constexpr auto DATABASE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 4;
22 constexpr auto DATABASE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 4;
23
23
24
24
25 struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
25 struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
26
26
27 CatalogueTreeModel *m_TreeModel = nullptr;
27 CatalogueTreeModel *m_TreeModel = nullptr;
28
28
29 void configureTreeWidget(QTreeView *treeView);
29 void configureTreeWidget(QTreeView *treeView);
30 QModelIndex addDatabaseItem(const QString &name);
30 QModelIndex addDatabaseItem(const QString &name);
31 CatalogueAbstractTreeItem *getDatabaseItem(const QString &name);
31 CatalogueAbstractTreeItem *getDatabaseItem(const QString &name);
32 void addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
32 void addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
33 const QModelIndex &databaseIndex);
33 const QModelIndex &databaseIndex);
34
34
35 CatalogueTreeItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue) const;
35 CatalogueTreeItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue) const;
36 void setHasChanges(bool value, const QModelIndex &index, QTreeView *treeView);
36 void setHasChanges(bool value, const QModelIndex &index, QTreeView *treeView);
37 bool hasChanges(const QModelIndex &index, QTreeView *treeView);
37 bool hasChanges(const QModelIndex &index, QTreeView *treeView);
38
39 int selectionType(QTreeView *treeView) const
40 {
41 auto selectedItems = treeView->selectionModel()->selectedRows();
42 if (selectedItems.isEmpty()) {
43 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
44 }
45 else {
46 auto firstIndex = selectedItems.first();
47 auto firstItem = m_TreeModel->item(firstIndex);
48 if (!firstItem) {
49 Q_ASSERT(false);
50 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
51 }
52 auto selectionType = firstItem->type();
53
54 for (auto itemIndex : selectedItems) {
55 auto item = m_TreeModel->item(itemIndex);
56 if (!item || item->type() != selectionType) {
57 // Incoherent multi selection
58 selectionType = CatalogueAbstractTreeItem::DEFAULT_TYPE;
59 break;
60 }
61 }
62
63 return selectionType;
64 }
65 }
66
67 QVector<std::shared_ptr<DBCatalogue> > selectedCatalogues(QTreeView *treeView) const
68 {
69 QVector<std::shared_ptr<DBCatalogue> > catalogues;
70 auto selectedItems = treeView->selectionModel()->selectedRows();
71 for (auto itemIndex : selectedItems) {
72 auto item = m_TreeModel->item(itemIndex);
73 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
74 catalogues.append(static_cast<CatalogueTreeItem *>(item)->catalogue());
75 }
76 }
77
78 return catalogues;
79 }
80
81 QStringList selectedRepositories(QTreeView *treeView) const
82 {
83 QStringList repositories;
84 auto selectedItems = treeView->selectionModel()->selectedRows();
85 for (auto itemIndex : selectedItems) {
86 auto item = m_TreeModel->item(itemIndex);
87 if (item && item->type() == DATABASE_ITEM_TYPE) {
88 repositories.append(item->text());
89 }
90 }
91
92 return repositories;
93 }
38 };
94 };
39
95
40 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
96 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
41 : QWidget(parent),
97 : QWidget(parent),
42 ui(new Ui::CatalogueSideBarWidget),
98 ui(new Ui::CatalogueSideBarWidget),
43 impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
99 impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
44 {
100 {
45 ui->setupUi(this);
101 ui->setupUi(this);
46
102
47 impl->m_TreeModel = new CatalogueTreeModel(this);
103 impl->m_TreeModel = new CatalogueTreeModel(this);
48 ui->treeView->setModel(impl->m_TreeModel);
104 ui->treeView->setModel(impl->m_TreeModel);
49
105
50 impl->configureTreeWidget(ui->treeView);
106 impl->configureTreeWidget(ui->treeView);
51
107
52 ui->treeView->header()->setStretchLastSection(false);
108 ui->treeView->header()->setStretchLastSection(false);
53 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
109 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
54 ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
110 ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
55
111
56 auto emitSelection = [this]() {
112 auto emitSelection = [this]() {
57
113
58 auto selectedItems = ui->treeView->selectionModel()->selectedRows();
114 auto selectionType = impl->selectionType(ui->treeView);
59 if (selectedItems.isEmpty()) {
115
60 emit this->selectionCleared();
116 switch (selectionType) {
117 case CATALOGUE_ITEM_TYPE:
118 emit this->catalogueSelected(impl->selectedCatalogues(ui->treeView));
119 break;
120 case DATABASE_ITEM_TYPE:
121 emit this->databaseSelected(impl->selectedRepositories(ui->treeView));
122 break;
123 case ALL_EVENT_ITEM_TYPE:
124 emit this->allEventsSelected();
125 break;
126 case TRASH_ITEM_TYPE:
127 emit this->trashSelected();
128 break;
129 default:
130 emit this->selectionCleared();
131 break;
61 }
132 }
62 else {
63 QVector<std::shared_ptr<DBCatalogue> > catalogues;
64 QStringList databases;
65 auto firstIndex = selectedItems.first();
66 auto firstItem = impl->m_TreeModel->item(firstIndex);
67 if (!firstItem) {
68 Q_ASSERT(false);
69 return;
70 }
71 auto selectionType = firstItem->type();
72
73 for (auto itemIndex : selectedItems) {
74 auto item = impl->m_TreeModel->item(itemIndex);
75 if (item && item->type() == selectionType) {
76 switch (selectionType) {
77 case CATALOGUE_ITEM_TYPE:
78 catalogues.append(static_cast<CatalogueTreeItem *>(item)->catalogue());
79 break;
80 case DATABASE_ITEM_TYPE:
81 databases.append(item->text());
82 case ALL_EVENT_ITEM_TYPE: // fallthrough
83 case TRASH_ITEM_TYPE: // fallthrough
84 default:
85 break;
86 }
87 }
88 else {
89 // Incoherent multi selection
90 selectionType = -1;
91 break;
92 }
93 }
94
95 switch (selectionType) {
96 case CATALOGUE_ITEM_TYPE:
97 emit this->catalogueSelected(catalogues);
98 break;
99 case DATABASE_ITEM_TYPE:
100 emit this->databaseSelected(databases);
101 break;
102 case ALL_EVENT_ITEM_TYPE:
103 emit this->allEventsSelected();
104 break;
105 case TRASH_ITEM_TYPE:
106 emit this->trashSelected();
107 break;
108 default:
109 emit this->selectionCleared();
110 break;
111 }
112 }
113
114
115 };
133 };
116
134
117 connect(ui->treeView, &QTreeView::clicked, emitSelection);
135 connect(ui->treeView, &QTreeView::clicked, emitSelection);
118 connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, emitSelection);
136 connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, emitSelection);
119 connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [emitSelection, this](auto index) {
137 connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [emitSelection, this](auto index) {
120 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
138 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
121 if (selectedIndexes.contains(index)) {
139 if (selectedIndexes.contains(index)) {
122 emitSelection();
140 emitSelection();
123 }
141 }
124
142
125 auto item = impl->m_TreeModel->item(index);
143 auto item = impl->m_TreeModel->item(index);
126 impl->setHasChanges(true, index, ui->treeView);
144 impl->setHasChanges(true, index, ui->treeView);
127 });
145 });
128
146
129 ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
147 ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
130 connect(ui->treeView, &QTreeView::customContextMenuRequested, this,
148 connect(ui->treeView, &QTreeView::customContextMenuRequested, this,
131 &CatalogueSideBarWidget::onContextMenuRequested);
149 &CatalogueSideBarWidget::onContextMenuRequested);
132 }
150 }
133
151
134 CatalogueSideBarWidget::~CatalogueSideBarWidget()
152 CatalogueSideBarWidget::~CatalogueSideBarWidget()
135 {
153 {
136 delete ui;
154 delete ui;
137 }
155 }
138
156
139 void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
157 void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
140 bool hasChanges)
158 bool hasChanges)
141 {
159 {
142 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
160 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
143 auto index = impl->m_TreeModel->indexOf(catalogueItem);
161 auto index = impl->m_TreeModel->indexOf(catalogueItem);
144 impl->setHasChanges(hasChanges, index, ui->treeView);
162 impl->setHasChanges(hasChanges, index, ui->treeView);
145 // catalogueItem->refresh();
163 // catalogueItem->refresh();
146 }
164 }
147 }
165 }
148
166
149 void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
167 void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
150 {
168 {
151 QMenu menu{this};
169 QMenu menu{this};
152
170
153 auto currentIndex = ui->treeView->currentIndex();
171 auto currentIndex = ui->treeView->currentIndex();
154 auto currentItem = impl->m_TreeModel->item(currentIndex);
172 auto currentItem = impl->m_TreeModel->item(currentIndex);
155 if (!currentItem) {
173 if (!currentItem) {
156 return;
174 return;
157 }
175 }
158
176
159 switch (currentItem->type()) {
177 switch (currentItem->type()) {
160 case CATALOGUE_ITEM_TYPE:
178 case CATALOGUE_ITEM_TYPE:
161 menu.addAction("Rename", [this, currentIndex]() { ui->treeView->edit(currentIndex); });
179 menu.addAction("Rename", [this, currentIndex]() { ui->treeView->edit(currentIndex); });
162 break;
180 break;
163 case DATABASE_ITEM_TYPE:
181 case DATABASE_ITEM_TYPE:
164 break;
182 break;
165 case ALL_EVENT_ITEM_TYPE:
183 case ALL_EVENT_ITEM_TYPE:
166 break;
184 break;
167 case TRASH_ITEM_TYPE:
185 case TRASH_ITEM_TYPE:
168 menu.addAction("Empty Trash", []() {
186 menu.addAction("Empty Trash", []() {
169 // TODO
187 // TODO
170 });
188 });
171 break;
189 break;
172 default:
190 default:
173 break;
191 break;
174 }
192 }
175
193
176 if (!menu.isEmpty()) {
194 if (!menu.isEmpty()) {
177 menu.exec(ui->treeView->mapToGlobal(pos));
195 menu.exec(ui->treeView->mapToGlobal(pos));
178 }
196 }
179 }
197 }
180
198
181 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(QTreeView *treeView)
199 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(QTreeView *treeView)
182 {
200 {
183 auto allEventsItem = new CatalogueTextTreeItem{QIcon{":/icones/allEvents.png"}, "All Events",
201 auto allEventsItem = new CatalogueTextTreeItem{QIcon{":/icones/allEvents.png"}, "All Events",
184 ALL_EVENT_ITEM_TYPE};
202 ALL_EVENT_ITEM_TYPE};
185 m_TreeModel->addTopLevelItem(allEventsItem);
203 m_TreeModel->addTopLevelItem(allEventsItem);
186
204
187 auto trashItem
205 auto trashItem
188 = new CatalogueTextTreeItem{QIcon{":/icones/trash.png"}, "Trash", TRASH_ITEM_TYPE};
206 = new CatalogueTextTreeItem{QIcon{":/icones/trash.png"}, "Trash", TRASH_ITEM_TYPE};
189 m_TreeModel->addTopLevelItem(trashItem);
207 m_TreeModel->addTopLevelItem(trashItem);
190
208
191 auto separator = new QFrame{treeView};
209 auto separator = new QFrame{treeView};
192 separator->setFrameShape(QFrame::HLine);
210 separator->setFrameShape(QFrame::HLine);
193 auto separatorItem
211 auto separatorItem
194 = new CatalogueTextTreeItem{QIcon{}, QString{}, CatalogueAbstractTreeItem::DEFAULT_TYPE};
212 = new CatalogueTextTreeItem{QIcon{}, QString{}, CatalogueAbstractTreeItem::DEFAULT_TYPE};
195 separatorItem->setEnabled(false);
213 separatorItem->setEnabled(false);
196 auto separatorIndex = m_TreeModel->addTopLevelItem(separatorItem);
214 auto separatorIndex = m_TreeModel->addTopLevelItem(separatorItem);
197 treeView->setIndexWidget(separatorIndex, separator);
215 treeView->setIndexWidget(separatorIndex, separator);
198
216
199 auto repositories = sqpApp->catalogueController().getRepositories();
217 auto repositories = sqpApp->catalogueController().getRepositories();
200 for (auto dbname : repositories) {
218 for (auto dbname : repositories) {
201 auto dbIndex = addDatabaseItem(dbname);
219 auto dbIndex = addDatabaseItem(dbname);
202 auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname);
220 auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname);
203 for (auto catalogue : catalogues) {
221 for (auto catalogue : catalogues) {
204 addCatalogueItem(catalogue, dbIndex);
222 addCatalogueItem(catalogue, dbIndex);
205 }
223 }
206 }
224 }
207
225
208 treeView->expandAll();
226 treeView->expandAll();
209 }
227 }
210
228
211 QModelIndex
229 QModelIndex
212 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name)
230 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name)
213 {
231 {
214 auto databaseItem
232 auto databaseItem
215 = new CatalogueTextTreeItem{QIcon{":/icones/database.png"}, {name}, DATABASE_ITEM_TYPE};
233 = new CatalogueTextTreeItem{QIcon{":/icones/database.png"}, {name}, DATABASE_ITEM_TYPE};
216 auto databaseIndex = m_TreeModel->addTopLevelItem(databaseItem);
234 auto databaseIndex = m_TreeModel->addTopLevelItem(databaseItem);
217
235
218 return databaseIndex;
236 return databaseIndex;
219 }
237 }
220
238
221 CatalogueAbstractTreeItem *
239 CatalogueAbstractTreeItem *
222 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name)
240 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name)
223 {
241 {
224 for (auto item : m_TreeModel->topLevelItems()) {
242 for (auto item : m_TreeModel->topLevelItems()) {
225 if (item->type() == DATABASE_ITEM_TYPE && item->text() == name) {
243 if (item->type() == DATABASE_ITEM_TYPE && item->text() == name) {
226 return item;
244 return item;
227 }
245 }
228 }
246 }
229
247
230 return nullptr;
248 return nullptr;
231 }
249 }
232
250
233 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
251 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
234 const std::shared_ptr<DBCatalogue> &catalogue, const QModelIndex &databaseIndex)
252 const std::shared_ptr<DBCatalogue> &catalogue, const QModelIndex &databaseIndex)
235 {
253 {
236 auto catalogueItem
254 auto catalogueItem
237 = new CatalogueTreeItem{catalogue, QIcon{":/icones/catalogue.png"}, CATALOGUE_ITEM_TYPE};
255 = new CatalogueTreeItem{catalogue, QIcon{":/icones/catalogue.png"}, CATALOGUE_ITEM_TYPE};
238 m_TreeModel->addChildItem(catalogueItem, databaseIndex);
256 m_TreeModel->addChildItem(catalogueItem, databaseIndex);
239 }
257 }
240
258
241 CatalogueTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
259 CatalogueTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
242 const std::shared_ptr<DBCatalogue> &catalogue) const
260 const std::shared_ptr<DBCatalogue> &catalogue) const
243 {
261 {
244 for (auto item : m_TreeModel->topLevelItems()) {
262 for (auto item : m_TreeModel->topLevelItems()) {
245 if (item->type() == DATABASE_ITEM_TYPE) {
263 if (item->type() == DATABASE_ITEM_TYPE) {
246 for (auto childItem : item->children()) {
264 for (auto childItem : item->children()) {
247 if (childItem->type() == CATALOGUE_ITEM_TYPE) {
265 if (childItem->type() == CATALOGUE_ITEM_TYPE) {
248 auto catalogueItem = static_cast<CatalogueTreeItem *>(childItem);
266 auto catalogueItem = static_cast<CatalogueTreeItem *>(childItem);
249 if (catalogueItem->catalogue() == catalogue) {
267 if (catalogueItem->catalogue() == catalogue) {
250 return catalogueItem;
268 return catalogueItem;
251 }
269 }
252 }
270 }
253 else {
271 else {
254 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
272 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
255 "structure. A database item should "
273 "structure. A database item should "
256 "only contain catalogues.";
274 "only contain catalogues.";
257 Q_ASSERT(false);
275 Q_ASSERT(false);
258 }
276 }
259 }
277 }
260 }
278 }
261 }
279 }
262
280
263 return nullptr;
281 return nullptr;
264 }
282 }
265
283
266 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(bool value,
284 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(bool value,
267 const QModelIndex &index,
285 const QModelIndex &index,
268 QTreeView *treeView)
286 QTreeView *treeView)
269 {
287 {
270 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
288 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
271 if (value) {
289 if (value) {
272 if (!hasChanges(validationIndex, treeView)) {
290 if (!hasChanges(validationIndex, treeView)) {
273 auto widget = CatalogueExplorerHelper::buildValidationWidget(
291 auto widget = CatalogueExplorerHelper::buildValidationWidget(
274 treeView,
292 treeView,
275 [this, validationIndex, treeView]() {
293 [this, validationIndex, treeView]() {
276 setHasChanges(false, validationIndex, treeView);
294 setHasChanges(false, validationIndex, treeView);
277 },
295 },
278 [this, validationIndex, treeView]() {
296 [this, validationIndex, treeView]() {
279 setHasChanges(false, validationIndex, treeView);
297 setHasChanges(false, validationIndex, treeView);
280 });
298 });
281 treeView->setIndexWidget(validationIndex, widget);
299 treeView->setIndexWidget(validationIndex, widget);
282 }
300 }
283 }
301 }
284 else {
302 else {
285 // Note: the widget is destroyed
303 // Note: the widget is destroyed
286 treeView->setIndexWidget(validationIndex, nullptr);
304 treeView->setIndexWidget(validationIndex, nullptr);
287 }
305 }
288 }
306 }
289
307
290 bool CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::hasChanges(const QModelIndex &index,
308 bool CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::hasChanges(const QModelIndex &index,
291 QTreeView *treeView)
309 QTreeView *treeView)
292 {
310 {
293 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
311 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
294 return treeView->indexWidget(validationIndex) != nullptr;
312 return treeView->indexWidget(validationIndex) != nullptr;
295 }
313 }
@@ -1,74 +1,81
1 #include "Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h"
1 #include "Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h"
2
2
3 struct CatalogueAbstractTreeItem::CatalogueAbstractTreeItemPrivate {
3 struct CatalogueAbstractTreeItem::CatalogueAbstractTreeItemPrivate {
4 int m_Type;
4 int m_Type;
5 QVector<CatalogueAbstractTreeItem *> m_Children;
5 QVector<CatalogueAbstractTreeItem *> m_Children;
6 CatalogueAbstractTreeItem *m_Parent = nullptr;
6 CatalogueAbstractTreeItem *m_Parent = nullptr;
7
7
8 CatalogueAbstractTreeItemPrivate(int type) : m_Type(type) {}
8 CatalogueAbstractTreeItemPrivate(int type) : m_Type(type) {}
9 };
9 };
10
10
11 CatalogueAbstractTreeItem::CatalogueAbstractTreeItem(int type)
11 CatalogueAbstractTreeItem::CatalogueAbstractTreeItem(int type)
12 : impl{spimpl::make_unique_impl<CatalogueAbstractTreeItemPrivate>(type)}
12 : impl{spimpl::make_unique_impl<CatalogueAbstractTreeItemPrivate>(type)}
13 {
13 {
14 }
14 }
15
15
16 CatalogueAbstractTreeItem::~CatalogueAbstractTreeItem()
16 CatalogueAbstractTreeItem::~CatalogueAbstractTreeItem()
17 {
17 {
18 qDeleteAll(impl->m_Children);
18 qDeleteAll(impl->m_Children);
19 }
19 }
20
20
21 void CatalogueAbstractTreeItem::addChild(CatalogueAbstractTreeItem *child)
21 void CatalogueAbstractTreeItem::addChild(CatalogueAbstractTreeItem *child)
22 {
22 {
23 impl->m_Children << child;
23 impl->m_Children << child;
24 child->impl->m_Parent = this;
24 child->impl->m_Parent = this;
25 }
25 }
26
26
27 QVector<CatalogueAbstractTreeItem *> CatalogueAbstractTreeItem::children() const
27 QVector<CatalogueAbstractTreeItem *> CatalogueAbstractTreeItem::children() const
28 {
28 {
29 return impl->m_Children;
29 return impl->m_Children;
30 }
30 }
31
31
32 CatalogueAbstractTreeItem *CatalogueAbstractTreeItem::parent() const
32 CatalogueAbstractTreeItem *CatalogueAbstractTreeItem::parent() const
33 {
33 {
34 return impl->m_Parent;
34 return impl->m_Parent;
35 }
35 }
36
36
37 int CatalogueAbstractTreeItem::type() const
37 int CatalogueAbstractTreeItem::type() const
38 {
38 {
39 return impl->m_Type;
39 return impl->m_Type;
40 }
40 }
41
41
42 QString CatalogueAbstractTreeItem::text(int column) const
42 QString CatalogueAbstractTreeItem::text(int column) const
43 {
43 {
44 return data(0, Qt::DisplayRole).toString();
44 return data(0, Qt::DisplayRole).toString();
45 }
45 }
46
46
47 QVariant CatalogueAbstractTreeItem::data(int column, int role) const
47 QVariant CatalogueAbstractTreeItem::data(int column, int role) const
48 {
48 {
49 Q_UNUSED(column);
49 Q_UNUSED(column);
50 Q_UNUSED(role);
50 Q_UNUSED(role);
51 return QVariant();
51 return QVariant();
52 }
52 }
53
53
54 Qt::ItemFlags CatalogueAbstractTreeItem::flags(int column) const
54 Qt::ItemFlags CatalogueAbstractTreeItem::flags(int column) const
55 {
55 {
56 Q_UNUSED(column);
56 Q_UNUSED(column);
57 return Qt::NoItemFlags;
57 return Qt::NoItemFlags;
58 }
58 }
59
59
60 bool CatalogueAbstractTreeItem::setData(int column, int role, const QVariant &value)
60 bool CatalogueAbstractTreeItem::setData(int column, int role, const QVariant &value)
61 {
61 {
62 Q_UNUSED(column);
62 Q_UNUSED(column);
63 Q_UNUSED(role);
63 Q_UNUSED(role);
64 Q_UNUSED(value);
64 Q_UNUSED(value);
65
65
66 return false;
66 return false;
67 }
67 }
68
68
69 bool CatalogueAbstractTreeItem::canDropMimeData(const QMimeData *data, Qt::DropAction action)
69 bool CatalogueAbstractTreeItem::canDropMimeData(const QMimeData *data, Qt::DropAction action)
70 {
70 {
71 Q_UNUSED(data);
71 Q_UNUSED(data);
72 Q_UNUSED(action);
72 Q_UNUSED(action);
73 return false;
73 return false;
74 }
74 }
75
76 bool CatalogueAbstractTreeItem::dropMimeData(const QMimeData *data, Qt::DropAction action)
77 {
78 Q_UNUSED(data);
79 Q_UNUSED(action);
80 return false;
81 }
@@ -1,85 +1,95
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 return data->hasFormat(MIME_TYPE_EVENT_LIST);
79 return data->hasFormat(MIME_TYPE_EVENT_LIST);
80 }
80 }
81
81
82 bool CatalogueTreeItem::dropMimeData(const QMimeData *data, Qt::DropAction action)
83 {
84 Q_ASSERT(canDropMimeData(data, action));
85
86 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
87 // impl->m_Catalogue->addEvents(events); TODO: move events in the new catalogue
88 // Warning: Check that the events aren't already in the catalogue
89 // Also check for the repository !!!
90 }
91
82 std::shared_ptr<DBCatalogue> CatalogueTreeItem::catalogue() const
92 std::shared_ptr<DBCatalogue> CatalogueTreeItem::catalogue() const
83 {
93 {
84 return impl->m_Catalogue;
94 return impl->m_Catalogue;
85 }
95 }
@@ -1,190 +1,201
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(QModelIndex(), QModelIndex());
46 emit dataChanged(parentIndex, parentIndex);
47 }
47 }
48
48
49 CatalogueAbstractTreeItem *CatalogueTreeModel::item(const QModelIndex &index) const
49 CatalogueAbstractTreeItem *CatalogueTreeModel::item(const QModelIndex &index) const
50 {
50 {
51 return static_cast<CatalogueAbstractTreeItem *>(index.internalPointer());
51 return static_cast<CatalogueAbstractTreeItem *>(index.internalPointer());
52 }
52 }
53
53
54 QModelIndex CatalogueTreeModel::indexOf(CatalogueAbstractTreeItem *item, int column) const
54 QModelIndex CatalogueTreeModel::indexOf(CatalogueAbstractTreeItem *item, int column) const
55 {
55 {
56 auto parentItem = item->parent();
56 auto parentItem = item->parent();
57 if (!parentItem) {
57 if (!parentItem) {
58 return QModelIndex();
58 return QModelIndex();
59 }
59 }
60
60
61 auto row = parentItem->children().indexOf(item);
61 auto row = parentItem->children().indexOf(item);
62 return createIndex(row, column, item);
62 return createIndex(row, column, item);
63 }
63 }
64
64
65 QModelIndex CatalogueTreeModel::index(int row, int column, const QModelIndex &parent) const
65 QModelIndex CatalogueTreeModel::index(int row, int column, const QModelIndex &parent) const
66 {
66 {
67 if (column > 0) {
67 if (column > 0) {
68 int a = 0;
68 int a = 0;
69 }
69 }
70
70
71 if (!hasIndex(row, column, parent)) {
71 if (!hasIndex(row, column, parent)) {
72 return QModelIndex();
72 return QModelIndex();
73 }
73 }
74
74
75 CatalogueAbstractTreeItem *parentItem = nullptr;
75 CatalogueAbstractTreeItem *parentItem = nullptr;
76
76
77 if (!parent.isValid()) {
77 if (!parent.isValid()) {
78 parentItem = impl->m_RootItem.get();
78 parentItem = impl->m_RootItem.get();
79 }
79 }
80 else {
80 else {
81 parentItem = item(parent);
81 parentItem = item(parent);
82 }
82 }
83
83
84 auto childItem = parentItem->children().value(row);
84 auto childItem = parentItem->children().value(row);
85 if (childItem) {
85 if (childItem) {
86 return createIndex(row, column, childItem);
86 return createIndex(row, column, childItem);
87 }
87 }
88
88
89 return QModelIndex();
89 return QModelIndex();
90 }
90 }
91
91
92
92
93 QModelIndex CatalogueTreeModel::parent(const QModelIndex &index) const
93 QModelIndex CatalogueTreeModel::parent(const QModelIndex &index) const
94 {
94 {
95 if (!index.isValid()) {
95 if (!index.isValid()) {
96 return QModelIndex();
96 return QModelIndex();
97 }
97 }
98
98
99 auto childItem = item(index);
99 auto childItem = item(index);
100 auto parentItem = childItem->parent();
100 auto parentItem = childItem->parent();
101
101
102 if (parentItem == nullptr || parentItem->parent() == nullptr) {
102 if (parentItem == nullptr || parentItem->parent() == nullptr) {
103 return QModelIndex();
103 return QModelIndex();
104 }
104 }
105
105
106 auto row = parentItem->parent()->children().indexOf(parentItem);
106 auto row = parentItem->parent()->children().indexOf(parentItem);
107 return createIndex(row, 0, parentItem);
107 return createIndex(row, 0, parentItem);
108 }
108 }
109
109
110 int CatalogueTreeModel::rowCount(const QModelIndex &parent) const
110 int CatalogueTreeModel::rowCount(const QModelIndex &parent) const
111 {
111 {
112 CatalogueAbstractTreeItem *parentItem = nullptr;
112 CatalogueAbstractTreeItem *parentItem = nullptr;
113
113
114 if (!parent.isValid()) {
114 if (!parent.isValid()) {
115 parentItem = impl->m_RootItem.get();
115 parentItem = impl->m_RootItem.get();
116 }
116 }
117 else {
117 else {
118 parentItem = item(parent);
118 parentItem = item(parent);
119 }
119 }
120
120
121 return parentItem->children().count();
121 return parentItem->children().count();
122 }
122 }
123
123
124 int CatalogueTreeModel::columnCount(const QModelIndex &parent) const
124 int CatalogueTreeModel::columnCount(const QModelIndex &parent) const
125 {
125 {
126 return (int)Column::Count;
126 return (int)Column::Count;
127 }
127 }
128
128
129 Qt::ItemFlags CatalogueTreeModel::flags(const QModelIndex &index) const
129 Qt::ItemFlags CatalogueTreeModel::flags(const QModelIndex &index) const
130 {
130 {
131 auto treeItem = item(index);
131 auto treeItem = item(index);
132 if (treeItem) {
132 if (treeItem) {
133 return treeItem->flags(index.column());
133 return treeItem->flags(index.column());
134 }
134 }
135
135
136 return Qt::NoItemFlags;
136 return Qt::NoItemFlags;
137 }
137 }
138
138
139 QVariant CatalogueTreeModel::data(const QModelIndex &index, int role) const
139 QVariant CatalogueTreeModel::data(const QModelIndex &index, int role) const
140 {
140 {
141 auto treeItem = item(index);
141 auto treeItem = item(index);
142 if (treeItem) {
142 if (treeItem) {
143 return treeItem->data(index.column(), role);
143 return treeItem->data(index.column(), role);
144 }
144 }
145
145
146 return QModelIndex();
146 return QModelIndex();
147 }
147 }
148
148
149 bool CatalogueTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
149 bool CatalogueTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
150 {
150 {
151 auto treeItem = item(index);
151 auto treeItem = item(index);
152 if (treeItem) {
152 if (treeItem) {
153 auto result = treeItem->setData(index.column(), role, value);
153 auto result = treeItem->setData(index.column(), role, value);
154
154
155 if (result && index.column() == (int)Column::Name) {
155 if (result && index.column() == (int)Column::Name) {
156 emit itemRenamed(index);
156 emit itemRenamed(index);
157 }
157 }
158
158
159 return result;
159 return result;
160 }
160 }
161
161
162 return false;
162 return false;
163 }
163 }
164 bool CatalogueTreeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
164 bool CatalogueTreeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
165 int column, const QModelIndex &parent) const
165 int column, const QModelIndex &parent) const
166 {
166 {
167 auto draggedIndex = parent;
167 auto draggedIndex = parent;
168 auto draggedItem = item(draggedIndex);
168 auto draggedItem = item(draggedIndex);
169 if (draggedItem) {
169 if (draggedItem) {
170 return draggedItem->canDropMimeData(data, action);
170 return draggedItem->canDropMimeData(data, action);
171 }
171 }
172
172
173 return false;
173 return false;
174 }
174 }
175
175
176 bool CatalogueTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row,
176 bool CatalogueTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row,
177 int column, const QModelIndex &parent)
177 int column, const QModelIndex &parent)
178 {
178 {
179 return false;
179 bool result = false;
180
181 auto draggedIndex = parent;
182 auto draggedItem = item(draggedIndex);
183 if (draggedItem) {
184 result = draggedItem->dropMimeData(data, action);
185 if (result) {
186 emit itemDropped(draggedIndex);
187 }
188 }
189
190 return result;
180 }
191 }
181
192
182 Qt::DropActions CatalogueTreeModel::supportedDropActions() const
193 Qt::DropActions CatalogueTreeModel::supportedDropActions() const
183 {
194 {
184 return Qt::CopyAction | Qt::MoveAction;
195 return Qt::CopyAction | Qt::MoveAction;
185 }
196 }
186
197
187 QStringList CatalogueTreeModel::mimeTypes() const
198 QStringList CatalogueTreeModel::mimeTypes() const
188 {
199 {
189 return {MIME_TYPE_EVENT_LIST};
200 return {MIME_TYPE_EVENT_LIST};
190 }
201 }
@@ -1,97 +1,100
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>CatalogueSideBarWidget</class>
3 <class>CatalogueSideBarWidget</class>
4 <widget class="QWidget" name="CatalogueSideBarWidget">
4 <widget class="QWidget" name="CatalogueSideBarWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>330</width>
9 <width>330</width>
10 <height>523</height>
10 <height>523</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="windowTitle">
13 <property name="windowTitle">
14 <string>Form</string>
14 <string>Form</string>
15 </property>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout">
16 <layout class="QVBoxLayout" name="verticalLayout">
17 <property name="leftMargin">
17 <property name="leftMargin">
18 <number>0</number>
18 <number>0</number>
19 </property>
19 </property>
20 <property name="topMargin">
20 <property name="topMargin">
21 <number>0</number>
21 <number>0</number>
22 </property>
22 </property>
23 <property name="rightMargin">
23 <property name="rightMargin">
24 <number>0</number>
24 <number>0</number>
25 </property>
25 </property>
26 <property name="bottomMargin">
26 <property name="bottomMargin">
27 <number>0</number>
27 <number>0</number>
28 </property>
28 </property>
29 <item>
29 <item>
30 <layout class="QHBoxLayout" name="horizontalLayout">
30 <layout class="QHBoxLayout" name="horizontalLayout">
31 <item>
31 <item>
32 <widget class="QToolButton" name="btnAdd">
32 <widget class="QToolButton" name="btnAdd">
33 <property name="text">
33 <property name="text">
34 <string>+</string>
34 <string>+</string>
35 </property>
35 </property>
36 <property name="icon">
36 <property name="icon">
37 <iconset resource="../../resources/sqpguiresources.qrc">
37 <iconset resource="../../resources/sqpguiresources.qrc">
38 <normaloff>:/icones/add.png</normaloff>:/icones/add.png</iconset>
38 <normaloff>:/icones/add.png</normaloff>:/icones/add.png</iconset>
39 </property>
39 </property>
40 <property name="autoRaise">
40 <property name="autoRaise">
41 <bool>true</bool>
41 <bool>true</bool>
42 </property>
42 </property>
43 </widget>
43 </widget>
44 </item>
44 </item>
45 <item>
45 <item>
46 <widget class="QToolButton" name="btnRemove">
46 <widget class="QToolButton" name="btnRemove">
47 <property name="text">
47 <property name="text">
48 <string> - </string>
48 <string> - </string>
49 </property>
49 </property>
50 <property name="icon">
50 <property name="icon">
51 <iconset resource="../../resources/sqpguiresources.qrc">
51 <iconset resource="../../resources/sqpguiresources.qrc">
52 <normaloff>:/icones/remove.png</normaloff>:/icones/remove.png</iconset>
52 <normaloff>:/icones/remove.png</normaloff>:/icones/remove.png</iconset>
53 </property>
53 </property>
54 <property name="autoRaise">
54 <property name="autoRaise">
55 <bool>true</bool>
55 <bool>true</bool>
56 </property>
56 </property>
57 </widget>
57 </widget>
58 </item>
58 </item>
59 <item>
59 <item>
60 <spacer name="horizontalSpacer">
60 <spacer name="horizontalSpacer">
61 <property name="orientation">
61 <property name="orientation">
62 <enum>Qt::Horizontal</enum>
62 <enum>Qt::Horizontal</enum>
63 </property>
63 </property>
64 <property name="sizeHint" stdset="0">
64 <property name="sizeHint" stdset="0">
65 <size>
65 <size>
66 <width>40</width>
66 <width>40</width>
67 <height>20</height>
67 <height>20</height>
68 </size>
68 </size>
69 </property>
69 </property>
70 </spacer>
70 </spacer>
71 </item>
71 </item>
72 </layout>
72 </layout>
73 </item>
73 </item>
74 <item>
74 <item>
75 <widget class="QTreeView" name="treeView">
75 <widget class="QTreeView" name="treeView">
76 <property name="acceptDrops">
76 <property name="acceptDrops">
77 <bool>true</bool>
77 <bool>true</bool>
78 </property>
78 </property>
79 <property name="dragDropMode">
79 <property name="dragDropMode">
80 <enum>QAbstractItemView::DragDrop</enum>
80 <enum>QAbstractItemView::DragDrop</enum>
81 </property>
81 </property>
82 <property name="selectionMode">
83 <enum>QAbstractItemView::ExtendedSelection</enum>
84 </property>
82 <attribute name="headerVisible">
85 <attribute name="headerVisible">
83 <bool>false</bool>
86 <bool>false</bool>
84 </attribute>
87 </attribute>
85 <attribute name="headerStretchLastSection">
88 <attribute name="headerStretchLastSection">
86 <bool>false</bool>
89 <bool>false</bool>
87 </attribute>
90 </attribute>
88 </widget>
91 </widget>
89 </item>
92 </item>
90 </layout>
93 </layout>
91 </widget>
94 </widget>
92 <resources>
95 <resources>
93 <include location="../../resources/sqpguiresources.qrc"/>
96 <include location="../../resources/sqpguiresources.qrc"/>
94 <include location="../../resources/sqpguiresources.qrc"/>
97 <include location="../../resources/sqpguiresources.qrc"/>
95 </resources>
98 </resources>
96 <connections/>
99 <connections/>
97 </ui>
100 </ui>
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

Status change > Approved

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