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