diff --git a/pglab/ColumnPage.cpp b/pglab/ColumnPage.cpp index 18fef08..9c5e2e3 100644 --- a/pglab/ColumnPage.cpp +++ b/pglab/ColumnPage.cpp @@ -34,6 +34,7 @@ ColumnPage::ColumnPage(QWidget *parent) connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ColumnPage::tableView_selectionChanged); + connect(m_columnModel, &ColumnTableModel::modelReset, m_definitionView, &SqlCodePreview::clear); } void ColumnPage::setData(std::shared_ptr cat, const std::optional &cls) @@ -43,7 +44,6 @@ void ColumnPage::setData(std::shared_ptr cat, const std m_columnModel->setData(cat, cls); m_Class = cls; m_tableView->resizeColumnsToContents(); - m_definitionView->setPlainText(""); } void ColumnPage::tableView_selectionChanged(const QItemSelection &/*selected*/, const QItemSelection &/*deselected*/) diff --git a/pglab/ColumnTableModel.cpp b/pglab/ColumnTableModel.cpp index 617197c..7a9cef5 100644 --- a/pglab/ColumnTableModel.cpp +++ b/pglab/ColumnTableModel.cpp @@ -31,38 +31,12 @@ namespace { void ColumnTableModel::setData(std::shared_ptr cat, const std::optional &table) { - beginResetModel(); - SCOPE_EXIT { endResetModel(); }; - + if (cat != m_catalog) { + m_catalog = cat; + refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed, this, &ColumnTableModel::refresh); + } m_table = table; - m_catalog = cat; - if (m_table) { - m_columns = cat->attributes()->getColumnsForRelation(table->oid()); - // hide system and dropped columns - auto column_filter_pred = table->hasoids ? ColumnFilterWithOidsPred : ColumnFilterWithoutOidsPred; - auto si = std::remove_if(m_columns.begin(), m_columns.end(), column_filter_pred); - // move columns to end and remove them - m_columns.erase(si, m_columns.end()); - - // sort remaining columns by order in table - std::sort(m_columns.begin(), m_columns.end(), - [] (auto &l, auto &r) -> bool { return l.num < r.num; }); - } - else - m_columns.clear(); - - - if (m_table) { - m_indexes = m_catalog->indexes()->getIndexesForTable(table->oid()); - std::sort(m_indexes.begin(), m_indexes.end(), - [] (const auto &l, const auto &r) -> bool - { - return l.isprimary > r.isprimary - || (l.isprimary == r.isprimary && l.oid() < r.oid()); - }); - } - else - m_indexes.clear(); + refresh(); } QVariant ColumnTableModel::headerData(int section, Qt::Orientation orientation, int role) const @@ -245,6 +219,42 @@ QString ColumnTableModel::getFKey(const PgAttribute &column) const return result; } +void ColumnTableModel::refresh() +{ + beginResetModel(); + SCOPE_EXIT { endResetModel(); }; + + if (m_table) { + m_columns = m_catalog->attributes()->getColumnsForRelation(m_table->oid()); + // hide system and dropped columns + auto column_filter_pred = m_table->hasoids ? ColumnFilterWithOidsPred : ColumnFilterWithoutOidsPred; + auto si = std::remove_if(m_columns.begin(), m_columns.end(), column_filter_pred); + // move columns to end and remove them + m_columns.erase(si, m_columns.end()); + + // sort remaining columns by order in table + std::sort(m_columns.begin(), m_columns.end(), + [] (auto &l, auto &r) -> bool { return l.num < r.num; }); + } + else + m_columns.clear(); + + + if (m_table) { + m_indexes = m_catalog->indexes()->getIndexesForTable(m_table->oid()); + std::sort(m_indexes.begin(), m_indexes.end(), + [] (const auto &l, const auto &r) -> bool + { + return l.isprimary > r.isprimary + || (l.isprimary == r.isprimary && l.oid() < r.oid()); + }); + } + else + m_indexes.clear(); + + emit +} + QVariant ColumnTableModel::data(const QModelIndex &index, int role) const { if (role == Qt::ForegroundRole && index.column() == TypeCol) { diff --git a/pglab/ColumnTableModel.h b/pglab/ColumnTableModel.h index fb1f5c7..418160c 100644 --- a/pglab/ColumnTableModel.h +++ b/pglab/ColumnTableModel.h @@ -3,6 +3,7 @@ #include "BaseTableModel.h" #include "catalog/PgAttribute.h" +#include "catalog/PgDatabaseCatalog.h" #include "catalog/PgClass.h" #include "catalog/PgIndex.h" #include @@ -13,6 +14,7 @@ class PgDatabaseCatalog; class PgAttribute; class ColumnTableModel: public BaseTableModel { + Q_OBJECT public: enum e_Columns : int { AttnumCol, @@ -49,8 +51,15 @@ protected: t_Columns m_columns; std::vector m_indexes; + QMetaObject::Connection refreshConnection; + QString getFKey(const PgAttribute &column) const; + + +private slots: + /// Retrieves required data from catalog, called everytime it might have changed + void refresh(); }; #endif // COLUMNTABLEMODEL_H diff --git a/pglab/DatabaseWindow.cpp b/pglab/DatabaseWindow.cpp index 6ce4cf6..2cee827 100644 --- a/pglab/DatabaseWindow.cpp +++ b/pglab/DatabaseWindow.cpp @@ -3,6 +3,7 @@ #include "CrudTab.h" #include "widgets/CatalogTablesPage.h" #include "OpenDatabase.h" +#include "catalog/PgDatabaseCatalog.h" #include "ConnectionController.h" #include "MasterController.h" #include "TaskExecutor.h" @@ -221,6 +222,11 @@ void DatabaseWindow::createActions() action->setObjectName("actionPasteLangString"); action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_V)); } + { + QIcon icon; + auto action = actionRefreshCatalog = new QAction(icon, tr("Refresh"), this); + action->setObjectName("actionRefreshCatalog"); + } { QIcon icon; icon.addFile(QString::fromUtf8(":/icons/script_save.png"), QSize(), QIcon::Normal, QIcon::On); @@ -278,6 +284,11 @@ void DatabaseWindow::initMenus() actionCancelQuery }); + menuCatalog = mb->addMenu(tr("Catalog")); + menuCatalog->addActions({ + actionRefreshCatalog + }); + menuWindow = mb->addMenu(tr("Window")); menuWindow->addActions({ actionInspectUserSchemas, @@ -500,6 +511,11 @@ void DatabaseWindow::on_actionPasteLangString_triggered() } } +void DatabaseWindow::on_actionRefreshCatalog_triggered() +{ + m_database->refresh(); +} + void DatabaseWindow::on_actionSaveSql_triggered() { auto query_tool = GetActiveQueryTool(); diff --git a/pglab/DatabaseWindow.h b/pglab/DatabaseWindow.h index 333e18a..7e296bd 100644 --- a/pglab/DatabaseWindow.h +++ b/pglab/DatabaseWindow.h @@ -78,6 +78,7 @@ private: QAction *actionNewSql = nullptr; QAction *actionOpenSql = nullptr; QAction *actionPasteLangString = nullptr; + QAction *actionRefreshCatalog = nullptr; QAction *actionSaveSql = nullptr; QAction *actionSaveSqlAs = nullptr; QAction *actionSaveCopyOfSqlAs = nullptr; @@ -87,6 +88,7 @@ private: QMenu *menuFile = nullptr; QMenu *menuHelp = nullptr; QMenu *menuQuery = nullptr; + QMenu *menuCatalog = nullptr; QMenu *menuWindow = nullptr; @@ -140,6 +142,7 @@ private slots: void on_actionNewSql_triggered(); void on_actionOpenSql_triggered(); void on_actionPasteLangString_triggered(); + void on_actionRefreshCatalog_triggered(); void on_actionSaveSql_triggered(); void on_actionSaveSqlAs_triggered(); void on_actionSaveCopyOfSqlAs_triggered(); diff --git a/pglab/OpenDatabase.cpp b/pglab/OpenDatabase.cpp index dc4fd6c..e128bfe 100644 --- a/pglab/OpenDatabase.cpp +++ b/pglab/OpenDatabase.cpp @@ -27,14 +27,7 @@ OpenDatabase::~OpenDatabase() = default; void OpenDatabase::Init() { - Pgsql::Connection conn; - std::string connstr = m_config.connectionString().toStdString(); - if (conn.connect(connstr.c_str())) { - m_catalog->loadAll(conn, nullptr); - } - else { - qDebug() << "Connect failed connstr: " << connstr.c_str(); - } + refresh(); } std::shared_ptr OpenDatabase::catalog() @@ -51,3 +44,15 @@ TypeSelectionItemModel* OpenDatabase::typeSelectionModel() } return m_typeSelectionModel; } + +void OpenDatabase::refresh() +{ + Pgsql::Connection conn; + std::string connstr = m_config.connectionString().toStdString(); + if (conn.connect(connstr.c_str())) { + m_catalog->loadAll(conn, nullptr); + } + else { + qDebug() << "Connect failed connstr: " << connstr.c_str(); + } +} diff --git a/pglab/OpenDatabase.h b/pglab/OpenDatabase.h index 41e4287..f445e5e 100644 --- a/pglab/OpenDatabase.h +++ b/pglab/OpenDatabase.h @@ -39,6 +39,7 @@ public: std::shared_ptr catalog(); TypeSelectionItemModel* typeSelectionModel(); + void refresh(); const ConnectionConfig& config() const { return m_config; } private: diff --git a/pglablib/catalog/PgDatabaseCatalog.h b/pglablib/catalog/PgDatabaseCatalog.h index f1ba75f..60262ca 100644 --- a/pglablib/catalog/PgDatabaseCatalog.h +++ b/pglablib/catalog/PgDatabaseCatalog.h @@ -32,6 +32,11 @@ class PgInheritsContainer; class PgLanguageContainer; class PgSequenceContainer; +/// Manages all the catalog data for the database so the program +/// can efficiently retrieve information from memory. +/// +/// All the containers are created once during the first load. After +/// that they are reused on reload so signals will stay connected. class PgDatabaseCatalog: public QObject, public std::enable_shared_from_this { Q_OBJECT public: