##// END OF EJS Templates
Add catalogue handling
perrinel -
r1356:3771be3f513d
parent child
Show More
@@ -1,85 +1,86
1 1 #ifndef SCIQLOP_CATALOGUECONTROLLER_H
2 2 #define SCIQLOP_CATALOGUECONTROLLER_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Data/SqpRange.h>
7 7
8 8 #include <QLoggingCategory>
9 9 #include <QObject>
10 10 #include <QUuid>
11 11
12 12 #include <Common/spimpl.h>
13 13
14 14 #include <memory>
15 15
16 16 class DBCatalogue;
17 17 class DBEvent;
18 18 class DBEventProduct;
19 19
20 20 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueController)
21 21
22 22 class DataSourceItem;
23 23 class Variable;
24 24
25 25 /**
26 26 * @brief The CatalogueController class aims to handle catalogues and event using the CatalogueAPI
27 27 * library.
28 28 */
29 29 class SCIQLOP_CORE_EXPORT CatalogueController : public QObject {
30 30 Q_OBJECT
31 31 public:
32 32 explicit CatalogueController(QObject *parent = 0);
33 33 virtual ~CatalogueController();
34 34
35 35 // DB
36 36 QStringList getRepositories() const;
37 37 void addDB(const QString &dbPath);
38 38 void saveDB(const QString &destinationPath, const QString &repository);
39 39
40 40 // Event
41 41 /// retrieveEvents with empty repository retrieve them from the default repository
42 42 std::list<std::shared_ptr<DBEvent> > retrieveEvents(const QString &repository) const;
43 43 std::list<std::shared_ptr<DBEvent> > retrieveAllEvents() const;
44 44
45 45 void addEvent(std::shared_ptr<DBEvent> event);
46 46 void updateEvent(std::shared_ptr<DBEvent> event);
47 47 void updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct);
48 48 void removeEvent(std::shared_ptr<DBEvent> event);
49 49 // void trashEvent(std::shared_ptr<DBEvent> event);
50 50 // void restore(std::shared_ptr<DBEvent> event);
51 51 void saveEvent(std::shared_ptr<DBEvent> event);
52 52 void discardEvent(std::shared_ptr<DBEvent> event, bool &removed);
53 53 bool eventHasChanges(std::shared_ptr<DBEvent> event) const;
54 54
55 55 // Catalogue
56 56 std::list<std::shared_ptr<DBEvent> >
57 57 retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const;
58 58
59 59 /// retrieveEvents with empty repository retrieve them from the default repository
60 60 std::list<std::shared_ptr<DBCatalogue> > retrieveCatalogues(const QString &repository
61 61 = QString()) const;
62 62 void addCatalogue(std::shared_ptr<DBCatalogue> catalogue);
63 63 void updateCatalogue(std::shared_ptr<DBCatalogue> catalogue);
64 64 void removeCatalogue(std::shared_ptr<DBCatalogue> catalogue);
65 65 void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue);
66 void discardCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool &removed);
66 67
67 68 void saveAll();
68 69 bool hasChanges() const;
69 70
70 71 /// Returns the MIME data associated to a list of variables
71 72 QByteArray mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const;
72 73
73 74 /// Returns the list of variables contained in a MIME data
74 75 QVector<std::shared_ptr<DBEvent> > eventsForMimeData(const QByteArray &mimeData) const;
75 76
76 77 public slots:
77 78 /// Manage init/end of the controller
78 79 void initialize();
79 80
80 81 private:
81 82 class CatalogueControllerPrivate;
82 83 spimpl::unique_impl_ptr<CatalogueControllerPrivate> impl;
83 84 };
84 85
85 86 #endif // SCIQLOP_CATALOGUECONTROLLER_H
@@ -1,492 +1,526
1 1 #include <Catalogue/CatalogueController.h>
2 2
3 3 #include <Variable/Variable.h>
4 4
5 5 #include <CatalogueDao.h>
6 6
7 7 #include <ComparaisonPredicate.h>
8 8 #include <CompoundPredicate.h>
9 9 #include <DBCatalogue.h>
10 10 #include <DBEvent.h>
11 11 #include <DBEventProduct.h>
12 12 #include <DBTag.h>
13 13 #include <IRequestPredicate.h>
14 14
15 15 #include <QDataStream>
16 16 #include <QMutex>
17 17 #include <QThread>
18 18
19 19 #include <QDir>
20 20 #include <QStandardPaths>
21 21
22 22 Q_LOGGING_CATEGORY(LOG_CatalogueController, "CatalogueController")
23 23
24 24 namespace {
25 25
26 26 static QString REPOSITORY_WORK_SUFFIX = QString{"_work"};
27 27 static QString REPOSITORY_TRASH_SUFFIX = QString{"_trash"};
28 28 }
29 29
30 30 /**
31 31 * Possible types of an repository
32 32 */
33 enum class DBType { SYNC, WORK, TRASH};
33 enum class DBType { SYNC, WORK, TRASH };
34 34 class CatalogueController::CatalogueControllerPrivate {
35 35
36 36 public:
37 37 explicit CatalogueControllerPrivate(CatalogueController *parent) : m_Q{parent} {}
38 38
39 39 CatalogueDao m_CatalogueDao;
40 40
41 41 QStringList m_RepositoryList;
42 42 CatalogueController *m_Q;
43 43
44 QSet<QString> m_EventKeysWithChanges;
44 QSet<QString> m_KeysWithChanges;
45 45
46 46 QString eventUniqueKey(const std::shared_ptr<DBEvent> &event) const;
47 QString catalogueUniqueKey(const std::shared_ptr<DBCatalogue> &catalogue) const;
47 48
48 49 void copyDBtoDB(const QString &dbFrom, const QString &dbTo);
49 50 QString toWorkRepository(QString repository);
50 51 QString toSyncRepository(QString repository);
51 52 void savAllDB();
52 53
53 54 void saveEvent(std::shared_ptr<DBEvent> event, bool persist = true);
54 55 void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool persist = true);
55 56
56 std::shared_ptr<IRequestPredicate> createFinder(const QUuid& uniqId, const QString & repository, DBType type);
57 std::shared_ptr<IRequestPredicate> createFinder(const QUuid &uniqId, const QString &repository,
58 DBType type);
57 59 };
58 60
59 61 CatalogueController::CatalogueController(QObject *parent)
60 62 : impl{spimpl::make_unique_impl<CatalogueControllerPrivate>(this)}
61 63 {
62 64 qCDebug(LOG_CatalogueController()) << tr("CatalogueController construction")
63 65 << QThread::currentThread();
64 66 }
65 67
66 68 CatalogueController::~CatalogueController()
67 69 {
68 70 qCDebug(LOG_CatalogueController()) << tr("CatalogueController destruction")
69 71 << QThread::currentThread();
70 72 }
71 73
72 74 QStringList CatalogueController::getRepositories() const
73 75 {
74 76 return impl->m_RepositoryList;
75 77 }
76 78
77 79 void CatalogueController::addDB(const QString &dbPath)
78 80 {
79 81 QDir dbDir(dbPath);
80 82 if (dbDir.exists()) {
81 83 auto dirName = dbDir.dirName();
82 84
83 85 if (std::find(impl->m_RepositoryList.cbegin(), impl->m_RepositoryList.cend(), dirName)
84 86 != impl->m_RepositoryList.cend()) {
85 87 qCCritical(LOG_CatalogueController())
86 88 << tr("Impossible to addDB that is already loaded");
87 89 }
88 90
89 91 if (!impl->m_CatalogueDao.addDB(dbPath, dirName)) {
90 92 qCCritical(LOG_CatalogueController())
91 93 << tr("Impossible to addDB %1 from %2 ").arg(dirName, dbPath);
92 94 }
93 95 else {
94 96 impl->m_RepositoryList << dirName;
95 97 impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName));
96 98 }
97 99 }
98 100 else {
99 101 qCCritical(LOG_CatalogueController()) << tr("Impossible to addDB that not exists: ")
100 102 << dbPath;
101 103 }
102 104 }
103 105
104 106 void CatalogueController::saveDB(const QString &destinationPath, const QString &repository)
105 107 {
106 108 if (!impl->m_CatalogueDao.saveDB(destinationPath, repository)) {
107 109 qCCritical(LOG_CatalogueController())
108 110 << tr("Impossible to saveDB %1 from %2 ").arg(repository, destinationPath);
109 111 }
110 112 }
111 113
112 114 std::list<std::shared_ptr<DBEvent> >
113 115 CatalogueController::retrieveEvents(const QString &repository) const
114 116 {
115 117 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
116 118
117 119 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
118 120 auto events = impl->m_CatalogueDao.getEvents(impl->toWorkRepository(dbDireName));
119 121 for (auto event : events) {
120 122 eventsShared.push_back(std::make_shared<DBEvent>(event));
121 123 }
122 124 return eventsShared;
123 125 }
124 126
125 127 std::list<std::shared_ptr<DBEvent> > CatalogueController::retrieveAllEvents() const
126 128 {
127 129 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
128 130 for (auto repository : impl->m_RepositoryList) {
129 131 eventsShared.splice(eventsShared.end(), retrieveEvents(repository));
130 132 }
131 133
132 134 return eventsShared;
133 135 }
134 136
135 137 std::list<std::shared_ptr<DBEvent> >
136 138 CatalogueController::retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const
137 139 {
138 140 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
139 141 auto events = impl->m_CatalogueDao.getCatalogueEvents(*catalogue);
140 142 for (auto event : events) {
141 143 eventsShared.push_back(std::make_shared<DBEvent>(event));
142 144 }
143 145 return eventsShared;
144 146 }
145 147
146 148 void CatalogueController::updateEvent(std::shared_ptr<DBEvent> event)
147 149 {
148 150 event->setRepository(impl->toWorkRepository(event->getRepository()));
149 151
150 152 auto uniqueId = impl->eventUniqueKey(event);
151 impl->m_EventKeysWithChanges.insert(uniqueId);
153 impl->m_KeysWithChanges.insert(uniqueId);
152 154
153 155 impl->m_CatalogueDao.updateEvent(*event);
154 156 }
155 157
156 158 void CatalogueController::updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct)
157 159 {
158 160 impl->m_CatalogueDao.updateEventProduct(*eventProduct);
159 161 }
160 162
161 163 void CatalogueController::removeEvent(std::shared_ptr<DBEvent> event)
162 164 {
163 165 // Remove it from both repository and repository_work
164 166 event->setRepository(impl->toWorkRepository(event->getRepository()));
165 167 impl->m_CatalogueDao.removeEvent(*event);
166 168 event->setRepository(impl->toSyncRepository(event->getRepository()));
167 169 impl->m_CatalogueDao.removeEvent(*event);
168 170 impl->savAllDB();
169 171 }
170 172
171 173 void CatalogueController::addEvent(std::shared_ptr<DBEvent> event)
172 174 {
173 175 event->setRepository(impl->toWorkRepository(event->getRepository()));
174 176
175 177 auto eventTemp = *event;
176 178 impl->m_CatalogueDao.addEvent(eventTemp);
177 179
178 180 // Call update is necessary at the creation of add Event if it has some tags or some event
179 181 // products
180 182 if (!event->getEventProducts().empty() || !event->getTags().empty()) {
181 183
182 184 auto eventProductsTemp = eventTemp.getEventProducts();
183 185 auto eventProductTempUpdated = std::list<DBEventProduct>{};
184 186 for (auto eventProductTemp : eventProductsTemp) {
185 187 eventProductTemp.setEvent(eventTemp);
186 188 eventProductTempUpdated.push_back(eventProductTemp);
187 189 }
188 190 eventTemp.setEventProducts(eventProductTempUpdated);
189 191
190 192 impl->m_CatalogueDao.updateEvent(eventTemp);
191 193 }
192 194
193 195 auto workPred = impl->createFinder(event->getUniqId(), event->getRepository(), DBType::WORK);
194 196
195 197 auto workEvent = impl->m_CatalogueDao.getEvent(workPred);
196 198 *event = workEvent;
197 199
198 200
199 201 auto uniqueId = impl->eventUniqueKey(event);
200 impl->m_EventKeysWithChanges.insert(uniqueId);
202 impl->m_KeysWithChanges.insert(uniqueId);
201 203 }
202 204
203 205 void CatalogueController::saveEvent(std::shared_ptr<DBEvent> event)
204 206 {
205 207 impl->saveEvent(event, true);
206 impl->m_EventKeysWithChanges.remove(impl->eventUniqueKey(event));
208 impl->m_KeysWithChanges.remove(impl->eventUniqueKey(event));
207 209 }
208 210
209 211 void CatalogueController::discardEvent(std::shared_ptr<DBEvent> event, bool &removed)
210 212 {
211 213 auto syncPred = impl->createFinder(event->getUniqId(), event->getRepository(), DBType::SYNC);
212 214 auto workPred = impl->createFinder(event->getUniqId(), event->getRepository(), DBType::WORK);
213 215
214 216 auto syncEvent = impl->m_CatalogueDao.getEvent(syncPred);
215 217 if (!syncEvent.getUniqId().isNull()) {
216 218 removed = false;
217 219 impl->m_CatalogueDao.copyEvent(syncEvent, impl->toWorkRepository(event->getRepository()),
218 220 true);
219 221
220 222 auto workEvent = impl->m_CatalogueDao.getEvent(workPred);
221 223 *event = workEvent;
222 impl->m_EventKeysWithChanges.remove(impl->eventUniqueKey(event));
224 impl->m_KeysWithChanges.remove(impl->eventUniqueKey(event));
223 225 }
224 226 else {
225 227 removed = true;
226 228 // Since the element wasn't in sync repository. Discard it means remove it
227 229 event->setRepository(impl->toWorkRepository(event->getRepository()));
228 230 impl->m_CatalogueDao.removeEvent(*event);
229 231 }
230 232 }
231 233
232 234 bool CatalogueController::eventHasChanges(std::shared_ptr<DBEvent> event) const
233 235 {
234 return impl->m_EventKeysWithChanges.contains(impl->eventUniqueKey(event));
236 return impl->m_KeysWithChanges.contains(impl->eventUniqueKey(event));
235 237 }
236 238
237 239 std::list<std::shared_ptr<DBCatalogue> >
238 240 CatalogueController::retrieveCatalogues(const QString &repository) const
239 241 {
240 242 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
241 243
242 244 auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
243 245 auto catalogues = impl->m_CatalogueDao.getCatalogues(impl->toWorkRepository(dbDireName));
244 246 for (auto catalogue : catalogues) {
245 247 cataloguesShared.push_back(std::make_shared<DBCatalogue>(catalogue));
246 248 }
247 249 return cataloguesShared;
248 250 }
249 251
250 252 void CatalogueController::addCatalogue(std::shared_ptr<DBCatalogue> catalogue)
251 253 {
252 254 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
253 255
254 256 auto catalogueTemp = *catalogue;
255 257 impl->m_CatalogueDao.addCatalogue(catalogueTemp);
256 258
257 auto workPred = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::WORK);
259 auto workPred
260 = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::WORK);
258 261
259 262 auto workCatalogue = impl->m_CatalogueDao.getCatalogue(workPred);
260 263 *catalogue = workCatalogue;
261 264
262 // auto uniqueId = impl->eventUniqueKey(catalogue);
263 // impl->m_EventKeysWithChanges.insert(uniqueId);
265 auto uniqueId = impl->catalogueUniqueKey(catalogue);
266 impl->m_KeysWithChanges.insert(uniqueId);
264 267 }
265 268
266 269 void CatalogueController::updateCatalogue(std::shared_ptr<DBCatalogue> catalogue)
267 270 {
268 271 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
269 272
270 // auto uniqueId = impl->eventUniqueKey(event);
271 // impl->m_EventKeysWithChanges.insert(uniqueId);
273 auto uniqueId = impl->catalogueUniqueKey(catalogue);
274 impl->m_KeysWithChanges.insert(uniqueId);
272 275
273 276 impl->m_CatalogueDao.updateCatalogue(*catalogue);
274 277 }
275 278
276 279 void CatalogueController::removeCatalogue(std::shared_ptr<DBCatalogue> catalogue)
277 280 {
278 281 // Remove it from both repository and repository_work
279 282 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
280 283 impl->m_CatalogueDao.removeCatalogue(*catalogue);
281 284 catalogue->setRepository(impl->toSyncRepository(catalogue->getRepository()));
282 285 impl->m_CatalogueDao.removeCatalogue(*catalogue);
283 286 impl->savAllDB();
284 287 }
285 288
286 289 void CatalogueController::saveCatalogue(std::shared_ptr<DBCatalogue> catalogue)
287 290 {
288 291 impl->saveCatalogue(catalogue, true);
289 // impl->m_EventKeysWithChanges.remove(impl->eventUniqueKey(event));
292 impl->m_KeysWithChanges.remove(impl->catalogueUniqueKey(catalogue));
293 }
294
295 void CatalogueController::discardCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool &removed)
296 {
297 auto syncPred
298 = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::SYNC);
299 auto workPred
300 = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::WORK);
301
302 auto syncCatalogue = impl->m_CatalogueDao.getCatalogue(syncPred);
303 if (!syncCatalogue.getUniqId().isNull()) {
304 removed = false;
305 impl->m_CatalogueDao.copyCatalogue(
306 syncCatalogue, impl->toWorkRepository(catalogue->getRepository()), true);
307
308 auto workCatalogue = impl->m_CatalogueDao.getCatalogue(workPred);
309 *catalogue = workCatalogue;
310 impl->m_KeysWithChanges.remove(impl->catalogueUniqueKey(catalogue));
311 }
312 else {
313 removed = true;
314 // Since the element wasn't in sync repository. Discard it means remove it
315 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
316 impl->m_CatalogueDao.removeCatalogue(*catalogue);
317 }
290 318 }
291 319
292 320 void CatalogueController::saveAll()
293 321 {
294 322 for (auto repository : impl->m_RepositoryList) {
295 323 // Save Event
296 324 auto events = this->retrieveEvents(repository);
297 325 for (auto event : events) {
298 326 impl->saveEvent(event, false);
299 327 }
300 328
301 329 // Save Catalogue
302 330 auto catalogues = this->retrieveCatalogues(repository);
303 331 for (auto catalogue : catalogues) {
304 332 impl->saveCatalogue(catalogue, false);
305 333 }
306 334 }
307 335
308 336 impl->savAllDB();
309 impl->m_EventKeysWithChanges.clear();
337 impl->m_KeysWithChanges.clear();
310 338 }
311 339
312 340 bool CatalogueController::hasChanges() const
313 341 {
314 return !impl->m_EventKeysWithChanges.isEmpty(); // TODO: catalogues
342 return !impl->m_KeysWithChanges.isEmpty();
315 343 }
316 344
317 345 QByteArray
318 346 CatalogueController::mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const
319 347 {
320 348 auto encodedData = QByteArray{};
321 349
322 350 QMap<QString, QVariantList> idsPerRepository;
323 351 for (auto event : events) {
324 352 idsPerRepository[event->getRepository()] << event->getUniqId();
325 353 }
326 354
327 355 QDataStream stream{&encodedData, QIODevice::WriteOnly};
328 356 stream << idsPerRepository;
329 357
330 358 return encodedData;
331 359 }
332 360
333 361 QVector<std::shared_ptr<DBEvent> >
334 362 CatalogueController::eventsForMimeData(const QByteArray &mimeData) const
335 363 {
336 364 auto events = QVector<std::shared_ptr<DBEvent> >{};
337 365 QDataStream stream{mimeData};
338 366
339 367 QMap<QString, QVariantList> idsPerRepository;
340 368 stream >> idsPerRepository;
341 369
342 370 for (auto it = idsPerRepository.cbegin(); it != idsPerRepository.cend(); ++it) {
343 371 auto repository = it.key();
344 372 auto allRepositoryEvent = retrieveEvents(repository);
345 373 for (auto uuid : it.value()) {
346 374 for (auto repositoryEvent : allRepositoryEvent) {
347 375 if (uuid.toUuid() == repositoryEvent->getUniqId()) {
348 376 events << repositoryEvent;
349 377 }
350 378 }
351 379 }
352 380 }
353 381
354 382 return events;
355 383 }
356 384
357 385 void CatalogueController::initialize()
358 386 {
359 387 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init")
360 388 << QThread::currentThread();
361 389
362 390 impl->m_CatalogueDao.initialize();
363 391 auto defaultRepositoryLocation
364 392 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
365 393
366 394 QDir defaultRepositoryLocationDir;
367 395 if (defaultRepositoryLocationDir.mkpath(defaultRepositoryLocation)) {
368 396 defaultRepositoryLocationDir.cd(defaultRepositoryLocation);
369 397 auto defaultRepository = defaultRepositoryLocationDir.absoluteFilePath(REPOSITORY_DEFAULT);
370 398
371 399 qCInfo(LOG_CatalogueController()) << tr("Persistant data loading from: ")
372 400 << defaultRepository;
373 401
374 402 QDir dbDir(defaultRepository);
375 403 impl->m_RepositoryList << REPOSITORY_DEFAULT;
376 404 if (dbDir.exists()) {
377 405 auto dirName = dbDir.dirName();
378 406
379 407 if (impl->m_CatalogueDao.addDB(defaultRepository, dirName)) {
380 408 impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName));
381 409 }
382 410 }
383 411 else {
384 412 qCInfo(LOG_CatalogueController()) << tr("Initialisation of Default repository detected")
385 413 << defaultRepository;
386 414 }
387 415 }
388 416 else {
389 417 qCWarning(LOG_CatalogueController())
390 418 << tr("Cannot load the persistent default repository from ")
391 419 << defaultRepositoryLocation;
392 420 }
393 421
394 422 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init END");
395 423 }
396 424
397 425 QString CatalogueController::CatalogueControllerPrivate::eventUniqueKey(
398 426 const std::shared_ptr<DBEvent> &event) const
399 427 {
400 428 return event->getUniqId().toString().append(event->getRepository());
401 429 }
402 430
431 QString CatalogueController::CatalogueControllerPrivate::catalogueUniqueKey(
432 const std::shared_ptr<DBCatalogue> &catalogue) const
433 {
434 return catalogue->getUniqId().toString().append(catalogue->getRepository());
435 }
436
403 437 void CatalogueController::CatalogueControllerPrivate::copyDBtoDB(const QString &dbFrom,
404 438 const QString &dbTo)
405 439 {
406 440 // auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
407 441 auto catalogues = m_CatalogueDao.getCatalogues(dbFrom);
408 442 auto events = m_CatalogueDao.getEvents(dbFrom);
409 443 for (auto catalogue : catalogues) {
410 444 m_CatalogueDao.copyCatalogue(catalogue, dbTo, true);
411 445 }
412 446
413 447 for (auto event : events) {
414 448 m_CatalogueDao.copyEvent(event, dbTo, true);
415 449 }
416 450 }
417 451
418 452 QString CatalogueController::CatalogueControllerPrivate::toWorkRepository(QString repository)
419 453 {
420 454 auto syncRepository = toSyncRepository(repository);
421 455
422 456 return QString("%1%2").arg(syncRepository, REPOSITORY_WORK_SUFFIX);
423 457 }
424 458
425 459 QString CatalogueController::CatalogueControllerPrivate::toSyncRepository(QString repository)
426 460 {
427 461 auto syncRepository = repository;
428 462 if (repository.endsWith(REPOSITORY_WORK_SUFFIX)) {
429 463 syncRepository.remove(REPOSITORY_WORK_SUFFIX);
430 464 }
431 465 else if (repository.endsWith(REPOSITORY_TRASH_SUFFIX)) {
432 466 syncRepository.remove(REPOSITORY_TRASH_SUFFIX);
433 467 }
434 468 return syncRepository;
435 469 }
436 470
437 471 void CatalogueController::CatalogueControllerPrivate::savAllDB()
438 472 {
439 473 for (auto repository : m_RepositoryList) {
440 474 auto defaultRepositoryLocation
441 475 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
442 476 m_CatalogueDao.saveDB(defaultRepositoryLocation, repository);
443 477 }
444 478 }
445 479
446 480 void CatalogueController::CatalogueControllerPrivate::saveEvent(std::shared_ptr<DBEvent> event,
447 481 bool persist)
448 482 {
449 483 m_CatalogueDao.copyEvent(*event, toSyncRepository(event->getRepository()), true);
450 484 if (persist) {
451 485 savAllDB();
452 486 }
453 487 }
454 488
455 489 void CatalogueController::CatalogueControllerPrivate::saveCatalogue(
456 490 std::shared_ptr<DBCatalogue> catalogue, bool persist)
457 491 {
458 492 m_CatalogueDao.copyCatalogue(*catalogue, toSyncRepository(catalogue->getRepository()), true);
459 493 if (persist) {
460 494 savAllDB();
461 495 }
462 496 }
463 497
464 std::shared_ptr<IRequestPredicate> CatalogueController::CatalogueControllerPrivate::createFinder(const QUuid &uniqId, const QString &repository, DBType type)
498 std::shared_ptr<IRequestPredicate> CatalogueController::CatalogueControllerPrivate::createFinder(
499 const QUuid &uniqId, const QString &repository, DBType type)
465 500 {
466 501 // update catalogue parameter
467 auto uniqIdPredicate = std::make_shared<ComparaisonPredicate>(
468 QString{"uniqId"}, uniqId, ComparaisonOperation::EQUALEQUAL);
502 auto uniqIdPredicate = std::make_shared<ComparaisonPredicate>(QString{"uniqId"}, uniqId,
503 ComparaisonOperation::EQUALEQUAL);
469 504
470 505 auto repositoryType = repository;
471 506 switch (type) {
472 case DBType::SYNC:
473 repositoryType = toSyncRepository(repositoryType);
474 break;
475 case DBType::WORK:
476 repositoryType =toWorkRepository(repositoryType);
477 break;
478 case DBType::TRASH:
479 default:
480 break;
507 case DBType::SYNC:
508 repositoryType = toSyncRepository(repositoryType);
509 break;
510 case DBType::WORK:
511 repositoryType = toWorkRepository(repositoryType);
512 break;
513 case DBType::TRASH:
514 default:
515 break;
481 516 }
482 517
483 518 auto repositoryPredicate = std::make_shared<ComparaisonPredicate>(
484 QString{"repository"}, repositoryType,
485 ComparaisonOperation::EQUALEQUAL);
519 QString{"repository"}, repositoryType, ComparaisonOperation::EQUALEQUAL);
486 520
487 521 auto finderPred = std::make_shared<CompoundPredicate>(CompoundOperation::AND);
488 522 finderPred->AddRequestPredicate(uniqIdPredicate);
489 523 finderPred->AddRequestPredicate(repositoryPredicate);
490 524
491 525 return finderPred;
492 526 }
@@ -1,46 +1,49
1 1 #ifndef SCIQLOP_CATALOGUESIDEBARWIDGET_H
2 2 #define SCIQLOP_CATALOGUESIDEBARWIDGET_H
3 3
4 4 #include <Common/spimpl.h>
5 5 #include <QLoggingCategory>
6 6 #include <QTreeWidgetItem>
7 7 #include <QWidget>
8 8
9 9 class DBCatalogue;
10 10
11 11 namespace Ui {
12 12 class CatalogueSideBarWidget;
13 13 }
14 14
15 15 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget)
16 16
17 17 class CatalogueSideBarWidget : public QWidget {
18 18 Q_OBJECT
19 19
20 20 signals:
21 21 void catalogueSelected(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
22 22 void databaseSelected(const QStringList &databases);
23 23 void allEventsSelected();
24 24 void trashSelected();
25 25 void selectionCleared();
26 26
27 27 public:
28 28 explicit CatalogueSideBarWidget(QWidget *parent = 0);
29 29 virtual ~CatalogueSideBarWidget();
30 30
31 31 void addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue, const QString &repository);
32 32 void setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue, bool hasChanges);
33 33
34 34 QVector<std::shared_ptr<DBCatalogue> > getCatalogues(const QString &repository) const;
35 35
36 private slots:
37 void emitSelection();
38
36 39 private:
37 40 Ui::CatalogueSideBarWidget *ui;
38 41
39 42 class CatalogueSideBarWidgetPrivate;
40 43 spimpl::unique_impl_ptr<CatalogueSideBarWidgetPrivate> impl;
41 44
42 45 private slots:
43 46 void onContextMenuRequested(const QPoint &pos);
44 47 };
45 48
46 49 #endif // SCIQLOP_CATALOGUESIDEBARWIDGET_H
@@ -1,35 +1,36
1 1 #ifndef SCIQLOP_CATALOGUEABSTRACTTREEITEM_H
2 2 #define SCIQLOP_CATALOGUEABSTRACTTREEITEM_H
3 3
4 4 #include <Common/spimpl.h>
5 5 #include <QVariant>
6 6 #include <QVector>
7 7
8 8 class QMimeData;
9 9
10 10 class CatalogueAbstractTreeItem {
11 11 public:
12 12 constexpr static const int DEFAULT_TYPE = -1;
13 13
14 14 CatalogueAbstractTreeItem(int type = DEFAULT_TYPE);
15 15 virtual ~CatalogueAbstractTreeItem();
16 16
17 17 void addChild(CatalogueAbstractTreeItem *child);
18 void removeChild(CatalogueAbstractTreeItem *child);
18 19 QVector<CatalogueAbstractTreeItem *> children() const;
19 20 CatalogueAbstractTreeItem *parent() const;
20 21
21 22 int type() const;
22 23 QString text(int column = 0) const;
23 24
24 25 virtual QVariant data(int column, int role) const;
25 26 virtual Qt::ItemFlags flags(int column) const;
26 27 virtual bool setData(int column, int role, const QVariant &value);
27 28 virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action);
28 29 virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action);
29 30
30 31 private:
31 32 class CatalogueAbstractTreeItemPrivate;
32 33 spimpl::unique_impl_ptr<CatalogueAbstractTreeItemPrivate> impl;
33 34 };
34 35
35 36 #endif // SCIQLOP_CATALOGUEABSTRACTTREEITEM_H
@@ -1,56 +1,59
1 1 #ifndef SCIQLOP_CATALOGUETREEMODEL_H
2 2 #define SCIQLOP_CATALOGUETREEMODEL_H
3 3
4 4 #include <Common/spimpl.h>
5 5 #include <QAbstractItemModel>
6 6
7 7 class CatalogueAbstractTreeItem;
8 8
9 9 /**
10 10 * @brief Model to display catalogue items based on QTreeWidgetItem
11 11 * @warning Do not use the method QTreeWidgetItem::treeWidget for an item added to this model or the
12 12 * application will crash
13 13 */
14 14 class CatalogueTreeModel : public QAbstractItemModel {
15 15 Q_OBJECT
16 16
17 17 signals:
18 18 void itemRenamed(const QModelIndex &index);
19 19 void itemDropped(const QModelIndex &parentIndex);
20 20
21 21 public:
22 22 CatalogueTreeModel(QObject *parent = nullptr);
23 23
24 24 enum class Column { Name, Validation, Count };
25 25
26 26 QModelIndex addTopLevelItem(CatalogueAbstractTreeItem *item);
27 27 QVector<CatalogueAbstractTreeItem *> topLevelItems() const;
28 28
29 29 void addChildItem(CatalogueAbstractTreeItem *child, const QModelIndex &parentIndex);
30 void removeChildItem(CatalogueAbstractTreeItem *child, const QModelIndex &parentIndex);
31 /// Refresh the data for the specified index
32 void refresh(const QModelIndex &index);
30 33
31 34 CatalogueAbstractTreeItem *item(const QModelIndex &index) const;
32 35 QModelIndex indexOf(CatalogueAbstractTreeItem *item, int column = 0) const;
33 36
34 37 // model
35 38 QModelIndex index(int row, int column,
36 39 const QModelIndex &parent = QModelIndex()) const override;
37 40 QModelIndex parent(const QModelIndex &index) const override;
38 41 int rowCount(const QModelIndex &parent) const override;
39 42 int columnCount(const QModelIndex &parent) const override;
40 43 Qt::ItemFlags flags(const QModelIndex &index) const override;
41 44 QVariant data(const QModelIndex &index, int role) const override;
42 45 bool setData(const QModelIndex &index, const QVariant &value, int role) override;
43 46
44 47 bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
45 48 const QModelIndex &parent) const override;
46 49 bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
47 50 const QModelIndex &parent) override;
48 51 Qt::DropActions supportedDropActions() const;
49 52 QStringList mimeTypes() const;
50 53
51 54 private:
52 55 class CatalogueTreeModelPrivate;
53 56 spimpl::unique_impl_ptr<CatalogueTreeModelPrivate> impl;
54 57 };
55 58
56 59 #endif // CATALOGUETREEMODEL_H
@@ -1,147 +1,147
1 1 #include "Catalogue/CatalogueActionManager.h"
2 2
3 3 #include <Actions/ActionsGuiController.h>
4 4 #include <Catalogue/CatalogueController.h>
5 5 #include <DataSource/DataSourceItem.h>
6 6 #include <SqpApplication.h>
7 7 #include <Variable/Variable.h>
8 8 #include <Visualization/VisualizationGraphWidget.h>
9 9 #include <Visualization/VisualizationSelectionZoneItem.h>
10 10
11 11 #include <Catalogue/CatalogueEventsWidget.h>
12 12 #include <Catalogue/CatalogueExplorer.h>
13 13 #include <Catalogue/CatalogueSideBarWidget.h>
14 14 #include <Catalogue/CreateEventDialog.h>
15 15
16 16 #include <CatalogueDao.h>
17 17 #include <DBCatalogue.h>
18 18 #include <DBEvent.h>
19 19 #include <DBEventProduct.h>
20 20
21 21 #include <QBoxLayout>
22 22 #include <QComboBox>
23 23 #include <QDialog>
24 24 #include <QDialogButtonBox>
25 25 #include <QLineEdit>
26 26 #include <memory>
27 27
28 28 struct CatalogueActionManager::CatalogueActionManagerPrivate {
29 29
30 30 CatalogueExplorer *m_CatalogueExplorer = nullptr;
31 31
32 32 CatalogueActionManagerPrivate(CatalogueExplorer *catalogueExplorer)
33 33 : m_CatalogueExplorer(catalogueExplorer)
34 34 {
35 35 }
36 36
37 37 void createEventFromZones(const QString &eventName,
38 38 const QVector<VisualizationSelectionZoneItem *> &zones,
39 39 const std::shared_ptr<DBCatalogue> &catalogue = nullptr)
40 40 {
41 41 auto event = std::make_shared<DBEvent>();
42 42 event->setName(eventName);
43 43
44 44 std::list<DBEventProduct> productList;
45 45 for (auto zone : zones) {
46 46 auto graph = zone->parentGraphWidget();
47 47 for (auto var : graph->variables()) {
48 48 auto eventProduct = std::make_shared<DBEventProduct>();
49 49 eventProduct->setEvent(*event);
50 50
51 51 auto productId
52 52 = var->metadata().value(DataSourceItem::ID_DATA_KEY, "UnknownID").toString();
53 53
54 54 auto zoneRange = zone->range();
55 55 eventProduct->setTStart(zoneRange.m_TStart);
56 56 eventProduct->setTEnd(zoneRange.m_TEnd);
57 57
58 58 eventProduct->setProductId(productId);
59 59
60 60 productList.push_back(*eventProduct);
61 61
62 62 m_CatalogueExplorer->addSelectionZoneItem(event, productId, zone);
63 63 }
64 64 }
65 65
66 66 event->setEventProducts(productList);
67 67
68 68 sqpApp->catalogueController().addEvent(event);
69 69
70 70
71 71 if (catalogue) {
72 // TODO
73 // catalogue->addEvent(event);
72 catalogue->addEvent(event->getUniqId());
73 sqpApp->catalogueController().updateCatalogue(catalogue);
74 74 m_CatalogueExplorer->sideBarWidget().setCatalogueChanges(catalogue, true);
75 75 if (m_CatalogueExplorer->eventsWidget().displayedCatalogues().contains(catalogue)) {
76 76 m_CatalogueExplorer->eventsWidget().addEvent(event);
77 77 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
78 78 }
79 79 }
80 80 else if (m_CatalogueExplorer->eventsWidget().isAllEventsDisplayed()) {
81 81 m_CatalogueExplorer->eventsWidget().addEvent(event);
82 82 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
83 83 }
84 84 }
85 85 };
86 86
87 87 CatalogueActionManager::CatalogueActionManager(CatalogueExplorer *catalogueExplorer)
88 88 : impl{spimpl::make_unique_impl<CatalogueActionManagerPrivate>(catalogueExplorer)}
89 89 {
90 90 }
91 91
92 92 void CatalogueActionManager::installSelectionZoneActions()
93 93 {
94 94 auto &actionController = sqpApp->actionsGuiController();
95 95
96 96 auto createEventEnableFuntion = [](auto zones) {
97 97
98 98 // Checks that all variables in the zones doesn't refer to the same product
99 99 QSet<QString> usedDatasource;
100 100 for (auto zone : zones) {
101 101 auto graph = zone->parentGraphWidget();
102 102 auto variables = graph->variables();
103 103
104 104 for (auto var : variables) {
105 105 auto datasourceId = var->metadata().value(DataSourceItem::ID_DATA_KEY).toString();
106 106 if (!usedDatasource.contains(datasourceId)) {
107 107 usedDatasource.insert(datasourceId);
108 108 }
109 109 else {
110 110 return false;
111 111 }
112 112 }
113 113 }
114 114
115 115 return true;
116 116 };
117 117
118 118 auto createEventAction = actionController.addSectionZoneAction(
119 119 {QObject::tr("Catalogues")}, QObject::tr("New Event..."), [this](auto zones) {
120 120 CreateEventDialog dialog(
121 121 impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT));
122 122 dialog.hideCatalogueChoice();
123 123 if (dialog.exec() == QDialog::Accepted) {
124 124 impl->createEventFromZones(dialog.eventName(), zones);
125 125 }
126 126 });
127 127 createEventAction->setEnableFunction(createEventEnableFuntion);
128 128
129 129 auto createEventInCatalogueAction = actionController.addSectionZoneAction(
130 130 {QObject::tr("Catalogues")}, QObject::tr("New Event in Catalogue..."), [this](auto zones) {
131 131 CreateEventDialog dialog(
132 132 impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT));
133 133 if (dialog.exec() == QDialog::Accepted) {
134 134 auto selectedCatalogue = dialog.selectedCatalogue();
135 135 if (!selectedCatalogue) {
136 136 selectedCatalogue = std::make_shared<DBCatalogue>();
137 137 selectedCatalogue->setName(dialog.catalogueName());
138 // sqpApp->catalogueController().addCatalogue(selectedCatalogue); TODO
138 sqpApp->catalogueController().addCatalogue(selectedCatalogue);
139 139 impl->m_CatalogueExplorer->sideBarWidget().addCatalogue(selectedCatalogue,
140 140 REPOSITORY_DEFAULT);
141 141 }
142 142
143 143 impl->createEventFromZones(dialog.eventName(), zones, selectedCatalogue);
144 144 }
145 145 });
146 146 createEventInCatalogueAction->setEnableFunction(createEventEnableFuntion);
147 147 }
@@ -1,337 +1,422
1 1 #include "Catalogue/CatalogueSideBarWidget.h"
2 2 #include "ui_CatalogueSideBarWidget.h"
3 3 #include <SqpApplication.h>
4 4
5 5 #include <Catalogue/CatalogueController.h>
6 6 #include <Catalogue/CatalogueExplorerHelper.h>
7 7 #include <Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.h>
8 8 #include <Catalogue/CatalogueTreeItems/CatalogueTreeItem.h>
9 9 #include <Catalogue/CatalogueTreeModel.h>
10 10 #include <CatalogueDao.h>
11 11 #include <ComparaisonPredicate.h>
12 12 #include <DBCatalogue.h>
13 13
14 14 #include <QMenu>
15 #include <QMessageBox>
15 16
16 17 Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
17 18
18 19
19 20 constexpr auto ALL_EVENT_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 1;
20 21 constexpr auto TRASH_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 2;
21 22 constexpr auto CATALOGUE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 3;
22 23 constexpr auto DATABASE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 4;
23 24
24 25
25 26 struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
26 27
27 28 CatalogueTreeModel *m_TreeModel = nullptr;
28 29
29 30 void configureTreeWidget(QTreeView *treeView);
30 31 QModelIndex addDatabaseItem(const QString &name);
31 32 CatalogueAbstractTreeItem *getDatabaseItem(const QString &name);
32 33 void addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
33 34 const QModelIndex &databaseIndex);
34 35
35 36 CatalogueTreeItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue) const;
36 void setHasChanges(bool value, const QModelIndex &index, QTreeView *treeView);
37 void setHasChanges(bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget);
37 38 bool hasChanges(const QModelIndex &index, QTreeView *treeView);
38 39
39 40 int selectionType(QTreeView *treeView) const
40 41 {
41 42 auto selectedItems = treeView->selectionModel()->selectedRows();
42 43 if (selectedItems.isEmpty()) {
43 44 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
44 45 }
45 46 else {
46 47 auto firstIndex = selectedItems.first();
47 48 auto firstItem = m_TreeModel->item(firstIndex);
48 49 if (!firstItem) {
49 50 Q_ASSERT(false);
50 51 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
51 52 }
52 53 auto selectionType = firstItem->type();
53 54
54 55 for (auto itemIndex : selectedItems) {
55 56 auto item = m_TreeModel->item(itemIndex);
56 57 if (!item || item->type() != selectionType) {
57 58 // Incoherent multi selection
58 59 selectionType = CatalogueAbstractTreeItem::DEFAULT_TYPE;
59 60 break;
60 61 }
61 62 }
62 63
63 64 return selectionType;
64 65 }
65 66 }
66 67
67 68 QVector<std::shared_ptr<DBCatalogue> > selectedCatalogues(QTreeView *treeView) const
68 69 {
69 70 QVector<std::shared_ptr<DBCatalogue> > catalogues;
70 71 auto selectedItems = treeView->selectionModel()->selectedRows();
71 72 for (auto itemIndex : selectedItems) {
72 73 auto item = m_TreeModel->item(itemIndex);
73 74 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
74 75 catalogues.append(static_cast<CatalogueTreeItem *>(item)->catalogue());
75 76 }
76 77 }
77 78
78 79 return catalogues;
79 80 }
80 81
81 82 QStringList selectedRepositories(QTreeView *treeView) const
82 83 {
83 84 QStringList repositories;
84 85 auto selectedItems = treeView->selectionModel()->selectedRows();
85 86 for (auto itemIndex : selectedItems) {
86 87 auto item = m_TreeModel->item(itemIndex);
87 88 if (item && item->type() == DATABASE_ITEM_TYPE) {
88 89 repositories.append(item->text());
89 90 }
90 91 }
91 92
92 93 return repositories;
93 94 }
94 95 };
95 96
96 97 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
97 98 : QWidget(parent),
98 99 ui(new Ui::CatalogueSideBarWidget),
99 100 impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
100 101 {
101 102 ui->setupUi(this);
102 103
103 104 impl->m_TreeModel = new CatalogueTreeModel(this);
104 105 ui->treeView->setModel(impl->m_TreeModel);
105 106
106 107 impl->configureTreeWidget(ui->treeView);
107 108
108 109 ui->treeView->header()->setStretchLastSection(false);
109 110 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
110 111 ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
111 112
112 auto emitSelection = [this]() {
113
114 auto selectionType = impl->selectionType(ui->treeView);
115
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;
113 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueSideBarWidget::emitSelection);
114 connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, this,
115 &CatalogueSideBarWidget::emitSelection);
116
117
118 // connect(ui->btnAdd, &QToolButton::clicked, [this]() {
119 // QVector<std::shared_ptr<DBCatalogue> > catalogues;
120 // impl->getSelectedItems(ui->treeView, events, eventProducts);
121
122 // if (!events.isEmpty() && eventProducts.isEmpty()) {
123
124 // if (QMessageBox::warning(this, tr("Remove Event(s)"),
125 // tr("The selected event(s) will be completly removed "
126 // "from the repository!\nAre you sure you want to
127 // continue?"),
128 // QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
129 // == QMessageBox::Yes) {
130
131 // for (auto event : events) {
132 // sqpApp->catalogueController().removeEvent(event);
133 // impl->removeEvent(event, ui->treeView);
134 // }
135 // }
136 // }
137 // });
138
139
140 connect(impl->m_TreeModel, &CatalogueTreeModel::itemDropped, [this](auto index) {
141 auto item = impl->m_TreeModel->item(index);
142 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
143 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
144 this->setCatalogueChanges(catalogue, true);
132 145 }
133 };
146 });
147 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
148 QVector<QPair<std::shared_ptr<DBCatalogue>, CatalogueAbstractTreeItem *> >
149 cataloguesToItems;
150 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
151
152 for (auto index : selectedIndexes) {
153 auto item = impl->m_TreeModel->item(index);
154 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
155 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
156 cataloguesToItems << qMakePair(catalogue, item);
157 }
158 }
159
160 if (!cataloguesToItems.isEmpty()) {
161
162 if (QMessageBox::warning(this, tr("Remove Catalogue(s)"),
163 tr("The selected catalogues(s) will be completly removed "
164 "from the repository!\nAre you sure you want to continue?"),
165 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
166 == QMessageBox::Yes) {
167
168 for (auto catalogueToItem : cataloguesToItems) {
169 sqpApp->catalogueController().removeCatalogue(catalogueToItem.first);
170 impl->m_TreeModel->removeChildItem(
171 catalogueToItem.second,
172 impl->m_TreeModel->indexOf(catalogueToItem.second->parent()));
173 }
174 }
175 }
176 });
134 177
135 connect(ui->treeView, &QTreeView::clicked, emitSelection);
136 connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, emitSelection);
137 connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [emitSelection, this](auto index) {
178 connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [this](auto index) {
138 179 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
139 180 if (selectedIndexes.contains(index)) {
140 emitSelection();
181 this->emitSelection();
141 182 }
142
143 auto item = impl->m_TreeModel->item(index);
144 impl->setHasChanges(true, index, ui->treeView);
183 impl->setHasChanges(true, index, this);
145 184 });
146 185
147 186 ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
148 187 connect(ui->treeView, &QTreeView::customContextMenuRequested, this,
149 188 &CatalogueSideBarWidget::onContextMenuRequested);
150 189 }
151 190
152 191 CatalogueSideBarWidget::~CatalogueSideBarWidget()
153 192 {
154 193 delete ui;
155 194 }
156 195
157 196 void CatalogueSideBarWidget::addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
158 197 const QString &repository)
159 198 {
160 199 auto repositoryItem = impl->getDatabaseItem(repository);
161 200 impl->addCatalogueItem(catalogue, impl->m_TreeModel->indexOf(repositoryItem));
162 201 }
163 202
164 203 void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
165 204 bool hasChanges)
166 205 {
167 206 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
168 207 auto index = impl->m_TreeModel->indexOf(catalogueItem);
169 impl->setHasChanges(hasChanges, index, ui->treeView);
208 impl->setHasChanges(hasChanges, index, this);
170 209 // catalogueItem->refresh();
171 210 }
172 211 }
173 212
174 213 QVector<std::shared_ptr<DBCatalogue> >
175 214 CatalogueSideBarWidget::getCatalogues(const QString &repository) const
176 215 {
177 216 QVector<std::shared_ptr<DBCatalogue> > result;
178 217 auto repositoryItem = impl->getDatabaseItem(repository);
179 218 for (auto child : repositoryItem->children()) {
180 219 if (child->type() == CATALOGUE_ITEM_TYPE) {
181 220 auto catalogueItem = static_cast<CatalogueTreeItem *>(child);
182 221 result << catalogueItem->catalogue();
183 222 }
184 223 else {
185 224 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogues: invalid structure";
186 225 }
187 226 }
188 227
189 228 return result;
190 229 }
191 230
231 void CatalogueSideBarWidget::emitSelection()
232 {
233 auto selectionType = impl->selectionType(ui->treeView);
234
235 switch (selectionType) {
236 case CATALOGUE_ITEM_TYPE:
237 emit this->catalogueSelected(impl->selectedCatalogues(ui->treeView));
238 break;
239 case DATABASE_ITEM_TYPE:
240 emit this->databaseSelected(impl->selectedRepositories(ui->treeView));
241 break;
242 case ALL_EVENT_ITEM_TYPE:
243 emit this->allEventsSelected();
244 break;
245 case TRASH_ITEM_TYPE:
246 emit this->trashSelected();
247 break;
248 default:
249 emit this->selectionCleared();
250 break;
251 }
252 }
253
192 254 void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
193 255 {
194 256 QMenu menu{this};
195 257
196 258 auto currentIndex = ui->treeView->currentIndex();
197 259 auto currentItem = impl->m_TreeModel->item(currentIndex);
198 260 if (!currentItem) {
199 261 return;
200 262 }
201 263
202 264 switch (currentItem->type()) {
203 265 case CATALOGUE_ITEM_TYPE:
204 266 menu.addAction("Rename", [this, currentIndex]() { ui->treeView->edit(currentIndex); });
205 267 break;
206 268 case DATABASE_ITEM_TYPE:
207 269 break;
208 270 case ALL_EVENT_ITEM_TYPE:
209 271 break;
210 272 case TRASH_ITEM_TYPE:
211 273 menu.addAction("Empty Trash", []() {
212 274 // TODO
213 275 });
214 276 break;
215 277 default:
216 278 break;
217 279 }
218 280
219 281 if (!menu.isEmpty()) {
220 282 menu.exec(ui->treeView->mapToGlobal(pos));
221 283 }
222 284 }
223 285
224 286 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(QTreeView *treeView)
225 287 {
226 288 auto allEventsItem = new CatalogueTextTreeItem{QIcon{":/icones/allEvents.png"}, "All Events",
227 289 ALL_EVENT_ITEM_TYPE};
228 290 auto allEventIndex = m_TreeModel->addTopLevelItem(allEventsItem);
229 291 treeView->setCurrentIndex(allEventIndex);
230 292
231 293 auto trashItem
232 294 = new CatalogueTextTreeItem{QIcon{":/icones/trash.png"}, "Trash", TRASH_ITEM_TYPE};
233 295 m_TreeModel->addTopLevelItem(trashItem);
234 296
235 297 auto separator = new QFrame{treeView};
236 298 separator->setFrameShape(QFrame::HLine);
237 299 auto separatorItem
238 300 = new CatalogueTextTreeItem{QIcon{}, QString{}, CatalogueAbstractTreeItem::DEFAULT_TYPE};
239 301 separatorItem->setEnabled(false);
240 302 auto separatorIndex = m_TreeModel->addTopLevelItem(separatorItem);
241 303 treeView->setIndexWidget(separatorIndex, separator);
242 304
243 305 auto repositories = sqpApp->catalogueController().getRepositories();
244 306 for (auto dbname : repositories) {
245 307 auto dbIndex = addDatabaseItem(dbname);
246 308 auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname);
247 309 for (auto catalogue : catalogues) {
248 310 addCatalogueItem(catalogue, dbIndex);
249 311 }
250 312 }
251 313
252 314 treeView->expandAll();
253 315 }
254 316
255 317 QModelIndex
256 318 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name)
257 319 {
258 320 auto databaseItem
259 321 = new CatalogueTextTreeItem{QIcon{":/icones/database.png"}, {name}, DATABASE_ITEM_TYPE};
260 322 auto databaseIndex = m_TreeModel->addTopLevelItem(databaseItem);
261 323
262 324 return databaseIndex;
263 325 }
264 326
265 327 CatalogueAbstractTreeItem *
266 328 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name)
267 329 {
268 330 for (auto item : m_TreeModel->topLevelItems()) {
269 331 if (item->type() == DATABASE_ITEM_TYPE && item->text() == name) {
270 332 return item;
271 333 }
272 334 }
273 335
274 336 return nullptr;
275 337 }
276 338
277 339 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
278 340 const std::shared_ptr<DBCatalogue> &catalogue, const QModelIndex &databaseIndex)
279 341 {
280 342 auto catalogueItem
281 343 = new CatalogueTreeItem{catalogue, QIcon{":/icones/catalogue.png"}, CATALOGUE_ITEM_TYPE};
282 344 m_TreeModel->addChildItem(catalogueItem, databaseIndex);
283 345 }
284 346
285 347 CatalogueTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
286 348 const std::shared_ptr<DBCatalogue> &catalogue) const
287 349 {
288 350 for (auto item : m_TreeModel->topLevelItems()) {
289 351 if (item->type() == DATABASE_ITEM_TYPE) {
290 352 for (auto childItem : item->children()) {
291 353 if (childItem->type() == CATALOGUE_ITEM_TYPE) {
292 354 auto catalogueItem = static_cast<CatalogueTreeItem *>(childItem);
293 355 if (catalogueItem->catalogue() == catalogue) {
294 356 return catalogueItem;
295 357 }
296 358 }
297 359 else {
298 360 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
299 361 "structure. A database item should "
300 362 "only contain catalogues.";
301 363 Q_ASSERT(false);
302 364 }
303 365 }
304 366 }
305 367 }
306 368
307 369 return nullptr;
308 370 }
309 371
310 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(bool value,
311 const QModelIndex &index,
312 QTreeView *treeView)
372 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(
373 bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget)
313 374 {
375 std::shared_ptr<DBCatalogue> catalogue = nullptr;
376 auto item = m_TreeModel->item(index);
377 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
378 catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
379 }
380
314 381 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
315 382 if (value) {
316 if (!hasChanges(validationIndex, treeView)) {
383 if (!hasChanges(validationIndex, sideBarWidget->ui->treeView)) {
317 384 auto widget = CatalogueExplorerHelper::buildValidationWidget(
318 treeView, [this, validationIndex,
319 treeView]() { setHasChanges(false, validationIndex, treeView); },
320 [this, validationIndex, treeView]() {
321 setHasChanges(false, validationIndex, treeView);
385 sideBarWidget->ui->treeView,
386 [this, validationIndex, sideBarWidget, catalogue]() {
387 if (catalogue) {
388 sqpApp->catalogueController().saveCatalogue(catalogue);
389 }
390 setHasChanges(false, validationIndex, sideBarWidget);
391 },
392 [this, validationIndex, sideBarWidget, catalogue, item]() {
393 if (catalogue) {
394 bool removed;
395 sqpApp->catalogueController().discardCatalogue(catalogue, removed);
396
397 if (removed) {
398 m_TreeModel->removeChildItem(item,
399 m_TreeModel->indexOf(item->parent()));
400 }
401 else {
402 m_TreeModel->refresh(m_TreeModel->indexOf(item));
403 setHasChanges(false, validationIndex, sideBarWidget);
404 }
405 sideBarWidget->emitSelection();
406 }
322 407 });
323 treeView->setIndexWidget(validationIndex, widget);
408 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, widget);
324 409 }
325 410 }
326 411 else {
327 412 // Note: the widget is destroyed
328 treeView->setIndexWidget(validationIndex, nullptr);
413 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, nullptr);
329 414 }
330 415 }
331 416
332 417 bool CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::hasChanges(const QModelIndex &index,
333 418 QTreeView *treeView)
334 419 {
335 420 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
336 421 return treeView->indexWidget(validationIndex) != nullptr;
337 422 }
@@ -1,81 +1,87
1 1 #include "Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h"
2 2
3 3 struct CatalogueAbstractTreeItem::CatalogueAbstractTreeItemPrivate {
4 4 int m_Type;
5 5 QVector<CatalogueAbstractTreeItem *> m_Children;
6 6 CatalogueAbstractTreeItem *m_Parent = nullptr;
7 7
8 8 CatalogueAbstractTreeItemPrivate(int type) : m_Type(type) {}
9 9 };
10 10
11 11 CatalogueAbstractTreeItem::CatalogueAbstractTreeItem(int type)
12 12 : impl{spimpl::make_unique_impl<CatalogueAbstractTreeItemPrivate>(type)}
13 13 {
14 14 }
15 15
16 16 CatalogueAbstractTreeItem::~CatalogueAbstractTreeItem()
17 17 {
18 18 qDeleteAll(impl->m_Children);
19 19 }
20 20
21 21 void CatalogueAbstractTreeItem::addChild(CatalogueAbstractTreeItem *child)
22 22 {
23 23 impl->m_Children << child;
24 24 child->impl->m_Parent = this;
25 25 }
26 26
27 void CatalogueAbstractTreeItem::removeChild(CatalogueAbstractTreeItem *child)
28 {
29 impl->m_Children.removeAll(child);
30 delete child;
31 }
32
27 33 QVector<CatalogueAbstractTreeItem *> CatalogueAbstractTreeItem::children() const
28 34 {
29 35 return impl->m_Children;
30 36 }
31 37
32 38 CatalogueAbstractTreeItem *CatalogueAbstractTreeItem::parent() const
33 39 {
34 40 return impl->m_Parent;
35 41 }
36 42
37 43 int CatalogueAbstractTreeItem::type() const
38 44 {
39 45 return impl->m_Type;
40 46 }
41 47
42 48 QString CatalogueAbstractTreeItem::text(int column) const
43 49 {
44 50 return data(0, Qt::DisplayRole).toString();
45 51 }
46 52
47 53 QVariant CatalogueAbstractTreeItem::data(int column, int role) const
48 54 {
49 55 Q_UNUSED(column);
50 56 Q_UNUSED(role);
51 57 return QVariant();
52 58 }
53 59
54 60 Qt::ItemFlags CatalogueAbstractTreeItem::flags(int column) const
55 61 {
56 62 Q_UNUSED(column);
57 63 return Qt::NoItemFlags;
58 64 }
59 65
60 66 bool CatalogueAbstractTreeItem::setData(int column, int role, const QVariant &value)
61 67 {
62 68 Q_UNUSED(column);
63 69 Q_UNUSED(role);
64 70 Q_UNUSED(value);
65 71
66 72 return false;
67 73 }
68 74
69 75 bool CatalogueAbstractTreeItem::canDropMimeData(const QMimeData *data, Qt::DropAction action)
70 76 {
71 77 Q_UNUSED(data);
72 78 Q_UNUSED(action);
73 79 return false;
74 80 }
75 81
76 82 bool CatalogueAbstractTreeItem::dropMimeData(const QMimeData *data, Qt::DropAction action)
77 83 {
78 84 Q_UNUSED(data);
79 85 Q_UNUSED(action);
80 86 return false;
81 87 }
@@ -1,95 +1,105
1 1 #include "Catalogue/CatalogueTreeItems/CatalogueTreeItem.h"
2 2 #include <Catalogue/CatalogueExplorerHelper.h>
3 3
4 4 #include <Catalogue/CatalogueController.h>
5 5 #include <Common/MimeTypesDef.h>
6 6 #include <QIcon>
7 7 #include <QMimeData>
8 8 #include <SqpApplication.h>
9 9
10 10 #include <memory>
11 11
12 12 #include <DBCatalogue.h>
13 13
14 14 struct CatalogueTreeItem::CatalogueTreeItemPrivate {
15 15
16 16 std::shared_ptr<DBCatalogue> m_Catalogue;
17 17 QIcon m_Icon;
18 18
19 19 CatalogueTreeItemPrivate(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon)
20 20 : m_Catalogue(catalogue), m_Icon(icon)
21 21 {
22 22 }
23 23 };
24 24
25 25
26 26 CatalogueTreeItem::CatalogueTreeItem(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon,
27 27 int type)
28 28 : CatalogueAbstractTreeItem(type),
29 29 impl{spimpl::make_unique_impl<CatalogueTreeItemPrivate>(catalogue, icon)}
30 30 {
31 31 }
32 32
33 33 QVariant CatalogueTreeItem::data(int column, int role) const
34 34 {
35 35 if (column == 0) {
36 36 switch (role) {
37 37 case Qt::EditRole: // fallthrough
38 38 case Qt::DisplayRole:
39 39 return impl->m_Catalogue->getName();
40 40 case Qt::DecorationRole:
41 41 return impl->m_Icon;
42 42 default:
43 43 break;
44 44 }
45 45 }
46 46
47 47 return QVariant();
48 48 }
49 49
50 50 bool CatalogueTreeItem::setData(int column, int role, const QVariant &value)
51 51 {
52 52 bool result = false;
53 53
54 54 if (role == Qt::EditRole && column == 0) {
55 55 auto newName = value.toString();
56 56 if (newName != impl->m_Catalogue->getName()) {
57 57 impl->m_Catalogue->setName(newName);
58 58 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
59 59 result = true;
60 60 }
61 61 }
62 62
63 63 return result;
64 64 }
65 65
66 66 Qt::ItemFlags CatalogueTreeItem::flags(int column) const
67 67 {
68 68 if (column == 0) {
69 69 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable
70 70 | Qt::ItemIsDropEnabled;
71 71 }
72 72 else {
73 73 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
74 74 }
75 75 }
76 76
77 77 bool CatalogueTreeItem::canDropMimeData(const QMimeData *data, Qt::DropAction action)
78 78 {
79 return data->hasFormat(MIME_TYPE_EVENT_LIST);
79 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
80 auto canDrop = data->hasFormat(MIME_TYPE_EVENT_LIST);
81
82 for (auto event : events) {
83 canDrop &= (event->getRepository() == impl->m_Catalogue->getRepository());
84 }
85 return canDrop;
80 86 }
81 87
82 88 bool CatalogueTreeItem::dropMimeData(const QMimeData *data, Qt::DropAction action)
83 89 {
84 90 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 91 // Warning: Check that the events aren't already in the catalogue
89 92 // Also check for the repository !!!
93
94 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
95
96 for (auto event : events) {
97 impl->m_Catalogue->addEvent(event->getUniqId());
98 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
99 }
90 100 }
91 101
92 102 std::shared_ptr<DBCatalogue> CatalogueTreeItem::catalogue() const
93 103 {
94 104 return impl->m_Catalogue;
95 105 }
@@ -1,201 +1,218
1 1 #include "Catalogue/CatalogueTreeModel.h"
2 2 #include <Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h>
3 3
4 4 #include <QMimeData>
5 5 #include <memory>
6 6
7 7 #include <Common/MimeTypesDef.h>
8 8
9 9 struct CatalogueTreeModel::CatalogueTreeModelPrivate {
10 10 std::unique_ptr<CatalogueAbstractTreeItem> m_RootItem = nullptr;
11 11
12 12 CatalogueTreeModelPrivate() : m_RootItem{std::make_unique<CatalogueAbstractTreeItem>()} {}
13 13 };
14 14
15 15 CatalogueTreeModel::CatalogueTreeModel(QObject *parent)
16 16 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueTreeModelPrivate>()}
17 17 {
18 18 }
19 19
20 20 QModelIndex CatalogueTreeModel::addTopLevelItem(CatalogueAbstractTreeItem *item)
21 21 {
22 22 auto nbTopLevelItems = impl->m_RootItem->children().count();
23 23 beginInsertRows(QModelIndex(), nbTopLevelItems, nbTopLevelItems);
24 24 impl->m_RootItem->addChild(item);
25 25 endInsertRows();
26 26
27 27 emit dataChanged(QModelIndex(), QModelIndex());
28 28
29 29 return index(nbTopLevelItems, 0);
30 30 }
31 31
32 32 QVector<CatalogueAbstractTreeItem *> CatalogueTreeModel::topLevelItems() const
33 33 {
34 34 return impl->m_RootItem->children();
35 35 }
36 36
37 37 void CatalogueTreeModel::addChildItem(CatalogueAbstractTreeItem *child,
38 38 const QModelIndex &parentIndex)
39 39 {
40 40 auto parentItem = item(parentIndex);
41 41 int c = parentItem->children().count();
42 42 beginInsertRows(parentIndex, c, c);
43 43 parentItem->addChild(child);
44 44 endInsertRows();
45 45
46 46 emit dataChanged(parentIndex, parentIndex);
47 47 }
48 48
49 void CatalogueTreeModel::removeChildItem(CatalogueAbstractTreeItem *child,
50 const QModelIndex &parentIndex)
51 {
52 auto parentItem = item(parentIndex);
53 int i = parentItem->children().indexOf(child);
54 beginRemoveRows(parentIndex, i, i);
55 parentItem->removeChild(child);
56 endRemoveRows();
57
58 emit dataChanged(parentIndex, parentIndex);
59 }
60
61 void CatalogueTreeModel::refresh(const QModelIndex &index)
62 {
63 emit dataChanged(index, index);
64 }
65
49 66 CatalogueAbstractTreeItem *CatalogueTreeModel::item(const QModelIndex &index) const
50 67 {
51 68 return static_cast<CatalogueAbstractTreeItem *>(index.internalPointer());
52 69 }
53 70
54 71 QModelIndex CatalogueTreeModel::indexOf(CatalogueAbstractTreeItem *item, int column) const
55 72 {
56 73 auto parentItem = item->parent();
57 74 if (!parentItem) {
58 75 return QModelIndex();
59 76 }
60 77
61 78 auto row = parentItem->children().indexOf(item);
62 79 return createIndex(row, column, item);
63 80 }
64 81
65 82 QModelIndex CatalogueTreeModel::index(int row, int column, const QModelIndex &parent) const
66 83 {
67 84 if (column > 0) {
68 85 int a = 0;
69 86 }
70 87
71 88 if (!hasIndex(row, column, parent)) {
72 89 return QModelIndex();
73 90 }
74 91
75 92 CatalogueAbstractTreeItem *parentItem = nullptr;
76 93
77 94 if (!parent.isValid()) {
78 95 parentItem = impl->m_RootItem.get();
79 96 }
80 97 else {
81 98 parentItem = item(parent);
82 99 }
83 100
84 101 auto childItem = parentItem->children().value(row);
85 102 if (childItem) {
86 103 return createIndex(row, column, childItem);
87 104 }
88 105
89 106 return QModelIndex();
90 107 }
91 108
92 109
93 110 QModelIndex CatalogueTreeModel::parent(const QModelIndex &index) const
94 111 {
95 112 if (!index.isValid()) {
96 113 return QModelIndex();
97 114 }
98 115
99 116 auto childItem = item(index);
100 117 auto parentItem = childItem->parent();
101 118
102 119 if (parentItem == nullptr || parentItem->parent() == nullptr) {
103 120 return QModelIndex();
104 121 }
105 122
106 123 auto row = parentItem->parent()->children().indexOf(parentItem);
107 124 return createIndex(row, 0, parentItem);
108 125 }
109 126
110 127 int CatalogueTreeModel::rowCount(const QModelIndex &parent) const
111 128 {
112 129 CatalogueAbstractTreeItem *parentItem = nullptr;
113 130
114 131 if (!parent.isValid()) {
115 132 parentItem = impl->m_RootItem.get();
116 133 }
117 134 else {
118 135 parentItem = item(parent);
119 136 }
120 137
121 138 return parentItem->children().count();
122 139 }
123 140
124 141 int CatalogueTreeModel::columnCount(const QModelIndex &parent) const
125 142 {
126 143 return (int)Column::Count;
127 144 }
128 145
129 146 Qt::ItemFlags CatalogueTreeModel::flags(const QModelIndex &index) const
130 147 {
131 148 auto treeItem = item(index);
132 149 if (treeItem) {
133 150 return treeItem->flags(index.column());
134 151 }
135 152
136 153 return Qt::NoItemFlags;
137 154 }
138 155
139 156 QVariant CatalogueTreeModel::data(const QModelIndex &index, int role) const
140 157 {
141 158 auto treeItem = item(index);
142 159 if (treeItem) {
143 160 return treeItem->data(index.column(), role);
144 161 }
145 162
146 163 return QModelIndex();
147 164 }
148 165
149 166 bool CatalogueTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
150 167 {
151 168 auto treeItem = item(index);
152 169 if (treeItem) {
153 170 auto result = treeItem->setData(index.column(), role, value);
154 171
155 172 if (result && index.column() == (int)Column::Name) {
156 173 emit itemRenamed(index);
157 174 }
158 175
159 176 return result;
160 177 }
161 178
162 179 return false;
163 180 }
164 181 bool CatalogueTreeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
165 182 int column, const QModelIndex &parent) const
166 183 {
167 184 auto draggedIndex = parent;
168 185 auto draggedItem = item(draggedIndex);
169 186 if (draggedItem) {
170 187 return draggedItem->canDropMimeData(data, action);
171 188 }
172 189
173 190 return false;
174 191 }
175 192
176 193 bool CatalogueTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row,
177 194 int column, const QModelIndex &parent)
178 195 {
179 196 bool result = false;
180 197
181 198 auto draggedIndex = parent;
182 199 auto draggedItem = item(draggedIndex);
183 200 if (draggedItem) {
184 201 result = draggedItem->dropMimeData(data, action);
185 202 if (result) {
186 203 emit itemDropped(draggedIndex);
187 204 }
188 205 }
189 206
190 207 return result;
191 208 }
192 209
193 210 Qt::DropActions CatalogueTreeModel::supportedDropActions() const
194 211 {
195 212 return Qt::CopyAction | Qt::MoveAction;
196 213 }
197 214
198 215 QStringList CatalogueTreeModel::mimeTypes() const
199 216 {
200 217 return {MIME_TYPE_EVENT_LIST};
201 218 }
@@ -1,106 +1,105
1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2 <ui version="4.0">
3 3 <class>CatalogueSideBarWidget</class>
4 4 <widget class="QWidget" name="CatalogueSideBarWidget">
5 5 <property name="geometry">
6 6 <rect>
7 7 <x>0</x>
8 8 <y>0</y>
9 9 <width>330</width>
10 10 <height>523</height>
11 11 </rect>
12 12 </property>
13 13 <property name="windowTitle">
14 14 <string>Form</string>
15 15 </property>
16 16 <layout class="QVBoxLayout" name="verticalLayout">
17 17 <property name="leftMargin">
18 18 <number>0</number>
19 19 </property>
20 20 <property name="topMargin">
21 21 <number>0</number>
22 22 </property>
23 23 <property name="rightMargin">
24 24 <number>0</number>
25 25 </property>
26 26 <property name="bottomMargin">
27 27 <number>0</number>
28 28 </property>
29 29 <item>
30 30 <layout class="QHBoxLayout" name="horizontalLayout">
31 31 <item>
32 32 <widget class="QToolButton" name="btnAdd">
33 33 <property name="enabled">
34 <bool>false</bool>
34 <bool>true</bool>
35 35 </property>
36 36 <property name="text">
37 37 <string>+</string>
38 38 </property>
39 39 <property name="icon">
40 40 <iconset resource="../../resources/sqpguiresources.qrc">
41 41 <normaloff>:/icones/add.png</normaloff>:/icones/add.png</iconset>
42 42 </property>
43 43 <property name="autoRaise">
44 44 <bool>true</bool>
45 45 </property>
46 46 </widget>
47 47 </item>
48 48 <item>
49 49 <widget class="QToolButton" name="btnRemove">
50 50 <property name="enabled">
51 <bool>false</bool>
51 <bool>true</bool>
52 52 </property>
53 53 <property name="text">
54 54 <string> - </string>
55 55 </property>
56 56 <property name="icon">
57 57 <iconset resource="../../resources/sqpguiresources.qrc">
58 58 <normaloff>:/icones/remove.png</normaloff>:/icones/remove.png</iconset>
59 59 </property>
60 60 <property name="autoRaise">
61 61 <bool>true</bool>
62 62 </property>
63 63 </widget>
64 64 </item>
65 65 <item>
66 66 <spacer name="horizontalSpacer">
67 67 <property name="orientation">
68 68 <enum>Qt::Horizontal</enum>
69 69 </property>
70 70 <property name="sizeHint" stdset="0">
71 71 <size>
72 72 <width>40</width>
73 73 <height>20</height>
74 74 </size>
75 75 </property>
76 76 </spacer>
77 77 </item>
78 78 </layout>
79 79 </item>
80 80 <item>
81 81 <widget class="QTreeView" name="treeView">
82 82 <property name="acceptDrops">
83 83 <bool>true</bool>
84 84 </property>
85 85 <property name="dragDropMode">
86 86 <enum>QAbstractItemView::DragDrop</enum>
87 87 </property>
88 88 <property name="selectionMode">
89 89 <enum>QAbstractItemView::ExtendedSelection</enum>
90 90 </property>
91 91 <attribute name="headerVisible">
92 92 <bool>false</bool>
93 93 </attribute>
94 94 <attribute name="headerStretchLastSection">
95 95 <bool>false</bool>
96 96 </attribute>
97 97 </widget>
98 98 </item>
99 99 </layout>
100 100 </widget>
101 101 <resources>
102 102 <include location="../../resources/sqpguiresources.qrc"/>
103 <include location="../../resources/sqpguiresources.qrc"/>
104 103 </resources>
105 104 <connections/>
106 105 </ui>
General Comments 0
You need to be logged in to leave comments. Login now