Fix theme editing (Bug #594909 part 1)

bzr-revno: 938
This commit is contained in:
Jon Tibble 2010-07-13 19:32:29 +01:00
commit b5f667fe51
6 changed files with 171 additions and 48 deletions

View File

@ -269,8 +269,22 @@ class Plugin(QtCore.QObject):
if self.settings_tab: if self.settings_tab:
self.settingsForm.insertTab(self.settings_tab, self.weight) self.settingsForm.insertTab(self.settings_tab, self.weight)
def canDeleteTheme(self, theme): def usesTheme(self, theme):
""" """
Called to ask the plugin if a theme can be deleted Called to find out if a plugin is currently using a theme.
Returns True if the theme is being used, otherwise returns False.
""" """
return True return False
def renameTheme(self, oldTheme, newTheme):
"""
Renames a theme a plugin is using making the plugin use the new name.
``oldTheme``
The name of the theme the plugin should stop using.
``newTheme``
The new name the plugin should now use.
"""
pass

View File

@ -36,15 +36,21 @@ from amendthemedialog import Ui_AmendThemeDialog
log = logging.getLogger(u'AmendThemeForm') log = logging.getLogger(u'AmendThemeForm')
class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
"""
The :class:`AmendThemeForm` class provides the user interface to set up
new and edit existing themes.
"""
def __init__(self, parent): def __init__(self, parent):
"""
Initialise the theme editor user interface
"""
QtGui.QDialog.__init__(self, parent) QtGui.QDialog.__init__(self, parent)
self.thememanager = parent self.thememanager = parent
self.path = None self.path = None
self.theme = ThemeXML() self.theme = ThemeXML()
self.setupUi(self) self.setupUi(self)
#define signals # define signals
#Buttons # Buttons
QtCore.QObject.connect(self.Color1PushButton, QtCore.QObject.connect(self.Color1PushButton,
QtCore.SIGNAL(u'pressed()'), self.onColor1PushButtonClicked) QtCore.SIGNAL(u'pressed()'), self.onColor1PushButtonClicked)
QtCore.QObject.connect(self.Color2PushButton, QtCore.QObject.connect(self.Color2PushButton,
@ -60,7 +66,7 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
QtCore.SIGNAL(u'pressed()'), self.onShadowColorPushButtonClicked) QtCore.SIGNAL(u'pressed()'), self.onShadowColorPushButtonClicked)
QtCore.QObject.connect(self.ImageToolButton, QtCore.QObject.connect(self.ImageToolButton,
QtCore.SIGNAL(u'clicked()'), self.onImageToolButtonClicked) QtCore.SIGNAL(u'clicked()'), self.onImageToolButtonClicked)
#Combo boxes # Combo boxes
QtCore.QObject.connect(self.BackgroundComboBox, QtCore.QObject.connect(self.BackgroundComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onBackgroundComboBoxSelected) QtCore.SIGNAL(u'activated(int)'), self.onBackgroundComboBoxSelected)
QtCore.QObject.connect(self.BackgroundTypeComboBox, QtCore.QObject.connect(self.BackgroundTypeComboBox,
@ -82,16 +88,13 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
QtCore.SIGNAL(u'activated(int)'), self.onHorizontalComboBoxSelected) QtCore.SIGNAL(u'activated(int)'), self.onHorizontalComboBoxSelected)
QtCore.QObject.connect(self.VerticalComboBox, QtCore.QObject.connect(self.VerticalComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onVerticalComboBoxSelected) QtCore.SIGNAL(u'activated(int)'), self.onVerticalComboBoxSelected)
#Spin boxes # Spin boxes
QtCore.QObject.connect(self.FontMainSizeSpinBox, QtCore.QObject.connect(self.FontMainSizeSpinBox,
QtCore.SIGNAL(u'editingFinished()'), QtCore.SIGNAL(u'editingFinished()'),
self.onFontMainSizeSpinBoxChanged) self.onFontMainSizeSpinBoxChanged)
QtCore.QObject.connect(self.FontFooterSizeSpinBox, QtCore.QObject.connect(self.FontFooterSizeSpinBox,
QtCore.SIGNAL(u'editingFinished()'), QtCore.SIGNAL(u'editingFinished()'),
self.onFontFooterSizeSpinBoxChanged) self.onFontFooterSizeSpinBoxChanged)
QtCore.QObject.connect(self.FontMainDefaultCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onFontMainDefaultCheckBoxChanged)
QtCore.QObject.connect(self.FontMainXSpinBox, QtCore.QObject.connect(self.FontMainXSpinBox,
QtCore.SIGNAL(u'editingFinished()'), self.onFontMainXSpinBoxChanged) QtCore.SIGNAL(u'editingFinished()'), self.onFontMainXSpinBoxChanged)
QtCore.QObject.connect(self.FontMainYSpinBox, QtCore.QObject.connect(self.FontMainYSpinBox,
@ -108,9 +111,6 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
QtCore.QObject.connect(self.FontMainLineSpacingSpinBox, QtCore.QObject.connect(self.FontMainLineSpacingSpinBox,
QtCore.SIGNAL(u'editingFinished()'), QtCore.SIGNAL(u'editingFinished()'),
self.onFontMainLineSpacingSpinBoxChanged) self.onFontMainLineSpacingSpinBoxChanged)
QtCore.QObject.connect(self.FontFooterDefaultCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onFontFooterDefaultCheckBoxChanged)
QtCore.QObject.connect(self.FontFooterXSpinBox, QtCore.QObject.connect(self.FontFooterXSpinBox,
QtCore.SIGNAL(u'editingFinished()'), QtCore.SIGNAL(u'editingFinished()'),
self.onFontFooterXSpinBoxChanged) self.onFontFooterXSpinBoxChanged)
@ -123,16 +123,23 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
QtCore.QObject.connect(self.FontFooterHeightSpinBox, QtCore.QObject.connect(self.FontFooterHeightSpinBox,
QtCore.SIGNAL(u'editingFinished()'), QtCore.SIGNAL(u'editingFinished()'),
self.onFontFooterHeightSpinBoxChanged) self.onFontFooterHeightSpinBoxChanged)
QtCore.QObject.connect(self.OutlineCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'), self.onOutlineCheckBoxChanged)
QtCore.QObject.connect(self.ShadowSpinBox, QtCore.QObject.connect(self.ShadowSpinBox,
QtCore.SIGNAL(u'editingFinished()'), QtCore.SIGNAL(u'editingFinished()'),
self.onShadowSpinBoxChanged) self.onShadowSpinBoxChanged)
QtCore.QObject.connect(self.ShadowCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'), self.onShadowCheckBoxChanged)
QtCore.QObject.connect(self.OutlineSpinBox, QtCore.QObject.connect(self.OutlineSpinBox,
QtCore.SIGNAL(u'editingFinished()'), QtCore.SIGNAL(u'editingFinished()'),
self.onOutlineSpinBoxChanged) self.onOutlineSpinBoxChanged)
# CheckBoxes
QtCore.QObject.connect(self.FontMainDefaultCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onFontMainDefaultCheckBoxChanged)
QtCore.QObject.connect(self.FontFooterDefaultCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onFontFooterDefaultCheckBoxChanged)
QtCore.QObject.connect(self.OutlineCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'), self.onOutlineCheckBoxChanged)
QtCore.QObject.connect(self.ShadowCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'), self.onShadowCheckBoxChanged)
QtCore.QObject.connect(self.SlideTransitionCheckBox, QtCore.QObject.connect(self.SlideTransitionCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'), QtCore.SIGNAL(u'stateChanged(int)'),
self.onSlideTransitionCheckBoxChanged) self.onSlideTransitionCheckBoxChanged)

View File

@ -48,6 +48,7 @@ class ThemeManager(QtGui.QWidget):
QtGui.QWidget.__init__(self, parent) QtGui.QWidget.__init__(self, parent)
self.parent = parent self.parent = parent
self.settingsSection = u'themes' self.settingsSection = u'themes'
self.serviceComboBox = self.parent.ServiceManagerContents.ThemeComboBox
self.Layout = QtGui.QVBoxLayout(self) self.Layout = QtGui.QVBoxLayout(self)
self.Layout.setSpacing(0) self.Layout.setSpacing(0)
self.Layout.setMargin(0) self.Layout.setMargin(0)
@ -183,9 +184,13 @@ class ThemeManager(QtGui.QWidget):
Loads the settings for the theme that is to be edited and launches the Loads the settings for the theme that is to be edited and launches the
theme editing form so the user can make their changes. theme editing form so the user can make their changes.
""" """
self.editingDefault = False
if check_item_selected(self.ThemeListWidget, translate('ThemeManager', if check_item_selected(self.ThemeListWidget, translate('ThemeManager',
'You must select a theme to edit.')): 'You must select a theme to edit.')):
item = self.ThemeListWidget.currentItem() item = self.ThemeListWidget.currentItem()
themeName = unicode(item.text())
if themeName != unicode(item.data(QtCore.Qt.UserRole).toString()):
self.editingDefault = True
theme = self.getThemeData( theme = self.getThemeData(
unicode(item.data(QtCore.Qt.UserRole).toString())) unicode(item.data(QtCore.Qt.UserRole).toString()))
if theme.background_type == u'image': if theme.background_type == u'image':
@ -215,37 +220,44 @@ class ThemeManager(QtGui.QWidget):
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
else: else:
for plugin in self.parent.plugin_manager.plugins: for plugin in self.parent.plugin_manager.plugins:
if not plugin.canDeleteTheme(theme): if plugin.usesTheme(theme):
QtGui.QMessageBox.critical(self, QtGui.QMessageBox.critical(self,
translate('ThemeManager', 'Error'), translate('ThemeManager', 'Error'),
unicode(translate('ThemeManager', unicode(translate('ThemeManager',
'Theme %s is use in %s plugin.')) % \ 'Theme %s is use in %s plugin.')) % \
(theme, plugin.name)) (theme, plugin.name))
return return
if unicode(self.parent.ServiceManagerContents.ThemeComboBox \ if unicode(self.serviceComboBox.currentText()) == theme:
.currentText()) == theme:
QtGui.QMessageBox.critical(self, QtGui.QMessageBox.critical(self,
translate('ThemeManager', 'Error'), translate('ThemeManager', 'Error'),
unicode(translate('ThemeManager', unicode(translate('ThemeManager',
'Theme %s is use by the service manager.')) % theme) 'Theme %s is use by the service manager.')) % theme)
return return
self.themelist.remove(theme)
th = theme + u'.png'
row = self.ThemeListWidget.row(item) row = self.ThemeListWidget.row(item)
self.ThemeListWidget.takeItem(row) self.ThemeListWidget.takeItem(row)
try: self.deleteTheme(theme)
os.remove(os.path.join(self.path, th))
os.remove(os.path.join(self.thumbPath, th)) def deleteTheme(self, theme):
encoding = get_filesystem_encoding() """
shutil.rmtree( Delete a theme.
os.path.join(self.path, theme).encode(encoding))
except OSError: ``theme``
#if not present do not worry The theme to delete.
pass """
# As we do not reload the themes push out the change self.themelist.remove(theme)
# Reaload the list as the internal lists and events need th = theme + u'.png'
# to be triggered try:
self.pushThemes() os.remove(os.path.join(self.path, th))
os.remove(os.path.join(self.thumbPath, th))
encoding = get_filesystem_encoding()
shutil.rmtree(os.path.join(self.path, theme).encode(encoding))
except OSError:
#if not present do not worry
pass
# As we do not reload the themes push out the change
# Reaload the list as the internal lists and events need
# to be triggered
self.pushThemes()
def onExportTheme(self): def onExportTheme(self):
""" """
@ -535,16 +547,23 @@ class ThemeManager(QtGui.QWidget):
os.mkdir(os.path.join(self.path, name)) os.mkdir(os.path.join(self.path, name))
theme_file = os.path.join(theme_dir, name + u'.xml') theme_file = os.path.join(theme_dir, name + u'.xml')
log.debug(theme_file) log.debug(theme_file)
editedServiceTheme = False
result = QtGui.QMessageBox.Yes result = QtGui.QMessageBox.Yes
if self.saveThemeName != name: if self.saveThemeName != name:
if os.path.exists(theme_file): if os.path.exists(theme_file):
result = QtGui.QMessageBox.question(self, result = QtGui.QMessageBox.question(self,
translate('ThemeManager', 'Theme Exists'), translate('ThemeManager', 'Theme Exists'),
translate('ThemeManager', translate('ThemeManager', 'A theme with this name already '
'A theme with this name already exists. ' 'exists. Would you like to overwrite it?'),
'Would you like to overwrite it?'),
(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), (QtGui.QMessageBox.Yes | QtGui.QMessageBox.No),
QtGui.QMessageBox.No) QtGui.QMessageBox.No)
if self.saveThemeName != u'':
for plugin in self.parent.plugin_manager.plugins:
if plugin.usesTheme(self.saveThemeName):
plugin.renameTheme(self.saveThemeName, name)
if unicode(self.serviceComboBox.currentText()) == name:
editedServiceTheme = True
self.deleteTheme(self.saveThemeName)
if result == QtGui.QMessageBox.Yes: if result == QtGui.QMessageBox.Yes:
# Save the theme, overwriting the existing theme if necessary. # Save the theme, overwriting the existing theme if necessary.
if image_to and self.oldBackgroundImage and \ if image_to and self.oldBackgroundImage and \
@ -572,6 +591,26 @@ class ThemeManager(QtGui.QWidget):
log.exception(u'Failed to save theme image') log.exception(u'Failed to save theme image')
self.generateAndSaveImage(self.path, name, theme_xml) self.generateAndSaveImage(self.path, name, theme_xml)
self.loadThemes() self.loadThemes()
# Check if we need to set a new service theme
if editedServiceTheme:
newThemeIndex = self.serviceComboBox.findText(name)
if newThemeIndex != -1:
self.serviceComboBox.setCurrentIndex(newThemeIndex)
if self.editingDefault:
newThemeItem = self.ThemeListWidget.findItems(name,
QtCore.Qt.MatchExactly)[0]
newThemeIndex = self.ThemeListWidget.indexFromItem(
newThemeItem).row()
self.global_theme = unicode(
self.ThemeListWidget.item(newThemeIndex).text())
newName = unicode(translate('ThemeManager', '%s (default)')) % \
self.global_theme
self.ThemeListWidget.item(newThemeIndex).setText(newName)
QtCore.QSettings().setValue(
self.settingsSection + u'/global theme',
QtCore.QVariant(self.global_theme))
Receiver.send_message(u'theme_update_global', self.global_theme)
self.pushThemes()
else: else:
# Don't close the dialog - allow the user to change the name of # Don't close the dialog - allow the user to change the name of
# the theme or to cancel the theme dialog completely. # the theme or to cancel the theme dialog completely.

View File

@ -95,7 +95,26 @@ class BiblePlugin(Plugin):
'displayed on the screen during the service.') 'displayed on the screen during the service.')
return about_text return about_text
def canDeleteTheme(self, theme): def usesTheme(self, theme):
"""
Called to find out if the bible plugin is currently using a theme.
Returns True if the theme is being used, otherwise returns False.
"""
if self.settings_tab.bible_theme == theme: if self.settings_tab.bible_theme == theme:
return False return True
return True return False
def renameTheme(self, oldTheme, newTheme):
"""
Rename the theme the bible plugin is using making the plugin use the
new name.
``oldTheme``
The name of the theme the plugin should stop using. Unused for
this particular plugin.
``newTheme``
The new name the plugin should now use.
"""
self.settings_tab.bible_theme = newTheme

View File

@ -69,8 +69,30 @@ class CustomPlugin(Plugin):
'songs plugin.<br>') 'songs plugin.<br>')
return about_text return about_text
def canDeleteTheme(self, theme): def usesTheme(self, theme):
if not self.custommanager.get_all_objects_filtered(CustomSlide, """
Called to find out if the custom plugin is currently using a theme.
Returns True if the theme is being used, otherwise returns False.
"""
if self.custommanager.get_all_objects_filtered(CustomSlide,
CustomSlide.theme_name == theme): CustomSlide.theme_name == theme):
return True return True
return False return False
def renameTheme(self, oldTheme, newTheme):
"""
Renames a theme the custom plugin is using making the plugin use the
new name.
``oldTheme``
The name of the theme the plugin should stop using.
``newTheme``
The new name the plugin should now use.
"""
customsUsingTheme = self.custommanager.get_all_objects_filtered(
CustomSlide, CustomSlide.theme_name == oldTheme)
for custom in customsUsingTheme:
custom.theme_name = newTheme
self.custommanager.save_object(custom)

View File

@ -192,8 +192,30 @@ class SongsPlugin(Plugin):
'This plugin allows songs to be managed and displayed.') 'This plugin allows songs to be managed and displayed.')
return about_text return about_text
def canDeleteTheme(self, theme): def usesTheme(self, theme):
if not self.manager.get_all_objects_filtered(Song, """
Called to find out if the song plugin is currently using a theme.
Returns True if the theme is being used, otherwise returns False.
"""
if self.manager.get_all_objects_filtered(Song,
Song.theme_name == theme): Song.theme_name == theme):
return True return True
return False return False
def renameTheme(self, oldTheme, newTheme):
"""
Renames a theme the song plugin is using making the plugin use the new
name.
``oldTheme``
The name of the theme the plugin should stop using.
``newTheme``
The new name the plugin should now use.
"""
songsUsingTheme = self.manager.get_all_objects_filtered(Song,
Song.theme_name == oldTheme)
for song in songsUsingTheme:
song.theme_name = newTheme
self.custommanager.save_object(song)