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/ConstraintModel.cpp b/pglab/ConstraintModel.cpp index 4eb2142..46c32bb 100644 --- a/pglab/ConstraintModel.cpp +++ b/pglab/ConstraintModel.cpp @@ -9,18 +9,23 @@ ConstraintModel::ConstraintModel(QObject *parent) { } - - - void ConstraintModel::setData(std::shared_ptr cat, const std::optional &table) +{ + if (cat != m_catalog) { + m_catalog = cat; + refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed, this, &ConstraintModel::refresh); + } + m_table = table; + refresh(); +} + +void ConstraintModel::refresh() { beginResetModel(); SCOPE_EXIT { endResetModel(); }; - m_table = table; - m_catalog = cat; - if (table) { - m_constraints = cat->constraints()->getConstraintsForRelation(table->oid()); + if (m_table) { + m_constraints = m_catalog->constraints()->getConstraintsForRelation(m_table->oid()); std::sort(m_constraints.begin(), m_constraints.end(), [] (auto &l, auto &r) { return l.type < r.type || @@ -116,8 +121,6 @@ QString IconForConstraintType(ConstraintType ct) return s; } - - QVariant ConstraintModel::getData(const QModelIndex &index) const { QVariant v; diff --git a/pglab/ConstraintModel.h b/pglab/ConstraintModel.h index ae807df..29b4bcf 100644 --- a/pglab/ConstraintModel.h +++ b/pglab/ConstraintModel.h @@ -48,6 +48,10 @@ private: using t_Constraints = std::vector; t_Constraints m_constraints; + QMetaObject::Connection refreshConnection; + +private slots: + void refresh(); }; #endif // CONSTRAINTMODEL_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/IndexModel.cpp b/pglab/IndexModel.cpp index 20343b4..968358a 100644 --- a/pglab/IndexModel.cpp +++ b/pglab/IndexModel.cpp @@ -6,14 +6,22 @@ #include "CustomDataRole.h" void IndexModel::setData(std::shared_ptr cat, const std::optional &table) +{ + if (cat != m_catalog) { + m_catalog = cat; + refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed, this, &IndexModel::refresh); + } + m_table = table; + refresh(); +} + +void IndexModel::refresh() { beginResetModel(); SCOPE_EXIT { endResetModel(); }; - m_catalog = cat; - m_table = table; - if (table) - m_indexes = cat->indexes()->getIndexesForTable(table->oid()); + if (m_table) + m_indexes = m_catalog->indexes()->getIndexesForTable(m_table->oid()); else m_indexes.clear(); } diff --git a/pglab/IndexModel.h b/pglab/IndexModel.h index c238635..677240f 100644 --- a/pglab/IndexModel.h +++ b/pglab/IndexModel.h @@ -57,6 +57,10 @@ private: using t_Indexes = std::vector; t_Indexes m_indexes; + QMetaObject::Connection refreshConnection; + +private slots: + void refresh(); }; #endif // INDEXMODEL_H 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/pglab/ProcTableModel.cpp b/pglab/ProcTableModel.cpp index 1fa52d8..09d4419 100644 --- a/pglab/ProcTableModel.cpp +++ b/pglab/ProcTableModel.cpp @@ -28,17 +28,21 @@ QVariant ProcTableModel::headerData(int section, Qt::Orientation orientation, in void ProcTableModel::setCatalog(std::shared_ptr cat) { - m_catalog = cat; - reloadData(); + if (cat != m_catalog) { + m_catalog = cat; + refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed, + this, &ProcTableModel::refresh); + } + refresh(); } void ProcTableModel::setNamespaceFilter(NamespaceFilter filter) { m_namespaceFilter = filter; - reloadData(); + refresh(); } -void ProcTableModel::reloadData() +void ProcTableModel::refresh() { if (!m_catalog) return; diff --git a/pglab/ProcTableModel.h b/pglab/ProcTableModel.h index 6a07d17..c467803 100644 --- a/pglab/ProcTableModel.h +++ b/pglab/ProcTableModel.h @@ -48,11 +48,12 @@ private: std::shared_ptr m_catalog; NamespaceFilter m_namespaceFilter = NamespaceFilter::User; std::vector m_procs; + QMetaObject::Connection refreshConnection; - void reloadData(); Oid getType(int column) const; QVariant getData(const QModelIndex &index) const; - +private slots: + void refresh(); }; diff --git a/pglab/SequenceModel.cpp b/pglab/SequenceModel.cpp index 6a4867b..659348f 100644 --- a/pglab/SequenceModel.cpp +++ b/pglab/SequenceModel.cpp @@ -32,17 +32,21 @@ QVariant SequenceModel::headerData(int section, Qt::Orientation orientation, int void SequenceModel::setCatalog(std::shared_ptr cat) { - m_catalog = cat; - reloadData(); + if (cat != m_catalog) { + m_catalog = cat; + refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed, + this, &SequenceModel::refresh); + } + refresh(); } void SequenceModel::setNamespaceFilter(NamespaceFilter filter) { m_namespaceFilter = filter; - reloadData(); + refresh(); } -void SequenceModel::reloadData() +void SequenceModel::refresh() { if (!m_catalog) return; diff --git a/pglab/SequenceModel.h b/pglab/SequenceModel.h index f055f05..00aa7d3 100644 --- a/pglab/SequenceModel.h +++ b/pglab/SequenceModel.h @@ -45,8 +45,9 @@ private: std::shared_ptr m_catalog; std::vector m_sequences; NamespaceFilter m_namespaceFilter = NamespaceFilter::User; + QMetaObject::Connection refreshConnection; - void reloadData(); + void refresh(); }; #endif // SEQUENCEMODEL_H diff --git a/pglab/TablesTableModel.cpp b/pglab/TablesTableModel.cpp index 0c4f767..bb7de12 100644 --- a/pglab/TablesTableModel.cpp +++ b/pglab/TablesTableModel.cpp @@ -1,4 +1,5 @@ #include "TablesTableModel.h" +#include "ScopeGuard.h" #include "catalog/PgDatabaseCatalog.h" #include "catalog/PgClass.h" #include "catalog/PgClassContainer.h" @@ -15,23 +16,27 @@ TablesTableModel::TablesTableModel(QObject *parent) void TablesTableModel::setNamespaceFilter(NamespaceFilter nsf) { m_namespaceFilter = nsf; - reloadData(); + refresh(); } void TablesTableModel::setCatalog(std::shared_ptr cat) { - m_catalog = cat; - reloadData(); - + if (cat != m_catalog) { + m_catalog = cat; + refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed, + this, &TablesTableModel::refresh); + } + refresh(); } -void TablesTableModel::reloadData() +void TablesTableModel::refresh() { + beginResetModel(); + SCOPE_EXIT { endResetModel(); }; + if (!m_catalog) return; - beginResetModel(); - // Later afscheiden naar filter functie auto classes = m_catalog->classes(); @@ -59,7 +64,6 @@ void TablesTableModel::reloadData() } doSort(1); - endResetModel(); } void TablesTableModel::setSortOrder(int so) diff --git a/pglab/TablesTableModel.h b/pglab/TablesTableModel.h index 4aa1ba7..52e8814 100644 --- a/pglab/TablesTableModel.h +++ b/pglab/TablesTableModel.h @@ -49,13 +49,16 @@ private: std::shared_ptr m_catalog; NamespaceFilter m_namespaceFilter = NamespaceFilter::User; t_Tables m_tables; + QMetaObject::Connection refreshConnection; - void reloadData(); Oid getType(int column) const; QVariant getData(const QModelIndex &index) const; // QString formatTableName(const PgClass &cls) const; void doSort(int so); +private slots: + void refresh(); + }; #endif // TABLESTABLEMODEL_H diff --git a/pglab/TriggerPage.cpp b/pglab/TriggerPage.cpp index dd78f00..3977c44 100644 --- a/pglab/TriggerPage.cpp +++ b/pglab/TriggerPage.cpp @@ -19,6 +19,7 @@ TriggerPage::TriggerPage(QWidget *parent) connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &TriggerPage::tableView_selectionChanged); + connect(m_model, &TriggerTableModel::modelReset, m_definitionView, &SqlCodePreview::clear); } diff --git a/pglab/TriggerTableModel.cpp b/pglab/TriggerTableModel.cpp index d69d070..c83ed34 100644 --- a/pglab/TriggerTableModel.cpp +++ b/pglab/TriggerTableModel.cpp @@ -2,6 +2,7 @@ #include "catalog/PgDatabaseCatalog.h" #include "catalog/PgTriggerContainer.h" #include "CustomDataRole.h" +#include "ScopeGuard.h" TriggerTableModel::TriggerTableModel(QObject *parent) : QAbstractTableModel(parent) @@ -30,12 +31,12 @@ QVariant TriggerTableModel::headerData(int section, Qt::Orientation orientation, void TriggerTableModel::setCatalog(std::shared_ptr cat) { - beginResetModel(); - - m_catalog = cat; - m_triggers = cat->triggers();//->getTriggersForRelation(table); - - endResetModel(); + if (cat != m_catalog) { + m_catalog = cat; + refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed, this, + &TriggerTableModel::refresh); + } + refresh(); } int TriggerTableModel::rowCount(const QModelIndex &) const @@ -98,3 +99,11 @@ QVariant TriggerTableModel::getData(const QModelIndex &index) const } return QVariant(); } + +void TriggerTableModel::refresh() +{ + beginResetModel(); + SCOPE_EXIT { endResetModel(); }; + + m_triggers = m_catalog->triggers(); +} diff --git a/pglab/TriggerTableModel.h b/pglab/TriggerTableModel.h index 744abbe..8f60d77 100644 --- a/pglab/TriggerTableModel.h +++ b/pglab/TriggerTableModel.h @@ -66,9 +66,13 @@ public: private: std::shared_ptr m_catalog; std::shared_ptr m_triggers; + QMetaObject::Connection refreshConnection; Oid getType(int column) const; QVariant getData(const QModelIndex &index) const; + +private slots: + void refresh(); }; diff --git a/pglab/widgets/CatalogConstraintPage.cpp b/pglab/widgets/CatalogConstraintPage.cpp index 752be3a..33ff420 100644 --- a/pglab/widgets/CatalogConstraintPage.cpp +++ b/pglab/widgets/CatalogConstraintPage.cpp @@ -16,6 +16,7 @@ CatalogConstraintPage::CatalogConstraintPage(QWidget *parent) connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &CatalogConstraintPage::tableView_selectionChanged); + connect(m_constraintModel, &ConstraintModel::modelReset, m_definitionView, &SqlCodePreview::clear); } void CatalogConstraintPage::catalogSet() @@ -26,7 +27,6 @@ void CatalogConstraintPage::setFilter(const std::optional &cls) { m_constraintModel->setData(m_catalog, cls); m_tableView->resizeColumnsToContents(); - m_definitionView->setPlainText({}); } void CatalogConstraintPage::tableView_selectionChanged(const QItemSelection &/*selected*/, const QItemSelection &/*deselected*/) diff --git a/pglab/widgets/CatalogFunctionsPage.cpp b/pglab/widgets/CatalogFunctionsPage.cpp index 2cf0a71..bd6f20f 100644 --- a/pglab/widgets/CatalogFunctionsPage.cpp +++ b/pglab/widgets/CatalogFunctionsPage.cpp @@ -41,6 +41,7 @@ CatalogFunctionsPage::CatalogFunctionsPage(QWidget *parent) connect(m_functionTable->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &CatalogFunctionsPage::functionTable_currentRowChanged); + connect(m_model, &ProcTableModel::modelReset, m_definitionView, &SqlCodePreview::clear); retranslateUi(); } diff --git a/pglab/widgets/CatalogIndexPage.cpp b/pglab/widgets/CatalogIndexPage.cpp index 25cafec..af5e9f3 100644 --- a/pglab/widgets/CatalogIndexPage.cpp +++ b/pglab/widgets/CatalogIndexPage.cpp @@ -16,6 +16,7 @@ CatalogIndexPage::CatalogIndexPage(QWidget *parent) connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &CatalogIndexPage::tableView_selectionChanged); + connect(m_indexModel, &IndexModel::modelReset, m_definitionView, &SqlCodePreview::clear); } void CatalogIndexPage::catalogSet() @@ -26,7 +27,6 @@ void CatalogIndexPage::setFilter(const std::optional &cls) { m_indexModel->setData(m_catalog, cls); m_tableView->resizeColumnsToContents(); - m_definitionView->setPlainText({}); } void CatalogIndexPage::tableView_selectionChanged(const QItemSelection &/*selected*/, const QItemSelection &/*deselected*/) diff --git a/pglab/widgets/CatalogSequencesPage.cpp b/pglab/widgets/CatalogSequencesPage.cpp index e8774ae..1af5c22 100644 --- a/pglab/widgets/CatalogSequencesPage.cpp +++ b/pglab/widgets/CatalogSequencesPage.cpp @@ -28,6 +28,8 @@ CatalogSequencesPage::CatalogSequencesPage(QWidget *parent) connect(m_sequenceTable->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &CatalogSequencesPage::sequenceTable_currentRowChanged); + connect(m_model, &SequenceModel::modelReset, + [this] () { selectedSequenceChanged({}); }); retranslateUi(); } diff --git a/pglab/widgets/CatalogTablesPage.cpp b/pglab/widgets/CatalogTablesPage.cpp index 1bc7460..07aebda 100644 --- a/pglab/widgets/CatalogTablesPage.cpp +++ b/pglab/widgets/CatalogTablesPage.cpp @@ -72,6 +72,12 @@ CatalogTablesPage::CatalogTablesPage(QWidget *parent) // Signals connect(m_tableView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &CatalogTablesPage::tableListTable_currentRowChanged); + connect(m_tablesModel, &TablesTableModel::modelReset, + [this] () + { + selectedTableChanged({}); + m_propertiesPage->setActiveRow({}); + }); connect(m_tablesModel, &QAbstractItemModel::layoutChanged, this, &CatalogTablesPage::tableListTable_layoutChanged); 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: