From ecebef09e66821cead3f030022b0434823e7a081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Carrillo?= Date: Wed, 10 Jul 2024 12:48:42 -0500 Subject: [PATCH] [ux] Use a combobox to edit sslmode setting --- pg_service_parser/conf/enums.py | 10 +++++ pg_service_parser/conf/service_settings.py | 5 ++- pg_service_parser/core/item_models.py | 14 +++++++ pg_service_parser/gui/dlg_pg_service.py | 2 + pg_service_parser/gui/item_delegates.py | 45 ++++++++++++++++++++++ 5 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 pg_service_parser/conf/enums.py create mode 100644 pg_service_parser/gui/item_delegates.py diff --git a/pg_service_parser/conf/enums.py b/pg_service_parser/conf/enums.py new file mode 100644 index 0000000..f44c624 --- /dev/null +++ b/pg_service_parser/conf/enums.py @@ -0,0 +1,10 @@ +from enum import Enum + + +class SslModeEnum(Enum): + DISABLE = "disable" + ALLOW = "allow" + PREFER = "prefer" + REQUIRE = "require" + VERIFY_CA = "verify-ca" + VERIFY_FULL = "verify-full" diff --git a/pg_service_parser/conf/service_settings.py b/pg_service_parser/conf/service_settings.py index ccf89d8..5e7eaa1 100644 --- a/pg_service_parser/conf/service_settings.py +++ b/pg_service_parser/conf/service_settings.py @@ -1,3 +1,5 @@ +from pg_service_parser.conf.enums import SslModeEnum + # Settings available for manual addition # See https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS SERVICE_SETTINGS = { @@ -10,8 +12,9 @@ "description": "Password to be used if the server demands password authentication.", }, "sslmode": { - "default": "", + "default": SslModeEnum.PREFER.value, "description": "This option determines whether or with what priority a secure SSL TCP/IP connection will be negotiated with the server.", + "values": SslModeEnum, }, "passfile": { "default": "", diff --git a/pg_service_parser/core/item_models.py b/pg_service_parser/core/item_models.py index 5de0b65..eb5aa75 100644 --- a/pg_service_parser/core/item_models.py +++ b/pg_service_parser/core/item_models.py @@ -1,6 +1,7 @@ from qgis.PyQt.QtCore import QAbstractTableModel, QModelIndex, Qt, pyqtSignal from qgis.PyQt.QtGui import QColorConstants, QFont +from pg_service_parser.conf.enums import SslModeEnum from pg_service_parser.conf.service_settings import SERVICE_SETTINGS @@ -8,6 +9,8 @@ class ServiceConfigModel(QAbstractTableModel): KEY_COL = 0 VALUE_COL = 1 + SSLMODE_KEY = "sslmode" + is_dirty_changed = pyqtSignal(bool) # Whether the model gets dirty or not def __init__(self, service_name: str, service_config: dict): @@ -85,6 +88,9 @@ def data(self, index, role=Qt.ItemDataRole.DisplayRole): or self.__model_data[key] != self.__original_data[key] ): return QColorConstants.DarkGreen + elif role == Qt.ItemDataRole.UserRole: + if index.column() == self.VALUE_COL and key == self.SSLMODE_KEY: + return {key: [e.value for e in SslModeEnum]} return None @@ -144,3 +150,11 @@ def invalid_settings(self): :return: List of invalid settings. """ return [k for k, v in self.__model_data.items() if v.strip() == ""] + + @staticmethod + def is_sslmode_edit_cell(index): + return ( + index.column() == ServiceConfigModel.VALUE_COL + and isinstance(index.data(Qt.ItemDataRole.UserRole), dict) + and ServiceConfigModel.SSLMODE_KEY in index.data(Qt.ItemDataRole.UserRole) + ) diff --git a/pg_service_parser/gui/dlg_pg_service.py b/pg_service_parser/gui/dlg_pg_service.py index d0eae50..35e1537 100644 --- a/pg_service_parser/gui/dlg_pg_service.py +++ b/pg_service_parser/gui/dlg_pg_service.py @@ -17,6 +17,7 @@ ) from pg_service_parser.gui.dlg_service_name import ServiceNameDialog 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 DIALOG_UI = get_ui_class("pg_service_dialog.ui") @@ -197,6 +198,7 @@ def __edit_service_changed(self, index): target_service, service_config(target_service, self.__conf_file_path) ) self.tblServiceConfig.setModel(self.__edit_model) + self.tblServiceConfig.setItemDelegate(ServiceConfigDelegate(self)) self.__edit_model.is_dirty_changed.connect(self.btnUpdateService.setEnabled) self.btnUpdateService.setDisabled(True) diff --git a/pg_service_parser/gui/item_delegates.py b/pg_service_parser/gui/item_delegates.py new file mode 100644 index 0000000..04767fd --- /dev/null +++ b/pg_service_parser/gui/item_delegates.py @@ -0,0 +1,45 @@ +# Adapted from +# https://github.com/xxyzz/WordDumb/blob/097dd6c1651fdc08b472e0bf639aec444b6e14ec/custom_lemmas.py#L398C1-L438C46 + +from qgis.PyQt.QtCore import Qt +from qgis.PyQt.QtWidgets import QComboBox, QStyledItemDelegate + +from pg_service_parser.core.item_models import ServiceConfigModel + + +class ServiceConfigDelegate(QStyledItemDelegate): + def __init__(self, parent): + super().__init__(parent) + + def createEditor(self, parent, option, index): + if ServiceConfigModel.is_sslmode_edit_cell(index): + options = list(index.data(Qt.ItemDataRole.UserRole).values())[0] + combo_box = QComboBox(parent) + if isinstance(options, list): + for value in options: + combo_box.addItem(value, value) + + combo_box.currentIndexChanged.connect(self.commit_and_close_editor) + + return combo_box + + return QStyledItemDelegate.createEditor(self, parent, option, index) + + def commit_and_close_editor(self): + editor = self.sender() + self.commitData.emit(editor) + self.closeEditor.emit(editor) + + def setEditorData(self, editor, index): + if ServiceConfigModel.is_sslmode_edit_cell(index): + value = index.data(Qt.ItemDataRole.DisplayRole) + editor.setCurrentText(value) + else: + QStyledItemDelegate.setEditorData(self, editor, index) + + def setModelData(self, editor, model, index): + if ServiceConfigModel.is_sslmode_edit_cell(index): + value = editor.currentData() + model.setData(index, value, Qt.ItemDataRole.EditRole) + else: + QStyledItemDelegate.setModelData(self, editor, model, index)