##// END OF EJS Templates
Some fixes
trabillard -
r1290:21b6c58e9bf1
parent child
Show More
@@ -1,135 +1,136
1 1 #include "Catalogue/CatalogueActionManager.h"
2 2
3 3 #include <Actions/ActionsGuiController.h>
4 4 #include <Catalogue/CatalogueController.h>
5 5 #include <DataSource/DataSourceItem.h>
6 6 #include <SqpApplication.h>
7 7 #include <Variable/Variable.h>
8 8 #include <Visualization/VisualizationGraphWidget.h>
9 9 #include <Visualization/VisualizationSelectionZoneItem.h>
10 10
11 11 #include <Catalogue/CatalogueEventsWidget.h>
12 12 #include <Catalogue/CatalogueExplorer.h>
13 13 #include <Catalogue/CatalogueSideBarWidget.h>
14 14 #include <Catalogue/CreateEventDialog.h>
15 15
16 #include <CatalogueDao.h>
16 17 #include <DBCatalogue.h>
17 18 #include <DBEvent.h>
18 19 #include <DBEventProduct.h>
19 20
20 21 #include <QBoxLayout>
21 22 #include <QComboBox>
22 23 #include <QDialog>
23 24 #include <QDialogButtonBox>
24 25 #include <QLineEdit>
25 26 #include <memory>
26 27
27 28 struct CatalogueActionManager::CatalogueActionManagerPrivate {
28 29
29 30 CatalogueExplorer *m_CatalogueExplorer = nullptr;
30 31
31 32 CatalogueActionManagerPrivate(CatalogueExplorer *catalogueExplorer)
32 33 : m_CatalogueExplorer(catalogueExplorer)
33 34 {
34 35 }
35 36
36 37 void createEventFromZones(const QString &eventName,
37 38 const QVector<VisualizationSelectionZoneItem *> &zones,
38 39 const std::shared_ptr<DBCatalogue> &catalogue = nullptr)
39 40 {
40 41 auto event = std::make_shared<DBEvent>();
41 42 event->setName(eventName);
42 43
43 44 std::list<DBEventProduct> productList;
44 45 for (auto zone : zones) {
45 46 auto graph = zone->parentGraphWidget();
46 47 for (auto var : graph->variables()) {
47 48 auto eventProduct = std::make_shared<DBEventProduct>();
48 49 eventProduct->setEvent(*event);
49 50
50 51 auto zoneRange = zone->range();
51 52 eventProduct->setTStart(zoneRange.m_TStart);
52 53 eventProduct->setTEnd(zoneRange.m_TEnd);
53 54
54 55 eventProduct->setProductId(
55 56 var->metadata().value(DataSourceItem::ID_DATA_KEY, "UnknownID").toString());
56 57
57 58 productList.push_back(*eventProduct);
58 59 }
59 60 }
60 61
61 62 event->setEventProducts(productList);
62 63
63 64 sqpApp->catalogueController().addEvent(event);
64 65
65 66
66 67 if (catalogue) {
67 68 // TODO
68 69 // catalogue->addEvent(event);
69 70 m_CatalogueExplorer->sideBarWidget().setCatalogueChanges(catalogue, true);
70 71 if (m_CatalogueExplorer->eventsWidget().displayedCatalogues().contains(catalogue)) {
71 72 m_CatalogueExplorer->eventsWidget().addEvent(event);
72 73 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
73 74 }
74 75 }
75 76 else if (m_CatalogueExplorer->eventsWidget().isAllEventsDisplayed()) {
76 77 m_CatalogueExplorer->eventsWidget().addEvent(event);
77 78 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
78 79 }
79 80 }
80 81 };
81 82
82 83 CatalogueActionManager::CatalogueActionManager(CatalogueExplorer *catalogueExplorer)
83 84 : impl{spimpl::make_unique_impl<CatalogueActionManagerPrivate>(catalogueExplorer)}
84 85 {
85 86 }
86 87
87 88 void CatalogueActionManager::installSelectionZoneActions()
88 89 {
89 90 auto &actionController = sqpApp->actionsGuiController();
90 91
91 92 auto createEventEnableFuntion = [](auto zones) {
92 93 QSet<VisualizationGraphWidget *> usedGraphs;
93 94 for (auto zone : zones) {
94 95 auto graph = zone->parentGraphWidget();
95 96 if (!usedGraphs.contains(graph)) {
96 97 usedGraphs.insert(graph);
97 98 }
98 99 else {
99 100 return false;
100 101 }
101 102 }
102 103
103 104 return true;
104 105 };
105 106
106 107 auto createEventAction = actionController.addSectionZoneAction(
107 108 {QObject::tr("Catalogues")}, QObject::tr("New Event..."), [this](auto zones) {
108 109 CreateEventDialog dialog(
109 impl->m_CatalogueExplorer->sideBarWidget().getCatalogues("Default"));
110 impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT));
110 111 dialog.hideCatalogueChoice();
111 112 if (dialog.exec() == QDialog::Accepted) {
112 113 impl->createEventFromZones(dialog.eventName(), zones);
113 114 }
114 115 });
115 116 createEventAction->setEnableFunction(createEventEnableFuntion);
116 117
117 118 auto createEventInCatalogueAction = actionController.addSectionZoneAction(
118 119 {QObject::tr("Catalogues")}, QObject::tr("New Event in Catalogue..."), [this](auto zones) {
119 120 CreateEventDialog dialog(
120 impl->m_CatalogueExplorer->sideBarWidget().getCatalogues("Default"));
121 impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT));
121 122 if (dialog.exec() == QDialog::Accepted) {
122 123 auto selectedCatalogue = dialog.selectedCatalogue();
123 124 if (!selectedCatalogue) {
124 125 selectedCatalogue = std::make_shared<DBCatalogue>();
125 126 selectedCatalogue->setName(dialog.catalogueName());
126 127 // sqpApp->catalogueController().addCatalogue(selectedCatalogue); TODO
127 128 impl->m_CatalogueExplorer->sideBarWidget().addCatalogue(selectedCatalogue,
128 "Default");
129 REPOSITORY_DEFAULT);
129 130 }
130 131
131 132 impl->createEventFromZones(dialog.eventName(), zones, selectedCatalogue);
132 133 }
133 134 });
134 135 createEventInCatalogueAction->setEnableFunction(createEventEnableFuntion);
135 136 }
@@ -1,407 +1,409
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 17
18 18 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
19 19
20 20 /// Fixed size of the validation column
21 21 const auto VALIDATION_COLUMN_SIZE = 35;
22 22
23 23 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
24 24
25 25 CatalogueEventsModel *m_Model = nullptr;
26 26 QStringList m_ZonesForTimeMode;
27 27 QString m_ZoneForGraphMode;
28 28 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
29 29
30 30 VisualizationWidget *m_VisualizationWidget = nullptr;
31 31
32 32 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, QTreeView *treeView)
33 33 {
34 34 treeView->setSortingEnabled(false);
35 35 m_Model->setEvents(events);
36 36 treeView->setSortingEnabled(true);
37 37 }
38 38
39 39 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
40 40 {
41 41 treeView->setSortingEnabled(false);
42 42 m_Model->addEvent(event);
43 43 treeView->setSortingEnabled(true);
44 44 }
45 45
46 46 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
47 47 {
48 48 treeView->setSortingEnabled(false);
49 49 m_Model->removeEvent(event);
50 50 treeView->setSortingEnabled(true);
51 51 }
52 52
53 53 QStringList getAvailableVisualizationZoneList() const
54 54 {
55 55 if (m_VisualizationWidget) {
56 56 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
57 57 return tab->availableZoneWidgets();
58 58 }
59 59 }
60 60
61 61 return QStringList{};
62 62 }
63 63
64 64 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
65 65 bool allowMultiSelection, const QPoint &location)
66 66 {
67 67 auto availableZones = getAvailableVisualizationZoneList();
68 68 if (availableZones.isEmpty()) {
69 69 return QStringList{};
70 70 }
71 71
72 72 QDialog d(parent, Qt::Tool);
73 73 d.setWindowTitle("Choose a zone");
74 74 auto layout = new QVBoxLayout{&d};
75 75 layout->setContentsMargins(0, 0, 0, 0);
76 76 auto listWidget = new QListWidget{&d};
77 77 layout->addWidget(listWidget);
78 78
79 79 QSet<QListWidgetItem *> checkedItems;
80 80 for (auto zone : availableZones) {
81 81 auto item = new QListWidgetItem{zone};
82 82 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
83 83 if (selectedZones.contains(zone)) {
84 84 item->setCheckState(Qt::Checked);
85 85 checkedItems << item;
86 86 }
87 87 else {
88 88 item->setCheckState(Qt::Unchecked);
89 89 }
90 90
91 91 listWidget->addItem(item);
92 92 }
93 93
94 94 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
95 95 layout->addWidget(buttonBox);
96 96
97 97 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
98 98 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
99 99
100 100 QObject::connect(listWidget, &QListWidget::itemChanged,
101 101 [&checkedItems, allowMultiSelection, listWidget](auto item) {
102 102 if (item->checkState() == Qt::Checked) {
103 103 if (!allowMultiSelection) {
104 104 for (auto checkedItem : checkedItems) {
105 105 listWidget->blockSignals(true);
106 106 checkedItem->setCheckState(Qt::Unchecked);
107 107 listWidget->blockSignals(false);
108 108 }
109 109
110 110 checkedItems.clear();
111 111 }
112 112 checkedItems << item;
113 113 }
114 114 else {
115 115 checkedItems.remove(item);
116 116 }
117 117 });
118 118
119 119 QStringList result;
120 120
121 121 d.setMinimumWidth(120);
122 122 d.resize(d.minimumSizeHint());
123 123 d.move(location);
124 124 if (d.exec() == QDialog::Accepted) {
125 125 for (auto item : checkedItems) {
126 126 result += item->text();
127 127 }
128 128 }
129 129 else {
130 130 result = selectedZones;
131 131 }
132 132
133 133 return result;
134 134 }
135 135
136 136 void updateForTimeMode(QTreeView *treeView)
137 137 {
138 138 auto selectedRows = treeView->selectionModel()->selectedRows();
139 139
140 140 if (selectedRows.count() == 1) {
141 141 auto event = m_Model->getEvent(selectedRows.first());
142 142 if (event) {
143 143 if (m_VisualizationWidget) {
144 144 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
145 145
146 146 for (auto zoneName : m_ZonesForTimeMode) {
147 147 if (auto zone = tab->getZoneWithName(zoneName)) {
148 148 SqpRange eventRange;
149 149 eventRange.m_TStart = event->getTStart();
150 150 eventRange.m_TEnd = event->getTEnd();
151 151 zone->setZoneRange(eventRange);
152 152 }
153 153 }
154 154 }
155 155 else {
156 156 qCWarning(LOG_CatalogueEventsWidget())
157 157 << "updateTimeZone: no tab found in the visualization";
158 158 }
159 159 }
160 160 else {
161 161 qCWarning(LOG_CatalogueEventsWidget())
162 162 << "updateTimeZone: visualization widget not found";
163 163 }
164 164 }
165 165 }
166 166 else {
167 167 qCWarning(LOG_CatalogueEventsWidget())
168 168 << "updateTimeZone: not compatible with multiple events selected";
169 169 }
170 170 }
171 171
172 172 void updateForGraphMode(QTreeView *treeView)
173 173 {
174 174 auto selectedRows = treeView->selectionModel()->selectedRows();
175 175
176 176 if (selectedRows.count() == 1) {
177 177 auto event = m_Model->getEvent(selectedRows.first());
178 178 if (m_VisualizationWidget) {
179 179 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
180 180 if (auto zone = tab->getZoneWithName(m_ZoneForGraphMode)) {
181 181 // TODO
182 182 }
183 183 }
184 184 else {
185 185 qCWarning(LOG_CatalogueEventsWidget())
186 186 << "updateGraphMode: no tab found in the visualization";
187 187 }
188 188 }
189 189 else {
190 190 qCWarning(LOG_CatalogueEventsWidget())
191 191 << "updateGraphMode: visualization widget not found";
192 192 }
193 193 }
194 194 else {
195 195 qCWarning(LOG_CatalogueEventsWidget())
196 196 << "updateGraphMode: not compatible with multiple events selected";
197 197 }
198 198 }
199 199 };
200 200
201 201 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
202 202 : QWidget(parent),
203 203 ui(new Ui::CatalogueEventsWidget),
204 204 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
205 205 {
206 206 ui->setupUi(this);
207 207
208 208 impl->m_Model = new CatalogueEventsModel{this};
209 209 ui->treeView->setModel(impl->m_Model);
210 210
211 211 ui->treeView->setSortingEnabled(true);
212 212 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
213 213 ui->treeView->setDragEnabled(true);
214 214
215 215 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
216 216 if (checked) {
217 217 ui->btnChart->setChecked(false);
218 218 impl->m_ZonesForTimeMode
219 219 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
220 220 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
221 221
222 222 impl->updateForTimeMode(ui->treeView);
223 223 }
224 224 });
225 225
226 226 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
227 227 if (checked) {
228 228 ui->btnTime->setChecked(false);
229 229 impl->m_ZoneForGraphMode
230 230 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
231 231 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
232 232 .value(0);
233 233
234 234 impl->updateForGraphMode(ui->treeView);
235 235 }
236 236 });
237 237
238 238 auto emitSelection = [this]() {
239 239 QVector<std::shared_ptr<DBEvent> > events;
240 240 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
241 241
242 242 for (auto rowIndex : ui->treeView->selectionModel()->selectedRows()) {
243 243
244 244 auto itemType = impl->m_Model->itemTypeOf(rowIndex);
245 245 if (itemType == CatalogueEventsModel::ItemType::Event) {
246 246 events << impl->m_Model->getEvent(rowIndex);
247 247 }
248 248 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
249 249 eventProducts << qMakePair(impl->m_Model->getParentEvent(rowIndex),
250 250 impl->m_Model->getEventProduct(rowIndex));
251 251 }
252 252 }
253 253
254 254 if (!events.isEmpty() && eventProducts.isEmpty()) {
255 255 emit this->eventsSelected(events);
256 256 }
257 257 else if (events.isEmpty() && !eventProducts.isEmpty()) {
258 258 emit this->eventProductsSelected(eventProducts);
259 259 }
260 260 else {
261 261 emit this->selectionCleared();
262 262 }
263 263 };
264 264
265 265 connect(ui->treeView, &QTreeView::clicked, emitSelection);
266 266 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, emitSelection);
267 267
268 268 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
269 269 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
270 270 ui->btnChart->setEnabled(isNotMultiSelection);
271 271 ui->btnTime->setEnabled(isNotMultiSelection);
272 272
273 273 if (isNotMultiSelection && ui->btnTime->isChecked()) {
274 274 impl->updateForTimeMode(ui->treeView);
275 275 }
276 276 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
277 277 impl->updateForGraphMode(ui->treeView);
278 278 }
279 279 });
280 280
281 281 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
282 282 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
283 283 QHeaderView::Stretch);
284 284 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
285 285 QHeaderView::Fixed);
286 286 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
287 287 VALIDATION_COLUMN_SIZE);
288 288 ui->treeView->header()->setSortIndicatorShown(true);
289 289
290 290 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
291 291 auto allEvents = impl->m_Model->events();
292 292 for (auto event : allEvents) {
293 293 setEventChanges(event, impl->m_Model->eventsHasChanges(event));
294 294 }
295 295 });
296 296
297 297 populateWithAllEvents();
298 298 }
299 299
300 300 CatalogueEventsWidget::~CatalogueEventsWidget()
301 301 {
302 302 delete ui;
303 303 }
304 304
305 305 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
306 306 {
307 307 impl->m_VisualizationWidget = visualization;
308 308 }
309 309
310 310 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
311 311 {
312 312 impl->addEvent(event, ui->treeView);
313 313 }
314 314
315 315 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
316 316 {
317 317 impl->m_Model->refreshEvent(event);
318 318
319 319 auto eventIndex = impl->m_Model->indexOf(event);
320 320 auto validationIndex
321 321 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
322 322
323 if (hasChanges) {
324 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
325 auto widget = CatalogueExplorerHelper::buildValidationWidget(
326 ui->treeView,
327 [this, event]() {
328 sqpApp->catalogueController().saveEvent(event);
329 setEventChanges(event, false);
330 },
331 [this, event]() { setEventChanges(event, false); });
332 ui->treeView->setIndexWidget(validationIndex, widget);
333 }
323 if (validationIndex.isValid()) {
324 if (hasChanges) {
325 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
326 auto widget = CatalogueExplorerHelper::buildValidationWidget(
327 ui->treeView,
328 [this, event]() {
329 sqpApp->catalogueController().saveEvent(event);
330 setEventChanges(event, false);
331 },
332 [this, event]() { setEventChanges(event, false); });
333 ui->treeView->setIndexWidget(validationIndex, widget);
334 }
334 335
335 impl->m_Model->setEventHasChanges(event, hasChanges);
336 impl->m_Model->setEventHasChanges(event, hasChanges);
337 }
336 338 }
337 339 else {
338 340 qCWarning(LOG_CatalogueEventsWidget())
339 341 << "setEventChanges: the event is not displayed in the model.";
340 342 }
341 343 }
342 344
343 345 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
344 346 {
345 347 return impl->m_DisplayedCatalogues;
346 348 }
347 349
348 350 bool CatalogueEventsWidget::isAllEventsDisplayed() const
349 351 {
350 352 return impl->m_DisplayedCatalogues.isEmpty() && !impl->m_Model->events().isEmpty();
351 353 }
352 354
353 355 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
354 356 {
355 357 return impl->m_Model->indexOf(event).isValid();
356 358 }
357 359
358 360 void CatalogueEventsWidget::populateWithCatalogues(
359 361 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
360 362 {
361 363 impl->m_DisplayedCatalogues = catalogues;
362 364
363 365 QSet<QUuid> eventIds;
364 366 QVector<std::shared_ptr<DBEvent> > events;
365 367
366 368 for (auto catalogue : catalogues) {
367 369 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
368 370 for (auto event : catalogueEvents) {
369 371 if (!eventIds.contains(event->getUniqId())) {
370 372 events << event;
371 373 eventIds.insert(event->getUniqId());
372 374 }
373 375 }
374 376 }
375 377
376 378 impl->setEvents(events, ui->treeView);
377 379 }
378 380
379 381 void CatalogueEventsWidget::populateWithAllEvents()
380 382 {
381 383 impl->m_DisplayedCatalogues.clear();
382 384
383 385 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
384 386
385 387 QVector<std::shared_ptr<DBEvent> > events;
386 388 for (auto event : allEvents) {
387 389 events << event;
388 390 }
389 391
390 392 impl->setEvents(events, ui->treeView);
391 393 }
392 394
393 395 void CatalogueEventsWidget::clear()
394 396 {
395 397 impl->m_DisplayedCatalogues.clear();
396 398 impl->setEvents({}, ui->treeView);
397 399 }
398 400
399 401 void CatalogueEventsWidget::refresh()
400 402 {
401 403 if (impl->m_DisplayedCatalogues.isEmpty()) {
402 404 populateWithAllEvents();
403 405 }
404 406 else {
405 407 populateWithCatalogues(impl->m_DisplayedCatalogues);
406 408 }
407 409 }
@@ -1,338 +1,339
1 1 #include "Catalogue/CatalogueSideBarWidget.h"
2 2 #include "ui_CatalogueSideBarWidget.h"
3 3 #include <SqpApplication.h>
4 4
5 5 #include <Catalogue/CatalogueController.h>
6 6 #include <Catalogue/CatalogueExplorerHelper.h>
7 7 #include <Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.h>
8 8 #include <Catalogue/CatalogueTreeItems/CatalogueTreeItem.h>
9 9 #include <Catalogue/CatalogueTreeModel.h>
10 10 #include <CatalogueDao.h>
11 11 #include <ComparaisonPredicate.h>
12 12 #include <DBCatalogue.h>
13 13
14 14 #include <QMenu>
15 15
16 16 Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
17 17
18 18
19 19 constexpr auto ALL_EVENT_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 1;
20 20 constexpr auto TRASH_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 2;
21 21 constexpr auto CATALOGUE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 3;
22 22 constexpr auto DATABASE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 4;
23 23
24 24
25 25 struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
26 26
27 27 CatalogueTreeModel *m_TreeModel = nullptr;
28 28
29 29 void configureTreeWidget(QTreeView *treeView);
30 30 QModelIndex addDatabaseItem(const QString &name);
31 31 CatalogueAbstractTreeItem *getDatabaseItem(const QString &name);
32 32 void addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
33 33 const QModelIndex &databaseIndex);
34 34
35 35 CatalogueTreeItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue) const;
36 36 void setHasChanges(bool value, const QModelIndex &index, QTreeView *treeView);
37 37 bool hasChanges(const QModelIndex &index, QTreeView *treeView);
38 38
39 39 int selectionType(QTreeView *treeView) const
40 40 {
41 41 auto selectedItems = treeView->selectionModel()->selectedRows();
42 42 if (selectedItems.isEmpty()) {
43 43 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
44 44 }
45 45 else {
46 46 auto firstIndex = selectedItems.first();
47 47 auto firstItem = m_TreeModel->item(firstIndex);
48 48 if (!firstItem) {
49 49 Q_ASSERT(false);
50 50 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
51 51 }
52 52 auto selectionType = firstItem->type();
53 53
54 54 for (auto itemIndex : selectedItems) {
55 55 auto item = m_TreeModel->item(itemIndex);
56 56 if (!item || item->type() != selectionType) {
57 57 // Incoherent multi selection
58 58 selectionType = CatalogueAbstractTreeItem::DEFAULT_TYPE;
59 59 break;
60 60 }
61 61 }
62 62
63 63 return selectionType;
64 64 }
65 65 }
66 66
67 67 QVector<std::shared_ptr<DBCatalogue> > selectedCatalogues(QTreeView *treeView) const
68 68 {
69 69 QVector<std::shared_ptr<DBCatalogue> > catalogues;
70 70 auto selectedItems = treeView->selectionModel()->selectedRows();
71 71 for (auto itemIndex : selectedItems) {
72 72 auto item = m_TreeModel->item(itemIndex);
73 73 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
74 74 catalogues.append(static_cast<CatalogueTreeItem *>(item)->catalogue());
75 75 }
76 76 }
77 77
78 78 return catalogues;
79 79 }
80 80
81 81 QStringList selectedRepositories(QTreeView *treeView) const
82 82 {
83 83 QStringList repositories;
84 84 auto selectedItems = treeView->selectionModel()->selectedRows();
85 85 for (auto itemIndex : selectedItems) {
86 86 auto item = m_TreeModel->item(itemIndex);
87 87 if (item && item->type() == DATABASE_ITEM_TYPE) {
88 88 repositories.append(item->text());
89 89 }
90 90 }
91 91
92 92 return repositories;
93 93 }
94 94 };
95 95
96 96 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
97 97 : QWidget(parent),
98 98 ui(new Ui::CatalogueSideBarWidget),
99 99 impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
100 100 {
101 101 ui->setupUi(this);
102 102
103 103 impl->m_TreeModel = new CatalogueTreeModel(this);
104 104 ui->treeView->setModel(impl->m_TreeModel);
105 105
106 106 impl->configureTreeWidget(ui->treeView);
107 107
108 108 ui->treeView->header()->setStretchLastSection(false);
109 109 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
110 110 ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
111 111
112 112 auto emitSelection = [this]() {
113 113
114 114 auto selectionType = impl->selectionType(ui->treeView);
115 115
116 116 switch (selectionType) {
117 117 case CATALOGUE_ITEM_TYPE:
118 118 emit this->catalogueSelected(impl->selectedCatalogues(ui->treeView));
119 119 break;
120 120 case DATABASE_ITEM_TYPE:
121 121 emit this->databaseSelected(impl->selectedRepositories(ui->treeView));
122 122 break;
123 123 case ALL_EVENT_ITEM_TYPE:
124 124 emit this->allEventsSelected();
125 125 break;
126 126 case TRASH_ITEM_TYPE:
127 127 emit this->trashSelected();
128 128 break;
129 129 default:
130 130 emit this->selectionCleared();
131 131 break;
132 132 }
133 133 };
134 134
135 135 connect(ui->treeView, &QTreeView::clicked, emitSelection);
136 136 connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, emitSelection);
137 137 connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [emitSelection, this](auto index) {
138 138 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
139 139 if (selectedIndexes.contains(index)) {
140 140 emitSelection();
141 141 }
142 142
143 143 auto item = impl->m_TreeModel->item(index);
144 144 impl->setHasChanges(true, index, ui->treeView);
145 145 });
146 146
147 147 ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
148 148 connect(ui->treeView, &QTreeView::customContextMenuRequested, this,
149 149 &CatalogueSideBarWidget::onContextMenuRequested);
150 150 }
151 151
152 152 CatalogueSideBarWidget::~CatalogueSideBarWidget()
153 153 {
154 154 delete ui;
155 155 }
156 156
157 157 void CatalogueSideBarWidget::addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
158 158 const QString &repository)
159 159 {
160 160 auto repositoryItem = impl->getDatabaseItem(repository);
161 161 impl->addCatalogueItem(catalogue, impl->m_TreeModel->indexOf(repositoryItem));
162 162 }
163 163
164 164 void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
165 165 bool hasChanges)
166 166 {
167 167 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
168 168 auto index = impl->m_TreeModel->indexOf(catalogueItem);
169 169 impl->setHasChanges(hasChanges, index, ui->treeView);
170 170 // catalogueItem->refresh();
171 171 }
172 172 }
173 173
174 174 QVector<std::shared_ptr<DBCatalogue> >
175 175 CatalogueSideBarWidget::getCatalogues(const QString &repository) const
176 176 {
177 177 QVector<std::shared_ptr<DBCatalogue> > result;
178 178 auto repositoryItem = impl->getDatabaseItem(repository);
179 179 for (auto child : repositoryItem->children()) {
180 180 if (child->type() == CATALOGUE_ITEM_TYPE) {
181 181 auto catalogueItem = static_cast<CatalogueTreeItem *>(child);
182 182 result << catalogueItem->catalogue();
183 183 }
184 184 else {
185 185 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogues: invalid structure";
186 186 }
187 187 }
188 188
189 189 return result;
190 190 }
191 191
192 192 void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
193 193 {
194 194 QMenu menu{this};
195 195
196 196 auto currentIndex = ui->treeView->currentIndex();
197 197 auto currentItem = impl->m_TreeModel->item(currentIndex);
198 198 if (!currentItem) {
199 199 return;
200 200 }
201 201
202 202 switch (currentItem->type()) {
203 203 case CATALOGUE_ITEM_TYPE:
204 204 menu.addAction("Rename", [this, currentIndex]() { ui->treeView->edit(currentIndex); });
205 205 break;
206 206 case DATABASE_ITEM_TYPE:
207 207 break;
208 208 case ALL_EVENT_ITEM_TYPE:
209 209 break;
210 210 case TRASH_ITEM_TYPE:
211 211 menu.addAction("Empty Trash", []() {
212 212 // TODO
213 213 });
214 214 break;
215 215 default:
216 216 break;
217 217 }
218 218
219 219 if (!menu.isEmpty()) {
220 220 menu.exec(ui->treeView->mapToGlobal(pos));
221 221 }
222 222 }
223 223
224 224 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(QTreeView *treeView)
225 225 {
226 226 auto allEventsItem = new CatalogueTextTreeItem{QIcon{":/icones/allEvents.png"}, "All Events",
227 227 ALL_EVENT_ITEM_TYPE};
228 m_TreeModel->addTopLevelItem(allEventsItem);
228 auto allEventIndex = m_TreeModel->addTopLevelItem(allEventsItem);
229 treeView->setCurrentIndex(allEventIndex);
229 230
230 231 auto trashItem
231 232 = new CatalogueTextTreeItem{QIcon{":/icones/trash.png"}, "Trash", TRASH_ITEM_TYPE};
232 233 m_TreeModel->addTopLevelItem(trashItem);
233 234
234 235 auto separator = new QFrame{treeView};
235 236 separator->setFrameShape(QFrame::HLine);
236 237 auto separatorItem
237 238 = new CatalogueTextTreeItem{QIcon{}, QString{}, CatalogueAbstractTreeItem::DEFAULT_TYPE};
238 239 separatorItem->setEnabled(false);
239 240 auto separatorIndex = m_TreeModel->addTopLevelItem(separatorItem);
240 241 treeView->setIndexWidget(separatorIndex, separator);
241 242
242 243 auto repositories = sqpApp->catalogueController().getRepositories();
243 244 for (auto dbname : repositories) {
244 245 auto dbIndex = addDatabaseItem(dbname);
245 246 auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname);
246 247 for (auto catalogue : catalogues) {
247 248 addCatalogueItem(catalogue, dbIndex);
248 249 }
249 250 }
250 251
251 252 treeView->expandAll();
252 253 }
253 254
254 255 QModelIndex
255 256 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name)
256 257 {
257 258 auto databaseItem
258 259 = new CatalogueTextTreeItem{QIcon{":/icones/database.png"}, {name}, DATABASE_ITEM_TYPE};
259 260 auto databaseIndex = m_TreeModel->addTopLevelItem(databaseItem);
260 261
261 262 return databaseIndex;
262 263 }
263 264
264 265 CatalogueAbstractTreeItem *
265 266 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name)
266 267 {
267 268 for (auto item : m_TreeModel->topLevelItems()) {
268 269 if (item->type() == DATABASE_ITEM_TYPE && item->text() == name) {
269 270 return item;
270 271 }
271 272 }
272 273
273 274 return nullptr;
274 275 }
275 276
276 277 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
277 278 const std::shared_ptr<DBCatalogue> &catalogue, const QModelIndex &databaseIndex)
278 279 {
279 280 auto catalogueItem
280 281 = new CatalogueTreeItem{catalogue, QIcon{":/icones/catalogue.png"}, CATALOGUE_ITEM_TYPE};
281 282 m_TreeModel->addChildItem(catalogueItem, databaseIndex);
282 283 }
283 284
284 285 CatalogueTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
285 286 const std::shared_ptr<DBCatalogue> &catalogue) const
286 287 {
287 288 for (auto item : m_TreeModel->topLevelItems()) {
288 289 if (item->type() == DATABASE_ITEM_TYPE) {
289 290 for (auto childItem : item->children()) {
290 291 if (childItem->type() == CATALOGUE_ITEM_TYPE) {
291 292 auto catalogueItem = static_cast<CatalogueTreeItem *>(childItem);
292 293 if (catalogueItem->catalogue() == catalogue) {
293 294 return catalogueItem;
294 295 }
295 296 }
296 297 else {
297 298 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
298 299 "structure. A database item should "
299 300 "only contain catalogues.";
300 301 Q_ASSERT(false);
301 302 }
302 303 }
303 304 }
304 305 }
305 306
306 307 return nullptr;
307 308 }
308 309
309 310 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(bool value,
310 311 const QModelIndex &index,
311 312 QTreeView *treeView)
312 313 {
313 314 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
314 315 if (value) {
315 316 if (!hasChanges(validationIndex, treeView)) {
316 317 auto widget = CatalogueExplorerHelper::buildValidationWidget(
317 318 treeView,
318 319 [this, validationIndex, treeView]() {
319 320 setHasChanges(false, validationIndex, treeView);
320 321 },
321 322 [this, validationIndex, treeView]() {
322 323 setHasChanges(false, validationIndex, treeView);
323 324 });
324 325 treeView->setIndexWidget(validationIndex, widget);
325 326 }
326 327 }
327 328 else {
328 329 // Note: the widget is destroyed
329 330 treeView->setIndexWidget(validationIndex, nullptr);
330 331 }
331 332 }
332 333
333 334 bool CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::hasChanges(const QModelIndex &index,
334 335 QTreeView *treeView)
335 336 {
336 337 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
337 338 return treeView->indexWidget(validationIndex) != nullptr;
338 339 }
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