Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add remove service settings #31

Merged
merged 4 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions pg_service_parser/conf/service_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# See https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS
SERVICE_SETTINGS = {
"host": "localhost",
"port": "5432",
"dbname": "",
"user": "",
"password": "",
"passfile": "",
}
69 changes: 54 additions & 15 deletions pg_service_parser/core/item_models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from qgis.PyQt.QtCore import QAbstractTableModel, Qt, pyqtSignal
from qgis.PyQt.QtCore import QAbstractTableModel, QModelIndex, Qt, pyqtSignal
from qgis.PyQt.QtGui import QColorConstants, QFont


Expand All @@ -8,19 +8,43 @@ class ServiceConfigModel(QAbstractTableModel):

is_dirty_changed = pyqtSignal(bool) # Whether the model gets dirty or not

def __init__(self, service_name, service_config):
def __init__(self, service_name: str, service_config: dict):
super().__init__()
self.__service_name = service_name
self.__model_data = service_config
self.__original_data = service_config.copy()
self.__dirty = False

def rowCount(self, parent):
def rowCount(self, parent=QModelIndex()):
return len(self.__model_data)

def columnCount(self, parent):
def columnCount(self, parent=QModelIndex()):
return 2

def index_to_setting_key(self, index):
return list(self.__model_data.keys())[index.row()]

def add_settings(self, settings: dict):
self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount() + len(settings) - 1)
self.__model_data.update(settings)
self.__set_dirty_status(True)
self.endInsertRows()

if self.__model_data == self.__original_data:
self.__set_dirty_status(False)

def remove_setting(self, index: QModelIndex):
if not index.isValid():
return

self.beginRemoveRows(QModelIndex(), index.row(), index.row())
del self.__model_data[list(self.__model_data.keys())[index.row()]]
self.__set_dirty_status(True)
self.endRemoveRows()

if self.__model_data == self.__original_data:
self.__set_dirty_status(False)

def data(self, index, role=Qt.DisplayRole):
if not index.isValid():
return None
Expand All @@ -38,15 +62,18 @@ def data(self, index, role=Qt.DisplayRole):
font = QFont()
font.setBold(True)
return font
elif (
index.column() == self.VALUE_COL
and self.__model_data[key] != self.__original_data[key]
elif index.column() == self.VALUE_COL and (
key not in self.__original_data
or self.__model_data[key] != self.__original_data[key]
):
font = QFont()
font.setItalic(True)
return font
elif role == Qt.ForegroundRole and index.column() == self.VALUE_COL:
if self.__model_data[key] != self.__original_data[key]:
if (
key not in self.__original_data
or self.__model_data[key] != self.__original_data[key]
):
return QColorConstants.DarkGreen

return None
Expand All @@ -59,13 +86,11 @@ def setData(self, index, value, role=Qt.EditRole) -> bool:
if value != self.__model_data[key]:
self.__model_data[key] = value

if value != self.__original_data[key]:
self.__dirty = True
self.is_dirty_changed.emit(True)
if key not in self.__original_data or value != self.__original_data[key]:
self.__set_dirty_status(True)
else:
if self.__model_data == self.__original_data:
self.__dirty = False
self.is_dirty_changed.emit(False)
self.__set_dirty_status(False)

return True

Expand All @@ -84,6 +109,13 @@ def flags(self, idx):
def is_dirty(self):
return self.__dirty

def __set_dirty_status(self, status: bool):
self.__dirty = status
self.is_dirty_changed.emit(status)

def current_setting_keys(self) -> list[str]:
return list(self.__model_data.keys())

def service_config(self):
return self.__model_data.copy()

Expand All @@ -93,5 +125,12 @@ def service_name(self):
def set_not_dirty(self):
# Data saved in the provider
self.__original_data = self.__model_data.copy()
self.__dirty = False
self.is_dirty_changed.emit(False)
self.__set_dirty_status(False)

def invalid_settings(self):
"""
Validation for service entries.

:return: List of invalid settings.
"""
return [k for k, v in self.__model_data.items() if v.strip() == ""]
43 changes: 43 additions & 0 deletions pg_service_parser/gui/dlg_pg_service.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
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 pg_service_parser.conf.service_settings import SERVICE_SETTINGS
from pg_service_parser.core.item_models import ServiceConfigModel
from pg_service_parser.core.pg_service_parser_wrapper import (
conf_path,
Expand All @@ -10,6 +12,7 @@
service_names,
write_service,
)
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")
Expand All @@ -35,6 +38,8 @@ def __init__(self, parent):

self.__edit_model = None

self.btnAddSettings.setIcon(QgsApplication.getThemeIcon("/symbologyAdd.svg"))
self.btnRemoveSetting.setIcon(QgsApplication.getThemeIcon("/symbologyRemove.svg"))
self.txtConfFile.setText(str(conf_file_path))
self.lblWarning.setVisible(False)

Expand All @@ -43,6 +48,8 @@ def __init__(self, parent):
self.cboSourceService.currentIndexChanged.connect(self.__source_service_changed)
self.tabWidget.currentChanged.connect(self.__current_tab_changed)
self.cboEditService.currentIndexChanged.connect(self.__edit_service_changed)
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.__initialize_edit_services()
Expand Down Expand Up @@ -157,9 +164,45 @@ def __edit_service_changed(self, index):
self.__edit_model.is_dirty_changed.connect(self.btnUpdateService.setEnabled)
self.btnUpdateService.setDisabled(True)

@pyqtSlot()
def __add_settings_clicked(self):
dlg = ServiceSettingsDialog(self, self.__edit_model.current_setting_keys())
dlg.exec_()

if dlg.settings_to_add:
settings = {k: v for k, v in SERVICE_SETTINGS.items() if k in dlg.settings_to_add}
self.__edit_model.add_settings(settings)

@pyqtSlot()
def __remove_setting_clicked(self):
selected_indexes = self.tblServiceConfig.selectedIndexes()
if selected_indexes:
setting_key = self.__edit_model.index_to_setting_key(selected_indexes[0])
if (
QMessageBox.question(
self,
"Remove service setting",
f"Are you sure you want to remove the '{setting_key}' setting?",
QMessageBox.Yes | QMessageBox.No,
QMessageBox.No,
)
== QMessageBox.Yes
):
self.__edit_model.remove_setting(selected_indexes[0])

@pyqtSlot()
def __update_service_clicked(self):
if self.__edit_model and self.__edit_model.is_dirty():
invalid = self.__edit_model.invalid_settings()
if invalid:
self.bar.pushWarning(
"PG service",
"Settings '{}' have invalid values. Adjust them and try again.".format(
"', '".join(invalid)
),
)
return

target_service = self.cboEditService.currentText()
write_service(target_service, self.__edit_model.service_config())
self.bar.pushSuccess("PG service", f"PG service '{target_service}' updated!")
Expand Down
24 changes: 24 additions & 0 deletions pg_service_parser/gui/dlg_service_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from qgis.PyQt.QtCore import pyqtSlot
from qgis.PyQt.QtWidgets import QDialog

from pg_service_parser.conf.service_settings import SERVICE_SETTINGS
from pg_service_parser.utils import get_ui_class

DIALOG_UI = get_ui_class("service_settings_dialog.ui")


class ServiceSettingsDialog(QDialog, DIALOG_UI):

def __init__(self, parent, settings_to_hide: list[str]):
QDialog.__init__(self, parent)
self.setupUi(self)

self.buttonBox.accepted.connect(self.__accepted)

settings = set(SERVICE_SETTINGS.keys()) - set(settings_to_hide)
self.lstSettings.addItems(settings)
self.settings_to_add = []

@pyqtSlot()
def __accepted(self):
self.settings_to_add = [item.text() for item in self.lstSettings.selectedItems()]
123 changes: 86 additions & 37 deletions pg_service_parser/ui/pg_service_dialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -81,42 +81,8 @@
<attribute name="title">
<string>Edit</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="lblEditService">
<property name="text">
<string>Edit service</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cboEditService">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<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>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<widget class="QTableView" name="tblServiceConfig">
<property name="editTriggers">
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
Expand Down Expand Up @@ -144,7 +110,56 @@
</attribute>
</widget>
</item>
<item>
<item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="btnAddSettings">
<property name="maximumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>Add settings to current service</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnRemoveSetting">
<property name="maximumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>Remove setting from current service</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<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>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer_2">
Expand All @@ -168,6 +183,40 @@
</item>
</layout>
</item>
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="lblEditService">
<property name="text">
<string>Edit service</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cboEditService">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<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>
</layout>
</widget>
<widget class="QWidget" name="tabCopy">
Expand Down
Loading