diff --git a/core/include/Catalogue/CatalogueController.h b/core/include/Catalogue/CatalogueController.h index 7d12271..717037d 100644 --- a/core/include/Catalogue/CatalogueController.h +++ b/core/include/Catalogue/CatalogueController.h @@ -52,7 +52,8 @@ public: // Catalogue // bool createCatalogue(const QString &name, QVector eventList); /// retrieveEvents with empty repository retrieve them from the default repository - std::list > retrieveCatalogues(const QString &repository) const; + std::list > retrieveCatalogues(const QString &repository + = QString()) const; void updateCatalogue(std::shared_ptr catalogue); void removeCatalogue(std::shared_ptr catalogue); void saveCatalogue(std::shared_ptr catalogue); diff --git a/core/src/Catalogue/CatalogueController.cpp b/core/src/Catalogue/CatalogueController.cpp index f06adf5..be76fcf 100644 --- a/core/src/Catalogue/CatalogueController.cpp +++ b/core/src/Catalogue/CatalogueController.cpp @@ -148,7 +148,7 @@ void CatalogueController::removeEvent(std::shared_ptr event) void CatalogueController::addEvent(std::shared_ptr event) { - event->setRepository(impl->toSyncRepository(event->getRepository())); + event->setRepository(impl->toWorkRepository(event->getRepository())); impl->m_CatalogueDao.addEvent(*event); @@ -255,14 +255,23 @@ void CatalogueController::waitForFinish() void CatalogueController::CatalogueControllerPrivate::copyDBtoDB(const QString &dbFrom, const QString &dbTo) { - auto catalogues = m_Q->retrieveCatalogues(dbFrom); - auto events = m_Q->retrieveEvents(dbFrom); - + auto cataloguesShared = std::list >{}; + auto catalogues = m_CatalogueDao.getCatalogues(dbFrom); for (auto catalogue : catalogues) { - m_CatalogueDao.copyCatalogue(*catalogue, dbTo, true); + cataloguesShared.push_back(std::make_shared(catalogue)); } + auto eventsShared = std::list >{}; + auto events = m_CatalogueDao.getEvents(dbFrom); for (auto event : events) { + eventsShared.push_back(std::make_shared(event)); + } + + for (auto catalogue : cataloguesShared) { + m_CatalogueDao.copyCatalogue(*catalogue, dbTo, true); + } + + for (auto event : eventsShared) { m_CatalogueDao.copyEvent(*event, dbTo, true); } } diff --git a/gui/include/Catalogue/CatalogueActionManager.h b/gui/include/Catalogue/CatalogueActionManager.h new file mode 100644 index 0000000..5bd3347 --- /dev/null +++ b/gui/include/Catalogue/CatalogueActionManager.h @@ -0,0 +1,17 @@ +#ifndef SCIQLOP_CATALOGUEACTIONMANAGER_H +#define SCIQLOP_CATALOGUEACTIONMANAGER_H + +#include + +class CatalogueActionManager { +public: + CatalogueActionManager(); + + void installSelectionZoneActions(); + +private: + class CatalogueActionManagerPrivate; + spimpl::unique_impl_ptr impl; +}; + +#endif // SCIQLOP_CATALOGUEACTIONMANAGER_H diff --git a/gui/include/Catalogue/CatalogueEventsModel.h b/gui/include/Catalogue/CatalogueEventsModel.h index bc0bd70..e51ee47 100644 --- a/gui/include/Catalogue/CatalogueEventsModel.h +++ b/gui/include/Catalogue/CatalogueEventsModel.h @@ -3,17 +3,29 @@ #include #include +#include +#include class DBEvent; class DBEventProduct; +Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueEventsModel) + class CatalogueEventsModel : public QAbstractItemModel { + Q_OBJECT + +signals: + void modelSorted(); + public: CatalogueEventsModel(QObject *parent = nullptr); + enum class Column { Name, TStart, TEnd, Tags, Product, Validation, NbColumn }; + void setEvents(const QVector > &events); void addEvent(const std::shared_ptr &event); void removeEvent(const std::shared_ptr &event); + QVector > events() const; enum class ItemType { Root, Event, EventProduct }; ItemType itemTypeOf(const QModelIndex &index) const; @@ -21,8 +33,18 @@ public: std::shared_ptr getParentEvent(const QModelIndex &index) const; std::shared_ptr getEventProduct(const QModelIndex &index) const; + /// Refresh the data for the specified event void refreshEvent(const std::shared_ptr &event); + /// Returns a QModelIndex which represent the specified event + QModelIndex indexOf(const std::shared_ptr &event) const; + + /// Marks a change flag on the specified event to allow sorting on the validation column + void setEventHasChanges(const std::shared_ptr &event, bool hasChanges); + + /// Returns true if the specified event has unsaved changes + bool eventsHasChanges(const std::shared_ptr &event) const; + // Model QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; QModelIndex parent(const QModelIndex &index) const; diff --git a/gui/include/Catalogue/CatalogueEventsWidget.h b/gui/include/Catalogue/CatalogueEventsWidget.h index e7ce270..036b520 100644 --- a/gui/include/Catalogue/CatalogueEventsWidget.h +++ b/gui/include/Catalogue/CatalogueEventsWidget.h @@ -36,6 +36,7 @@ public: public slots: void populateWithCatalogues(const QVector > &catalogues); + void populateWithAllEvents(); private: Ui::CatalogueEventsWidget *ui; diff --git a/gui/include/Catalogue/CatalogueExplorerHelper.h b/gui/include/Catalogue/CatalogueExplorerHelper.h new file mode 100644 index 0000000..037901c --- /dev/null +++ b/gui/include/Catalogue/CatalogueExplorerHelper.h @@ -0,0 +1,13 @@ +#ifndef SCIQLOP_CATALOGUEEXPLORERHELPER_H +#define SCIQLOP_CATALOGUEEXPLORERHELPER_H + +#include + +#include + +struct CatalogueExplorerHelper { + static QWidget *buildValidationWidget(QWidget *parent, std::function save, + std::function discard); +}; + +#endif // SCIQLOP_CATALOGUEEXPLORERHELPER_H diff --git a/gui/include/Catalogue/CatalogueTreeWidgetItem.h b/gui/include/Catalogue/CatalogueTreeWidgetItem.h index a8b4f14..f9b0d65 100644 --- a/gui/include/Catalogue/CatalogueTreeWidgetItem.h +++ b/gui/include/Catalogue/CatalogueTreeWidgetItem.h @@ -22,6 +22,9 @@ public: /// changes void setHasChanges(bool value); + /// Returns true if the widget indicating the event has unsaved changes is displayed + bool hasChanges(); + /// Refreshes the data displayed by the item from the catalogue void refresh(); diff --git a/gui/include/Catalogue/CreateEventDialog.h b/gui/include/Catalogue/CreateEventDialog.h new file mode 100644 index 0000000..4cb4baa --- /dev/null +++ b/gui/include/Catalogue/CreateEventDialog.h @@ -0,0 +1,35 @@ +#ifndef SCIQLOP_CREATEEVENTDIALOG_H +#define SCIQLOP_CREATEEVENTDIALOG_H + +#include +#include +#include + +namespace Ui { +class CreateEventDialog; +} + +class DBCatalogue; + +class CreateEventDialog : public QDialog { + Q_OBJECT + +public: + explicit CreateEventDialog(QWidget *parent = 0); + virtual ~CreateEventDialog(); + + void hideCatalogueChoice(); + + QString eventName() const; + + std::shared_ptr selectedCatalogue() const; + QString catalogueName() const; + +private: + Ui::CreateEventDialog *ui; + + class CreateEventDialogPrivate; + spimpl::unique_impl_ptr impl; +}; + +#endif // SCIQLOP_CREATEEVENTDIALOG_H diff --git a/gui/meson.build b/gui/meson.build index 7899701..bd9cbe2 100644 --- a/gui/meson.build +++ b/gui/meson.build @@ -25,7 +25,9 @@ gui_moc_headers = [ 'include/Catalogue/CatalogueExplorer.h', 'include/Catalogue/CatalogueEventsWidget.h', 'include/Catalogue/CatalogueSideBarWidget.h', - 'include/Catalogue/CatalogueInspectorWidget.h' + 'include/Catalogue/CatalogueInspectorWidget.h', + 'include/Catalogue/CatalogueEventsModel.h', + 'include/Catalogue/CreateEventDialog.ui' ] gui_ui_files = [ @@ -46,7 +48,8 @@ gui_ui_files = [ 'ui/Catalogue/CatalogueExplorer.ui', 'ui/Catalogue/CatalogueEventsWidget.ui', 'ui/Catalogue/CatalogueSideBarWidget.ui', - 'ui/Catalogue/CatalogueInspectorWidget.ui' + 'ui/Catalogue/CatalogueInspectorWidget.ui', + 'ui/Catalogue/CreateEventDialog.ui' ] gui_qresources = ['resources/sqpguiresources.qrc'] @@ -116,7 +119,10 @@ gui_sources = [ 'src/Catalogue/CatalogueSideBarWidget.cpp', 'src/Catalogue/CatalogueInspectorWidget.cpp', 'src/Catalogue/CatalogueTreeWidgetItem.cpp', - 'src/Catalogue/CatalogueEventsModel.cpp' + 'src/Catalogue/CatalogueEventsModel.cpp', + 'src/Catalogue/CatalogueExplorerHelper.cpp', + 'src/Catalogue/CatalogueActionManager.cpp', + 'src/Catalogue/CreateEventDialog.cpp' ] gui_inc = include_directories(['include']) diff --git a/gui/src/Catalogue/CatalogueActionManager.cpp b/gui/src/Catalogue/CatalogueActionManager.cpp new file mode 100644 index 0000000..258ac5d --- /dev/null +++ b/gui/src/Catalogue/CatalogueActionManager.cpp @@ -0,0 +1,107 @@ +#include "Catalogue/CatalogueActionManager.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +struct CatalogueActionManager::CatalogueActionManagerPrivate { + void createEventFromZones(const QString &eventName, + const QVector &zones, + const std::shared_ptr &catalogue = nullptr) + { + auto event = std::make_shared(); + event->setName(eventName); + + std::list productList; + for (auto zone : zones) { + auto graph = zone->parentGraphWidget(); + for (auto var : graph->variables()) { + auto eventProduct = std::make_shared(); + eventProduct->setEvent(*event); + + auto zoneRange = zone->range(); + eventProduct->setTStart(zoneRange.m_TStart); + eventProduct->setTEnd(zoneRange.m_TEnd); + + eventProduct->setProductId(var->metadata().value("id", "TODO").toString()); // todo + + productList.push_back(*eventProduct); + } + } + + event->setEventProducts(productList); + + sqpApp->catalogueController().addEvent(event); + + if (catalogue) { + // TODO + // catalogue->addEvent(event); + } + } +}; + +CatalogueActionManager::CatalogueActionManager() + : impl{spimpl::make_unique_impl()} +{ +} + +void CatalogueActionManager::installSelectionZoneActions() +{ + auto &actionController = sqpApp->actionsGuiController(); + + auto createEventEnableFuntion = [](auto zones) { + QSet usedGraphs; + for (auto zone : zones) { + auto graph = zone->parentGraphWidget(); + if (!usedGraphs.contains(graph)) { + usedGraphs.insert(graph); + } + else { + return false; + } + } + + return true; + }; + + auto createEventAction = actionController.addSectionZoneAction( + {QObject::tr("Catalogues")}, QObject::tr("New Event..."), [this](auto zones) { + CreateEventDialog dialog; + dialog.hideCatalogueChoice(); + if (dialog.exec() == QDialog::Accepted) { + impl->createEventFromZones(dialog.eventName(), zones); + } + }); + createEventAction->setEnableFunction(createEventEnableFuntion); + + auto createEventInCatalogueAction = actionController.addSectionZoneAction( + {QObject::tr("Catalogues")}, QObject::tr("New Event in Catalogue..."), [this](auto zones) { + CreateEventDialog dialog; + if (dialog.exec() == QDialog::Accepted) { + auto selectedCatalogue = dialog.selectedCatalogue(); + if (!selectedCatalogue) { + selectedCatalogue = std::make_shared(); + selectedCatalogue->setName(dialog.catalogueName()); + } + + impl->createEventFromZones(dialog.eventName(), zones, selectedCatalogue); + } + }); + createEventInCatalogueAction->setEnableFunction(createEventEnableFuntion); +} diff --git a/gui/src/Catalogue/CatalogueEventsModel.cpp b/gui/src/Catalogue/CatalogueEventsModel.cpp index ad78d41..de66396 100644 --- a/gui/src/Catalogue/CatalogueEventsModel.cpp +++ b/gui/src/Catalogue/CatalogueEventsModel.cpp @@ -15,38 +15,46 @@ #include #include +Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel") + const auto EVENT_ITEM_TYPE = 1; const auto EVENT_PRODUCT_ITEM_TYPE = 2; struct CatalogueEventsModel::CatalogueEventsModelPrivate { QVector > m_Events; std::unordered_map > > m_EventProducts; + std::unordered_set > m_EventsWithChanges; - enum class Column { Name, TStart, TEnd, Tags, Product, NbColumn }; QStringList columnNames() { - return QStringList{tr("Event"), tr("TStart"), tr("TEnd"), tr("Tags"), tr("Product")}; + return QStringList{tr("Event"), tr("TStart"), tr("TEnd"), + tr("Tags"), tr("Product"), tr("")}; + } + + QVariant sortData(int col, const std::shared_ptr &event) const + { + if (col == (int)CatalogueEventsModel::Column::Validation) { + return m_EventsWithChanges.find(event) != m_EventsWithChanges.cend() ? true + : QVariant(); + } + + return eventData(col, event); } QVariant eventData(int col, const std::shared_ptr &event) const { switch (static_cast(col)) { - case Column::Name: + case CatalogueEventsModel::Column::Name: return event->getName(); - case Column::TStart: - return DateUtils::dateTime(event->getTStart()); - case Column::TEnd: - return DateUtils::dateTime(event->getTEnd()); - case Column::Product: { - auto eventProductsIt = m_EventProducts.find(event.get()); - if (eventProductsIt != m_EventProducts.cend()) { - return QString::number(m_EventProducts.at(event.get()).count()) + " product(s)"; - } - else { - return "0 product"; - } - } - case Column::Tags: { + case CatalogueEventsModel::Column::TStart: + return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart()) + : QVariant{}; + case CatalogueEventsModel::Column::TEnd: + return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd()) + : QVariant{}; + case CatalogueEventsModel::Column::Product: + return QString::number(nbEventProducts(event)) + " product(s)"; + case CatalogueEventsModel::Column::Tags: { QString tagList; auto tags = event->getTags(); for (auto tag : tags) { @@ -56,6 +64,8 @@ struct CatalogueEventsModel::CatalogueEventsModelPrivate { return tagList; } + case CatalogueEventsModel::Column::Validation: + return QVariant(); default: break; } @@ -71,20 +81,32 @@ struct CatalogueEventsModel::CatalogueEventsModelPrivate { } } + int nbEventProducts(const std::shared_ptr &event) const + { + auto eventProductsIt = m_EventProducts.find(event.get()); + if (eventProductsIt != m_EventProducts.cend()) { + return m_EventProducts.at(event.get()).count(); + } + else { + return 0; + } + } + QVariant eventProductData(int col, const std::shared_ptr &eventProduct) const { switch (static_cast(col)) { - case Column::Name: + case CatalogueEventsModel::Column::Name: return eventProduct->getProductId(); - case Column::TStart: + case CatalogueEventsModel::Column::TStart: return DateUtils::dateTime(eventProduct->getTStart()); - case Column::TEnd: + case CatalogueEventsModel::Column::TEnd: return DateUtils::dateTime(eventProduct->getTEnd()); - case Column::Product: + case CatalogueEventsModel::Column::Product: return eventProduct->getProductId(); - case Column::Tags: { + case CatalogueEventsModel::Column::Tags: return QString(); - } + case CatalogueEventsModel::Column::Validation: + return QVariant(); default: break; } @@ -105,6 +127,7 @@ void CatalogueEventsModel::setEvents(const QVector > &e impl->m_Events = events; impl->m_EventProducts.clear(); + impl->m_EventsWithChanges.clear(); for (auto event : events) { impl->parseEventProduct(event); } @@ -159,21 +182,58 @@ void CatalogueEventsModel::removeEvent(const std::shared_ptr &event) beginRemoveRows(QModelIndex(), index, index); impl->m_Events.removeAt(index); impl->m_EventProducts.erase(event.get()); + impl->m_EventsWithChanges.erase(event); endRemoveRows(); } } +QVector > CatalogueEventsModel::events() const +{ + return impl->m_Events; +} + void CatalogueEventsModel::refreshEvent(const std::shared_ptr &event) { - auto i = impl->m_Events.indexOf(event); - if (i >= 0) { - auto eventIndex = index(i, 0); + auto eventIndex = indexOf(event); + if (eventIndex.isValid()) { + + // Refreshes the event line auto colCount = columnCount(); - emit dataChanged(eventIndex, index(i, colCount)); + emit dataChanged(eventIndex, index(eventIndex.row(), colCount)); + // Also refreshes its children event products auto childCount = rowCount(eventIndex); emit dataChanged(index(0, 0, eventIndex), index(childCount, colCount, eventIndex)); } + else { + qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found."; + } +} + +QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr &event) const +{ + auto row = impl->m_Events.indexOf(event); + if (row >= 0) { + return index(row, 0); + } + + return QModelIndex(); +} + +void CatalogueEventsModel::setEventHasChanges(const std::shared_ptr &event, + bool hasChanges) +{ + if (hasChanges) { + impl->m_EventsWithChanges.insert(event); + } + else { + impl->m_EventsWithChanges.erase(event); + } +} + +bool CatalogueEventsModel::eventsHasChanges(const std::shared_ptr &event) const +{ + return impl->m_EventsWithChanges.find(event) != impl->m_EventsWithChanges.cend(); } QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const @@ -249,7 +309,7 @@ int CatalogueEventsModel::rowCount(const QModelIndex &parent) const int CatalogueEventsModel::columnCount(const QModelIndex &parent) const { - return static_cast(CatalogueEventsModelPrivate::Column::NbColumn); + return static_cast(CatalogueEventsModel::Column::NbColumn); } Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const @@ -296,8 +356,8 @@ void CatalogueEventsModel::sort(int column, Qt::SortOrder order) { std::sort(impl->m_Events.begin(), impl->m_Events.end(), [this, column, order](auto e1, auto e2) { - auto data1 = impl->eventData(column, e1); - auto data2 = impl->eventData(column, e2); + auto data1 = impl->sortData(column, e1); + auto data2 = impl->sortData(column, e2); auto result = data1.toString() < data2.toString(); @@ -305,6 +365,7 @@ void CatalogueEventsModel::sort(int column, Qt::SortOrder order) }); emit dataChanged(QModelIndex(), QModelIndex()); + emit modelSorted(); } Qt::DropActions CatalogueEventsModel::supportedDragActions() const diff --git a/gui/src/Catalogue/CatalogueEventsWidget.cpp b/gui/src/Catalogue/CatalogueEventsWidget.cpp index 410d933..de503c2 100644 --- a/gui/src/Catalogue/CatalogueEventsWidget.cpp +++ b/gui/src/Catalogue/CatalogueEventsWidget.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -16,8 +17,8 @@ Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget") -/// Format of the dates appearing in the label of a cursor -const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss"); +/// Fixed size of the validation column +const auto VALIDATION_COLUMN_SIZE = 35; struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate { @@ -277,8 +278,20 @@ CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent) }); ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); - ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch); + ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name, + QHeaderView::Stretch); + ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation, + QHeaderView::Fixed); + ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation, + VALIDATION_COLUMN_SIZE); ui->treeView->header()->setSortIndicatorShown(true); + + connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() { + auto allEvents = impl->m_Model->events(); + for (auto event : allEvents) { + setEventChanges(event, impl->m_Model->eventsHasChanges(event)); + } + }); } CatalogueEventsWidget::~CatalogueEventsWidget() @@ -294,6 +307,25 @@ void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualiz void CatalogueEventsWidget::setEventChanges(const std::shared_ptr &event, bool hasChanges) { impl->m_Model->refreshEvent(event); + + auto eventIndex = impl->m_Model->indexOf(event); + auto validationIndex + = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation); + + if (hasChanges) { + if (ui->treeView->indexWidget(validationIndex) == nullptr) { + auto widget = CatalogueExplorerHelper::buildValidationWidget( + ui->treeView, [this, event]() { setEventChanges(event, false); }, + [this, event]() { setEventChanges(event, false); }); + ui->treeView->setIndexWidget(validationIndex, widget); + } + } + else { + // Note: the widget is destroyed + ui->treeView->setIndexWidget(validationIndex, nullptr); + } + + impl->m_Model->setEventHasChanges(event, hasChanges); } void CatalogueEventsWidget::populateWithCatalogues( @@ -314,3 +346,15 @@ void CatalogueEventsWidget::populateWithCatalogues( impl->setEvents(events, ui->treeView); } + +void CatalogueEventsWidget::populateWithAllEvents() +{ + auto allEvents = sqpApp->catalogueController().retrieveAllEvents(); + + QVector > events; + for (auto event : allEvents) { + events << event; + } + + impl->setEvents(events, ui->treeView); +} diff --git a/gui/src/Catalogue/CatalogueExplorer.cpp b/gui/src/Catalogue/CatalogueExplorer.cpp index b0d99d7..e409089 100644 --- a/gui/src/Catalogue/CatalogueExplorer.cpp +++ b/gui/src/Catalogue/CatalogueExplorer.cpp @@ -1,12 +1,16 @@ #include "Catalogue/CatalogueExplorer.h" #include "ui_CatalogueExplorer.h" +#include +#include +#include #include #include #include struct CatalogueExplorer::CatalogueExplorerPrivate { + CatalogueActionManager m_ActionManager; }; CatalogueExplorer::CatalogueExplorer(QWidget *parent) @@ -16,6 +20,8 @@ CatalogueExplorer::CatalogueExplorer(QWidget *parent) { ui->setupUi(this); + impl->m_ActionManager.installSelectionZoneActions(); + connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto catalogues) { if (catalogues.count() == 1) { ui->inspector->setCatalogue(catalogues.first()); @@ -34,8 +40,10 @@ CatalogueExplorer::CatalogueExplorer(QWidget *parent) connect(ui->catalogues, &CatalogueSideBarWidget::trashSelected, [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); }); - connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected, - [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); }); + connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected, [this]() { + ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); + ui->events->populateWithAllEvents(); + }); connect(ui->catalogues, &CatalogueSideBarWidget::selectionCleared, [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); }); @@ -62,11 +70,15 @@ CatalogueExplorer::CatalogueExplorer(QWidget *parent) connect(ui->events, &CatalogueEventsWidget::selectionCleared, [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); }); - connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated, - [this](auto catalogue) { ui->catalogues->setCatalogueChanges(catalogue, true); }); + connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated, [this](auto catalogue) { + sqpApp->catalogueController().updateCatalogue(catalogue); + ui->catalogues->setCatalogueChanges(catalogue, true); + }); - connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated, - [this](auto event) { ui->events->setEventChanges(event, true); }); + connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated, [this](auto event) { + sqpApp->catalogueController().updateEvent(event); + ui->events->setEventChanges(event, true); + }); connect(ui->inspector, &CatalogueInspectorWidget::eventProductUpdated, [this](auto event, auto eventProduct) { ui->events->setEventChanges(event, true); }); diff --git a/gui/src/Catalogue/CatalogueExplorerHelper.cpp b/gui/src/Catalogue/CatalogueExplorerHelper.cpp new file mode 100644 index 0000000..1fb7767 --- /dev/null +++ b/gui/src/Catalogue/CatalogueExplorerHelper.cpp @@ -0,0 +1,32 @@ +#include "Catalogue/CatalogueExplorerHelper.h" + +#include +#include + +const auto VALIDATION_BUTTON_ICON_SIZE = 12; + +QWidget *CatalogueExplorerHelper::buildValidationWidget(QWidget *parent, std::function save, + std::function discard) +{ + auto widget = new QWidget{parent}; + + auto layout = new QHBoxLayout{widget}; + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + + auto btnValid = new QToolButton{widget}; + btnValid->setIcon(QIcon{":/icones/save"}); + btnValid->setIconSize(QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE}); + btnValid->setAutoRaise(true); + QObject::connect(btnValid, &QToolButton::clicked, save); + layout->addWidget(btnValid); + + auto btnDiscard = new QToolButton{widget}; + btnDiscard->setIcon(QIcon{":/icones/discard"}); + btnDiscard->setIconSize(QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE}); + btnDiscard->setAutoRaise(true); + QObject::connect(btnDiscard, &QToolButton::clicked, discard); + layout->addWidget(btnDiscard); + + return widget; +} diff --git a/gui/src/Catalogue/CatalogueSideBarWidget.cpp b/gui/src/Catalogue/CatalogueSideBarWidget.cpp index 0d64db1..e9f5d4e 100644 --- a/gui/src/Catalogue/CatalogueSideBarWidget.cpp +++ b/gui/src/Catalogue/CatalogueSideBarWidget.cpp @@ -176,11 +176,14 @@ void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget( treeWidget->addTopLevelItem(separatorItem); treeWidget->setItemWidget(separatorItem, 0, separator); - auto db = addDatabaseItem("Default", treeWidget); + auto repositories = sqpApp->catalogueController().getRepositories(); + for (auto dbname : repositories) { + auto db = addDatabaseItem(dbname, treeWidget); - auto catalogues = sqpApp->catalogueController().retrieveCatalogues("Default"); - for (auto catalogue : catalogues) { - addCatalogueItem(catalogue, db); + auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname); + for (auto catalogue : catalogues) { + addCatalogueItem(catalogue, db); + } } treeWidget->expandAll(); diff --git a/gui/src/Catalogue/CatalogueTreeWidgetItem.cpp b/gui/src/Catalogue/CatalogueTreeWidgetItem.cpp index afa3cef..92de0ff 100644 --- a/gui/src/Catalogue/CatalogueTreeWidgetItem.cpp +++ b/gui/src/Catalogue/CatalogueTreeWidgetItem.cpp @@ -1,12 +1,12 @@ #include "Catalogue/CatalogueTreeWidgetItem.h" +#include + +#include +#include #include #include -#include -#include - -const auto VALIDATION_BUTTON_ICON_SIZE = 12; /// Column in the tree widget where the apply and cancel buttons must appear const auto APPLY_CANCEL_BUTTONS_COLUMN = 1; @@ -50,6 +50,7 @@ void CatalogueTreeWidgetItem::setData(int column, int role, const QVariant &valu if (newName != impl->m_Catalogue->getName()) { setText(0, newName); impl->m_Catalogue->setName(newName); + sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue); setHasChanges(true); } } @@ -66,29 +67,11 @@ std::shared_ptr CatalogueTreeWidgetItem::catalogue() const void CatalogueTreeWidgetItem::setHasChanges(bool value) { if (value) { - if (treeWidget()->itemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN) == nullptr) { - auto widet = new QWidget{treeWidget()}; - - auto layout = new QHBoxLayout{widet}; - layout->setContentsMargins(0, 0, 0, 0); - layout->setSpacing(0); - - auto btnValid = new QToolButton{widet}; - btnValid->setIcon(QIcon{":/icones/save"}); - btnValid->setIconSize(QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE}); - btnValid->setAutoRaise(true); - QObject::connect(btnValid, &QToolButton::clicked, [this]() { setHasChanges(false); }); - layout->addWidget(btnValid); - - auto btnDiscard = new QToolButton{widet}; - btnDiscard->setIcon(QIcon{":/icones/discard"}); - btnDiscard->setIconSize( - QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE}); - btnDiscard->setAutoRaise(true); - QObject::connect(btnDiscard, &QToolButton::clicked, [this]() { setHasChanges(false); }); - layout->addWidget(btnDiscard); - - treeWidget()->setItemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN, {widet}); + if (!hasChanges()) { + auto widget = CatalogueExplorerHelper::buildValidationWidget( + treeWidget(), [this]() { setHasChanges(false); }, + [this]() { setHasChanges(false); }); + treeWidget()->setItemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN, widget); } } else { @@ -97,6 +80,11 @@ void CatalogueTreeWidgetItem::setHasChanges(bool value) } } +bool CatalogueTreeWidgetItem::hasChanges() +{ + return treeWidget()->itemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN) != nullptr; +} + void CatalogueTreeWidgetItem::refresh() { emitDataChanged(); diff --git a/gui/src/Catalogue/CreateEventDialog.cpp b/gui/src/Catalogue/CreateEventDialog.cpp new file mode 100644 index 0000000..c3e90c9 --- /dev/null +++ b/gui/src/Catalogue/CreateEventDialog.cpp @@ -0,0 +1,59 @@ +#include "Catalogue/CreateEventDialog.h" +#include "ui_CreateEventDialog.h" + +#include +#include + +#include + +struct CreateEventDialog::CreateEventDialogPrivate { + QVector > m_DisplayedCatalogues; +}; + +CreateEventDialog::CreateEventDialog(QWidget *parent) + : QDialog(parent), + ui(new Ui::CreateEventDialog), + impl{spimpl::make_unique_impl()} +{ + ui->setupUi(this); + + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + auto catalogues = sqpApp->catalogueController().retrieveCatalogues(); + for (auto cat : catalogues) { + ui->cbCatalogue->addItem(cat->getName()); + impl->m_DisplayedCatalogues << cat; + } +} + +CreateEventDialog::~CreateEventDialog() +{ + delete ui; +} + +void CreateEventDialog::hideCatalogueChoice() +{ + ui->cbCatalogue->hide(); + ui->lblCatalogue->hide(); +} + +QString CreateEventDialog::eventName() const +{ + return ui->leEvent->text(); +} + +std::shared_ptr CreateEventDialog::selectedCatalogue() const +{ + auto catalogue = impl->m_DisplayedCatalogues.value(ui->cbCatalogue->currentIndex()); + if (!catalogue || catalogue->getName() != catalogueName()) { + return nullptr; + } + + return catalogue; +} + +QString CreateEventDialog::catalogueName() const +{ + return ui->cbCatalogue->currentText(); +} diff --git a/gui/ui/Catalogue/CreateEventDialog.ui b/gui/ui/Catalogue/CreateEventDialog.ui new file mode 100644 index 0000000..b5352fe --- /dev/null +++ b/gui/ui/Catalogue/CreateEventDialog.ui @@ -0,0 +1,55 @@ + + + CreateEventDialog + + + + 0 + 0 + 324 + 93 + + + + New Event + + + + + + Event Name + + + + + + + + + + Catalogue + + + + + + + true + + + QComboBox::NoInsert + + + + + + + QDialogButtonBox::Ok + + + + + + + +