Restructuring catalog tabs

- Moved detail tabs of table to their own components
- Table list has become seperate component on seperate tab
- Table list does not use designer anymore
- Moved sequences and functions tabs into the catalog inspector
This commit is contained in:
eelke 2019-02-09 09:49:27 +01:00
parent a704332342
commit 42432b06a9
31 changed files with 598 additions and 472 deletions

View file

@ -1,154 +1,64 @@
#include "CatalogInspector.h"
#include "ui_TablesPage.h"
#include "catalog/PgAttribute.h"
#include "catalog/PgDatabaseCatalog.h"
#include "catalog/PgIndexContainer.h"
#include "catalog/PgTriggerContainer.h"
#include "ColumnPage.h"
#include "ColumnTableModel.h"
#include "ConstraintModel.h"
#include "IconColumnDelegate.h"
#include "IndexModel.h"
#include "OpenDatabase.h"
#include "PgLabItemDelegate.h"
#include "PropertiesPage.h"
#include "ResultTableModelUtil.h"
#include "SqlFormattingUtils.h"
#include "SqlSyntaxHighlighter.h"
#include "TriggerPage.h"
#include "UserConfiguration.h"
#include "SqlCodePreview.h"
#include <QStringBuilder>
#include <unordered_set>
#include "plugin_support/IPluginContentWidgetContext.h"
#include "widgets/CatalogFunctionsPage.h"
#include "widgets/CatalogSequencesPage.h"
#include "widgets/CatalogTablesPage.h"
#include <QApplication>
#include <QTabWidget>
#include <QStringBuilder>
#include <QVBoxLayout>
#include <unordered_set>
CatalogInspector::CatalogInspector(IPluginContentWidgetContext *context_, QWidget *parent)
: PluginContentWidget(context_, parent)
, ui(new Ui::TablesPage)
{
ui->setupUi(this);
m_tabWidget = new QTabWidget(this);
m_tablesPage = new CatalogTablesPage(this);
m_functionsPage = new CatalogFunctionsPage(this);
m_sequencesPage = new CatalogSequencesPage(this);
SetTableViewDefault(ui->tableListTable);
m_tablesModel = new TablesTableModel(this);
ui->tableListTable->setModel(m_tablesModel);
ui->tableListTable->setItemDelegate(new PgLabItemDelegate(this));
ui->tableListTable->setSortingEnabled(true);
ui->tableListTable->sortByColumn(0, Qt::AscendingOrder);
ui->tableListTable->setSelectionBehavior(QAbstractItemView::SelectRows);
auto layout = new QVBoxLayout(this);
setLayout(layout);
layout->addWidget(m_tabWidget);
m_tabWidget->addTab(m_tablesPage, "");
m_tabWidget->addTab(m_functionsPage, "");
m_tabWidget->addTab(m_sequencesPage, "");
// Constraints
SetTableViewDefault(ui->constraintsTable);
m_constraintModel = new ConstraintModel(this);
ui->constraintsTable->setModel(m_constraintModel);
ui->constraintsTable->setItemDelegateForColumn(0, new IconColumnDelegate(this));
// Indexes
SetTableViewDefault(ui->indexesTable);
m_indexModel = new IndexModel(this);
ui->indexesTable->setModel(m_indexModel);
ui->indexesTable->setItemDelegate(new PgLabItemDelegate(this));
ui->indexesTable->setItemDelegateForColumn(0, new IconColumnDelegate(this));
// Set code editor fonts
QFont code_font = UserConfiguration::instance()->codeFont();
ui->constraintSqlEdit->setFont(code_font);
ui->indexSqlEdit->setFont(code_font);
// Connect signals
// ---------------
// Table selection
connect(ui->tableListTable->selectionModel(), &QItemSelectionModel::currentRowChanged, this,
&CatalogInspector::tableListTable_currentRowChanged);
connect(m_tablesModel, &QAbstractItemModel::layoutChanged,
this, &CatalogInspector::tableListTable_layoutChanged);
//layoutChanged(const QList<QPersistentModelIndex> &parents = ..., QAbstractItemModel::LayoutChangeHint hint = ...)
connect(ui->constraintsTable->selectionModel(), &QItemSelectionModel::selectionChanged, this,
&CatalogInspector::constraintsTable_selectionChanged);
connect(ui->constraintsTable->model(), &QAbstractItemModel::modelReset, this,
&CatalogInspector::constraintsTable_modelReset);
// React to changes in de selected indexes, does not trigger when model is reset
connect(ui->indexesTable->selectionModel(), &QItemSelectionModel::selectionChanged, this,
&CatalogInspector::indexesTable_selectionChanged);
// Capture model reset independently
connect(ui->indexesTable->model(), &QAbstractItemModel::modelReset, this,
&CatalogInspector::indexesTable_modelReset);
// Non designer based code
// - Columns page
m_columnsPage = new ColumnPage(this);
ui->twDetails->insertTab(0, m_columnsPage, "");
// - Properties page
m_propertiesPage = new PropertiesPage(this);
m_propertiesPage->setSourceModel(m_tablesModel);
ui->twDetails->addTab(m_propertiesPage, "");
connect(ui->tableListTable->selectionModel(), &QItemSelectionModel::currentRowChanged,
m_propertiesPage, &PropertiesPage::setActiveRow);
// - Trigger page
m_triggerPage = new TriggerPage(this);
ui->twDetails->addTab(m_triggerPage, "");
// SQL tab
m_sqlCodePreview = new SqlCodePreview(this);
ui->twDetails->addTab(m_sqlCodePreview, "");
// Force focus on columns tab by default
ui->twDetails->setCurrentIndex(0);
auto db = context_->getObject<OpenDatabase>();
setCatalog(db->catalog());
retranslateUi(false);
}
void CatalogInspector::retranslateUi(bool all)
{
if (all)
ui->retranslateUi(this);
auto set_tabtext = [this] (QWidget *widget, QString translation) {
ui->twDetails->setTabText(ui->twDetails->indexOf(widget), translation);
};
set_tabtext(m_columnsPage, QApplication::translate("TablesPage", "Columns", nullptr));
set_tabtext(m_propertiesPage, QApplication::translate("TablesPage", "Properties", nullptr));
set_tabtext(m_triggerPage, QApplication::translate("TablesPage", "Triggers", nullptr));
set_tabtext(m_sqlCodePreview, QApplication::translate("TablesPage", "SQL", nullptr));
m_tablesPage->retranslateUi(all);
m_tabWidget->setTabText(m_tabWidget->indexOf(m_tablesPage),
QApplication::translate("CatalogInspector", "Tables", nullptr));
m_tabWidget->setTabText(m_tabWidget->indexOf(m_functionsPage),
QApplication::translate("CatalogInspector", "Functions", nullptr));
m_tabWidget->setTabText(m_tabWidget->indexOf(m_sequencesPage),
QApplication::translate("CatalogInspector", "Sequences", nullptr));
}
CatalogInspector::~CatalogInspector()
{
delete ui;
}
void CatalogInspector::setCatalog(std::shared_ptr<PgDatabaseCatalog> cat)
{
m_catalog = cat;
m_tablesModel->setCatalog(cat);
ui->tableListTable->resizeColumnsToContents();
m_triggerPage->setCatalog(cat);
auto highlighter = new SqlSyntaxHighlighter(ui->constraintSqlEdit->document());
highlighter->setTypes(*cat->types());
highlighter = new SqlSyntaxHighlighter(ui->indexSqlEdit->document());
highlighter->setTypes(*cat->types());
m_tablesPage->setCatalog(cat);
m_functionsPage->setCatalog(cat);
m_sequencesPage->setCatalog(cat);
}
void CatalogInspector::setNamespaceFilter(TablesTableModel::NamespaceFilter filter)
{
m_tablesModel->setNamespaceFilter(filter);
m_tablesPage->setNamespaceFilter(filter);
QString hint = "Catalog instpector";
QString caption = "Inspector";
switch (filter) {
@ -166,147 +76,6 @@ void CatalogInspector::setNamespaceFilter(TablesTableModel::NamespaceFilter filt
context()->setCaption(this, caption, hint);
}
void CatalogInspector::tableListTable_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
{
if (current.row() != previous.row()) {
if (current.isValid()) {
PgClass table = m_tablesModel->getTable(current.row());
selectedTableChanged(table);
}
else
selectedTableChanged({});
}
}
void CatalogInspector::tableListTable_layoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint )
{
auto&& index = ui->tableListTable->selectionModel()->currentIndex();
if (index.isValid()) {
PgClass table = m_tablesModel->getTable(index.row());
selectedTableChanged(table);
}
else
selectedTableChanged({});
}
void CatalogInspector::selectedTableChanged(const std::optional<PgClass> &table)
{
m_columnsPage->setData(m_catalog, table);
m_constraintModel->setData(m_catalog, table);
ui->constraintsTable->resizeColumnsToContents();
ui->constraintsTable->selectionModel()->reset();
m_indexModel->setData(m_catalog, table);
ui->indexesTable->resizeColumnsToContents();
m_triggerPage->setFilter(table);
updateSqlTab(table);
}
void CatalogInspector::constraintsTable_selectionChanged(const QItemSelection &/*selected*/, const QItemSelection &/*deselected*/)
{
const auto indexes = ui->constraintsTable->selectionModel()->selectedIndexes();
std::unordered_set<int> rijen;
for (const auto &e : indexes)
rijen.insert(e.row());
QString drops;
QString creates;
for (auto rij : rijen) {
const PgConstraint constraint = m_constraintModel->constraint(rij);
drops += getDropConstraintDefinition(*m_catalog, constraint) % "\n";
creates += getAlterTableConstraintDefinition(*m_catalog, constraint) % "\n";
}
ui->constraintSqlEdit->setPlainText(drops % "\n" % creates);
}
void CatalogInspector::constraintsTable_modelReset()
{
ui->constraintSqlEdit->clear();
}
void CatalogInspector::indexesTable_selectionChanged(const QItemSelection &/*selected*/, const QItemSelection &/*deselected*/)
{
const auto indexes = ui->indexesTable->selectionModel()->selectedIndexes();
std::unordered_set<int> rijen;
for (const auto &e : indexes)
rijen.insert(e.row());
QString drops;
QString creates;
for (auto rij : rijen) {
const PgIndex index = m_indexModel->getIndex(rij);
drops += index.dropSql() % "\n";
creates += index.createSql() % "\n";
}
ui->indexSqlEdit->setPlainText(drops % "\n" % creates);
}
void CatalogInspector::indexesTable_modelReset()
{
ui->indexSqlEdit->clear();
}
void CatalogInspector::on_tableListTable_doubleClicked(const QModelIndex &index)
{
PgClass table = m_tablesModel->getTable(index.row());
if (table.oid() != InvalidOid) {
context()->moduleAction("pglab.crudpage", "open", {
{ "oid", table.oid() }
});
}
}
void CatalogInspector::updateSqlTab(const std::optional<PgClass> &table)
{
if (!table.has_value()) {
m_sqlCodePreview->clear();
return;
}
QString drop_sql;
QString create_sql;
// create table
create_sql += table->createSql();
// - columns
// - constraints
// table details (inherits etc)
// Indexes
drop_sql += "-- drop Indexes\n";
create_sql += "-- create Indexes\n";
auto && indexes = m_catalog->indexes()->getIndexesForTable(table->oid());
for (auto && index : indexes) {
drop_sql += index.dropSql() % "\n";
create_sql += index.createSql() % "\n";
}
// Triggers
drop_sql += "-- drop Triggers\n";
create_sql += "-- create Triggers\n";
auto && triggers = m_catalog->triggers()->getTriggersForRelation(table->oid());
for (auto && trg : triggers) {
drop_sql += trg.dropSql() % "\n";
create_sql += trg.createSql() % "\n";
}
// Privileges
create_sql += "-- set Privileges\n";
create_sql += table->grantSql() % "\n";
// Comments
create_sql += "-- set Comments table + columns\n";
//
m_sqlCodePreview->setPlainText(drop_sql % "\n\n" % create_sql);
}
void CatalogInspectorModule::init()
{
registerModuleAction("open",