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