Skip to content

Commit

Permalink
Reduce duplicate code between the two configuration dialogs
Browse files Browse the repository at this point in the history
  • Loading branch information
s0600204 committed May 20, 2020
1 parent 46c3cc1 commit ec62b4b
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 210 deletions.
111 changes: 9 additions & 102 deletions lisp/ui/settings/app_configuration.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of Linux Show Player
#
# Copyright 2016 Francesco Ceruti <ceppofrancy@gmail.com>
# Copyright 2020 Francesco Ceruti <ceppofrancy@gmail.com>
#
# Linux Show Player is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand All @@ -15,127 +15,34 @@
# You should have received a copy of the GNU General Public License
# along with Linux Show Player. If not, see <http://www.gnu.org/licenses/>.

import logging
from collections import namedtuple

from PyQt5 import QtCore
from PyQt5.QtCore import QModelIndex
from PyQt5.QtWidgets import QVBoxLayout, QDialogButtonBox, QDialog

from lisp.core.dicttree import DictNode
from lisp.ui.settings.configuration_dialog import ConfigurationDialog
from lisp.ui.ui_utils import translate
from lisp.ui.widgets.pagestreewidget import PagesTreeModel, PagesTreeWidget

logger = logging.getLogger(__name__)

PageEntry = namedtuple("PageEntry", ("page", "config"))


class AppConfigurationDialog(QDialog):
class AppConfigurationDialog(ConfigurationDialog):
PagesRegistry = DictNode()

def __init__(self, **kwargs):
super().__init__(**kwargs)
self.setWindowTitle(translate("AppConfiguration", "LiSP preferences"))
self.setWindowModality(QtCore.Qt.WindowModal)
self.setMinimumSize(800, 510)
self.resize(800, 510)
self.setLayout(QVBoxLayout())

self.configurations = {}

self.model = PagesTreeModel(tr_context="SettingsPageName")
for page_node in AppConfigurationDialog.PagesRegistry.children:
self._populateModel(QModelIndex(), page_node)

self.mainPage = PagesTreeWidget(self.model)
self.mainPage.selectFirst()
self.layout().addWidget(self.mainPage)

self.dialogButtons = QDialogButtonBox(self)
self.dialogButtons.setStandardButtons(
QDialogButtonBox.Cancel
| QDialogButtonBox.Apply
| QDialogButtonBox.Ok
)
self.layout().addWidget(self.dialogButtons)

self.dialogButtons.button(QDialogButtonBox.Cancel).clicked.connect(
self.reject
)
self.dialogButtons.button(QDialogButtonBox.Apply).clicked.connect(
self.applySettings
)
self.dialogButtons.button(QDialogButtonBox.Ok).clicked.connect(
self.__onOk
)

def applySettings(self):
for conf, pages in self.configurations.items():
for page in pages:
conf.update(page.getSettings())

conf.write()

def _populateModel(self, model_parent, page_parent):
if page_parent.value is not None:
page_class = page_parent.value.page
config = page_parent.value.config
else:
page_class = None
config = None

try:
if page_class is None:
# The current node have no page, use the parent model-index
# as parent for it's children
model_index = model_parent
else:
page_instance = page_class()
page_instance.loadSettings(config)
model_index = self.model.addPage(
page_instance, parent=model_parent
)

# Keep track of configurations and corresponding pages
self.configurations.setdefault(config, []).append(page_instance)
except Exception:
if not isinstance(page_class, type):
page_name = "InvalidPage"
else:
page_name = getattr(page_class, "Name", page_class.__name__)

logger.warning(
translate(
"AppConfigurationWarning",
'Cannot load configuration page: "{}" ({})',
).format(page_name, page_parent.path()),
exc_info=True,
)
else:
for page_node in page_parent.children:
self._populateModel(model_index, page_node)

def __onOk(self):
self.applySettings()
self.accept()

@staticmethod
def registerSettingsPage(path, page, config):
def _getConfigFromPageEntry(page_parent):
return page_parent.value.config

@classmethod
def registerSettingsPage(cls, path, page, config):
"""
:param path: indicate the page "position": 'category.sub.key'
:type path: str
:type page: type
:type config: lisp.core.configuration.Configuration
"""
AppConfigurationDialog.PagesRegistry.set(
cls.PagesRegistry.set(
path, PageEntry(page=page, config=config)
)

@staticmethod
def unregisterSettingsPage(path):
"""
:param path: indicate the page "position": 'category.sub.key'
:type path: str
"""
AppConfigurationDialog.PagesRegistry.pop(path)
141 changes: 141 additions & 0 deletions lisp/ui/settings/configuration_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# This file is part of Linux Show Player
#
# Copyright 2020 Francesco Ceruti <ceppofrancy@gmail.com>
#
# Linux Show Player is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Linux Show Player is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Linux Show Player. If not, see <http://www.gnu.org/licenses/>.

import logging

from PyQt5 import QtCore
from PyQt5.QtCore import QModelIndex
from PyQt5.QtWidgets import QVBoxLayout, QDialogButtonBox, QDialog

from lisp.ui.ui_utils import translate
from lisp.ui.widgets.pagestreewidget import PagesTreeModel, PagesTreeWidget

logger = logging.getLogger(__name__)


class ConfigurationDialog(QDialog):
'''
Note for implementing subclasses of this:
1) Define a named tuple named "PageEntry" (not a class member)
2) Define a class member named "PagesRegistry" of type "DictNode"
3) Define a static method named "_getConfigFromPageEntry"
which returns the config from step (1)
'''

def __init__(self, **kwargs):
super().__init__(**kwargs)
self.setWindowModality(QtCore.Qt.WindowModal)
self.setMinimumSize(800, 510)
self.resize(800, 510)
self.setLayout(QVBoxLayout())

self.configurations = {}

self.model = PagesTreeModel(tr_context="SettingsPageName")
for page_node in self.__class__.PagesRegistry.children:
self._populateModel(QModelIndex(), page_node)

self.mainPage = PagesTreeWidget(self.model)
self.mainPage.selectFirst()
self.layout().addWidget(self.mainPage)

self.dialogButtons = QDialogButtonBox(self)
self.dialogButtons.setStandardButtons(
QDialogButtonBox.Cancel
| QDialogButtonBox.Apply
| QDialogButtonBox.Ok
)
self.layout().addWidget(self.dialogButtons)

self.dialogButtons.button(QDialogButtonBox.Cancel).clicked.connect(
self.reject
)
self.dialogButtons.button(QDialogButtonBox.Apply).clicked.connect(
self.applySettings
)
self.dialogButtons.button(QDialogButtonBox.Ok).clicked.connect(
self.__onOk
)

def applySettings(self):
for conf, pages in self.configurations.items():
for page in pages:
conf.update(page.getSettings())

conf.write()

def _populateModel(self, model_parent, page_parent):
if page_parent.value is not None:
page_class = page_parent.value.page
config = self._getConfigFromPageEntry(page_parent)
else:
page_class = None
config = None

try:
if page_class is None:
# The current node have no page, use the parent model-index
# as parent for it's children
model_index = model_parent
else:
page_instance = page_class()
page_instance.loadSettings(config)
model_index = self.model.addPage(
page_instance, parent=model_parent
)

# Keep track of configurations and corresponding pages
self.configurations.setdefault(config, []).append(page_instance)
except Exception:
if not isinstance(page_class, type):
page_name = "InvalidPage"
else:
page_name = getattr(page_class, "Name", page_class.__name__)

logger.warning(
translate(
"ConfigurationWarning",
'Cannot load configuration page: "{}" ({})',
).format(page_name, page_parent.path()),
exc_info=True,
)
else:
for page_node in page_parent.children:
self._populateModel(model_index, page_node)

def __onOk(self):
self.applySettings()
self.accept()

@staticmethod
def _getConfigFromPageEntry(page_parent):
'''This needs overridding by any subclass.'''
logger.critical(
translate(
"ConfigurationCritical",
"Need to implement the Static Method `_getConfigFromPageEntry`"
)
)
return None

@classmethod
def unregisterSettingsPage(cls, path):
"""
:param path: indicate the page "position": 'category.sub.key'
:type path: str
"""
cls.PagesRegistry.pop(path)
Loading

0 comments on commit ec62b4b

Please sign in to comment.