diff --git a/src/friendlypics2/dialogs/main_window.py b/src/friendlypics2/dialogs/main_window.py index 4286895..82ed5b5 100644 --- a/src/friendlypics2/dialogs/main_window.py +++ b/src/friendlypics2/dialogs/main_window.py @@ -21,7 +21,6 @@ def __init__(self): # Initialize app settings self._app_settings = AppSettings() - self._app_settings.pinterest_user = "kevinp@ca.ibm.com" # Initialize window self._log.debug("Initializing main window...") diff --git a/src/friendlypics2/dialogs/settings_dlg.py b/src/friendlypics2/dialogs/settings_dlg.py index 8d9b02d..6225bb5 100644 --- a/src/friendlypics2/dialogs/settings_dlg.py +++ b/src/friendlypics2/dialogs/settings_dlg.py @@ -7,7 +7,11 @@ class SettingsItem: - """Interface to a single application setting or group of application settings""" + """Interface to a single application setting or group of application settings + + Loosely based on example code found + `here `__ + """ def __init__(self, data, parent=None): """ Args: @@ -25,6 +29,16 @@ def __init__(self, data, parent=None): def __str__(self): return json.dumps(self._item_data, indent=4) + def set_data(self, value): + """Modifies the data value for this setting + + Args: + value (str): + new value for this setting + """ + self._log.debug(f"Changing {self._item_data[0]} from {self._item_data[1]} to {value}") + self._item_data = (self._item_data[0], value) + @property def child_items(self): """list (SettingsItem): list of children owned by this item""" @@ -79,7 +93,11 @@ def row(self): class AppSettingsModel(QAbstractItemModel): - """Interface for rendering application settings stored in a hierarchical format""" + """Interface for rendering application settings stored in a hierarchical format + + Loosely based on example code found + `here `__ + """ def __init__(self, data): """ Args: @@ -92,6 +110,11 @@ def __init__(self, data): self._root_item = SettingsItem(("Setting", "Value")) self._setup_model_data(self._settings.data, self._root_item) + @property + def root_item(self): + """SettingsItem: gets the root node of our settings tree""" + return self._root_item + def _setup_model_data(self, data, parent): """Helper method used to populate our model data @@ -144,16 +167,42 @@ def data(self, index, role): # pylint: disable=no-self-use data for the specified setting within the given context, or None if no data suitable for the given role can be found """ - if not index.isValid(): - return None - - if role != Qt.DisplayRole: + if not index.isValid() or role != Qt.DisplayRole: return None item = index.internalPointer() return item.data(index.column()) + def setData(self, index, value, role): # pylint: disable=invalid-name + """Modifies the value of a settings + + Loosely based on example code found + `here `__ + + Args: + index (QModelIndex): + index of the app setting to modify + value (str): + new data value for the setting + role: + `ItemDataRole `__ + of the role within the view where the data is being edited + + Returns: + bool: True if the data was successfully modified, False if not + """ + if not index.isValid() or role != Qt.EditRole: + return False + + item = index.internalPointer() + item.set_data(value) + + # resync the data in the view + self.dataChanged.emit(index, index) + + return True + def flags(self, index): # pylint: disable=no-self-use """gets bit-field describing how a given setting should be rendered @@ -166,8 +215,8 @@ def flags(self, index): # pylint: disable=no-self-use """ if not index.isValid(): return Qt.NoItemFlags - - return Qt.ItemIsEnabled | Qt.ItemIsSelectable + # return QAbstractItemModel.flags(index) | Qt.ItemIsEditable + return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable def headerData(self, section, orientation, role): # pylint: disable=invalid-name """Gets column header text for the view @@ -288,14 +337,35 @@ def _load_ui(self): model = AppSettingsModel(self._settings) self.settings_view.setModel(model) - self.settings_view.setWindowTitle("Simple Tree Model") - self.settings_view.show() # Center the about box on the parent window parent_geom = self.parent().geometry() self.move(parent_geom.center() - self.rect().center()) + def _load_data(self, item): + """helper method that dumps the raw data from the settings data model to a dictionary + + Args: + item(SettingsItem): + reference to the item to retrieve settings data from. Data will be generated + recursively for all children owned by the settings item. + + Returns: + dict: updated settings data loaded from the data model + """ + retval = dict() + for cur_child in item.child_items: + if cur_child.child_items: + temp_data = self._load_data(cur_child) + else: + temp_data = cur_child.data(1) + retval[cur_child.data(0)] = temp_data + return retval + @Slot() def _save_clicked(self): """Callback for when the user clicks the save button""" - self._log.debug("Saving") + new_data = self._load_data(self.settings_view.model().root_item) + self._settings.data = new_data + self._settings.save() + self.close() diff --git a/src/friendlypics2/misc/app_settings.py b/src/friendlypics2/misc/app_settings.py index aa23ff3..a8f86b7 100644 --- a/src/friendlypics2/misc/app_settings.py +++ b/src/friendlypics2/misc/app_settings.py @@ -2,6 +2,7 @@ import logging from pathlib import Path import json +from copy import deepcopy import yaml from appdirs import user_config_dir @@ -31,6 +32,10 @@ def data(self): Used exclusively for the settings dialog""" return self._data + @data.setter + def data(self, value): + self._data = deepcopy(value) + @property def path(self): """Location of the config file managed by this class"""