##// END OF EJS Templates
Refresh catalogue menu when the catalogue list changed
trabillard -
r1327:07b2554d7734
parent child
Show More
@@ -1,27 +1,29
1 1 #ifndef SCIQLOP_ACTIONSGUICONTROLLER_H
2 2 #define SCIQLOP_ACTIONSGUICONTROLLER_H
3 3
4 4 #include <Actions/SelectionZoneAction.h>
5 5 #include <Common/spimpl.h>
6 6
7 7 #include <memory>
8 8
9 9 class ActionsGuiController {
10 10 public:
11 11 ActionsGuiController();
12 12
13 13 std::shared_ptr<SelectionZoneAction>
14 14 addSectionZoneAction(const QString &name, SelectionZoneAction::ExecuteFunction function);
15 15
16 16 std::shared_ptr<SelectionZoneAction>
17 17 addSectionZoneAction(const QStringList &subMenuList, const QString &name,
18 18 SelectionZoneAction::ExecuteFunction function);
19 19
20 20 QVector<std::shared_ptr<SelectionZoneAction> > selectionZoneActions() const;
21 21
22 void removeAction(const std::shared_ptr<SelectionZoneAction> &action);
23
22 24 private:
23 25 class ActionsGuiControllerPrivate;
24 26 spimpl::unique_impl_ptr<ActionsGuiControllerPrivate> impl;
25 27 };
26 28
27 29 #endif // SCIQLOP_ACTIONSGUICONTROLLER_H
@@ -1,19 +1,20
1 1 #ifndef SCIQLOP_CATALOGUEACTIONMANAGER_H
2 2 #define SCIQLOP_CATALOGUEACTIONMANAGER_H
3 3
4 4 #include <Common/spimpl.h>
5 5
6 6 class CatalogueExplorer;
7 7
8 8 class CatalogueActionManager {
9 9 public:
10 10 CatalogueActionManager(CatalogueExplorer *catalogueExplorer);
11 11
12 12 void installSelectionZoneActions();
13 void refreshCreateInCatalogueAction();
13 14
14 15 private:
15 16 class CatalogueActionManagerPrivate;
16 17 spimpl::unique_impl_ptr<CatalogueActionManagerPrivate> impl;
17 18 };
18 19
19 20 #endif // SCIQLOP_CATALOGUEACTIONMANAGER_H
@@ -1,56 +1,57
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 void catalogueSaved(const std::shared_ptr<DBCatalogue> &catalogue);
28 void catalogueListChanged();
28 29
29 30 public:
30 31 explicit CatalogueSideBarWidget(QWidget *parent = 0);
31 32 virtual ~CatalogueSideBarWidget();
32 33
33 34 CatalogueAbstractTreeItem *addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
34 35 const QString &repository);
35 36 void setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue, bool hasChanges);
36 37
37 38 QVector<std::shared_ptr<DBCatalogue> > getCatalogues(const QString &repository) const;
38 39
39 40 // QWidget interface
40 41 protected:
41 42 void keyPressEvent(QKeyEvent *event);
42 43
43 44 private slots:
44 45 void emitSelection();
45 46
46 47 private:
47 48 Ui::CatalogueSideBarWidget *ui;
48 49
49 50 class CatalogueSideBarWidgetPrivate;
50 51 spimpl::unique_impl_ptr<CatalogueSideBarWidgetPrivate> impl;
51 52
52 53 private slots:
53 54 void onContextMenuRequested(const QPoint &pos);
54 55 };
55 56
56 57 #endif // SCIQLOP_CATALOGUESIDEBARWIDGET_H
@@ -1,36 +1,41
1 1 #include "Actions/ActionsGuiController.h"
2 2
3 3 struct ActionsGuiController::ActionsGuiControllerPrivate {
4 4
5 5 QVector<std::shared_ptr<SelectionZoneAction> > m_SelectionZoneActions;
6 6 };
7 7
8 8 ActionsGuiController::ActionsGuiController()
9 9 : impl{spimpl::make_unique_impl<ActionsGuiControllerPrivate>()}
10 10 {
11 11 }
12 12
13 13 std::shared_ptr<SelectionZoneAction>
14 14 ActionsGuiController::addSectionZoneAction(const QString &name,
15 15 SelectionZoneAction::ExecuteFunction function)
16 16 {
17 17 auto action = std::make_shared<SelectionZoneAction>(name, function);
18 18 impl->m_SelectionZoneActions.push_back(action);
19 19
20 20 return action;
21 21 }
22 22
23 23 std::shared_ptr<SelectionZoneAction>
24 24 ActionsGuiController::addSectionZoneAction(const QStringList &subMenuList, const QString &name,
25 25 SelectionZoneAction::ExecuteFunction function)
26 26 {
27 27 auto action = std::make_shared<SelectionZoneAction>(subMenuList, name, function);
28 28 impl->m_SelectionZoneActions.push_back(action);
29 29
30 30 return action;
31 31 }
32 32
33 33 QVector<std::shared_ptr<SelectionZoneAction> > ActionsGuiController::selectionZoneActions() const
34 34 {
35 35 return impl->m_SelectionZoneActions;
36 36 }
37
38 void ActionsGuiController::removeAction(const std::shared_ptr<SelectionZoneAction> &action)
39 {
40 impl->m_SelectionZoneActions.removeAll(action);
41 }
@@ -1,153 +1,171
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
15 15 #include <CatalogueDao.h>
16 16 #include <DBCatalogue.h>
17 17 #include <DBEvent.h>
18 18 #include <DBEventProduct.h>
19 19
20 20 #include <QBoxLayout>
21 21 #include <QComboBox>
22 22 #include <QDialog>
23 23 #include <QDialogButtonBox>
24 24 #include <QLineEdit>
25 25 #include <memory>
26 26
27 27 const auto CATALOGUE_MENU_NAME = QObject::tr("Catalogues");
28 const auto CATALOGUE_CREATE_EVENT_MENU_NAME = QObject::tr("New Event");
28 const auto CATALOGUE_CREATE_EVENT_MENU_NAME = QObject::tr("New Event...");
29 29
30 const auto DEFAULT_EVENT_NAME = QObject::tr("New Event");
31 const auto DEFAULT_CATALOGUE_NAME = QObject::tr("New Catalogue");
30 const auto DEFAULT_EVENT_NAME = QObject::tr("Event");
31 const auto DEFAULT_CATALOGUE_NAME = QObject::tr("Catalogue");
32 32
33 33 struct CatalogueActionManager::CatalogueActionManagerPrivate {
34 34
35 35 CatalogueExplorer *m_CatalogueExplorer = nullptr;
36 QVector<std::shared_ptr<SelectionZoneAction> > m_CreateInCatalogueActions;
36 37
37 38 CatalogueActionManagerPrivate(CatalogueExplorer *catalogueExplorer)
38 39 : m_CatalogueExplorer(catalogueExplorer)
39 40 {
40 41 }
41 42
42 43 void createEventFromZones(const QString &eventName,
43 44 const QVector<VisualizationSelectionZoneItem *> &zones,
44 45 const std::shared_ptr<DBCatalogue> &catalogue = nullptr)
45 46 {
46 47 auto event = std::make_shared<DBEvent>();
47 48 event->setName(eventName);
48 49
49 50 std::list<DBEventProduct> productList;
50 51 for (auto zone : zones) {
51 52 auto graph = zone->parentGraphWidget();
52 53 for (auto var : graph->variables()) {
53 54 auto eventProduct = std::make_shared<DBEventProduct>();
54 55 eventProduct->setEvent(*event);
55 56
56 57 auto productId
57 58 = var->metadata().value(DataSourceItem::ID_DATA_KEY, "UnknownID").toString();
58 59
59 60 auto zoneRange = zone->range();
60 61 eventProduct->setTStart(zoneRange.m_TStart);
61 62 eventProduct->setTEnd(zoneRange.m_TEnd);
62 63
63 64 eventProduct->setProductId(productId);
64 65
65 66 productList.push_back(*eventProduct);
66 67 }
67 68 }
68 69
69 70 event->setEventProducts(productList);
70 71
71 72 sqpApp->catalogueController().addEvent(event);
72 73
73 74
74 75 if (catalogue) {
75 76 catalogue->addEvent(event->getUniqId());
76 77 sqpApp->catalogueController().updateCatalogue(catalogue);
77 78 m_CatalogueExplorer->sideBarWidget().setCatalogueChanges(catalogue, true);
78 79 if (m_CatalogueExplorer->eventsWidget().displayedCatalogues().contains(catalogue)) {
79 80 m_CatalogueExplorer->eventsWidget().addEvent(event);
80 81 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
81 82 }
82 83 }
83 84 else if (m_CatalogueExplorer->eventsWidget().isAllEventsDisplayed()) {
84 85 m_CatalogueExplorer->eventsWidget().addEvent(event);
85 86 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
86 87 }
87 88 }
89
90 SelectionZoneAction::EnableFunction createEventEnableFuntion() const
91 {
92 return [](auto zones) {
93
94 // Checks that all variables in the zones doesn't refer to the same product
95 QSet<QString> usedDatasource;
96 for (auto zone : zones) {
97 auto graph = zone->parentGraphWidget();
98 auto variables = graph->variables();
99
100 for (auto var : variables) {
101 auto datasourceId
102 = var->metadata().value(DataSourceItem::ID_DATA_KEY).toString();
103 if (!usedDatasource.contains(datasourceId)) {
104 usedDatasource.insert(datasourceId);
105 }
106 else {
107 return false;
108 }
109 }
110 }
111
112 return true;
113 };
114 }
88 115 };
89 116
90 117 CatalogueActionManager::CatalogueActionManager(CatalogueExplorer *catalogueExplorer)
91 118 : impl{spimpl::make_unique_impl<CatalogueActionManagerPrivate>(catalogueExplorer)}
92 119 {
93 120 }
94 121
95 122 void CatalogueActionManager::installSelectionZoneActions()
96 123 {
97 124 auto &actionController = sqpApp->actionsGuiController();
98 125
99 auto createEventEnableFuntion = [](auto zones) {
100
101 // Checks that all variables in the zones doesn't refer to the same product
102 QSet<QString> usedDatasource;
103 for (auto zone : zones) {
104 auto graph = zone->parentGraphWidget();
105 auto variables = graph->variables();
106
107 for (auto var : variables) {
108 auto datasourceId = var->metadata().value(DataSourceItem::ID_DATA_KEY).toString();
109 if (!usedDatasource.contains(datasourceId)) {
110 usedDatasource.insert(datasourceId);
111 }
112 else {
113 return false;
114 }
115 }
116 }
117
118 return true;
119 };
120
121
122 126 auto createEventAction = actionController.addSectionZoneAction(
123 127 {CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME}, QObject::tr("Without Catalogue"),
124 128 [this](auto zones) { impl->createEventFromZones(DEFAULT_EVENT_NAME, zones); });
125 createEventAction->setEnableFunction(createEventEnableFuntion);
129 createEventAction->setEnableFunction(impl->createEventEnableFuntion());
126 130
127 131 auto createEventInNewCatalogueAction = actionController.addSectionZoneAction(
128 132 {CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME}, QObject::tr("In New Catalogue"),
129 133 [this](auto zones) {
130 134
131 135 auto newCatalogue = std::make_shared<DBCatalogue>();
132 136 newCatalogue->setName(DEFAULT_CATALOGUE_NAME);
133 137 sqpApp->catalogueController().addCatalogue(newCatalogue);
134 138 impl->m_CatalogueExplorer->sideBarWidget().addCatalogue(newCatalogue,
135 139 REPOSITORY_DEFAULT);
136 140
137 141 impl->createEventFromZones(DEFAULT_EVENT_NAME, zones, newCatalogue);
138 142 });
139 createEventInNewCatalogueAction->setEnableFunction(createEventEnableFuntion);
143 createEventInNewCatalogueAction->setEnableFunction(impl->createEventEnableFuntion());
144
145
146 refreshCreateInCatalogueAction();
147 }
148
149 void CatalogueActionManager::refreshCreateInCatalogueAction()
150 {
151 auto &actionController = sqpApp->actionsGuiController();
140 152
153 for (auto action : impl->m_CreateInCatalogueActions) {
154 actionController.removeAction(action);
155 }
156 impl->m_CreateInCatalogueActions.clear();
141 157
142 158 auto allCatalogues
143 159 = impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT);
160
144 161 for (auto catalogue : allCatalogues) {
145 162 auto catalogueName = catalogue->getName();
146 163 auto createEventInCatalogueAction = actionController.addSectionZoneAction(
147 164 {CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME},
148 QObject::tr("In ").append(catalogueName), [this, catalogue](auto zones) {
165 QObject::tr("In \"").append(catalogueName).append("\""), [this, catalogue](auto zones) {
149 166 impl->createEventFromZones(DEFAULT_EVENT_NAME, zones, catalogue);
150 167 });
151 createEventInCatalogueAction->setEnableFunction(createEventEnableFuntion);
168 createEventInCatalogueAction->setEnableFunction(impl->createEventEnableFuntion());
169 impl->m_CreateInCatalogueActions << createEventInCatalogueAction;
152 170 }
153 171 }
@@ -1,203 +1,207
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 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSaved, ui->events,
80 80 &CatalogueEventsWidget::refresh);
81 81
82 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueListChanged,
83 [this]() { impl->m_ActionManager.refreshCreateInCatalogueAction(); });
84
82 85 // Updates the inspectot when something is selected in the events
83 86 connect(ui->events, &CatalogueEventsWidget::eventsSelected, [this](auto events) {
84 87 if (events.count() == 1) {
85 88 ui->inspector->setEvent(events.first());
86 89 }
87 90 else {
88 91 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
89 92 }
90 93 });
91 94
92 95 connect(ui->events, &CatalogueEventsWidget::eventProductsSelected, [this](auto eventProducts) {
93 96 if (eventProducts.count() == 1) {
94 97 ui->inspector->setEventProduct(eventProducts.first().first,
95 98 eventProducts.first().second);
96 99 }
97 100 else {
98 101 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
99 102 }
100 103 });
101 104
102 105 connect(ui->events, &CatalogueEventsWidget::selectionCleared,
103 106 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
104 107
105 108 // Manage Selection Zones associated to events
106 109 connect(ui->events, &CatalogueEventsWidget::selectionZoneAdded,
107 110 [this](auto event, auto productId, auto zone) {
108 111 this->addSelectionZoneItem(event, productId, zone);
109 112 });
110 113
111 114 connect(ui->events, &CatalogueEventsWidget::eventsRemoved, [this](auto events) {
112 115 for (auto event : events) {
113 116 auto associatedSelectionZonesIt = impl->m_SelectionZonesPerEvents.find(event);
114 117 if (associatedSelectionZonesIt != impl->m_SelectionZonesPerEvents.cend()) {
115 118 for (auto selectionZone : associatedSelectionZonesIt->second) {
116 119 auto parentGraph = selectionZone->parentGraphWidget();
117 120 parentGraph->removeSelectionZone(selectionZone);
118 121 }
119 122
120 123 impl->m_SelectionZonesPerEvents.erase(event);
121 124 }
122 125 }
123 126 });
124 127
125 128 // Updates changes from the inspector
126 129 connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated, [this](auto catalogue) {
127 130 sqpApp->catalogueController().updateCatalogue(catalogue);
128 131 ui->catalogues->setCatalogueChanges(catalogue, true);
132 impl->m_ActionManager.refreshCreateInCatalogueAction();
129 133 });
130 134
131 135 connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated, [this](auto event) {
132 136 sqpApp->catalogueController().updateEvent(event);
133 137 ui->events->setEventChanges(event, true);
134 138 });
135 139
136 140 connect(ui->inspector, &CatalogueInspectorWidget::eventProductUpdated,
137 141 [this](auto event, auto eventProduct) {
138 142 sqpApp->catalogueController().updateEventProduct(eventProduct);
139 143 ui->events->setEventChanges(event, true);
140 144 });
141 145
142 146 connect(ui->events, &CatalogueEventsWidget::eventCataloguesModified,
143 147 [this](const QVector<std::shared_ptr<DBCatalogue> > &catalogues) {
144 148 for (auto catalogue : catalogues) {
145 149 ui->catalogues->setCatalogueChanges(catalogue, true);
146 150 }
147 151 });
148 152 }
149 153
150 154 CatalogueExplorer::~CatalogueExplorer()
151 155 {
152 156 disconnect(impl->m_Conn);
153 157 delete ui;
154 158 }
155 159
156 160 void CatalogueExplorer::setVisualizationWidget(VisualizationWidget *visualization)
157 161 {
158 162 ui->events->setVisualizationWidget(visualization);
159 163 }
160 164
161 165 CatalogueEventsWidget &CatalogueExplorer::eventsWidget() const
162 166 {
163 167 return *ui->events;
164 168 }
165 169
166 170 CatalogueSideBarWidget &CatalogueExplorer::sideBarWidget() const
167 171 {
168 172 return *ui->catalogues;
169 173 }
170 174
171 175 void CatalogueExplorer::clearSelectionZones()
172 176 {
173 177 impl->m_SelectionZonesPerEvents.clear();
174 178 }
175 179
176 180 void CatalogueExplorer::addSelectionZoneItem(const std::shared_ptr<DBEvent> &event,
177 181 const QString &productId,
178 182 VisualizationSelectionZoneItem *selectionZone)
179 183 {
180 184 impl->m_SelectionZonesPerEvents[event] << selectionZone;
181 185 connect(selectionZone, &VisualizationSelectionZoneItem::rangeEdited,
182 186 [event, productId, this](auto range) {
183 187 auto productList = event->getEventProducts();
184 188 for (auto &product : productList) {
185 189 if (product.getProductId() == productId) {
186 190 product.setTStart(range.m_TStart);
187 191 product.setTEnd(range.m_TEnd);
188 192 }
189 193 }
190 194 event->setEventProducts(productList);
191 195 sqpApp->catalogueController().updateEvent(event);
192 196 ui->events->refreshEvent(event);
193 197 ui->events->setEventChanges(event, true);
194 198 ui->inspector->refresh();
195 199 });
196 200
197 201 impl->m_Conn = connect(selectionZone, &VisualizationSelectionZoneItem::destroyed,
198 202 [event, selectionZone, this]() {
199 203 if (!impl->m_SelectionZonesPerEvents.empty()) {
200 204 impl->m_SelectionZonesPerEvents[event].removeAll(selectionZone);
201 205 }
202 206 });
203 207 }
@@ -1,451 +1,461
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 15 #include <QKeyEvent>
16 16 #include <QMenu>
17 17 #include <QMessageBox>
18 18 #include <QMimeData>
19 19
20 20 Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
21 21
22 22
23 23 constexpr auto ALL_EVENT_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 1;
24 24 constexpr auto TRASH_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 2;
25 25 constexpr auto CATALOGUE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 3;
26 26 constexpr auto DATABASE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 4;
27 27
28 const auto DEFAULT_CATALOGUE_NAME = QObject::tr("Catalogue");
29
28 30
29 31 struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
30 32
31 33 CatalogueTreeModel *m_TreeModel = nullptr;
32 34
33 35 void configureTreeWidget(QTreeView *treeView);
34 36 QModelIndex addDatabaseItem(const QString &name);
35 37 CatalogueAbstractTreeItem *getDatabaseItem(const QString &name);
36 38 CatalogueAbstractTreeItem *addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
37 39 const QModelIndex &databaseIndex);
38 40
39 41 CatalogueTreeItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue) const;
40 42 void setHasChanges(bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget);
41 43 bool hasChanges(const QModelIndex &index, QTreeView *treeView);
42 44
43 45 int selectionType(QTreeView *treeView) const
44 46 {
45 47 auto selectedItems = treeView->selectionModel()->selectedRows();
46 48 if (selectedItems.isEmpty()) {
47 49 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
48 50 }
49 51 else {
50 52 auto firstIndex = selectedItems.first();
51 53 auto firstItem = m_TreeModel->item(firstIndex);
52 54 if (!firstItem) {
53 55 Q_ASSERT(false);
54 56 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
55 57 }
56 58 auto selectionType = firstItem->type();
57 59
58 60 for (auto itemIndex : selectedItems) {
59 61 auto item = m_TreeModel->item(itemIndex);
60 62 if (!item || item->type() != selectionType) {
61 63 // Incoherent multi selection
62 64 selectionType = CatalogueAbstractTreeItem::DEFAULT_TYPE;
63 65 break;
64 66 }
65 67 }
66 68
67 69 return selectionType;
68 70 }
69 71 }
70 72
71 73 QVector<std::shared_ptr<DBCatalogue> > selectedCatalogues(QTreeView *treeView) const
72 74 {
73 75 QVector<std::shared_ptr<DBCatalogue> > catalogues;
74 76 auto selectedItems = treeView->selectionModel()->selectedRows();
75 77 for (auto itemIndex : selectedItems) {
76 78 auto item = m_TreeModel->item(itemIndex);
77 79 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
78 80 catalogues.append(static_cast<CatalogueTreeItem *>(item)->catalogue());
79 81 }
80 82 }
81 83
82 84 return catalogues;
83 85 }
84 86
85 87 QStringList selectedRepositories(QTreeView *treeView) const
86 88 {
87 89 QStringList repositories;
88 90 auto selectedItems = treeView->selectionModel()->selectedRows();
89 91 for (auto itemIndex : selectedItems) {
90 92 auto item = m_TreeModel->item(itemIndex);
91 93 if (item && item->type() == DATABASE_ITEM_TYPE) {
92 94 repositories.append(item->text());
93 95 }
94 96 }
95 97
96 98 return repositories;
97 99 }
98 100 };
99 101
100 102 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
101 103 : QWidget(parent),
102 104 ui(new Ui::CatalogueSideBarWidget),
103 105 impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
104 106 {
105 107 ui->setupUi(this);
106 108
107 109 impl->m_TreeModel = new CatalogueTreeModel(this);
108 110 ui->treeView->setModel(impl->m_TreeModel);
109 111
110 112 impl->configureTreeWidget(ui->treeView);
113 emit catalogueListChanged();
111 114
112 115 ui->treeView->header()->setStretchLastSection(false);
113 116 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
114 117 ui->treeView->header()->setSectionResizeMode((int)CatalogueTreeModel::Column::Name,
115 118 QHeaderView::Stretch);
116 119
117 120 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueSideBarWidget::emitSelection);
118 121 connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, this,
119 122 &CatalogueSideBarWidget::emitSelection);
120 123
121 124
122 125 connect(ui->btnAdd, &QToolButton::clicked, [this]() {
123 126 auto catalogue = std::make_shared<DBCatalogue>();
124 catalogue->setName(QString("Cat"));
127 catalogue->setName(DEFAULT_CATALOGUE_NAME);
125 128 sqpApp->catalogueController().addCatalogue(catalogue);
126 129 auto item = this->addCatalogue(catalogue, REPOSITORY_DEFAULT);
127 130 this->setCatalogueChanges(catalogue, true);
128 131 ui->treeView->edit(impl->m_TreeModel->indexOf(item));
129 132
130 133 });
131 134
132 135
133 136 connect(impl->m_TreeModel, &CatalogueTreeModel::itemDropped,
134 137 [this](auto index, auto mimeData, auto action) {
135 138 auto item = impl->m_TreeModel->item(index);
136 139
137 140 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
138 141 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
139 142 this->setCatalogueChanges(catalogue, true);
140 143 }
141 144
142 145 if (action == Qt::MoveAction) {
143 146 /// Display a save button on source catalogues
144 147 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
145 148 mimeData->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
146 149 for (auto catalogue : sourceCatalogues) {
147 150 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
148 151 catalogueItem->replaceCatalogue(catalogue);
149 152 this->setCatalogueChanges(catalogue, true);
150 153 }
151 154 }
152 155
153 156 this->emitSelection();
154 157 }
155 158 });
156 159
157 160 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
158 161 QVector<QPair<std::shared_ptr<DBCatalogue>, CatalogueAbstractTreeItem *> >
159 162 cataloguesToItems;
160 163 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
161 164
162 165 for (auto index : selectedIndexes) {
163 166 auto item = impl->m_TreeModel->item(index);
164 167 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
165 168 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
166 169 cataloguesToItems << qMakePair(catalogue, item);
167 170 }
168 171 }
169 172
170 173 if (!cataloguesToItems.isEmpty()) {
171 174
172 175 if (QMessageBox::warning(this, tr("Remove Catalogue(s)"),
173 176 tr("The selected catalogues(s) will be completly removed "
174 177 "from the repository!\nAre you sure you want to continue?"),
175 178 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
176 179 == QMessageBox::Yes) {
177 180
178 181 for (auto catalogueToItem : cataloguesToItems) {
179 182 sqpApp->catalogueController().removeCatalogue(catalogueToItem.first);
180 183 impl->m_TreeModel->removeChildItem(
181 184 catalogueToItem.second,
182 185 impl->m_TreeModel->indexOf(catalogueToItem.second->parent()));
183 186 }
184 187 emitSelection();
188 emit catalogueListChanged();
185 189 }
186 190 }
187 191 });
188 192
189 193 connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [this](auto index) {
190 194 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
191 195 if (selectedIndexes.contains(index)) {
192 196 this->emitSelection();
193 197 }
194 198 impl->setHasChanges(true, index, this);
199 emit this->catalogueListChanged();
195 200 });
196 201
197 202 ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
198 203 connect(ui->treeView, &QTreeView::customContextMenuRequested, this,
199 204 &CatalogueSideBarWidget::onContextMenuRequested);
200 205 }
201 206
202 207 CatalogueSideBarWidget::~CatalogueSideBarWidget()
203 208 {
204 209 delete ui;
205 210 }
206 211
207 212 CatalogueAbstractTreeItem *
208 213 CatalogueSideBarWidget::addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
209 214 const QString &repository)
210 215 {
211 216 auto repositoryItem = impl->getDatabaseItem(repository);
212 return impl->addCatalogueItem(catalogue, impl->m_TreeModel->indexOf(repositoryItem));
217 auto catalogueItem
218 = impl->addCatalogueItem(catalogue, impl->m_TreeModel->indexOf(repositoryItem));
219
220 emit catalogueListChanged();
221
222 return catalogueItem;
213 223 }
214 224
215 225 void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
216 226 bool hasChanges)
217 227 {
218 228 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
219 229 auto index = impl->m_TreeModel->indexOf(catalogueItem);
220 230 impl->setHasChanges(hasChanges, index, this);
221 231 // catalogueItem->refresh();
222 232 }
223 233 }
224 234
225 235 QVector<std::shared_ptr<DBCatalogue> >
226 236 CatalogueSideBarWidget::getCatalogues(const QString &repository) const
227 237 {
228 238 QVector<std::shared_ptr<DBCatalogue> > result;
229 239 auto repositoryItem = impl->getDatabaseItem(repository);
230 240 for (auto child : repositoryItem->children()) {
231 241 if (child->type() == CATALOGUE_ITEM_TYPE) {
232 242 auto catalogueItem = static_cast<CatalogueTreeItem *>(child);
233 243 result << catalogueItem->catalogue();
234 244 }
235 245 else {
236 246 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogues: invalid structure";
237 247 }
238 248 }
239 249
240 250 return result;
241 251 }
242 252
243 253 void CatalogueSideBarWidget::emitSelection()
244 254 {
245 255 auto selectionType = impl->selectionType(ui->treeView);
246 256
247 257 switch (selectionType) {
248 258 case CATALOGUE_ITEM_TYPE:
249 259 emit this->catalogueSelected(impl->selectedCatalogues(ui->treeView));
250 260 break;
251 261 case DATABASE_ITEM_TYPE:
252 262 emit this->databaseSelected(impl->selectedRepositories(ui->treeView));
253 263 break;
254 264 case ALL_EVENT_ITEM_TYPE:
255 265 emit this->allEventsSelected();
256 266 break;
257 267 case TRASH_ITEM_TYPE:
258 268 emit this->trashSelected();
259 269 break;
260 270 default:
261 271 emit this->selectionCleared();
262 272 break;
263 273 }
264 274 }
265 275
266 276 void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
267 277 {
268 278 QMenu menu{this};
269 279
270 280 auto currentIndex = ui->treeView->currentIndex();
271 281 auto currentItem = impl->m_TreeModel->item(currentIndex);
272 282 if (!currentItem) {
273 283 return;
274 284 }
275 285
276 286 switch (currentItem->type()) {
277 287 case CATALOGUE_ITEM_TYPE:
278 288 menu.addAction("Rename", [this, currentIndex]() { ui->treeView->edit(currentIndex); });
279 289 break;
280 290 case DATABASE_ITEM_TYPE:
281 291 break;
282 292 case ALL_EVENT_ITEM_TYPE:
283 293 break;
284 294 case TRASH_ITEM_TYPE:
285 295 menu.addAction("Empty Trash", []() {
286 296 // TODO
287 297 });
288 298 break;
289 299 default:
290 300 break;
291 301 }
292 302
293 303 if (!menu.isEmpty()) {
294 304 menu.exec(ui->treeView->mapToGlobal(pos));
295 305 }
296 306 }
297 307
298 308 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(QTreeView *treeView)
299 309 {
300 310 auto allEventsItem = new CatalogueTextTreeItem{QIcon{":/icones/allEvents.png"}, "All Events",
301 311 ALL_EVENT_ITEM_TYPE};
302 312 auto allEventIndex = m_TreeModel->addTopLevelItem(allEventsItem);
303 313 treeView->setCurrentIndex(allEventIndex);
304 314
305 315 auto trashItem
306 316 = new CatalogueTextTreeItem{QIcon{":/icones/trash.png"}, "Trash", TRASH_ITEM_TYPE};
307 317 m_TreeModel->addTopLevelItem(trashItem);
308 318
309 319 auto separator = new QFrame{treeView};
310 320 separator->setFrameShape(QFrame::HLine);
311 321 auto separatorItem
312 322 = new CatalogueTextTreeItem{QIcon{}, QString{}, CatalogueAbstractTreeItem::DEFAULT_TYPE};
313 323 separatorItem->setEnabled(false);
314 324 auto separatorIndex = m_TreeModel->addTopLevelItem(separatorItem);
315 325 treeView->setIndexWidget(separatorIndex, separator);
316 326
317 327 auto repositories = sqpApp->catalogueController().getRepositories();
318 328 for (auto dbname : repositories) {
319 329 auto dbIndex = addDatabaseItem(dbname);
320 330 auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname);
321 331 for (auto catalogue : catalogues) {
322 332 addCatalogueItem(catalogue, dbIndex);
323 333 }
324 334 }
325 335
326 336 treeView->expandAll();
327 337 }
328 338
329 339 QModelIndex
330 340 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name)
331 341 {
332 342 auto databaseItem
333 343 = new CatalogueTextTreeItem{QIcon{":/icones/database.png"}, {name}, DATABASE_ITEM_TYPE};
334 344 auto databaseIndex = m_TreeModel->addTopLevelItem(databaseItem);
335 345
336 346 return databaseIndex;
337 347 }
338 348
339 349 CatalogueAbstractTreeItem *
340 350 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name)
341 351 {
342 352 for (auto item : m_TreeModel->topLevelItems()) {
343 353 if (item->type() == DATABASE_ITEM_TYPE && item->text() == name) {
344 354 return item;
345 355 }
346 356 }
347 357
348 358 return nullptr;
349 359 }
350 360
351 361 CatalogueAbstractTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
352 362 const std::shared_ptr<DBCatalogue> &catalogue, const QModelIndex &databaseIndex)
353 363 {
354 364 auto catalogueItem
355 365 = new CatalogueTreeItem{catalogue, QIcon{":/icones/catalogue.png"}, CATALOGUE_ITEM_TYPE};
356 366 m_TreeModel->addChildItem(catalogueItem, databaseIndex);
357 367
358 368 return catalogueItem;
359 369 }
360 370
361 371 CatalogueTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
362 372 const std::shared_ptr<DBCatalogue> &catalogue) const
363 373 {
364 374 for (auto item : m_TreeModel->topLevelItems()) {
365 375 if (item->type() == DATABASE_ITEM_TYPE) {
366 376 for (auto childItem : item->children()) {
367 377 if (childItem->type() == CATALOGUE_ITEM_TYPE) {
368 378 auto catalogueItem = static_cast<CatalogueTreeItem *>(childItem);
369 379 if (catalogueItem->catalogue()->getUniqId() == catalogue->getUniqId()) {
370 380 return catalogueItem;
371 381 }
372 382 }
373 383 else {
374 384 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
375 385 "structure. A database item should "
376 386 "only contain catalogues.";
377 387 Q_ASSERT(false);
378 388 }
379 389 }
380 390 }
381 391 }
382 392
383 393 return nullptr;
384 394 }
385 395
386 396 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(
387 397 bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget)
388 398 {
389 399 std::shared_ptr<DBCatalogue> catalogue = nullptr;
390 400 auto item = m_TreeModel->item(index);
391 401 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
392 402 catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
393 403 }
394 404
395 405 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
396 406 if (value) {
397 407 if (!hasChanges(validationIndex, sideBarWidget->ui->treeView)) {
398 408 auto widget = CatalogueExplorerHelper::buildValidationWidget(
399 409 sideBarWidget->ui->treeView,
400 410 [this, validationIndex, sideBarWidget, catalogue]() {
401 411 if (catalogue) {
402 412 sqpApp->catalogueController().saveCatalogue(catalogue);
403 413 emit sideBarWidget->catalogueSaved(catalogue);
404 414 }
405 415 setHasChanges(false, validationIndex, sideBarWidget);
406 416 },
407 417 [this, validationIndex, sideBarWidget, catalogue, item]() {
408 418 if (catalogue) {
409 419 bool removed;
410 420 sqpApp->catalogueController().discardCatalogue(catalogue, removed);
411 421
412 422 if (removed) {
413 423 m_TreeModel->removeChildItem(item,
414 424 m_TreeModel->indexOf(item->parent()));
415 425 }
416 426 else {
417 427 m_TreeModel->refresh(m_TreeModel->indexOf(item));
418 428 setHasChanges(false, validationIndex, sideBarWidget);
419 429 }
420 430 sideBarWidget->emitSelection();
421 431 }
422 432 });
423 433 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, widget);
424 434 sideBarWidget->ui->treeView->header()->resizeSection(
425 435 (int)CatalogueTreeModel::Column::Validation, QHeaderView::ResizeToContents);
426 436 }
427 437 }
428 438 else {
429 439 // Note: the widget is destroyed
430 440 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, nullptr);
431 441 }
432 442 }
433 443
434 444 bool CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::hasChanges(const QModelIndex &index,
435 445 QTreeView *treeView)
436 446 {
437 447 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
438 448 return treeView->indexWidget(validationIndex) != nullptr;
439 449 }
440 450
441 451
442 452 void CatalogueSideBarWidget::keyPressEvent(QKeyEvent *event)
443 453 {
444 454 switch (event->key()) {
445 455 case Qt::Key_Delete: {
446 456 ui->btnRemove->click();
447 457 }
448 458 default:
449 459 break;
450 460 }
451 461 }
General Comments 0
You need to be logged in to leave comments. Login now