##// END OF EJS Templates
Fixes the refresh of data that was not working all the time
Fixes the refresh of data that was not working all the time

File last commit:

r1298:85d482a16060
r1324:c436df4b66de
Show More
CatalogueSideBarWidget.cpp
337 lines | 12.5 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>
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, QTreeView *treeView);
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);
auto emitSelection = [this]() {
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;
}
};
connect(ui->treeView, &QTreeView::clicked, emitSelection);
connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, emitSelection);
connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [emitSelection, this](auto index) {
auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
if (selectedIndexes.contains(index)) {
emitSelection();
}
auto item = impl->m_TreeModel->item(index);
impl->setHasChanges(true, index, ui->treeView);
});
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, ui->treeView);
// 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::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,
QTreeView *treeView)
{
auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
if (value) {
if (!hasChanges(validationIndex, treeView)) {
auto widget = CatalogueExplorerHelper::buildValidationWidget(
treeView, [this, validationIndex,
treeView]() { setHasChanges(false, validationIndex, treeView); },
[this, validationIndex, treeView]() {
setHasChanges(false, validationIndex, treeView);
});
treeView->setIndexWidget(validationIndex, widget);
}
}
else {
// Note: the widget is destroyed
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;
}