mirror of
https://github.com/fergalmoran/picard.git
synced 2026-02-21 07:04:02 +00:00
PICARD-1606: Handle OptionsPage exceptions
Avoids Picard crashing if e.g. a plugin provides a broken OptionsPage implementation. This gives the user better feedback and eventually even allows user to recover from the situation.
This commit is contained in:
@@ -22,7 +22,10 @@ from PyQt5 import (
|
||||
QtWidgets,
|
||||
)
|
||||
|
||||
from picard import config
|
||||
from picard import (
|
||||
config,
|
||||
log,
|
||||
)
|
||||
from picard.const import PICARD_URLS
|
||||
from picard.util import (
|
||||
restore_method,
|
||||
@@ -115,8 +118,11 @@ class OptionsDialog(PicardDialog):
|
||||
|
||||
self.pages = []
|
||||
for Page in page_classes:
|
||||
page = Page(self.ui.pages_stack)
|
||||
self.pages.append(page)
|
||||
try:
|
||||
page = Page(self.ui.pages_stack)
|
||||
self.pages.append(page)
|
||||
except Exception:
|
||||
log.exception('Failed initializing options page %r', page)
|
||||
self.item_to_page = {}
|
||||
self.page_to_item = {}
|
||||
self.default_item = None
|
||||
@@ -137,7 +143,11 @@ class OptionsDialog(PicardDialog):
|
||||
self.finished.connect(self.saveWindowState)
|
||||
|
||||
for page in self.pages:
|
||||
page.load()
|
||||
try:
|
||||
page.load()
|
||||
except Exception:
|
||||
log.exception('Failed loading options page %r', page)
|
||||
self.disable_page(page.NAME)
|
||||
self.ui.pages_tree.setCurrentItem(self.default_item)
|
||||
|
||||
def switch_page(self):
|
||||
@@ -146,6 +156,10 @@ class OptionsDialog(PicardDialog):
|
||||
page = self.item_to_page[items[0]]
|
||||
self.ui.pages_stack.setCurrentWidget(page)
|
||||
|
||||
def disable_page(self, name):
|
||||
item = self.page_to_item[name]
|
||||
item.setDisabled(True)
|
||||
|
||||
def help(self):
|
||||
current_page = self.ui.pages_stack.currentWidget()
|
||||
url = "{}#{}".format(PICARD_URLS['doc_options'], current_page.NAME)
|
||||
@@ -156,13 +170,27 @@ class OptionsDialog(PicardDialog):
|
||||
try:
|
||||
page.check()
|
||||
except OptionsCheckError as e:
|
||||
self.ui.pages_tree.setCurrentItem(self.page_to_item[page.NAME])
|
||||
page.display_error(e)
|
||||
self._show_page_error(page, e)
|
||||
return
|
||||
except Exception as e:
|
||||
log.exception('Failed checking options page %r', page)
|
||||
self._show_page_error(page, e)
|
||||
return
|
||||
for page in self.pages:
|
||||
page.save()
|
||||
try:
|
||||
page.save()
|
||||
except Exception as e:
|
||||
log.exception('Failed saving options page %r', page)
|
||||
self._show_page_error(page, e)
|
||||
return
|
||||
super().accept()
|
||||
|
||||
def _show_page_error(self, page, error):
|
||||
if not isinstance(error, OptionsCheckError):
|
||||
error = OptionsCheckError(_('Unexpected error'), str(error))
|
||||
self.ui.pages_tree.setCurrentItem(self.page_to_item[page.NAME])
|
||||
page.display_error(error)
|
||||
|
||||
def saveWindowState(self):
|
||||
config.persist["options_splitter"] = self.ui.splitter.saveState()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user