From b1b7e1081fb56eb1712142d89843f9e00f7e7724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Carrillo?= <gcarrillo@linuxmail.org> Date: Sat, 8 Jun 2024 19:05:28 -0500 Subject: [PATCH 1/5] [core] Add methods to handle QGIS service connections --- pg_service_parser/core/service_connections.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 pg_service_parser/core/service_connections.py diff --git a/pg_service_parser/core/service_connections.py b/pg_service_parser/core/service_connections.py new file mode 100644 index 0000000..bc0f56d --- /dev/null +++ b/pg_service_parser/core/service_connections.py @@ -0,0 +1,47 @@ +from qgis.core import ( + QgsAbstractDatabaseProviderConnection, + QgsDataSourceUri, + QgsProviderRegistry, +) +from qgis.gui import QgsGui +from qgis.PyQt.QtCore import QSettings + + +def get_connections(service: str) -> dict[str, QgsAbstractDatabaseProviderConnection]: + res = {} + provider = QgsProviderRegistry.instance().providerMetadata("postgres") + conns = provider.connections() + for key, pg_conn in conns.items(): + if QgsDataSourceUri(pg_conn.uri()).service() == service: + res[key] = pg_conn + + return res + + +def create_connection(service: str, name: str) -> None: + config = {} + uri = f"service='{service}'" + provider = QgsProviderRegistry.instance().providerMetadata("postgres") + conn = provider.createConnection(uri, config) + provider.saveConnection(conn, name) + # conn.store(name) + + +def remove_connection(conn_name: str) -> None: + provider = QgsProviderRegistry.instance().providerMetadata("postgres") + provider.deleteConnection(conn_name) + + +def edit_connection(conn_name: str) -> None: + provider = QgsProviderRegistry.instance().providerMetadata("postgres") + + if conn_name in provider.dbConnections(): + pg = QgsGui.sourceSelectProviderRegistry().providerByName("postgres") + w = pg.createDataSourceWidget() + + settings = QSettings() + settings.value("PostgreSQL/connections/selected") + settings.setValue("PostgreSQL/connections/selected", conn_name) + + w.refresh() # To reflect the newly selected connection + w.btnEdit_clicked() From 012a86c3fa81c9bbc3169a88646157af42769038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Carrillo?= <gcarrillo@linuxmail.org> Date: Mon, 10 Jun 2024 14:44:58 -0500 Subject: [PATCH 2/5] Add model to handle service connections --- pg_service_parser/core/connection_model.py | 64 ++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 pg_service_parser/core/connection_model.py diff --git a/pg_service_parser/core/connection_model.py b/pg_service_parser/core/connection_model.py new file mode 100644 index 0000000..9dc548a --- /dev/null +++ b/pg_service_parser/core/connection_model.py @@ -0,0 +1,64 @@ +from qgis.core import QgsAbstractDatabaseProviderConnection +from qgis.PyQt.QtCore import QAbstractTableModel, QModelIndex, Qt +from qgis.PyQt.QtGui import QFont + + +class ServiceConnectionModel(QAbstractTableModel): + KEY_COL = 0 + VALUE_COL = 1 + + def __init__( + self, service_name: str, connections: dict[str, QgsAbstractDatabaseProviderConnection] + ) -> None: + super().__init__() + self.__service_name = service_name + self.__model_data = connections + + def rowCount(self, parent=QModelIndex()): + return len(self.__model_data) + + def columnCount(self, parent=QModelIndex()): + return 2 + + def index_to_connection_key(self, index): + return list(self.__model_data.keys())[index.row()] + + def data(self, index, role=Qt.ItemDataRole.DisplayRole): + if not index.isValid(): + return None + + key = list(self.__model_data.keys())[index.row()] + if role == Qt.ItemDataRole.DisplayRole: + if index.column() == self.KEY_COL: + return key + elif index.column() == self.VALUE_COL: + return self.__model_data[key].uri() + elif role == Qt.ItemDataRole.FontRole: + if index.column() == self.KEY_COL: + font = QFont() + font.setBold(True) + return font + elif index.column() == self.VALUE_COL: + font = QFont() + font.setItalic(True) + return font + + return None + + def headerData( + self, section: int, orientation: Qt.Orientation, role: Qt.DisplayRole = Qt.DisplayRole + ): + if orientation == Qt.Horizontal: + if section == self.KEY_COL: + return "Connection name" + elif section == self.VALUE_COL: + return "Configuration" + + def flags(self, idx): + if not idx.isValid(): + return ~Qt.ItemFlag.ItemIsSelectable & ~Qt.ItemFlag.ItemIsEnabled + + return Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEnabled + + def service_name(self): + return self.__service_name From 47cf2a305b01fbe43aaf854935f03251e4d5e4f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Carrillo?= <gcarrillo@linuxmail.org> Date: Mon, 10 Jun 2024 18:38:22 -0500 Subject: [PATCH 3/5] [gui] Add tab for listing and managing (add/edit/remove) connections to a particular service; refactor ServiceNameDialog to also handle connection names --- pg_service_parser/core/connection_model.py | 13 +- pg_service_parser/core/service_connections.py | 14 +- .../core/{item_models.py => setting_model.py} | 0 pg_service_parser/gui/dlg_new_name.py | 42 ++++++ pg_service_parser/gui/dlg_pg_service.py | 111 +++++++++++++- pg_service_parser/gui/dlg_service_name.py | 21 --- ...vice_name_dialog.ui => new_name_dialog.ui} | 16 +- pg_service_parser/ui/pg_service_dialog.ui | 139 +++++++++++++++++- 8 files changed, 308 insertions(+), 48 deletions(-) rename pg_service_parser/core/{item_models.py => setting_model.py} (100%) create mode 100644 pg_service_parser/gui/dlg_new_name.py delete mode 100644 pg_service_parser/gui/dlg_service_name.py rename pg_service_parser/ui/{service_name_dialog.ui => new_name_dialog.ui} (86%) diff --git a/pg_service_parser/core/connection_model.py b/pg_service_parser/core/connection_model.py index 9dc548a..6c4a89d 100644 --- a/pg_service_parser/core/connection_model.py +++ b/pg_service_parser/core/connection_model.py @@ -42,17 +42,20 @@ def data(self, index, role=Qt.ItemDataRole.DisplayRole): font = QFont() font.setItalic(True) return font + elif role == Qt.ItemDataRole.ToolTipRole: + if index.column() == self.VALUE_COL: + return self.__model_data[key].uri() return None - def headerData( - self, section: int, orientation: Qt.Orientation, role: Qt.DisplayRole = Qt.DisplayRole - ): - if orientation == Qt.Horizontal: + def headerData(self, section, orientation, role): + if orientation == Qt.Orientation.Horizontal and role == Qt.ItemDataRole.DisplayRole: if section == self.KEY_COL: return "Connection name" elif section == self.VALUE_COL: - return "Configuration" + return "URI" + + return QAbstractTableModel.headerData(self, section, orientation, role) def flags(self, idx): if not idx.isValid(): diff --git a/pg_service_parser/core/service_connections.py b/pg_service_parser/core/service_connections.py index bc0f56d..03069f7 100644 --- a/pg_service_parser/core/service_connections.py +++ b/pg_service_parser/core/service_connections.py @@ -18,30 +18,30 @@ def get_connections(service: str) -> dict[str, QgsAbstractDatabaseProviderConnec return res -def create_connection(service: str, name: str) -> None: +def create_connection(service: str, connection_name: str) -> None: config = {} uri = f"service='{service}'" provider = QgsProviderRegistry.instance().providerMetadata("postgres") conn = provider.createConnection(uri, config) - provider.saveConnection(conn, name) + provider.saveConnection(conn, connection_name) # conn.store(name) -def remove_connection(conn_name: str) -> None: +def remove_connection(connection_name: str) -> None: provider = QgsProviderRegistry.instance().providerMetadata("postgres") - provider.deleteConnection(conn_name) + provider.deleteConnection(connection_name) -def edit_connection(conn_name: str) -> None: +def edit_connection(connection_name: str) -> None: provider = QgsProviderRegistry.instance().providerMetadata("postgres") - if conn_name in provider.dbConnections(): + if connection_name in provider.dbConnections(): pg = QgsGui.sourceSelectProviderRegistry().providerByName("postgres") w = pg.createDataSourceWidget() settings = QSettings() settings.value("PostgreSQL/connections/selected") - settings.setValue("PostgreSQL/connections/selected", conn_name) + settings.setValue("PostgreSQL/connections/selected", connection_name) w.refresh() # To reflect the newly selected connection w.btnEdit_clicked() diff --git a/pg_service_parser/core/item_models.py b/pg_service_parser/core/setting_model.py similarity index 100% rename from pg_service_parser/core/item_models.py rename to pg_service_parser/core/setting_model.py diff --git a/pg_service_parser/gui/dlg_new_name.py b/pg_service_parser/gui/dlg_new_name.py new file mode 100644 index 0000000..031d8dc --- /dev/null +++ b/pg_service_parser/gui/dlg_new_name.py @@ -0,0 +1,42 @@ +from enum import Enum + +from qgis.PyQt.QtCore import pyqtSlot +from qgis.PyQt.QtWidgets import QDialog, QWidget + +from pg_service_parser.utils import get_ui_class + +DIALOG_UI = get_ui_class("new_name_dialog.ui") + + +class EnumNewName(Enum): + SERVICE = 0 + CONNECTION = 1 + + +class NewNameDialog(QDialog, DIALOG_UI): + + def __init__(self, mode: EnumNewName, parent: QWidget, data: str = "") -> None: + QDialog.__init__(self, parent) + self.setupUi(self) + self.__mode = mode + + self.buttonBox.accepted.connect(self.__accepted) + + if self.__mode == EnumNewName.SERVICE: + self.setWindowTitle("Service name") + self.label.setText("Enter a service name") + self.txtNewName.setPlaceholderText("e.g., my-service") + self.new_name = "my-service" + elif self.__mode == EnumNewName.CONNECTION: + self.setWindowTitle("Connection name") + self.label.setText("Enter a connection name") + self.txtNewName.setPlaceholderText("e.g., My Service Connection") + self.new_name = f"{data} connection" + + @pyqtSlot() + def __accepted(self): + if self.txtNewName.text().strip(): + if self.__mode == EnumNewName.SERVICE: + self.new_name = self.txtNewName.text().strip().replace(" ", "-") + elif self.__mode == EnumNewName.CONNECTION: + self.new_name = self.txtNewName.text().strip() diff --git a/pg_service_parser/gui/dlg_pg_service.py b/pg_service_parser/gui/dlg_pg_service.py index bf9c27e..97b4a5b 100644 --- a/pg_service_parser/gui/dlg_pg_service.py +++ b/pg_service_parser/gui/dlg_pg_service.py @@ -2,11 +2,11 @@ from qgis.core import QgsApplication from qgis.gui import QgsMessageBar -from qgis.PyQt.QtCore import QItemSelection, Qt, pyqtSlot -from qgis.PyQt.QtWidgets import QDialog, QMessageBox, QSizePolicy +from qgis.PyQt.QtCore import QItemSelection, QModelIndex, Qt, pyqtSlot +from qgis.PyQt.QtWidgets import QDialog, QHeaderView, QMessageBox, QSizePolicy from pg_service_parser.conf.service_settings import SERVICE_SETTINGS, SETTINGS_TEMPLATE -from pg_service_parser.core.item_models import ServiceConfigModel +from pg_service_parser.core.connection_model import ServiceConnectionModel from pg_service_parser.core.pg_service_parser_wrapper import ( add_new_service, conf_path, @@ -15,7 +15,14 @@ service_names, write_service, ) -from pg_service_parser.gui.dlg_service_name import ServiceNameDialog +from pg_service_parser.core.service_connections import ( + create_connection, + edit_connection, + get_connections, + remove_connection, +) +from pg_service_parser.core.setting_model import ServiceConfigModel +from pg_service_parser.gui.dlg_new_name import EnumNewName, NewNameDialog from pg_service_parser.gui.dlg_service_settings import ServiceSettingsDialog from pg_service_parser.gui.item_delegates import ServiceConfigDelegate from pg_service_parser.utils import get_ui_class @@ -23,6 +30,7 @@ DIALOG_UI = get_ui_class("pg_service_dialog.ui") EDIT_TAB_INDEX = 0 COPY_TAB_INDEX = 1 +CONNECTION_TAB_INDEX = 2 class PgServiceDialog(QDialog, DIALOG_UI): @@ -53,9 +61,13 @@ def __initialize_dialog(self): return self.__edit_model = None + self.__connection_model = None self.btnAddSettings.setIcon(QgsApplication.getThemeIcon("/symbologyAdd.svg")) self.btnRemoveSetting.setIcon(QgsApplication.getThemeIcon("/symbologyRemove.svg")) + self.btnAddConnection.setIcon(QgsApplication.getThemeIcon("/symbologyAdd.svg")) + self.btnEditConnection.setIcon(QgsApplication.getThemeIcon("/symbologyEdit.svg")) + self.btnRemoveConnection.setIcon(QgsApplication.getThemeIcon("/symbologyRemove.svg")) self.txtConfFile.setText(str(self.__conf_file_path)) self.lblWarning.setVisible(False) self.lblConfFile.setText("Config file path found at ") @@ -63,6 +75,7 @@ def __initialize_dialog(self): self.txtConfFile.setVisible(True) self.tabWidget.setEnabled(True) self.btnCreateServiceFile.setVisible(False) + self.tblServiceConnections.horizontalHeader().setVisible(True) self.btnRemoveSetting.setEnabled(False) self.radOverwrite.toggled.connect(self.__update_target_controls) @@ -73,9 +86,15 @@ def __initialize_dialog(self): self.btnAddSettings.clicked.connect(self.__add_settings_clicked) self.btnRemoveSetting.clicked.connect(self.__remove_setting_clicked) self.btnUpdateService.clicked.connect(self.__update_service_clicked) + self.cboConnectionService.currentIndexChanged.connect(self.__connection_service_changed) + self.btnAddConnection.clicked.connect(self.__add_connection_clicked) + self.btnEditConnection.clicked.connect(self.__edit_connection_clicked) + self.btnRemoveConnection.clicked.connect(self.__remove_connection_clicked) + self.tblServiceConnections.doubleClicked.connect(self.__edit_double_clicked_connection) self.__initialize_edit_services() self.__initialize_copy_services() + self.__initialize_connection_services() self.__update_target_controls(True) self.__update_add_settings_button() @@ -85,11 +104,11 @@ def __initialize_dialog(self): @pyqtSlot() def __create_file_clicked(self): - dlg = ServiceNameDialog(self) + dlg = NewNameDialog(EnumNewName.SERVICE, self) dlg.exec() if dlg.result() == QDialog.DialogCode.Accepted: Path.touch(self.__conf_file_path) - add_new_service(dlg.service_name) + add_new_service(dlg.new_name) # Set flag to get a template after some initialization self.__new_empty_file = True @@ -138,6 +157,15 @@ def __initialize_edit_services(self): self.cboEditService.addItems(service_names(self.__conf_file_path)) self.cboEditService.setCurrentText(current_text) + def __initialize_connection_services(self): + self.__connection_model = None + current_text = self.cboConnectionService.currentText() # Remember latest currentText + self.cboConnectionService.blockSignals(True) # Avoid triggering custom slot while clearing + self.cboConnectionService.clear() + self.cboConnectionService.blockSignals(False) + self.cboConnectionService.addItems(service_names(self.__conf_file_path)) + self.cboConnectionService.setCurrentText(current_text) + @pyqtSlot() def __copy_service(self): # Validations @@ -178,6 +206,8 @@ def __current_tab_changed(self, index): pass # For now, services to be copied won't be altered in other tabs elif index == EDIT_TAB_INDEX: self.__initialize_edit_services() + elif index == CONNECTION_TAB_INDEX: + self.__initialize_connection_services() @pyqtSlot(int) def __edit_service_changed(self, index): @@ -275,3 +305,72 @@ def __update_service_clicked(self): self.__edit_model.set_not_dirty() else: self.bar.pushInfo("PG service", "Edit the service configuration and try again.") + + @pyqtSlot(int) + def __connection_service_changed(self, index): + self.__initialize_service_connections() + + def __initialize_service_connections(self, selected_index=QModelIndex()): + service = self.cboConnectionService.currentText() + self.__connection_model = ServiceConnectionModel(service, get_connections(service)) + self.__update_connection_controls(False) + self.tblServiceConnections.setModel(self.__connection_model) + self.tblServiceConnections.horizontalHeader().setSectionResizeMode( + 0, QHeaderView.ResizeToContents + ) + + self.tblServiceConnections.selectionModel().selectionChanged.connect( + self.__conn_table_selection_changed + ) + self.tblServiceConnections.selectRow(selected_index.row()) # Remember selection + + @pyqtSlot() + def __add_connection_clicked(self): + service = self.cboConnectionService.currentText() + dlg = NewNameDialog(EnumNewName.CONNECTION, self, service) + dlg.exec() + if dlg.result() == QDialog.DialogCode.Accepted: + create_connection(service, dlg.new_name) + self.__initialize_service_connections() + + @pyqtSlot() + def __edit_connection_clicked(self): + selected_indexes = self.tblServiceConnections.selectedIndexes() + if selected_indexes: + self.__edit_connection(selected_indexes[0]) + + @pyqtSlot(QModelIndex) + def __edit_double_clicked_connection(self, index): + self.__edit_connection(index) + + def __edit_connection(self, index): + connection_name = self.__connection_model.index_to_connection_key(index) + edit_connection(connection_name) + self.__initialize_service_connections(index) + + @pyqtSlot() + def __remove_connection_clicked(self): + selected_indexes = self.tblServiceConnections.selectedIndexes() + if selected_indexes: + connection_name = self.__connection_model.index_to_connection_key(selected_indexes[0]) + if ( + QMessageBox.question( + self, + "Remove service connection", + f"Are you sure you want to remove the connection to '{connection_name}'?", + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, + QMessageBox.StandardButton.No, + ) + == QMessageBox.StandardButton.Yes + ): + remove_connection(connection_name) + self.__initialize_service_connections() + + @pyqtSlot(QItemSelection, QItemSelection) + def __conn_table_selection_changed(self, selected, deselected): + selected_indexes = bool(self.tblServiceConnections.selectedIndexes()) + self.__update_connection_controls(selected_indexes) + + def __update_connection_controls(self, enable): + self.btnEditConnection.setEnabled(enable) + self.btnRemoveConnection.setEnabled(enable) diff --git a/pg_service_parser/gui/dlg_service_name.py b/pg_service_parser/gui/dlg_service_name.py deleted file mode 100644 index edb7798..0000000 --- a/pg_service_parser/gui/dlg_service_name.py +++ /dev/null @@ -1,21 +0,0 @@ -from qgis.PyQt.QtCore import pyqtSlot -from qgis.PyQt.QtWidgets import QDialog - -from pg_service_parser.utils import get_ui_class - -DIALOG_UI = get_ui_class("service_name_dialog.ui") - - -class ServiceNameDialog(QDialog, DIALOG_UI): - - def __init__(self, parent): - QDialog.__init__(self, parent) - self.setupUi(self) - - self.buttonBox.accepted.connect(self.__accepted) - self.service_name = "my-service" - - @pyqtSlot() - def __accepted(self): - if self.txtServiceName.text().strip(): - self.service_name = self.txtServiceName.text().replace(" ", "-") diff --git a/pg_service_parser/ui/service_name_dialog.ui b/pg_service_parser/ui/new_name_dialog.ui similarity index 86% rename from pg_service_parser/ui/service_name_dialog.ui rename to pg_service_parser/ui/new_name_dialog.ui index 69a0c96..bf54cf3 100644 --- a/pg_service_parser/ui/service_name_dialog.ui +++ b/pg_service_parser/ui/new_name_dialog.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>dlgServiceName</class> - <widget class="QDialog" name="dlgServiceName"> + <class>dlgNewName</class> + <widget class="QDialog" name="dlgNewName"> <property name="geometry"> <rect> <x>0</x> @@ -11,23 +11,23 @@ </rect> </property> <property name="windowTitle"> - <string>Service name</string> + <string>New name</string> </property> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> <widget class="QLabel" name="label"> <property name="text"> - <string>Enter a service name</string> + <string>Enter a new name</string> </property> </widget> </item> <item row="1" column="0"> - <widget class="QLineEdit" name="txtServiceName"> + <widget class="QLineEdit" name="txtNewName"> <property name="alignment"> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> </property> <property name="placeholderText"> - <string>e.g., my-service</string> + <string>e.g., new name</string> </property> <property name="clearButtonEnabled"> <bool>true</bool> @@ -66,7 +66,7 @@ <connection> <sender>buttonBox</sender> <signal>accepted()</signal> - <receiver>dlgServiceName</receiver> + <receiver>dlgNewName</receiver> <slot>accept()</slot> <hints> <hint type="sourcelabel"> @@ -82,7 +82,7 @@ <connection> <sender>buttonBox</sender> <signal>rejected()</signal> - <receiver>dlgServiceName</receiver> + <receiver>dlgNewName</receiver> <slot>reject()</slot> <hints> <hint type="sourcelabel"> diff --git a/pg_service_parser/ui/pg_service_dialog.ui b/pg_service_parser/ui/pg_service_dialog.ui index c43e301..902a0e2 100644 --- a/pg_service_parser/ui/pg_service_dialog.ui +++ b/pg_service_parser/ui/pg_service_dialog.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>497</width> + <width>499</width> <height>316</height> </rect> </property> @@ -326,6 +326,143 @@ </item> </layout> </widget> + <widget class="QWidget" name="tabConnections"> + <attribute name="title"> + <string>Connections</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0" colspan="2"> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QLabel" name="lblServiceConnections"> + <property name="text"> + <string>Service</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="cboConnectionService"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="1" column="0"> + <widget class="QTableView" name="tblServiceConnections"> + <property name="editTriggers"> + <set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::SingleSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + <property name="gridStyle"> + <enum>Qt::DotLine</enum> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + <attribute name="horizontalHeaderVisible"> + <bool>false</bool> + </attribute> + <attribute name="horizontalHeaderStretchLastSection"> + <bool>true</bool> + </attribute> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> + </widget> + </item> + <item row="1" column="1"> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QPushButton" name="btnAddConnection"> + <property name="maximumSize"> + <size> + <width>25</width> + <height>25</height> + </size> + </property> + <property name="toolTip"> + <string>Add connection to current service</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btnEditConnection"> + <property name="maximumSize"> + <size> + <width>25</width> + <height>25</height> + </size> + </property> + <property name="toolTip"> + <string>Edit connection</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btnRemoveConnection"> + <property name="maximumSize"> + <size> + <width>25</width> + <height>25</height> + </size> + </property> + <property name="toolTip"> + <string>Remove connection to current service</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> </widget> </item> <item> From a0468a33be83f9f5c3f5053eb10e4ea9b32bc6cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Carrillo?= <gcarrillo@linuxmail.org> Date: Fri, 4 Oct 2024 17:25:32 -0500 Subject: [PATCH 4/5] Address review: rename tabs --- pg_service_parser/ui/pg_service_dialog.ui | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pg_service_parser/ui/pg_service_dialog.ui b/pg_service_parser/ui/pg_service_dialog.ui index 902a0e2..c50ebb1 100644 --- a/pg_service_parser/ui/pg_service_dialog.ui +++ b/pg_service_parser/ui/pg_service_dialog.ui @@ -86,7 +86,7 @@ </property> <widget class="QWidget" name="tabEdit"> <attribute name="title"> - <string>Edit</string> + <string>Edit Service</string> </attribute> <layout class="QGridLayout" name="gridLayout_3"> <item row="1" column="0"> @@ -228,7 +228,7 @@ </widget> <widget class="QWidget" name="tabCopy"> <attribute name="title"> - <string>Copy</string> + <string>Copy Service</string> </attribute> <layout class="QGridLayout" name="gridLayout_2"> <item row="2" column="1"> @@ -328,7 +328,7 @@ </widget> <widget class="QWidget" name="tabConnections"> <attribute name="title"> - <string>Connections</string> + <string>QGIS Connections</string> </attribute> <layout class="QGridLayout" name="gridLayout_4"> <item row="0" column="0" colspan="2"> From 1c713662e43887ed6ff319005eb22ab2371b886f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Carrillo?= <gcarrillo@linuxmail.org> Date: Fri, 4 Oct 2024 17:42:20 -0500 Subject: [PATCH 5/5] [connections] Code cleanup, pass parent and widget mode to edit connection dialog --- pg_service_parser/core/service_connections.py | 13 +++++++------ pg_service_parser/gui/dlg_pg_service.py | 2 +- pg_service_parser/gui/item_delegates.py | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pg_service_parser/core/service_connections.py b/pg_service_parser/core/service_connections.py index 03069f7..41d798f 100644 --- a/pg_service_parser/core/service_connections.py +++ b/pg_service_parser/core/service_connections.py @@ -5,6 +5,7 @@ ) from qgis.gui import QgsGui from qgis.PyQt.QtCore import QSettings +from qgis.PyQt.QtWidgets import QWidget def get_connections(service: str) -> dict[str, QgsAbstractDatabaseProviderConnection]: @@ -24,7 +25,6 @@ def create_connection(service: str, connection_name: str) -> None: provider = QgsProviderRegistry.instance().providerMetadata("postgres") conn = provider.createConnection(uri, config) provider.saveConnection(conn, connection_name) - # conn.store(name) def remove_connection(connection_name: str) -> None: @@ -32,16 +32,17 @@ def remove_connection(connection_name: str) -> None: provider.deleteConnection(connection_name) -def edit_connection(connection_name: str) -> None: +def edit_connection(connection_name: str, parent: QWidget) -> None: provider = QgsProviderRegistry.instance().providerMetadata("postgres") if connection_name in provider.dbConnections(): pg = QgsGui.sourceSelectProviderRegistry().providerByName("postgres") - w = pg.createDataSourceWidget() + widget = pg.createDataSourceWidget( + parent, widgetMode=QgsProviderRegistry.WidgetMode.Standalone + ) settings = QSettings() - settings.value("PostgreSQL/connections/selected") settings.setValue("PostgreSQL/connections/selected", connection_name) - w.refresh() # To reflect the newly selected connection - w.btnEdit_clicked() + widget.refresh() # To reflect the newly selected connection + widget.btnEdit_clicked() diff --git a/pg_service_parser/gui/dlg_pg_service.py b/pg_service_parser/gui/dlg_pg_service.py index 97b4a5b..b7b9e1a 100644 --- a/pg_service_parser/gui/dlg_pg_service.py +++ b/pg_service_parser/gui/dlg_pg_service.py @@ -345,7 +345,7 @@ def __edit_double_clicked_connection(self, index): def __edit_connection(self, index): connection_name = self.__connection_model.index_to_connection_key(index) - edit_connection(connection_name) + edit_connection(connection_name, self) self.__initialize_service_connections(index) @pyqtSlot() diff --git a/pg_service_parser/gui/item_delegates.py b/pg_service_parser/gui/item_delegates.py index 04767fd..66f1758 100644 --- a/pg_service_parser/gui/item_delegates.py +++ b/pg_service_parser/gui/item_delegates.py @@ -4,7 +4,7 @@ from qgis.PyQt.QtCore import Qt from qgis.PyQt.QtWidgets import QComboBox, QStyledItemDelegate -from pg_service_parser.core.item_models import ServiceConfigModel +from pg_service_parser.core.setting_model import ServiceConfigModel class ServiceConfigDelegate(QStyledItemDelegate):