Skip to content

Commit

Permalink
[gui] Add tab for listing and managing (add/edit/remove) connections …
Browse files Browse the repository at this point in the history
…to a particular service; refactor ServiceNameDialog to also handle connection names
  • Loading branch information
gacarrillor committed Jun 10, 2024
1 parent d6f8ca2 commit 04c98c4
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 48 deletions.
13 changes: 8 additions & 5 deletions pg_service_parser/core/connection_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down
14 changes: 7 additions & 7 deletions pg_service_parser/core/service_connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
File renamed without changes.
42 changes: 42 additions & 0 deletions pg_service_parser/gui/dlg_new_name.py
Original file line number Diff line number Diff line change
@@ -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()
111 changes: 105 additions & 6 deletions pg_service_parser/gui/dlg_pg_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

from qgis.core import QgsApplication
from qgis.gui import QgsMessageBar
from qgis.PyQt.QtCore import 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,
Expand All @@ -15,13 +15,21 @@
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.utils import get_ui_class

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):
Expand Down Expand Up @@ -52,16 +60,21 @@ 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 ")
self.lblConfFile.setToolTip("")
self.txtConfFile.setVisible(True)
self.tabWidget.setEnabled(True)
self.btnCreateServiceFile.setVisible(False)
self.tblServiceConnections.horizontalHeader().setVisible(True)

self.radOverwrite.toggled.connect(self.__update_target_controls)
self.btnCopyService.clicked.connect(self.__copy_service)
Expand All @@ -71,9 +84,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.bar = QgsMessageBar()
Expand All @@ -82,11 +101,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
Expand Down Expand Up @@ -130,6 +149,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
Expand Down Expand Up @@ -170,6 +198,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):
Expand Down Expand Up @@ -252,3 +282,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)
21 changes: 0 additions & 21 deletions pg_service_parser/gui/dlg_service_name.py

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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>
Expand All @@ -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>
Expand Down Expand Up @@ -66,7 +66,7 @@
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>dlgServiceName</receiver>
<receiver>dlgNewName</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
Expand All @@ -82,7 +82,7 @@
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>dlgServiceName</receiver>
<receiver>dlgNewName</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
Expand Down
Loading

0 comments on commit 04c98c4

Please sign in to comment.