##// END OF EJS Templates
Remove Event from catalogue statique only remove the reference.
perrinel -
r1367:db186fab48c0
parent child
Show More
@@ -1,64 +1,66
1 1 #ifndef SCIQLOP_CATALOGUEEVENTSWIDGET_H
2 2 #define SCIQLOP_CATALOGUEEVENTSWIDGET_H
3 3
4 4 #include <Common/spimpl.h>
5 5 #include <QLoggingCategory>
6 6 #include <QWidget>
7 7
8 8 class DBCatalogue;
9 9 class DBEvent;
10 10 class DBEventProduct;
11 11 class VisualizationWidget;
12 12 class VisualizationSelectionZoneItem;
13 13
14 14 namespace Ui {
15 15 class CatalogueEventsWidget;
16 16 }
17 17
18 18 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueEventsWidget)
19 19
20 20 class CatalogueEventsWidget : public QWidget {
21 21 Q_OBJECT
22 22
23 23 signals:
24 24 void eventsSelected(const QVector<std::shared_ptr<DBEvent> > &event);
25 25 void eventsRemoved(const QVector<std::shared_ptr<DBEvent> > &event);
26 26 void eventProductsSelected(
27 27 const QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > >
28 28 &eventproducts);
29 29 void selectionCleared();
30 30 void selectionZoneAdded(const std::shared_ptr<DBEvent> &event, const QString &productId,
31 31 VisualizationSelectionZoneItem *selectionZone);
32 32
33 void eventCataloguesModified(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
34
33 35 public:
34 36 explicit CatalogueEventsWidget(QWidget *parent = 0);
35 37 virtual ~CatalogueEventsWidget();
36 38
37 39 void setVisualizationWidget(VisualizationWidget *visualization);
38 40
39 41 void addEvent(const std::shared_ptr<DBEvent> &event);
40 42 void setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges);
41 43
42 44 QVector<std::shared_ptr<DBCatalogue> > displayedCatalogues() const;
43 45 bool isAllEventsDisplayed() const;
44 46 bool isEventDisplayed(const std::shared_ptr<DBEvent> &event) const;
45 47
46 48 void refreshEvent(const std::shared_ptr<DBEvent> &event);
47 49
48 50 public slots:
49 51 void populateWithCatalogues(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
50 52 void populateWithAllEvents();
51 53 void clear();
52 54 void refresh();
53 55
54 56 private:
55 57 Ui::CatalogueEventsWidget *ui;
56 58
57 59 class CatalogueEventsWidgetPrivate;
58 60 spimpl::unique_impl_ptr<CatalogueEventsWidgetPrivate> impl;
59 61
60 62 private slots:
61 63 void emitSelection();
62 64 };
63 65
64 66 #endif // SCIQLOP_CATALOGUEEVENTSWIDGET_H
@@ -1,607 +1,614
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 <DBEventProduct.h>
10 10 #include <DataSource/DataSourceController.h>
11 11 #include <DataSource/DataSourceItem.h>
12 12 #include <SqpApplication.h>
13 13 #include <Variable/Variable.h>
14 14 #include <Variable/VariableController.h>
15 15 #include <Visualization/VisualizationGraphWidget.h>
16 16 #include <Visualization/VisualizationTabWidget.h>
17 17 #include <Visualization/VisualizationWidget.h>
18 18 #include <Visualization/VisualizationZoneWidget.h>
19 19
20 20 #include <QDialog>
21 21 #include <QDialogButtonBox>
22 22 #include <QListWidget>
23 23 #include <QMessageBox>
24 24
25 25 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
26 26
27 27 /// Fixed size of the validation column
28 28 const auto VALIDATION_COLUMN_SIZE = 35;
29 29
30 30 /// Percentage added to the range of a event when it is displayed
31 31 const auto EVENT_RANGE_MARGE = 30; // in %
32 32
33 33 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
34 34
35 35 CatalogueEventsModel *m_Model = nullptr;
36 36 QStringList m_ZonesForTimeMode;
37 37 QString m_ZoneForGraphMode;
38 38 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
39 39 bool m_AllEventDisplayed = false;
40 40 QVector<VisualizationGraphWidget *> m_CustomGraphs;
41 41
42 42 VisualizationWidget *m_VisualizationWidget = nullptr;
43 43
44 44 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget)
45 45 {
46 46 widget->ui->treeView->setSortingEnabled(false);
47 47 m_Model->setSourceCatalogues(m_DisplayedCatalogues);
48 48 m_Model->setEvents(events);
49 49 widget->ui->treeView->setSortingEnabled(true);
50 50
51 51 for (auto event : events) {
52 52 if (sqpApp->catalogueController().eventHasChanges(event)) {
53 53 auto index = m_Model->indexOf(event);
54 54 widget->setEventChanges(event, true);
55 55 }
56 56 }
57 57 }
58 58
59 59 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
60 60 {
61 61 treeView->setSortingEnabled(false);
62 62 m_Model->addEvent(event);
63 63 treeView->setSortingEnabled(true);
64 64 }
65 65
66 66 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
67 67 {
68 68 treeView->setSortingEnabled(false);
69 69 m_Model->removeEvent(event);
70 70 treeView->setSortingEnabled(true);
71 71 }
72 72
73 73 QStringList getAvailableVisualizationZoneList() const
74 74 {
75 75 if (m_VisualizationWidget) {
76 76 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
77 77 return tab->availableZoneWidgets();
78 78 }
79 79 }
80 80
81 81 return QStringList{};
82 82 }
83 83
84 84 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
85 85 bool allowMultiSelection, const QPoint &location)
86 86 {
87 87 auto availableZones = getAvailableVisualizationZoneList();
88 88 if (availableZones.isEmpty()) {
89 89 return QStringList{};
90 90 }
91 91
92 92 QDialog d(parent, Qt::Tool);
93 93 d.setWindowTitle("Choose a zone");
94 94 auto layout = new QVBoxLayout{&d};
95 95 layout->setContentsMargins(0, 0, 0, 0);
96 96 auto listWidget = new QListWidget{&d};
97 97 layout->addWidget(listWidget);
98 98
99 99 QSet<QListWidgetItem *> checkedItems;
100 100 for (auto zone : availableZones) {
101 101 auto item = new QListWidgetItem{zone};
102 102 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
103 103 if (selectedZones.contains(zone)) {
104 104 item->setCheckState(Qt::Checked);
105 105 checkedItems << item;
106 106 }
107 107 else {
108 108 item->setCheckState(Qt::Unchecked);
109 109 }
110 110
111 111 listWidget->addItem(item);
112 112 }
113 113
114 114 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
115 115 layout->addWidget(buttonBox);
116 116
117 117 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
118 118 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
119 119
120 120 QObject::connect(listWidget, &QListWidget::itemChanged,
121 121 [&checkedItems, allowMultiSelection, listWidget](auto item) {
122 122 if (item->checkState() == Qt::Checked) {
123 123 if (!allowMultiSelection) {
124 124 for (auto checkedItem : checkedItems) {
125 125 listWidget->blockSignals(true);
126 126 checkedItem->setCheckState(Qt::Unchecked);
127 127 listWidget->blockSignals(false);
128 128 }
129 129
130 130 checkedItems.clear();
131 131 }
132 132 checkedItems << item;
133 133 }
134 134 else {
135 135 checkedItems.remove(item);
136 136 }
137 137 });
138 138
139 139 QStringList result;
140 140
141 141 d.setMinimumWidth(120);
142 142 d.resize(d.minimumSizeHint());
143 143 d.move(location);
144 144 if (d.exec() == QDialog::Accepted) {
145 145 for (auto item : checkedItems) {
146 146 result += item->text();
147 147 }
148 148 }
149 149 else {
150 150 result = selectedZones;
151 151 }
152 152
153 153 return result;
154 154 }
155 155
156 156 void updateForTimeMode(QTreeView *treeView)
157 157 {
158 158 auto selectedRows = treeView->selectionModel()->selectedRows();
159 159
160 160 if (selectedRows.count() == 1) {
161 161 auto event = m_Model->getEvent(selectedRows.first());
162 162 if (event) {
163 163 if (m_VisualizationWidget) {
164 164 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
165 165
166 166 for (auto zoneName : m_ZonesForTimeMode) {
167 167 if (auto zone = tab->getZoneWithName(zoneName)) {
168 168 SqpRange eventRange;
169 169 eventRange.m_TStart = event->getTStart();
170 170 eventRange.m_TEnd = event->getTEnd();
171 171 zone->setZoneRange(eventRange);
172 172 }
173 173 }
174 174 }
175 175 else {
176 176 qCWarning(LOG_CatalogueEventsWidget())
177 177 << "updateTimeZone: no tab found in the visualization";
178 178 }
179 179 }
180 180 else {
181 181 qCWarning(LOG_CatalogueEventsWidget())
182 182 << "updateTimeZone: visualization widget not found";
183 183 }
184 184 }
185 185 }
186 186 else {
187 187 qCWarning(LOG_CatalogueEventsWidget())
188 188 << "updateTimeZone: not compatible with multiple events selected";
189 189 }
190 190 }
191 191
192 192 QVector<SqpRange> getGraphRanges(const std::shared_ptr<DBEvent> &event)
193 193 {
194 194 // Retrieves the range of each product and the maximum size
195 195 QVector<SqpRange> graphRanges;
196 196 double maxDt = 0;
197 197 for (auto eventProduct : event->getEventProducts()) {
198 198 SqpRange eventRange;
199 199 eventRange.m_TStart = eventProduct.getTStart();
200 200 eventRange.m_TEnd = eventProduct.getTEnd();
201 201 graphRanges << eventRange;
202 202
203 203 auto dt = eventRange.m_TEnd - eventRange.m_TStart;
204 204 if (dt > maxDt) {
205 205 maxDt = dt;
206 206 }
207 207 }
208 208
209 209 // Adds the marge
210 210 maxDt *= (100.0 + EVENT_RANGE_MARGE) / 100.0;
211 211
212 212 // Corrects the graph ranges so that they all have the same size
213 213 QVector<SqpRange> correctedGraphRanges;
214 214 for (auto range : graphRanges) {
215 215 auto dt = range.m_TEnd - range.m_TStart;
216 216 auto diff = qAbs((maxDt - dt) / 2.0);
217 217
218 218 SqpRange correctedRange;
219 219 correctedRange.m_TStart = range.m_TStart - diff;
220 220 correctedRange.m_TEnd = range.m_TEnd + diff;
221 221
222 222 correctedGraphRanges << correctedRange;
223 223 }
224 224
225 225 return correctedGraphRanges;
226 226 }
227 227
228 228 void updateForGraphMode(CatalogueEventsWidget *catalogueEventWidget)
229 229 {
230 230 auto selectedRows = catalogueEventWidget->ui->treeView->selectionModel()->selectedRows();
231 231 if (selectedRows.count() != 1) {
232 232 qCWarning(LOG_CatalogueEventsWidget())
233 233 << "updateGraphMode: not compatible with multiple events selected";
234 234 return;
235 235 }
236 236
237 237 if (!m_VisualizationWidget) {
238 238 qCWarning(LOG_CatalogueEventsWidget())
239 239 << "updateGraphMode: visualization widget not found";
240 240 return;
241 241 }
242 242
243 243 auto event = m_Model->getEvent(selectedRows.first());
244 244 if (!event) {
245 245 // A event product is probably selected
246 246 qCInfo(LOG_CatalogueEventsWidget()) << "updateGraphMode: no events are selected";
247 247 return;
248 248 }
249 249
250 250 auto tab = m_VisualizationWidget->currentTabWidget();
251 251 if (!tab) {
252 252 qCWarning(LOG_CatalogueEventsWidget())
253 253 << "updateGraphMode: no tab found in the visualization";
254 254 return;
255 255 }
256 256
257 257 auto zone = tab->getZoneWithName(m_ZoneForGraphMode);
258 258 if (!zone) {
259 259 qCWarning(LOG_CatalogueEventsWidget()) << "updateGraphMode: zone not found";
260 260 return;
261 261 }
262 262
263 263 // Closes the previous graph and delete the asociated variables
264 264 for (auto graph : m_CustomGraphs) {
265 265 graph->close();
266 266 auto variables = graph->variables().toVector();
267 267
268 268 QMetaObject::invokeMethod(&sqpApp->variableController(), "deleteVariables",
269 269 Qt::QueuedConnection,
270 270 Q_ARG(QVector<std::shared_ptr<Variable> >, variables));
271 271 }
272 272 m_CustomGraphs.clear();
273 273
274 274 // Closes the remaining graphs inside the zone
275 275 zone->closeAllGraphs();
276 276
277 277 // Calculates the range of each graph which will be created
278 278 auto graphRange = getGraphRanges(event);
279 279
280 280 // Loops through the event products and create the graph
281 281 auto itRange = graphRange.cbegin();
282 282 for (auto eventProduct : event->getEventProducts()) {
283 283 auto productId = eventProduct.getProductId();
284 284
285 285 auto range = *itRange;
286 286 ++itRange;
287 287
288 288 SqpRange productRange;
289 289 productRange.m_TStart = eventProduct.getTStart();
290 290 productRange.m_TEnd = eventProduct.getTEnd();
291 291
292 292 auto context = new QObject{catalogueEventWidget};
293 293 QObject::connect(
294 294 &sqpApp->variableController(), &VariableController::variableAdded, context,
295 295 [this, catalogueEventWidget, zone, context, event, range, productRange,
296 296 productId](auto variable) {
297 297
298 298 if (variable->metadata().value(DataSourceItem::ID_DATA_KEY).toString()
299 299 == productId) {
300 300 auto graph = zone->createGraph(variable);
301 301 graph->setAutoRangeOnVariableInitialization(false);
302 302
303 303 auto selectionZone
304 304 = graph->addSelectionZone(event->getName(), productRange);
305 305 emit catalogueEventWidget->selectionZoneAdded(event, productId,
306 306 selectionZone);
307 307 m_CustomGraphs << graph;
308 308
309 309 graph->setGraphRange(range, true);
310 310
311 311 // Removes the graph from the graph list if it is closed manually
312 312 QObject::connect(graph, &VisualizationGraphWidget::destroyed,
313 313 [this, graph]() { m_CustomGraphs.removeAll(graph); });
314 314
315 315 delete context; // removes the connection
316 316 }
317 317 },
318 318 Qt::QueuedConnection);
319 319
320 320 QMetaObject::invokeMethod(&sqpApp->dataSourceController(),
321 321 "requestVariableFromProductIdKey", Qt::QueuedConnection,
322 322 Q_ARG(QString, productId));
323 323 }
324 324 }
325 325
326 326 void getSelectedItems(
327 327 QTreeView *treeView, QVector<std::shared_ptr<DBEvent> > &events,
328 328 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > &eventProducts)
329 329 {
330 330 for (auto rowIndex : treeView->selectionModel()->selectedRows()) {
331 331 auto itemType = m_Model->itemTypeOf(rowIndex);
332 332 if (itemType == CatalogueEventsModel::ItemType::Event) {
333 333 events << m_Model->getEvent(rowIndex);
334 334 }
335 335 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
336 336 eventProducts << qMakePair(m_Model->getParentEvent(rowIndex),
337 337 m_Model->getEventProduct(rowIndex));
338 338 }
339 339 }
340 340 }
341 341 };
342 342
343 343 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
344 344 : QWidget(parent),
345 345 ui(new Ui::CatalogueEventsWidget),
346 346 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
347 347 {
348 348 ui->setupUi(this);
349 349
350 350 impl->m_Model = new CatalogueEventsModel{this};
351 351 ui->treeView->setModel(impl->m_Model);
352 352
353 353 ui->treeView->setSortingEnabled(true);
354 354 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
355 355 ui->treeView->setDragEnabled(true);
356 356
357 357 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
358 358 if (checked) {
359 359 ui->btnChart->setChecked(false);
360 360 impl->m_ZonesForTimeMode
361 361 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
362 362 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
363 363
364 364 impl->updateForTimeMode(ui->treeView);
365 365 }
366 366 });
367 367
368 368 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
369 369 if (checked) {
370 370 ui->btnTime->setChecked(false);
371 371 impl->m_ZoneForGraphMode
372 372 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
373 373 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
374 374 .value(0);
375 375
376 376 impl->updateForGraphMode(this);
377 377 }
378 378 });
379 379
380 380 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
381 381 QVector<std::shared_ptr<DBEvent> > events;
382 382 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
383 383 impl->getSelectedItems(ui->treeView, events, eventProducts);
384 384
385 385 if (!events.isEmpty() && eventProducts.isEmpty()) {
386 386
387 387 auto canRemoveEvent
388 388 = !this->isAllEventsDisplayed()
389 389 || (QMessageBox::warning(
390 390 this, tr("Remove Event(s)"),
391 391 tr("The selected event(s) will be permanently removed "
392 392 "from the repository!\nAre you sure you want to continue?"),
393 393 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
394 394 == QMessageBox::Yes);
395 395
396 396 if (canRemoveEvent) {
397 397 for (auto event : events) {
398 398 if (this->isAllEventsDisplayed()) {
399 sqpApp->catalogueController().removeEvent(event);
399 400 impl->removeEvent(event, ui->treeView);
400 401 }
401 402 else {
403 QVector<std::shared_ptr<DBCatalogue> > modifiedCatalogues;
402 404 for (auto catalogue : this->displayedCatalogues()) {
403 catalogue->removeEvent(event->getUniqId());
404 sqpApp->catalogueController().updateCatalogue(catalogue);
405 if (catalogue->removeEvent(event->getUniqId())) {
406 sqpApp->catalogueController().updateCatalogue(catalogue);
407 modifiedCatalogues << catalogue;
408 }
409 }
410 if (!modifiedCatalogues.empty()) {
411 emit eventCataloguesModified(modifiedCatalogues);
405 412 }
406 413 }
407 414 impl->m_Model->removeEvent(event);
408 415 }
409 416
410 417
411 418 emit this->eventsRemoved(events);
412 419 }
413 420 }
414 421 });
415 422
416 423 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueEventsWidget::emitSelection);
417 424 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
418 425 &CatalogueEventsWidget::emitSelection);
419 426
420 427 ui->btnRemove->setEnabled(false); // Disabled by default when nothing is selected
421 428 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
422 429 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
423 430 ui->btnChart->setEnabled(isNotMultiSelection);
424 431 ui->btnTime->setEnabled(isNotMultiSelection);
425 432
426 433 if (isNotMultiSelection && ui->btnTime->isChecked()) {
427 434 impl->updateForTimeMode(ui->treeView);
428 435 }
429 436 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
430 437 impl->updateForGraphMode(this);
431 438 }
432 439
433 440 QVector<std::shared_ptr<DBEvent> > events;
434 441 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
435 442 impl->getSelectedItems(ui->treeView, events, eventProducts);
436 443 ui->btnRemove->setEnabled(!events.isEmpty() && eventProducts.isEmpty());
437 444 });
438 445
439 446 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
440 447 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Tags,
441 448 QHeaderView::Stretch);
442 449 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
443 450 QHeaderView::Fixed);
444 451 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
445 452 QHeaderView::Interactive);
446 453 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
447 454 VALIDATION_COLUMN_SIZE);
448 455 ui->treeView->header()->setSortIndicatorShown(true);
449 456
450 457 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
451 458 auto allEvents = impl->m_Model->events();
452 459 for (auto event : allEvents) {
453 460 setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event));
454 461 }
455 462 });
456 463
457 464 populateWithAllEvents();
458 465 }
459 466
460 467 CatalogueEventsWidget::~CatalogueEventsWidget()
461 468 {
462 469 delete ui;
463 470 }
464 471
465 472 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
466 473 {
467 474 impl->m_VisualizationWidget = visualization;
468 475 }
469 476
470 477 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
471 478 {
472 479 impl->addEvent(event, ui->treeView);
473 480 }
474 481
475 482 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
476 483 {
477 484 impl->m_Model->refreshEvent(event);
478 485
479 486 auto eventIndex = impl->m_Model->indexOf(event);
480 487 auto validationIndex
481 488 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
482 489
483 490 if (validationIndex.isValid()) {
484 491 if (hasChanges) {
485 492 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
486 493 auto widget = CatalogueExplorerHelper::buildValidationWidget(
487 494 ui->treeView,
488 495 [this, event]() {
489 496 sqpApp->catalogueController().saveEvent(event);
490 497 setEventChanges(event, false);
491 498 },
492 499 [this, event]() {
493 500 bool removed = false;
494 501 sqpApp->catalogueController().discardEvent(event, removed);
495 502 if (removed) {
496 503 impl->m_Model->removeEvent(event);
497 504 }
498 505 else {
499 506 setEventChanges(event, false);
500 507 impl->m_Model->refreshEvent(event, true);
501 508 }
502 509 emitSelection();
503 510 });
504 511 ui->treeView->setIndexWidget(validationIndex, widget);
505 512 }
506 513 }
507 514 else {
508 515 // Note: the widget is destroyed
509 516 ui->treeView->setIndexWidget(validationIndex, nullptr);
510 517 }
511 518 }
512 519 else {
513 520 qCWarning(LOG_CatalogueEventsWidget())
514 521 << "setEventChanges: the event is not displayed in the model.";
515 522 }
516 523 }
517 524
518 525 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
519 526 {
520 527 return impl->m_DisplayedCatalogues;
521 528 }
522 529
523 530 bool CatalogueEventsWidget::isAllEventsDisplayed() const
524 531 {
525 532 return impl->m_AllEventDisplayed;
526 533 }
527 534
528 535 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
529 536 {
530 537 return impl->m_Model->indexOf(event).isValid();
531 538 }
532 539
533 540 void CatalogueEventsWidget::refreshEvent(const std::shared_ptr<DBEvent> &event)
534 541 {
535 542 impl->m_Model->refreshEvent(event, true);
536 543 }
537 544
538 545 void CatalogueEventsWidget::populateWithCatalogues(
539 546 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
540 547 {
541 548 impl->m_DisplayedCatalogues = catalogues;
542 549 impl->m_AllEventDisplayed = false;
543 550
544 551 QSet<QUuid> eventIds;
545 552 QVector<std::shared_ptr<DBEvent> > events;
546 553
547 554 for (auto catalogue : catalogues) {
548 555 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
549 556 for (auto event : catalogueEvents) {
550 557 if (!eventIds.contains(event->getUniqId())) {
551 558 events << event;
552 559 eventIds.insert(event->getUniqId());
553 560 }
554 561 }
555 562 }
556 563
557 564 impl->setEvents(events, this);
558 565 }
559 566
560 567 void CatalogueEventsWidget::populateWithAllEvents()
561 568 {
562 569 impl->m_DisplayedCatalogues.clear();
563 570 impl->m_AllEventDisplayed = true;
564 571
565 572 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
566 573
567 574 QVector<std::shared_ptr<DBEvent> > events;
568 575 for (auto event : allEvents) {
569 576 events << event;
570 577 }
571 578
572 579 impl->setEvents(events, this);
573 580 }
574 581
575 582 void CatalogueEventsWidget::clear()
576 583 {
577 584 impl->m_DisplayedCatalogues.clear();
578 585 impl->m_AllEventDisplayed = false;
579 586 impl->setEvents({}, this);
580 587 }
581 588
582 589 void CatalogueEventsWidget::refresh()
583 590 {
584 591 if (isAllEventsDisplayed()) {
585 592 populateWithAllEvents();
586 593 }
587 594 else if (!impl->m_DisplayedCatalogues.isEmpty()) {
588 595 populateWithCatalogues(impl->m_DisplayedCatalogues);
589 596 }
590 597 }
591 598
592 599 void CatalogueEventsWidget::emitSelection()
593 600 {
594 601 QVector<std::shared_ptr<DBEvent> > events;
595 602 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
596 603 impl->getSelectedItems(ui->treeView, events, eventProducts);
597 604
598 605 if (!events.isEmpty() && eventProducts.isEmpty()) {
599 606 emit eventsSelected(events);
600 607 }
601 608 else if (events.isEmpty() && !eventProducts.isEmpty()) {
602 609 emit eventProductsSelected(eventProducts);
603 610 }
604 611 else {
605 612 emit selectionCleared();
606 613 }
607 614 }
@@ -1,193 +1,200
1 1 #include "Catalogue/CatalogueExplorer.h"
2 2 #include "ui_CatalogueExplorer.h"
3 3
4 4 #include <Catalogue/CatalogueActionManager.h>
5 5 #include <Catalogue/CatalogueController.h>
6 6 #include <SqpApplication.h>
7 7 #include <Visualization/VisualizationGraphWidget.h>
8 8 #include <Visualization/VisualizationSelectionZoneItem.h>
9 9 #include <Visualization/VisualizationWidget.h>
10 10
11 11 #include <DBCatalogue.h>
12 12 #include <DBEvent.h>
13 13 #include <DBEventProduct.h>
14 14
15 15 #include <unordered_map>
16 16
17 17 struct CatalogueExplorer::CatalogueExplorerPrivate {
18 18 CatalogueActionManager m_ActionManager;
19 19 std::unordered_map<std::shared_ptr<DBEvent>, QVector<VisualizationSelectionZoneItem *> >
20 20 m_SelectionZonesPerEvents;
21 21
22 22 QMetaObject::Connection m_Conn;
23 23
24 24 CatalogueExplorerPrivate(CatalogueExplorer *catalogueExplorer)
25 25 : m_ActionManager(catalogueExplorer)
26 26 {
27 27 }
28 28 };
29 29
30 30 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
31 31 : QDialog(parent, Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint),
32 32 ui(new Ui::CatalogueExplorer),
33 33 impl{spimpl::make_unique_impl<CatalogueExplorerPrivate>(this)}
34 34 {
35 35 ui->setupUi(this);
36 36
37 37 impl->m_ActionManager.installSelectionZoneActions();
38 38
39 39 // Updates events and inspector when something is selected in the catalogue widget
40 40 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto catalogues) {
41 41 if (catalogues.count() == 1) {
42 42 ui->inspector->setCatalogue(catalogues.first());
43 43 }
44 44 else {
45 45 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
46 46 }
47 47
48 48 ui->events->populateWithCatalogues(catalogues);
49 49 });
50 50
51 51 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databases) {
52 52 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
53 53 });
54 54
55 55 connect(ui->catalogues, &CatalogueSideBarWidget::trashSelected, [this]() {
56 56 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
57 57 ui->events->clear();
58 58 });
59 59
60 60 connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected, [this]() {
61 61 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
62 62 ui->events->populateWithAllEvents();
63 63 });
64 64
65 65 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databaseList) {
66 66 QVector<std::shared_ptr<DBCatalogue> > catalogueList;
67 67 for (auto database : databaseList) {
68 68 catalogueList.append(ui->catalogues->getCatalogues(database));
69 69 }
70 70 ui->events->populateWithCatalogues(catalogueList);
71 71 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
72 72 });
73 73
74 74 connect(ui->catalogues, &CatalogueSideBarWidget::selectionCleared, [this]() {
75 75 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
76 76 ui->events->clear();
77 77 });
78 78
79 79 // Updates the inspectot when something is selected in the events
80 80 connect(ui->events, &CatalogueEventsWidget::eventsSelected, [this](auto events) {
81 81 if (events.count() == 1) {
82 82 ui->inspector->setEvent(events.first());
83 83 }
84 84 else {
85 85 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
86 86 }
87 87 });
88 88
89 89 connect(ui->events, &CatalogueEventsWidget::eventProductsSelected, [this](auto eventProducts) {
90 90 if (eventProducts.count() == 1) {
91 91 ui->inspector->setEventProduct(eventProducts.first().first,
92 92 eventProducts.first().second);
93 93 }
94 94 else {
95 95 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
96 96 }
97 97 });
98 98
99 99 connect(ui->events, &CatalogueEventsWidget::selectionCleared,
100 100 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
101 101
102 102 // Manage Selection Zones associated to events
103 103 connect(ui->events, &CatalogueEventsWidget::selectionZoneAdded,
104 104 [this](auto event, auto productId, auto zone) {
105 105 this->addSelectionZoneItem(event, productId, zone);
106 106 });
107 107
108 108 connect(ui->events, &CatalogueEventsWidget::eventsRemoved, [this](auto events) {
109 109 for (auto event : events) {
110 110 auto associatedSelectionZonesIt = impl->m_SelectionZonesPerEvents.find(event);
111 111 if (associatedSelectionZonesIt != impl->m_SelectionZonesPerEvents.cend()) {
112 112 for (auto selectionZone : associatedSelectionZonesIt->second) {
113 113 auto parentGraph = selectionZone->parentGraphWidget();
114 114 parentGraph->removeSelectionZone(selectionZone);
115 115 }
116 116
117 117 impl->m_SelectionZonesPerEvents.erase(event);
118 118 }
119 119 }
120 120 });
121 121
122 122 // Updates changes from the inspector
123 123 connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated, [this](auto catalogue) {
124 124 sqpApp->catalogueController().updateCatalogue(catalogue);
125 125 ui->catalogues->setCatalogueChanges(catalogue, true);
126 126 });
127 127
128 128 connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated, [this](auto event) {
129 129 sqpApp->catalogueController().updateEvent(event);
130 130 ui->events->setEventChanges(event, true);
131 131 });
132 132
133 133 connect(ui->inspector, &CatalogueInspectorWidget::eventProductUpdated,
134 134 [this](auto event, auto eventProduct) {
135 135 sqpApp->catalogueController().updateEventProduct(eventProduct);
136 136 ui->events->setEventChanges(event, true);
137 137 });
138
139 connect(ui->events, &CatalogueEventsWidget::eventCataloguesModified,
140 [this](const QVector<std::shared_ptr<DBCatalogue> > &catalogues) {
141 for (auto catalogue : catalogues) {
142 ui->catalogues->setCatalogueChanges(catalogue, true);
143 }
144 });
138 145 }
139 146
140 147 CatalogueExplorer::~CatalogueExplorer()
141 148 {
142 149 disconnect(impl->m_Conn);
143 150 delete ui;
144 151 }
145 152
146 153 void CatalogueExplorer::setVisualizationWidget(VisualizationWidget *visualization)
147 154 {
148 155 ui->events->setVisualizationWidget(visualization);
149 156 }
150 157
151 158 CatalogueEventsWidget &CatalogueExplorer::eventsWidget() const
152 159 {
153 160 return *ui->events;
154 161 }
155 162
156 163 CatalogueSideBarWidget &CatalogueExplorer::sideBarWidget() const
157 164 {
158 165 return *ui->catalogues;
159 166 }
160 167
161 168 void CatalogueExplorer::clearSelectionZones()
162 169 {
163 170 impl->m_SelectionZonesPerEvents.clear();
164 171 }
165 172
166 173 void CatalogueExplorer::addSelectionZoneItem(const std::shared_ptr<DBEvent> &event,
167 174 const QString &productId,
168 175 VisualizationSelectionZoneItem *selectionZone)
169 176 {
170 177 impl->m_SelectionZonesPerEvents[event] << selectionZone;
171 178 connect(selectionZone, &VisualizationSelectionZoneItem::rangeEdited,
172 179 [event, productId, this](auto range) {
173 180 auto productList = event->getEventProducts();
174 181 for (auto &product : productList) {
175 182 if (product.getProductId() == productId) {
176 183 product.setTStart(range.m_TStart);
177 184 product.setTEnd(range.m_TEnd);
178 185 }
179 186 }
180 187 event->setEventProducts(productList);
181 188 sqpApp->catalogueController().updateEvent(event);
182 189 ui->events->refreshEvent(event);
183 190 ui->events->setEventChanges(event, true);
184 191 ui->inspector->refresh();
185 192 });
186 193
187 194 impl->m_Conn = connect(selectionZone, &VisualizationSelectionZoneItem::destroyed,
188 195 [event, selectionZone, this]() {
189 196 if (!impl->m_SelectionZonesPerEvents.empty()) {
190 197 impl->m_SelectionZonesPerEvents[event].removeAll(selectionZone);
191 198 }
192 199 });
193 200 }
@@ -1,129 +1,126
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 79 // Check that the event is not dropped on the same catalogue
80 80 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
81 81 data->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
82 82 for (auto catalogue : sourceCatalogues) {
83 83 if (catalogue->getUniqId() == impl->m_Catalogue->getUniqId()) {
84 84 return false;
85 85 }
86 86 }
87 87
88 88 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
89 89 auto canDrop = data->hasFormat(MIME_TYPE_EVENT_LIST);
90 90
91 91 for (auto event : events) {
92 92 canDrop &= (event->getRepository() == impl->m_Catalogue->getRepository());
93 93 }
94 94
95 95 return canDrop;
96 96 }
97 97
98 98 bool CatalogueTreeItem::dropMimeData(const QMimeData *data, Qt::DropAction action)
99 99 {
100 100 Q_ASSERT(canDropMimeData(data, action));
101 101 // Warning: Check that the events aren't already in the catalogue
102 102 // No need to check check for the repository: inter-repository drop is forbidden in
103 103 // canDropMimeData
104 104
105 105 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
106 106 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
107 107 data->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
108 108
109 109 for (auto event : events) {
110 110
111 111 if (action == Qt::MoveAction) {
112 112 for (auto catalogue : sourceCatalogues) {
113 113 catalogue->removeEvent(event->getUniqId());
114 sqpApp->catalogueController().updateCatalogue(catalogue);
114 115 }
115 116 }
116 117
117 118 impl->m_Catalogue->addEvent(event->getUniqId());
119 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
118 120 }
119
120 for (auto catalogue : sourceCatalogues) {
121 sqpApp->catalogueController().updateCatalogue(catalogue);
122 }
123 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
124 121 }
125 122
126 123 std::shared_ptr<DBCatalogue> CatalogueTreeItem::catalogue() const
127 124 {
128 125 return impl->m_Catalogue;
129 126 }
General Comments 0
You need to be logged in to leave comments. Login now