Skip to content

Commit

Permalink
Merge pull request #24 from TheFriendlyCoder/settings
Browse files Browse the repository at this point in the history
Fixes #23 added edit support for settings
  • Loading branch information
TheFriendlyCoder committed Aug 3, 2020
2 parents 8fbe4eb + e15bc73 commit ff348de
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 11 deletions.
1 change: 0 additions & 1 deletion src/friendlypics2/dialogs/main_window.py
Expand Up @@ -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...")
Expand Down
89 changes: 79 additions & 10 deletions src/friendlypics2/dialogs/settings_dlg.py
Expand Up @@ -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 <https://github.com/pyside/Examples/blob/master/examples/itemviews/simpletreemodel/simpletreemodel.py>`__
"""
def __init__(self, data, parent=None):
"""
Args:
Expand All @@ -25,6 +29,15 @@ 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._item_data = (self._item_data[0], value)

@property
def child_items(self):
"""list (SettingsItem): list of children owned by this item"""
Expand Down Expand Up @@ -79,7 +92,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 <https://github.com/pyside/Examples/blob/master/examples/itemviews/simpletreemodel/simpletreemodel.py>`__
"""
def __init__(self, data):
"""
Args:
Expand All @@ -92,6 +109,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
Expand Down Expand Up @@ -144,16 +166,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 <https://doc.qt.io/qtforpython/overviews/model-view-programming.html#an-editable-model>`__
Args:
index (QModelIndex):
index of the app setting to modify
value (str):
new data value for the setting
role:
`ItemDataRole <https://doc.qt.io/qt-5/qt.html#ItemDataRole-enum>`__
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
Expand All @@ -167,7 +215,7 @@ def flags(self, index): # pylint: disable=no-self-use
if not index.isValid():
return Qt.NoItemFlags

return Qt.ItemIsEnabled | Qt.ItemIsSelectable
return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable

def headerData(self, section, orientation, role): # pylint: disable=invalid-name
"""Gets column header text for the view
Expand Down Expand Up @@ -288,14 +336,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()
5 changes: 5 additions & 0 deletions src/friendlypics2/misc/app_settings.py
Expand Up @@ -2,6 +2,7 @@
import logging
from pathlib import Path
import json
from copy import deepcopy

import yaml
from appdirs import user_config_dir
Expand Down Expand Up @@ -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"""
Expand Down

0 comments on commit ff348de

Please sign in to comment.