##// END OF EJS Templates
Add catalogue handling
Add catalogue handling

File last commit:

r1276:4af886ed9de4
r1276:4af886ed9de4
Show More
CatalogueSideBarWidget.cpp
422 lines | 16.3 KiB | text/x-c | CppLexer
/ gui / src / Catalogue / CatalogueSideBarWidget.cpp
#include "Catalogue/CatalogueSideBarWidget.h"
#include "ui_CatalogueSideBarWidget.h"
#include <SqpApplication.h>
#include <Catalogue/CatalogueController.h>
#include <Catalogue/CatalogueExplorerHelper.h>
#include <Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.h>
#include <Catalogue/CatalogueTreeItems/CatalogueTreeItem.h>
#include <Catalogue/CatalogueTreeModel.h>
#include <CatalogueDao.h>
#include <ComparaisonPredicate.h>
#include <DBCatalogue.h>
#include <QMenu>
#include <QMessageBox>
Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
constexpr auto ALL_EVENT_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 1;
constexpr auto TRASH_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 2;
constexpr auto CATALOGUE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 3;
constexpr auto DATABASE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 4;
struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
CatalogueTreeModel *m_TreeModel = nullptr;
void configureTreeWidget(QTreeView *treeView);
QModelIndex addDatabaseItem(const QString &name);
CatalogueAbstractTreeItem *getDatabaseItem(const QString &name);
void addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
const QModelIndex &databaseIndex);
CatalogueTreeItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue) const;
void setHasChanges(bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget);
bool hasChanges(const QModelIndex &index, QTreeView *treeView);
int selectionType(QTreeView *treeView) const
{
auto selectedItems = treeView->selectionModel()->selectedRows();
if (selectedItems.isEmpty()) {
return CatalogueAbstractTreeItem::DEFAULT_TYPE;
}
else {
auto firstIndex = selectedItems.first();
auto firstItem = m_TreeModel->item(firstIndex);
if (!firstItem) {
Q_ASSERT(false);
return CatalogueAbstractTreeItem::DEFAULT_TYPE;
}
auto selectionType = firstItem->type();
for (auto itemIndex : selectedItems) {
auto item = m_TreeModel->item(itemIndex);
if (!item || item->type() != selectionType) {
// Incoherent multi selection
selectionType = CatalogueAbstractTreeItem::DEFAULT_TYPE;
break;
}
}
return selectionType;
}
}
QVector<std::shared_ptr<DBCatalogue> > selectedCatalogues(QTreeView *treeView) const
{
QVector<std::shared_ptr<DBCatalogue> > catalogues;
auto selectedItems = treeView->selectionModel()->selectedRows();
for (auto itemIndex : selectedItems) {
auto item = m_TreeModel->item(itemIndex);
if (item && item->type() == CATALOGUE_ITEM_TYPE) {
catalogues.append(static_cast<CatalogueTreeItem *>(item)->catalogue());
}
}
return catalogues;
}
QStringList selectedRepositories(QTreeView *treeView) const
{
QStringList repositories;
auto selectedItems = treeView->selectionModel()->selectedRows();
for (auto itemIndex : selectedItems) {
auto item = m_TreeModel->item(itemIndex);
if (item && item->type() == DATABASE_ITEM_TYPE) {
repositories.append(item->text());
}
}
return repositories;
}
};
CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
: QWidget(parent),
ui(new Ui::CatalogueSideBarWidget),
impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
{
ui->setupUi(this);
impl->m_TreeModel = new CatalogueTreeModel(this);
ui->treeView->setModel(impl->m_TreeModel);
impl->configureTreeWidget(ui->treeView);
ui->treeView->header()->setStretchLastSection(false);
ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
connect(ui->treeView, &QTreeView::clicked, this, &CatalogueSideBarWidget::emitSelection);
connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, this,
&CatalogueSideBarWidget::emitSelection);
// connect(ui->btnAdd, &QToolButton::clicked, [this]() {
// QVector<std::shared_ptr<DBCatalogue> > catalogues;
// impl->getSelectedItems(ui->treeView, events, eventProducts);
// if (!events.isEmpty() && eventProducts.isEmpty()) {
// if (QMessageBox::warning(this, tr("Remove Event(s)"),
// tr("The selected event(s) will be completly removed "
// "from the repository!\nAre you sure you want to
// continue?"),
// QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
// == QMessageBox::Yes) {
// for (auto event : events) {
// sqpApp->catalogueController().removeEvent(event);
// impl->removeEvent(event, ui->treeView);
// }
// }
// }
// });
connect(impl->m_TreeModel, &CatalogueTreeModel::itemDropped, [this](auto index) {
auto item = impl->m_TreeModel->item(index);
if (item && item->type() == CATALOGUE_ITEM_TYPE) {
auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
this->setCatalogueChanges(catalogue, true);
}
});
connect(ui->btnRemove, &QToolButton::clicked, [this]() {
QVector<QPair<std::shared_ptr<DBCatalogue>, CatalogueAbstractTreeItem *> >
cataloguesToItems;
auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
for (auto index : selectedIndexes) {
auto item = impl->m_TreeModel->item(index);
if (item && item->type() == CATALOGUE_ITEM_TYPE) {
auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
cataloguesToItems << qMakePair(catalogue, item);
}
}
if (!cataloguesToItems.isEmpty()) {
if (QMessageBox::warning(this, tr("Remove Catalogue(s)"),
tr("The selected catalogues(s) will be completly removed "
"from the repository!\nAre you sure you want to continue?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
== QMessageBox::Yes) {
for (auto catalogueToItem : cataloguesToItems) {
sqpApp->catalogueController().removeCatalogue(catalogueToItem.first);
impl->m_TreeModel->removeChildItem(
catalogueToItem.second,
impl->m_TreeModel->indexOf(catalogueToItem.second->parent()));
}
}
}
});
connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [this](auto index) {
auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
if (selectedIndexes.contains(index)) {
this->emitSelection();
}
impl->setHasChanges(true, index, this);
});
ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->treeView, &QTreeView::customContextMenuRequested, this,
&CatalogueSideBarWidget::onContextMenuRequested);
}
CatalogueSideBarWidget::~CatalogueSideBarWidget()
{
delete ui;
}
void CatalogueSideBarWidget::addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
const QString &repository)
{
auto repositoryItem = impl->getDatabaseItem(repository);
impl->addCatalogueItem(catalogue, impl->m_TreeModel->indexOf(repositoryItem));
}
void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
bool hasChanges)
{
if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
auto index = impl->m_TreeModel->indexOf(catalogueItem);
impl->setHasChanges(hasChanges, index, this);
// catalogueItem->refresh();
}
}
QVector<std::shared_ptr<DBCatalogue> >
CatalogueSideBarWidget::getCatalogues(const QString &repository) const
{
QVector<std::shared_ptr<DBCatalogue> > result;
auto repositoryItem = impl->getDatabaseItem(repository);
for (auto child : repositoryItem->children()) {
if (child->type() == CATALOGUE_ITEM_TYPE) {
auto catalogueItem = static_cast<CatalogueTreeItem *>(child);
result << catalogueItem->catalogue();
}
else {
qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogues: invalid structure";
}
}
return result;
}
void CatalogueSideBarWidget::emitSelection()
{
auto selectionType = impl->selectionType(ui->treeView);
switch (selectionType) {
case CATALOGUE_ITEM_TYPE:
emit this->catalogueSelected(impl->selectedCatalogues(ui->treeView));
break;
case DATABASE_ITEM_TYPE:
emit this->databaseSelected(impl->selectedRepositories(ui->treeView));
break;
case ALL_EVENT_ITEM_TYPE:
emit this->allEventsSelected();
break;
case TRASH_ITEM_TYPE:
emit this->trashSelected();
break;
default:
emit this->selectionCleared();
break;
}
}
void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
{
QMenu menu{this};
auto currentIndex = ui->treeView->currentIndex();
auto currentItem = impl->m_TreeModel->item(currentIndex);
if (!currentItem) {
return;
}
switch (currentItem->type()) {
case CATALOGUE_ITEM_TYPE:
menu.addAction("Rename", [this, currentIndex]() { ui->treeView->edit(currentIndex); });
break;
case DATABASE_ITEM_TYPE:
break;
case ALL_EVENT_ITEM_TYPE:
break;
case TRASH_ITEM_TYPE:
menu.addAction("Empty Trash", []() {
// TODO
});
break;
default:
break;
}
if (!menu.isEmpty()) {
menu.exec(ui->treeView->mapToGlobal(pos));
}
}
void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(QTreeView *treeView)
{
auto allEventsItem = new CatalogueTextTreeItem{QIcon{":/icones/allEvents.png"}, "All Events",
ALL_EVENT_ITEM_TYPE};
auto allEventIndex = m_TreeModel->addTopLevelItem(allEventsItem);
treeView->setCurrentIndex(allEventIndex);
auto trashItem
= new CatalogueTextTreeItem{QIcon{":/icones/trash.png"}, "Trash", TRASH_ITEM_TYPE};
m_TreeModel->addTopLevelItem(trashItem);
auto separator = new QFrame{treeView};
separator->setFrameShape(QFrame::HLine);
auto separatorItem
= new CatalogueTextTreeItem{QIcon{}, QString{}, CatalogueAbstractTreeItem::DEFAULT_TYPE};
separatorItem->setEnabled(false);
auto separatorIndex = m_TreeModel->addTopLevelItem(separatorItem);
treeView->setIndexWidget(separatorIndex, separator);
auto repositories = sqpApp->catalogueController().getRepositories();
for (auto dbname : repositories) {
auto dbIndex = addDatabaseItem(dbname);
auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname);
for (auto catalogue : catalogues) {
addCatalogueItem(catalogue, dbIndex);
}
}
treeView->expandAll();
}
QModelIndex
CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name)
{
auto databaseItem
= new CatalogueTextTreeItem{QIcon{":/icones/database.png"}, {name}, DATABASE_ITEM_TYPE};
auto databaseIndex = m_TreeModel->addTopLevelItem(databaseItem);
return databaseIndex;
}
CatalogueAbstractTreeItem *
CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name)
{
for (auto item : m_TreeModel->topLevelItems()) {
if (item->type() == DATABASE_ITEM_TYPE && item->text() == name) {
return item;
}
}
return nullptr;
}
void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
const std::shared_ptr<DBCatalogue> &catalogue, const QModelIndex &databaseIndex)
{
auto catalogueItem
= new CatalogueTreeItem{catalogue, QIcon{":/icones/catalogue.png"}, CATALOGUE_ITEM_TYPE};
m_TreeModel->addChildItem(catalogueItem, databaseIndex);
}
CatalogueTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
const std::shared_ptr<DBCatalogue> &catalogue) const
{
for (auto item : m_TreeModel->topLevelItems()) {
if (item->type() == DATABASE_ITEM_TYPE) {
for (auto childItem : item->children()) {
if (childItem->type() == CATALOGUE_ITEM_TYPE) {
auto catalogueItem = static_cast<CatalogueTreeItem *>(childItem);
if (catalogueItem->catalogue() == catalogue) {
return catalogueItem;
}
}
else {
qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
"structure. A database item should "
"only contain catalogues.";
Q_ASSERT(false);
}
}
}
}
return nullptr;
}
void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(
bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget)
{
std::shared_ptr<DBCatalogue> catalogue = nullptr;
auto item = m_TreeModel->item(index);
if (item && item->type() == CATALOGUE_ITEM_TYPE) {
catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
}
auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
if (value) {
if (!hasChanges(validationIndex, sideBarWidget->ui->treeView)) {
auto widget = CatalogueExplorerHelper::buildValidationWidget(
sideBarWidget->ui->treeView,
[this, validationIndex, sideBarWidget, catalogue]() {
if (catalogue) {
sqpApp->catalogueController().saveCatalogue(catalogue);
}
setHasChanges(false, validationIndex, sideBarWidget);
},
[this, validationIndex, sideBarWidget, catalogue, item]() {
if (catalogue) {
bool removed;
sqpApp->catalogueController().discardCatalogue(catalogue, removed);
if (removed) {
m_TreeModel->removeChildItem(item,
m_TreeModel->indexOf(item->parent()));
}
else {
m_TreeModel->refresh(m_TreeModel->indexOf(item));
setHasChanges(false, validationIndex, sideBarWidget);
}
sideBarWidget->emitSelection();
}
});
sideBarWidget->ui->treeView->setIndexWidget(validationIndex, widget);
}
}
else {
// Note: the widget is destroyed
sideBarWidget->ui->treeView->setIndexWidget(validationIndex, nullptr);
}
}
bool CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::hasChanges(const QModelIndex &index,
QTreeView *treeView)
{
auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
return treeView->indexWidget(validationIndex) != nullptr;
}