forked from openlp/openlp
Merged from trunk
This commit is contained in:
commit
76a731c725
@ -174,6 +174,8 @@ def resize_image(image, width, height):
|
|||||||
"""
|
"""
|
||||||
preview = QtGui.QImage(image)
|
preview = QtGui.QImage(image)
|
||||||
if not preview.isNull():
|
if not preview.isNull():
|
||||||
|
if preview.width() == width and preview.height == height:
|
||||||
|
return preview
|
||||||
preview = preview.scaled(width, height, QtCore.Qt.KeepAspectRatio,
|
preview = preview.scaled(width, height, QtCore.Qt.KeepAspectRatio,
|
||||||
QtCore.Qt.SmoothTransformation)
|
QtCore.Qt.SmoothTransformation)
|
||||||
realw = preview.width()
|
realw = preview.width()
|
||||||
|
@ -323,9 +323,15 @@ class MediaManagerItem(QtGui.QWidget):
|
|||||||
translate('MediaManagerItem',
|
translate('MediaManagerItem',
|
||||||
'&Add to selected Service Item'),
|
'&Add to selected Service Item'),
|
||||||
self.onAddEditClick))
|
self.onAddEditClick))
|
||||||
QtCore.QObject.connect(
|
if QtCore.QSettings().value(u'advanced/double click live',
|
||||||
self.listView, QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
|
QtCore.QVariant(False)).toBool():
|
||||||
self.onPreviewClick)
|
QtCore.QObject.connect(self.listView,
|
||||||
|
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
|
||||||
|
self.onLiveClick)
|
||||||
|
else:
|
||||||
|
QtCore.QObject.connect(self.listView,
|
||||||
|
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
|
||||||
|
self.onPreviewClick)
|
||||||
|
|
||||||
def initialise(self):
|
def initialise(self):
|
||||||
"""
|
"""
|
||||||
@ -379,14 +385,17 @@ class MediaManagerItem(QtGui.QWidget):
|
|||||||
"""
|
"""
|
||||||
Validates to see if the file still exists or thumbnail is up to date
|
Validates to see if the file still exists or thumbnail is up to date
|
||||||
"""
|
"""
|
||||||
if os.path.exists(file):
|
if not os.path.exists(file):
|
||||||
|
return False
|
||||||
|
if os.path.exists(thumb):
|
||||||
filedate = os.stat(file).st_mtime
|
filedate = os.stat(file).st_mtime
|
||||||
thumbdate = os.stat(thumb).st_mtime
|
thumbdate = os.stat(thumb).st_mtime
|
||||||
#if file updated rebuild icon
|
#if file updated rebuild icon
|
||||||
if filedate > thumbdate:
|
if filedate > thumbdate:
|
||||||
self.iconFromFile(file, thumb)
|
self.iconFromFile(file, thumb)
|
||||||
return True
|
else:
|
||||||
return False
|
self.iconFromFile(file, thumb)
|
||||||
|
return True
|
||||||
|
|
||||||
def iconFromFile(self, file, thumb):
|
def iconFromFile(self, file, thumb):
|
||||||
"""
|
"""
|
||||||
@ -521,7 +530,7 @@ class MediaManagerItem(QtGui.QWidget):
|
|||||||
if self.serviceItemIconName:
|
if self.serviceItemIconName:
|
||||||
service_item.add_icon(self.serviceItemIconName)
|
service_item.add_icon(self.serviceItemIconName)
|
||||||
else:
|
else:
|
||||||
service_item.add_icon(self.parent.icon)
|
service_item.add_icon(self.parent.icon_path)
|
||||||
if self.generateSlideData(service_item, item):
|
if self.generateSlideData(service_item, item):
|
||||||
return service_item
|
return service_item
|
||||||
else:
|
else:
|
||||||
|
@ -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
|
||||||
|
@ -117,8 +117,7 @@ class ServiceItem(object):
|
|||||||
service item in the service manager.
|
service item in the service manager.
|
||||||
|
|
||||||
``icon``
|
``icon``
|
||||||
An instance of QIcon or a string to an icon in the resource or on
|
A string to an icon in the resources or on disk.
|
||||||
disk.
|
|
||||||
"""
|
"""
|
||||||
self.icon = icon
|
self.icon = icon
|
||||||
self.iconic_representation = build_icon(icon)
|
self.iconic_representation = build_icon(icon)
|
||||||
|
@ -49,6 +49,7 @@ from splashscreen import SplashScreen
|
|||||||
from displaytab import DisplayTab
|
from displaytab import DisplayTab
|
||||||
from generaltab import GeneralTab
|
from generaltab import GeneralTab
|
||||||
from themestab import ThemesTab
|
from themestab import ThemesTab
|
||||||
|
from advancedtab import AdvancedTab
|
||||||
from aboutform import AboutForm
|
from aboutform import AboutForm
|
||||||
from pluginform import PluginForm
|
from pluginform import PluginForm
|
||||||
from settingsform import SettingsForm
|
from settingsform import SettingsForm
|
||||||
|
190
openlp/core/ui/advancedtab.py
Normal file
190
openlp/core/ui/advancedtab.py
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# OpenLP - Open Source Lyrics Projection #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# Copyright (c) 2008-2010 Raoul Snyman #
|
||||||
|
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
|
||||||
|
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
|
||||||
|
# Thompson, Jon Tibble, Carsten Tinggaard #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# This program 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; version 2 of the License. #
|
||||||
|
# #
|
||||||
|
# This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
|
###############################################################################
|
||||||
|
"""
|
||||||
|
The :mod:`advancedtab` provides an advanced settings facility.
|
||||||
|
"""
|
||||||
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
|
from openlp.core.lib import SettingsTab, translate
|
||||||
|
|
||||||
|
class AdvancedTab(SettingsTab):
|
||||||
|
"""
|
||||||
|
The :class:`AdvancedTab` manages the advanced settings tab including the UI
|
||||||
|
and the loading and saving of the displayed settings.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
Initialise the settings tab
|
||||||
|
"""
|
||||||
|
SettingsTab.__init__(self, u'Advanced')
|
||||||
|
|
||||||
|
def setupUi(self):
|
||||||
|
"""
|
||||||
|
Configure the UI elements for the tab.
|
||||||
|
"""
|
||||||
|
self.setObjectName(u'AdvancedTab')
|
||||||
|
self.tabTitleVisible = translate('AdvancedTab', 'Advanced')
|
||||||
|
self.advancedTabLayout = QtGui.QHBoxLayout(self)
|
||||||
|
self.advancedTabLayout.setSpacing(8)
|
||||||
|
self.advancedTabLayout.setMargin(8)
|
||||||
|
self.leftWidget = QtGui.QWidget(self)
|
||||||
|
self.leftLayout = QtGui.QVBoxLayout(self.leftWidget)
|
||||||
|
self.leftLayout.setSpacing(8)
|
||||||
|
self.leftLayout.setMargin(0)
|
||||||
|
self.uiGroupBox = QtGui.QGroupBox(self.leftWidget)
|
||||||
|
self.uiGroupBox.setObjectName(u'uiGroupBox')
|
||||||
|
self.uiLayout = QtGui.QVBoxLayout(self.uiGroupBox)
|
||||||
|
self.uiLayout.setSpacing(8)
|
||||||
|
self.uiLayout.setMargin(6)
|
||||||
|
self.uiLayout.setObjectName(u'uiLayout')
|
||||||
|
self.recentLayout = QtGui.QHBoxLayout()
|
||||||
|
self.recentLayout.setSpacing(8)
|
||||||
|
self.recentLayout.setMargin(0)
|
||||||
|
self.recentLayout.setObjectName(u'recentLayout')
|
||||||
|
self.recentLabel = QtGui.QLabel(self.uiGroupBox)
|
||||||
|
self.recentLabel.setObjectName(u'recentLabel')
|
||||||
|
self.recentLayout.addWidget(self.recentLabel)
|
||||||
|
self.recentSpinBox = QtGui.QSpinBox(self.uiGroupBox)
|
||||||
|
self.recentSpinBox.setObjectName(u'recentSpinBox')
|
||||||
|
self.recentSpinBox.setMinimum(0)
|
||||||
|
self.recentLayout.addWidget(self.recentSpinBox)
|
||||||
|
self.recentSpacer = QtGui.QSpacerItem(50, 20,
|
||||||
|
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||||
|
self.recentLayout.addItem(self.recentSpacer)
|
||||||
|
self.uiLayout.addLayout(self.recentLayout)
|
||||||
|
self.mediaPluginCheckBox = QtGui.QCheckBox(self.uiGroupBox)
|
||||||
|
self.mediaPluginCheckBox.setObjectName(u'mediaPluginCheckBox')
|
||||||
|
self.uiLayout.addWidget(self.mediaPluginCheckBox)
|
||||||
|
self.doubleClickLiveCheckBox = QtGui.QCheckBox(self.uiGroupBox)
|
||||||
|
self.doubleClickLiveCheckBox.setObjectName(u'doubleClickLiveCheckBox')
|
||||||
|
self.uiLayout.addWidget(self.doubleClickLiveCheckBox)
|
||||||
|
self.leftLayout.addWidget(self.uiGroupBox)
|
||||||
|
# self.sharedDirGroupBox = QtGui.QGroupBox(self.leftWidget)
|
||||||
|
# self.sharedDirGroupBox.setObjectName(u'sharedDirGroupBox')
|
||||||
|
# self.sharedDirGroupBox.setGeometry(QtCore.QRect(0, 65, 500, 85))
|
||||||
|
# self.sharedDirGroupBox.setMaximumSize(QtCore.QSize(500, 85))
|
||||||
|
# self.sharedDirLayout = QtGui.QVBoxLayout(self.sharedDirGroupBox)
|
||||||
|
# self.sharedDirLayout.setSpacing(8)
|
||||||
|
# self.sharedDirLayout.setMargin(8)
|
||||||
|
# self.sharedCheckBox = QtGui.QCheckBox(self.sharedDirGroupBox)
|
||||||
|
# self.sharedCheckBox.setObjectName(u'sharedCheckBox')
|
||||||
|
# self.sharedDirLayout.addWidget(self.sharedCheckBox)
|
||||||
|
# self.sharedSubLayout = QtGui.QHBoxLayout()
|
||||||
|
# self.sharedSubLayout.setSpacing(8)
|
||||||
|
# self.sharedSubLayout.setMargin(0)
|
||||||
|
# self.sharedLabel = QtGui.QLabel(self.sharedDirGroupBox)
|
||||||
|
# self.sharedLabel.setObjectName(u'sharedLabel')
|
||||||
|
# self.sharedSubLayout.addWidget(self.sharedLabel)
|
||||||
|
# self.sharedLineEdit = QtGui.QLineEdit(self.sharedDirGroupBox)
|
||||||
|
# self.sharedLineEdit.setObjectName(u'sharedLineEdit')
|
||||||
|
# self.sharedSubLayout.addWidget(self.sharedLineEdit)
|
||||||
|
# self.sharedPushButton = QtGui.QPushButton(self.sharedDirGroupBox)
|
||||||
|
# self.sharedPushButton.setObjectName(u'sharedPushButton')
|
||||||
|
# self.sharedSubLayout.addWidget(self.sharedPushButton)
|
||||||
|
# self.sharedDirLayout.addLayout(self.sharedSubLayout)
|
||||||
|
# self.leftLayout.addWidget(self.sharedDirGroupBox)
|
||||||
|
self.leftSpacer = QtGui.QSpacerItem(20, 40,
|
||||||
|
QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||||
|
self.leftLayout.addItem(self.leftSpacer)
|
||||||
|
self.advancedTabLayout.addWidget(self.leftWidget)
|
||||||
|
self.rightWidget = QtGui.QWidget(self)
|
||||||
|
self.rightLayout = QtGui.QVBoxLayout(self.rightWidget)
|
||||||
|
self.rightLayout.setSpacing(8)
|
||||||
|
self.rightLayout.setMargin(0)
|
||||||
|
# self.databaseGroupBox = QtGui.QGroupBox(self.rightWidget)
|
||||||
|
# self.databaseGroupBox.setObjectName(u'databaseGroupBox')
|
||||||
|
# self.databaseGroupBox.setEnabled(False)
|
||||||
|
# self.databaseLayout = QtGui.QVBoxLayout(self.databaseGroupBox)
|
||||||
|
# self.databaseLayout.setSpacing(8)
|
||||||
|
# self.databaseLayout.setMargin(8)
|
||||||
|
# self.rightLayout.addWidget(self.databaseGroupBox)
|
||||||
|
self.rightSpacer = QtGui.QSpacerItem(20, 40,
|
||||||
|
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
||||||
|
self.rightLayout.addItem(self.rightSpacer)
|
||||||
|
self.advancedTabLayout.addWidget(self.rightWidget)
|
||||||
|
# QtCore.QObject.connect(self.sharedCheckBox,
|
||||||
|
# QtCore.SIGNAL(u'stateChanged(int)'), self.onSharedCheckBoxChanged)
|
||||||
|
|
||||||
|
def retranslateUi(self):
|
||||||
|
"""
|
||||||
|
Setup the interface translation strings.
|
||||||
|
"""
|
||||||
|
self.uiGroupBox.setTitle(translate('AdvancedTab', 'UI Settings'))
|
||||||
|
self.recentLabel.setText(
|
||||||
|
translate('AdvancedTab', 'Number of recent files to display:'))
|
||||||
|
self.mediaPluginCheckBox.setText(translate('AdvancedTab',
|
||||||
|
'Save currently selected media manager plugin'))
|
||||||
|
self.doubleClickLiveCheckBox.setText(translate('AdvancedTab',
|
||||||
|
'Double-click to send items straight to live (requires restart)'))
|
||||||
|
# self.sharedDirGroupBox.setTitle(
|
||||||
|
# translate('AdvancedTab', 'Central Data Store'))
|
||||||
|
# self.sharedCheckBox.setText(
|
||||||
|
# translate('AdvancedTab', 'Enable a shared data location'))
|
||||||
|
# self.sharedLabel.setText(translate('AdvancedTab', 'Store location:'))
|
||||||
|
# self.sharedPushButton.setText(translate('AdvancedTab', 'Browse...'))
|
||||||
|
# self.databaseGroupBox.setTitle(translate('AdvancedTab', 'Databases'))
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
"""
|
||||||
|
Load settings from disk.
|
||||||
|
"""
|
||||||
|
settings = QtCore.QSettings()
|
||||||
|
settings.beginGroup(self.settingsSection)
|
||||||
|
# The max recent files value does not have an interface and so never
|
||||||
|
# gets actually stored in the settings therefore the default value of
|
||||||
|
# 20 will always be used.
|
||||||
|
self.recentSpinBox.setMaximum(QtCore.QSettings().value(
|
||||||
|
u'max recent files', QtCore.QVariant(20)).toInt()[0])
|
||||||
|
self.recentSpinBox.setValue(settings.value(u'recent file count',
|
||||||
|
QtCore.QVariant(4)).toInt()[0])
|
||||||
|
self.mediaPluginCheckBox.setChecked(
|
||||||
|
settings.value(u'save current plugin',
|
||||||
|
QtCore.QVariant(False)).toBool())
|
||||||
|
self.doubleClickLiveCheckBox.setChecked(
|
||||||
|
settings.value(u'double click live',
|
||||||
|
QtCore.QVariant(False)).toBool())
|
||||||
|
settings.endGroup()
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
"""
|
||||||
|
Save settings to disk.
|
||||||
|
"""
|
||||||
|
settings = QtCore.QSettings()
|
||||||
|
settings.beginGroup(self.settingsSection)
|
||||||
|
settings.setValue(u'recent file count',
|
||||||
|
QtCore.QVariant(self.recentSpinBox.value()))
|
||||||
|
settings.setValue(u'save current plugin',
|
||||||
|
QtCore.QVariant(self.mediaPluginCheckBox.isChecked()))
|
||||||
|
settings.setValue(u'double click live',
|
||||||
|
QtCore.QVariant(self.doubleClickLiveCheckBox.isChecked()))
|
||||||
|
settings.endGroup()
|
||||||
|
|
||||||
|
def onSharedCheckBoxChanged(self, checked):
|
||||||
|
"""
|
||||||
|
Enables the widgets to allow a shared data location
|
||||||
|
"""
|
||||||
|
self.sharedLabel.setEnabled(checked)
|
||||||
|
self.sharedTextEdit.setEnabled(checked)
|
||||||
|
self.sharedPushButton.setEnabled(checked)
|
@ -130,9 +130,9 @@ class Ui_AmendThemeDialog(object):
|
|||||||
self.ImageLineEdit.setObjectName(u'ImageLineEdit')
|
self.ImageLineEdit.setObjectName(u'ImageLineEdit')
|
||||||
self.horizontalLayout_2.addWidget(self.ImageLineEdit)
|
self.horizontalLayout_2.addWidget(self.ImageLineEdit)
|
||||||
self.ImageToolButton = QtGui.QToolButton(self.ImageFilenameWidget)
|
self.ImageToolButton = QtGui.QToolButton(self.ImageFilenameWidget)
|
||||||
icon1 = build_icon(u':/general/general_open.png')
|
self.ImageToolButton.setIcon(build_icon(u':/general/general_open.png'))
|
||||||
self.ImageToolButton.setIcon(icon1)
|
|
||||||
self.ImageToolButton.setObjectName(u'ImageToolButton')
|
self.ImageToolButton.setObjectName(u'ImageToolButton')
|
||||||
|
self.ImageToolButton.setAutoRaise(True)
|
||||||
self.horizontalLayout_2.addWidget(self.ImageToolButton)
|
self.horizontalLayout_2.addWidget(self.ImageToolButton)
|
||||||
self.BackgroundLayout.setWidget(4, QtGui.QFormLayout.FieldRole,
|
self.BackgroundLayout.setWidget(4, QtGui.QFormLayout.FieldRole,
|
||||||
self.ImageFilenameWidget)
|
self.ImageFilenameWidget)
|
||||||
|
@ -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,
|
||||||
@ -59,8 +65,8 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
|
|||||||
QtCore.QObject.connect(self.ShadowColorPushButton,
|
QtCore.QObject.connect(self.ShadowColorPushButton,
|
||||||
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'pressed()'), 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)
|
||||||
|
@ -44,10 +44,12 @@ class DisplayTab(SettingsTab):
|
|||||||
"""
|
"""
|
||||||
self.tabTitleVisible = translate('DisplayTab', 'Displays')
|
self.tabTitleVisible = translate('DisplayTab', 'Displays')
|
||||||
self.layoutWidget = QtGui.QWidget(self)
|
self.layoutWidget = QtGui.QWidget(self)
|
||||||
self.layoutWidget.setGeometry(QtCore.QRect(0, 40, 241, 79))
|
|
||||||
self.layoutWidget.setObjectName(u'layoutWidget')
|
self.layoutWidget.setObjectName(u'layoutWidget')
|
||||||
self.verticalLayout = QtGui.QVBoxLayout(self.layoutWidget)
|
self.verticalLayout = QtGui.QVBoxLayout(self.layoutWidget)
|
||||||
self.verticalLayout.setObjectName(u'verticalLayout')
|
self.verticalLayout.setObjectName(u'verticalLayout')
|
||||||
|
self.OverrideCheckBox = QtGui.QCheckBox(self.layoutWidget)
|
||||||
|
self.OverrideCheckBox.setObjectName(u'OverrideCheckBox')
|
||||||
|
self.verticalLayout.addWidget(self.OverrideCheckBox)
|
||||||
self.CurrentGroupBox = QtGui.QGroupBox(self.layoutWidget)
|
self.CurrentGroupBox = QtGui.QGroupBox(self.layoutWidget)
|
||||||
self.CurrentGroupBox.setObjectName(u'CurrentGroupBox')
|
self.CurrentGroupBox.setObjectName(u'CurrentGroupBox')
|
||||||
self.horizontalLayout = QtGui.QHBoxLayout(self.CurrentGroupBox)
|
self.horizontalLayout = QtGui.QHBoxLayout(self.CurrentGroupBox)
|
||||||
@ -153,9 +155,7 @@ class DisplayTab(SettingsTab):
|
|||||||
self.WidthEdit.setObjectName(u'WidthEdit')
|
self.WidthEdit.setObjectName(u'WidthEdit')
|
||||||
self.verticalLayout_5.addWidget(self.WidthEdit)
|
self.verticalLayout_5.addWidget(self.WidthEdit)
|
||||||
self.horizontalLayout_2.addLayout(self.verticalLayout_5)
|
self.horizontalLayout_2.addLayout(self.verticalLayout_5)
|
||||||
self.OverrideCheckBox = QtGui.QCheckBox(self)
|
self.verticalLayout.addWidget(self.CurrentGroupBox_2)
|
||||||
self.OverrideCheckBox.setGeometry(QtCore.QRect(0, 10, 191, 23))
|
|
||||||
self.OverrideCheckBox.setObjectName(u'OverrideCheckBox')
|
|
||||||
QtCore.QMetaObject.connectSlotsByName(self)
|
QtCore.QMetaObject.connectSlotsByName(self)
|
||||||
QtCore.QObject.connect(self.OverrideCheckBox,
|
QtCore.QObject.connect(self.OverrideCheckBox,
|
||||||
QtCore.SIGNAL(u'stateChanged(int)'), self.onOverrideCheckBoxChanged)
|
QtCore.SIGNAL(u'stateChanged(int)'), self.onOverrideCheckBoxChanged)
|
||||||
|
@ -469,7 +469,8 @@ class Ui_MainWindow(object):
|
|||||||
'&Plugin List'))
|
'&Plugin List'))
|
||||||
self.SettingsPluginListItem.setStatusTip(
|
self.SettingsPluginListItem.setStatusTip(
|
||||||
translate('MainWindow', 'List the Plugins'))
|
translate('MainWindow', 'List the Plugins'))
|
||||||
self.SettingsPluginListItem.setShortcut(translate('MainWindow', 'Alt+F7'))
|
self.SettingsPluginListItem.setShortcut(
|
||||||
|
translate('MainWindow', 'Alt+F7'))
|
||||||
self.HelpDocumentationItem.setText(
|
self.HelpDocumentationItem.setText(
|
||||||
translate('MainWindow', '&User Guide'))
|
translate('MainWindow', '&User Guide'))
|
||||||
self.HelpAboutItem.setText(translate('MainWindow', '&About'))
|
self.HelpAboutItem.setText(translate('MainWindow', '&About'))
|
||||||
@ -657,6 +658,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
log.info(u'Load Themes')
|
log.info(u'Load Themes')
|
||||||
self.ThemeManagerContents.loadThemes()
|
self.ThemeManagerContents.loadThemes()
|
||||||
log.info(u'Load data from Settings')
|
log.info(u'Load data from Settings')
|
||||||
|
if QtCore.QSettings().value(u'advanced/save current plugin',
|
||||||
|
QtCore.QVariant(False)).toBool():
|
||||||
|
savedPlugin = QtCore.QSettings().value(
|
||||||
|
u'advanced/current media plugin', QtCore.QVariant()).toInt()[0]
|
||||||
|
if savedPlugin != -1:
|
||||||
|
self.MediaToolBox.setCurrentIndex(savedPlugin)
|
||||||
self.settingsForm.postSetUp()
|
self.settingsForm.postSetUp()
|
||||||
|
|
||||||
def setAutoLanguage(self, value):
|
def setAutoLanguage(self, value):
|
||||||
@ -819,6 +826,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
"""
|
"""
|
||||||
# Clean temporary files used by services
|
# Clean temporary files used by services
|
||||||
self.ServiceManagerContents.cleanUp()
|
self.ServiceManagerContents.cleanUp()
|
||||||
|
if QtCore.QSettings().value(u'advanced/save current plugin',
|
||||||
|
QtCore.QVariant(False)).toBool():
|
||||||
|
QtCore.QSettings().setValue(u'advanced/current media plugin',
|
||||||
|
QtCore.QVariant(self.MediaToolBox.currentIndex()))
|
||||||
# Call the cleanup method to shutdown plugins.
|
# Call the cleanup method to shutdown plugins.
|
||||||
log.info(u'cleanup plugins')
|
log.info(u'cleanup plugins')
|
||||||
self.plugin_manager.finalise_plugins()
|
self.plugin_manager.finalise_plugins()
|
||||||
@ -897,6 +908,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
self.ViewLivePanel.setChecked(visible)
|
self.ViewLivePanel.setChecked(visible)
|
||||||
|
|
||||||
def loadSettings(self):
|
def loadSettings(self):
|
||||||
|
"""
|
||||||
|
Load the main window settings.
|
||||||
|
"""
|
||||||
log.debug(u'Loading QSettings')
|
log.debug(u'Loading QSettings')
|
||||||
settings = QtCore.QSettings()
|
settings = QtCore.QSettings()
|
||||||
settings.beginGroup(self.generalSettingsSection)
|
settings.beginGroup(self.generalSettingsSection)
|
||||||
@ -911,6 +925,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
|
|
||||||
def saveSettings(self):
|
def saveSettings(self):
|
||||||
|
"""
|
||||||
|
Save the main window settings.
|
||||||
|
"""
|
||||||
log.debug(u'Saving QSettings')
|
log.debug(u'Saving QSettings')
|
||||||
settings = QtCore.QSettings()
|
settings = QtCore.QSettings()
|
||||||
settings.beginGroup(self.generalSettingsSection)
|
settings.beginGroup(self.generalSettingsSection)
|
||||||
@ -928,15 +945,19 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
|
|
||||||
def updateFileMenu(self):
|
def updateFileMenu(self):
|
||||||
|
"""
|
||||||
|
Updates the file menu with the latest list of service files accessed.
|
||||||
|
"""
|
||||||
|
recentFileCount = QtCore.QSettings().value(
|
||||||
|
u'advanced/recent file count', QtCore.QVariant(4)).toInt()[0]
|
||||||
self.FileMenu.clear()
|
self.FileMenu.clear()
|
||||||
add_actions(self.FileMenu, self.FileMenuActions[:-1])
|
add_actions(self.FileMenu, self.FileMenuActions[:-1])
|
||||||
existingRecentFiles = []
|
existingRecentFiles = [file for file in self.recentFiles
|
||||||
for file in self.recentFiles:
|
if QtCore.QFile.exists(file)]
|
||||||
if QtCore.QFile.exists(file):
|
recentFilesToDisplay = existingRecentFiles[0:recentFileCount]
|
||||||
existingRecentFiles.append(file)
|
if recentFilesToDisplay:
|
||||||
if existingRecentFiles:
|
|
||||||
self.FileMenu.addSeparator()
|
self.FileMenu.addSeparator()
|
||||||
for fileId, filename in enumerate(existingRecentFiles):
|
for fileId, filename in enumerate(recentFilesToDisplay):
|
||||||
action = QtGui.QAction(u'&%d %s' % (fileId +1,
|
action = QtGui.QAction(u'&%d %s' % (fileId +1,
|
||||||
QtCore.QFileInfo(filename).fileName()), self)
|
QtCore.QFileInfo(filename).fileName()), self)
|
||||||
action.setData(QtCore.QVariant(filename))
|
action.setData(QtCore.QVariant(filename))
|
||||||
@ -947,13 +968,22 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
self.FileMenu.addAction(self.FileMenuActions[-1])
|
self.FileMenu.addAction(self.FileMenuActions[-1])
|
||||||
|
|
||||||
def addRecentFile(self, filename):
|
def addRecentFile(self, filename):
|
||||||
recentFileCount = QtCore.QSettings().value(
|
"""
|
||||||
self.generalSettingsSection + u'/max recent files',
|
Adds a service to the list of recently used files.
|
||||||
QtCore.QVariant(4)).toInt()[0]
|
|
||||||
|
``filename``
|
||||||
|
The service filename to add
|
||||||
|
"""
|
||||||
|
# The maxRecentFiles value does not have an interface and so never gets
|
||||||
|
# actually stored in the settings therefore the default value of 20
|
||||||
|
# will always be used.
|
||||||
|
maxRecentFiles = QtCore.QSettings().value(u'advanced/max recent files',
|
||||||
|
QtCore.QVariant(20)).toInt()[0]
|
||||||
if filename:
|
if filename:
|
||||||
position = self.recentFiles.indexOf(filename)
|
position = self.recentFiles.indexOf(filename)
|
||||||
if position != -1:
|
if position != -1:
|
||||||
self.recentFiles.removeAt(position)
|
self.recentFiles.removeAt(position)
|
||||||
self.recentFiles.insert(0, QtCore.QString(filename))
|
self.recentFiles.insert(0, QtCore.QString(filename))
|
||||||
while self.recentFiles.count() > recentFileCount:
|
while self.recentFiles.count() > maxRecentFiles:
|
||||||
self.recentFiles.removeLast()
|
# Don't care what API says takeLast works, removeLast doesn't!
|
||||||
|
self.recentFiles.takeLast()
|
||||||
|
@ -29,7 +29,7 @@ import logging
|
|||||||
|
|
||||||
from PyQt4 import QtGui
|
from PyQt4 import QtGui
|
||||||
|
|
||||||
from openlp.core.ui import GeneralTab, ThemesTab, DisplayTab
|
from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab, DisplayTab
|
||||||
from settingsdialog import Ui_SettingsDialog
|
from settingsdialog import Ui_SettingsDialog
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -53,6 +53,9 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
|
|||||||
# Display tab
|
# Display tab
|
||||||
self.DisplayTab = DisplayTab(screens)
|
self.DisplayTab = DisplayTab(screens)
|
||||||
self.addTab(u'Display', self.DisplayTab)
|
self.addTab(u'Display', self.DisplayTab)
|
||||||
|
# Advanced tab
|
||||||
|
self.advancedTab = AdvancedTab()
|
||||||
|
self.addTab(u'Advanced', self.advancedTab)
|
||||||
|
|
||||||
def addTab(self, name, tab):
|
def addTab(self, name, tab):
|
||||||
"""
|
"""
|
||||||
@ -66,9 +69,9 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
|
|||||||
Add a tab to the form at a specific location
|
Add a tab to the form at a specific location
|
||||||
"""
|
"""
|
||||||
log.debug(u'Inserting %s tab' % tab.tabTitle)
|
log.debug(u'Inserting %s tab' % tab.tabTitle)
|
||||||
#13 : There are 3 tables currently and locations starts at -10
|
# 14 : There are 3 tables currently and locations starts at -10
|
||||||
self.SettingsTabWidget.insertTab(
|
self.SettingsTabWidget.insertTab(
|
||||||
location + 13, tab, tab.tabTitleVisible)
|
location + 14, tab, tab.tabTitleVisible)
|
||||||
|
|
||||||
def removeTab(self, name):
|
def removeTab(self, name):
|
||||||
"""
|
"""
|
||||||
|
@ -202,15 +202,21 @@ class SlideController(QtGui.QWidget):
|
|||||||
self.Toolbar.addToolbarWidget(u'Hide Menu', self.HideMenu)
|
self.Toolbar.addToolbarWidget(u'Hide Menu', self.HideMenu)
|
||||||
self.HideMenu.setMenu(QtGui.QMenu(
|
self.HideMenu.setMenu(QtGui.QMenu(
|
||||||
translate('SlideController', 'Hide'), self.Toolbar))
|
translate('SlideController', 'Hide'), self.Toolbar))
|
||||||
self.BlankScreen = QtGui.QAction(QtGui.QIcon( u':/slides/slide_blank.png'), u'Blank Screen', self.HideMenu)
|
self.BlankScreen = QtGui.QAction(QtGui.QIcon(
|
||||||
|
u':/slides/slide_blank.png'), u'Blank Screen', self.HideMenu)
|
||||||
self.BlankScreen.setCheckable(True)
|
self.BlankScreen.setCheckable(True)
|
||||||
QtCore.QObject.connect(self.BlankScreen, QtCore.SIGNAL("triggered(bool)"), self.onBlankDisplay)
|
QtCore.QObject.connect(self.BlankScreen,
|
||||||
self.ThemeScreen = QtGui.QAction(QtGui.QIcon(u':/slides/slide_theme.png'), u'Blank to Theme', self.HideMenu)
|
QtCore.SIGNAL("triggered(bool)"), self.onBlankDisplay)
|
||||||
|
self.ThemeScreen = QtGui.QAction(QtGui.QIcon(
|
||||||
|
u':/slides/slide_theme.png'), u'Blank to Theme', self.HideMenu)
|
||||||
self.ThemeScreen.setCheckable(True)
|
self.ThemeScreen.setCheckable(True)
|
||||||
QtCore.QObject.connect(self.ThemeScreen, QtCore.SIGNAL("triggered(bool)"), self.onThemeDisplay)
|
QtCore.QObject.connect(self.ThemeScreen,
|
||||||
self.DesktopScreen = QtGui.QAction(QtGui.QIcon(u':/slides/slide_desktop.png'), u'Show Desktop', self.HideMenu)
|
QtCore.SIGNAL("triggered(bool)"), self.onThemeDisplay)
|
||||||
|
self.DesktopScreen = QtGui.QAction(QtGui.QIcon(
|
||||||
|
u':/slides/slide_desktop.png'), u'Show Desktop', self.HideMenu)
|
||||||
self.DesktopScreen.setCheckable(True)
|
self.DesktopScreen.setCheckable(True)
|
||||||
QtCore.QObject.connect(self.DesktopScreen, QtCore.SIGNAL("triggered(bool)"), self.onHideDisplay)
|
QtCore.QObject.connect(self.DesktopScreen,
|
||||||
|
QtCore.SIGNAL("triggered(bool)"), self.onHideDisplay)
|
||||||
self.HideMenu.setDefaultAction(self.BlankScreen)
|
self.HideMenu.setDefaultAction(self.BlankScreen)
|
||||||
self.HideMenu.menu().addAction(self.BlankScreen)
|
self.HideMenu.menu().addAction(self.BlankScreen)
|
||||||
self.HideMenu.menu().addAction(self.ThemeScreen)
|
self.HideMenu.menu().addAction(self.ThemeScreen)
|
||||||
@ -241,9 +247,8 @@ class SlideController(QtGui.QWidget):
|
|||||||
self.Toolbar.addToolbarWidget(
|
self.Toolbar.addToolbarWidget(
|
||||||
u'Image SpinBox', self.DelaySpinBox)
|
u'Image SpinBox', self.DelaySpinBox)
|
||||||
self.DelaySpinBox.setSuffix(translate('SlideController', 's'))
|
self.DelaySpinBox.setSuffix(translate('SlideController', 's'))
|
||||||
self.DelaySpinBox.setToolTip(
|
self.DelaySpinBox.setToolTip(translate('SlideController',
|
||||||
translate('SlideController',
|
'Delay between slides in seconds'))
|
||||||
'Delay between slides in seconds'))
|
|
||||||
self.ControllerLayout.addWidget(self.Toolbar)
|
self.ControllerLayout.addWidget(self.Toolbar)
|
||||||
#Build a Media ToolBar
|
#Build a Media ToolBar
|
||||||
self.Mediabar = OpenLPToolbar(self)
|
self.Mediabar = OpenLPToolbar(self)
|
||||||
@ -268,8 +273,7 @@ class SlideController(QtGui.QWidget):
|
|||||||
self.volumeSlider = Phonon.VolumeSlider()
|
self.volumeSlider = Phonon.VolumeSlider()
|
||||||
self.volumeSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
|
self.volumeSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
|
||||||
self.volumeSlider.setObjectName(u'volumeSlider')
|
self.volumeSlider.setObjectName(u'volumeSlider')
|
||||||
self.Mediabar.addToolbarWidget(
|
self.Mediabar.addToolbarWidget(u'Audio Volume', self.volumeSlider)
|
||||||
u'Audio Volume', self.volumeSlider)
|
|
||||||
self.ControllerLayout.addWidget(self.Mediabar)
|
self.ControllerLayout.addWidget(self.Mediabar)
|
||||||
# Build the Song Toolbar
|
# Build the Song Toolbar
|
||||||
if isLive:
|
if isLive:
|
||||||
@ -328,6 +332,11 @@ class SlideController(QtGui.QWidget):
|
|||||||
# Signals
|
# Signals
|
||||||
QtCore.QObject.connect(self.PreviewListWidget,
|
QtCore.QObject.connect(self.PreviewListWidget,
|
||||||
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
|
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
|
||||||
|
if not self.isLive:
|
||||||
|
if QtCore.QSettings().value(u'advanced/double click live',
|
||||||
|
QtCore.QVariant(False)).toBool():
|
||||||
|
QtCore.QObject.connect(self.PreviewListWidget,
|
||||||
|
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onGoLive)
|
||||||
if isLive:
|
if isLive:
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'slidecontroller_live_spin_delay'),
|
QtCore.SIGNAL(u'slidecontroller_live_spin_delay'),
|
||||||
|
@ -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)
|
||||||
@ -116,6 +117,7 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
self.thumbPath = os.path.join(self.path, u'thumbnails')
|
self.thumbPath = os.path.join(self.path, u'thumbnails')
|
||||||
self.checkThemesExists(self.thumbPath)
|
self.checkThemesExists(self.thumbPath)
|
||||||
self.amendThemeForm.path = self.path
|
self.amendThemeForm.path = self.path
|
||||||
|
self.oldBackgroundImage = None
|
||||||
# Last little bits of setting up
|
# Last little bits of setting up
|
||||||
self.global_theme = unicode(QtCore.QSettings().value(
|
self.global_theme = unicode(QtCore.QSettings().value(
|
||||||
self.settingsSection + u'/global theme',
|
self.settingsSection + u'/global theme',
|
||||||
@ -182,11 +184,17 @@ 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':
|
||||||
|
self.oldBackgroundImage = theme.background_filename
|
||||||
self.amendThemeForm.loadTheme(theme)
|
self.amendThemeForm.loadTheme(theme)
|
||||||
self.saveThemeName = unicode(
|
self.saveThemeName = unicode(
|
||||||
item.data(QtCore.Qt.UserRole).toString())
|
item.data(QtCore.Qt.UserRole).toString())
|
||||||
@ -212,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):
|
||||||
"""
|
"""
|
||||||
@ -532,18 +547,31 @@ 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 \
|
||||||
|
image_to != self.oldBackgroundImage:
|
||||||
|
try:
|
||||||
|
os.remove(self.oldBackgroundImage)
|
||||||
|
except OSError:
|
||||||
|
log.exception(u'Unable to remove old theme background')
|
||||||
outfile = None
|
outfile = None
|
||||||
try:
|
try:
|
||||||
outfile = open(theme_file, u'w')
|
outfile = open(theme_file, u'w')
|
||||||
@ -563,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.
|
||||||
|
@ -38,7 +38,8 @@ class BiblePlugin(Plugin):
|
|||||||
def __init__(self, plugin_helpers):
|
def __init__(self, plugin_helpers):
|
||||||
Plugin.__init__(self, u'Bibles', u'1.9.2', plugin_helpers)
|
Plugin.__init__(self, u'Bibles', u'1.9.2', plugin_helpers)
|
||||||
self.weight = -9
|
self.weight = -9
|
||||||
self.icon = build_icon(u':/plugins/plugin_bibles.png')
|
self.icon_path = u':/plugins/plugin_bibles.png'
|
||||||
|
self.icon = build_icon(self.icon_path)
|
||||||
#Register the bible Manager
|
#Register the bible Manager
|
||||||
self.status = PluginStatus.Active
|
self.status = PluginStatus.Active
|
||||||
self.manager = None
|
self.manager = None
|
||||||
@ -94,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
|
||||||
|
@ -50,7 +50,8 @@ class CustomPlugin(Plugin):
|
|||||||
self.weight = -5
|
self.weight = -5
|
||||||
self.custommanager = Manager(u'custom', init_schema)
|
self.custommanager = Manager(u'custom', init_schema)
|
||||||
self.edit_custom_form = EditCustomForm(self.custommanager)
|
self.edit_custom_form = EditCustomForm(self.custommanager)
|
||||||
self.icon = build_icon(u':/plugins/plugin_custom.png')
|
self.icon_path = u':/plugins/plugin_custom.png'
|
||||||
|
self.icon = build_icon(self.icon_path)
|
||||||
self.status = PluginStatus.Active
|
self.status = PluginStatus.Active
|
||||||
|
|
||||||
def getSettingsTab(self):
|
def getSettingsTab(self):
|
||||||
@ -68,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)
|
||||||
|
@ -36,7 +36,8 @@ class ImagePlugin(Plugin):
|
|||||||
def __init__(self, plugin_helpers):
|
def __init__(self, plugin_helpers):
|
||||||
Plugin.__init__(self, u'Images', u'1.9.2', plugin_helpers)
|
Plugin.__init__(self, u'Images', u'1.9.2', plugin_helpers)
|
||||||
self.weight = -7
|
self.weight = -7
|
||||||
self.icon = build_icon(u':/plugins/plugin_images.png')
|
self.icon_path = u':/plugins/plugin_images.png'
|
||||||
|
self.icon = build_icon(self.icon_path)
|
||||||
self.status = PluginStatus.Active
|
self.status = PluginStatus.Active
|
||||||
|
|
||||||
def getSettingsTab(self):
|
def getSettingsTab(self):
|
||||||
|
@ -38,7 +38,8 @@ class MediaPlugin(Plugin):
|
|||||||
def __init__(self, plugin_helpers):
|
def __init__(self, plugin_helpers):
|
||||||
Plugin.__init__(self, u'Media', u'1.9.2', plugin_helpers)
|
Plugin.__init__(self, u'Media', u'1.9.2', plugin_helpers)
|
||||||
self.weight = -6
|
self.weight = -6
|
||||||
self.icon = build_icon(u':/plugins/plugin_media.png')
|
self.icon_path = u':/plugins/plugin_media.png'
|
||||||
|
self.icon = build_icon(self.icon_path)
|
||||||
# passed with drag and drop messages
|
# passed with drag and drop messages
|
||||||
self.dnd_id = u'Media'
|
self.dnd_id = u'Media'
|
||||||
self.status = PluginStatus.Active
|
self.status = PluginStatus.Active
|
||||||
|
@ -37,8 +37,6 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from openlp.core.lib import resize_image
|
|
||||||
|
|
||||||
if os.name == u'nt':
|
if os.name == u'nt':
|
||||||
from win32com.client import Dispatch
|
from win32com.client import Dispatch
|
||||||
import pywintypes
|
import pywintypes
|
||||||
@ -74,6 +72,7 @@ class ImpressController(PresentationController):
|
|||||||
self.alsosupports = [u'.ppt', u'.pps', u'.pptx', u'.ppsx']
|
self.alsosupports = [u'.ppt', u'.pps', u'.pptx', u'.ppsx']
|
||||||
self.process = None
|
self.process = None
|
||||||
self.desktop = None
|
self.desktop = None
|
||||||
|
self.manager = None
|
||||||
|
|
||||||
def check_available(self):
|
def check_available(self):
|
||||||
"""
|
"""
|
||||||
@ -104,6 +103,10 @@ class ImpressController(PresentationController):
|
|||||||
self.process.waitForStarted()
|
self.process.waitForStarted()
|
||||||
|
|
||||||
def get_uno_desktop(self):
|
def get_uno_desktop(self):
|
||||||
|
"""
|
||||||
|
On non-Windows platforms, use Uno. Get the OpenOffice desktop
|
||||||
|
which will be used to manage impress
|
||||||
|
"""
|
||||||
log.debug(u'get UNO Desktop Openoffice')
|
log.debug(u'get UNO Desktop Openoffice')
|
||||||
ctx = None
|
ctx = None
|
||||||
loop = 0
|
loop = 0
|
||||||
@ -134,10 +137,19 @@ class ImpressController(PresentationController):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def get_com_desktop(self):
|
def get_com_desktop(self):
|
||||||
|
"""
|
||||||
|
On Windows platforms, use COM. Return the desktop object which
|
||||||
|
will be used to manage Impress
|
||||||
|
"""
|
||||||
log.debug(u'get COM Desktop OpenOffice')
|
log.debug(u'get COM Desktop OpenOffice')
|
||||||
|
if not self.manager:
|
||||||
|
return None
|
||||||
return self.manager.createInstance(u'com.sun.star.frame.Desktop')
|
return self.manager.createInstance(u'com.sun.star.frame.Desktop')
|
||||||
|
|
||||||
def get_com_servicemanager(self):
|
def get_com_servicemanager(self):
|
||||||
|
"""
|
||||||
|
Return the OOo service manager for windows
|
||||||
|
"""
|
||||||
log.debug(u'get_com_servicemanager openoffice')
|
log.debug(u'get_com_servicemanager openoffice')
|
||||||
try:
|
try:
|
||||||
return Dispatch(u'com.sun.star.ServiceManager')
|
return Dispatch(u'com.sun.star.ServiceManager')
|
||||||
@ -171,13 +183,23 @@ class ImpressController(PresentationController):
|
|||||||
log.exception(u'Failed to terminate OpenOffice')
|
log.exception(u'Failed to terminate OpenOffice')
|
||||||
|
|
||||||
def add_doc(self, name):
|
def add_doc(self, name):
|
||||||
|
"""
|
||||||
|
Called when a new Impress document is opened
|
||||||
|
"""
|
||||||
log.debug(u'Add Doc OpenOffice')
|
log.debug(u'Add Doc OpenOffice')
|
||||||
doc = ImpressDocument(self, name)
|
doc = ImpressDocument(self, name)
|
||||||
self.docs.append(doc)
|
self.docs.append(doc)
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
class ImpressDocument(PresentationDocument):
|
class ImpressDocument(PresentationDocument):
|
||||||
|
"""
|
||||||
|
Class which holds information and controls a single presentation
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, controller, presentation):
|
def __init__(self, controller, presentation):
|
||||||
|
"""
|
||||||
|
Constructor, store information about the file and initialise
|
||||||
|
"""
|
||||||
log.debug(u'Init Presentation OpenOffice')
|
log.debug(u'Init Presentation OpenOffice')
|
||||||
PresentationDocument.__init__(self, controller, presentation)
|
PresentationDocument.__init__(self, controller, presentation)
|
||||||
self.document = None
|
self.document = None
|
||||||
@ -208,9 +230,8 @@ class ImpressDocument(PresentationDocument):
|
|||||||
desktop = self.controller.get_uno_desktop()
|
desktop = self.controller.get_uno_desktop()
|
||||||
url = uno.systemPathToFileUrl(self.filepath)
|
url = uno.systemPathToFileUrl(self.filepath)
|
||||||
if desktop is None:
|
if desktop is None:
|
||||||
return
|
return False
|
||||||
self.desktop = desktop
|
self.desktop = desktop
|
||||||
#print "s.dsk2 ", self.desktop
|
|
||||||
properties = []
|
properties = []
|
||||||
properties.append(self.create_property(u'Minimized', True))
|
properties.append(self.create_property(u'Minimized', True))
|
||||||
properties = tuple(properties)
|
properties = tuple(properties)
|
||||||
@ -219,12 +240,13 @@ class ImpressDocument(PresentationDocument):
|
|||||||
0, properties)
|
0, properties)
|
||||||
except:
|
except:
|
||||||
log.exception(u'Failed to load presentation')
|
log.exception(u'Failed to load presentation')
|
||||||
return
|
return False
|
||||||
self.presentation = self.document.getPresentation()
|
self.presentation = self.document.getPresentation()
|
||||||
self.presentation.Display = \
|
self.presentation.Display = \
|
||||||
self.controller.plugin.renderManager.screens.current_display + 1
|
self.controller.plugin.renderManager.screens.current_display + 1
|
||||||
self.control = None
|
self.control = None
|
||||||
self.create_thumbnails()
|
self.create_thumbnails()
|
||||||
|
return True
|
||||||
|
|
||||||
def create_thumbnails(self):
|
def create_thumbnails(self):
|
||||||
"""
|
"""
|
||||||
@ -234,30 +256,36 @@ class ImpressDocument(PresentationDocument):
|
|||||||
if self.check_thumbnails():
|
if self.check_thumbnails():
|
||||||
return
|
return
|
||||||
if os.name == u'nt':
|
if os.name == u'nt':
|
||||||
thumbdir = u'file:///' + self.thumbnailpath.replace(
|
thumbdirurl = u'file:///' + self.get_temp_folder().replace(
|
||||||
u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20')
|
u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20')
|
||||||
else:
|
else:
|
||||||
thumbdir = uno.systemPathToFileUrl(self.thumbnailpath)
|
thumbdirurl = uno.systemPathToFileUrl(self.get_temp_folder())
|
||||||
props = []
|
props = []
|
||||||
props.append(self.create_property(u'FilterName', u'impress_png_Export'))
|
props.append(self.create_property(u'FilterName', u'impress_png_Export'))
|
||||||
props = tuple(props)
|
props = tuple(props)
|
||||||
doc = self.document
|
doc = self.document
|
||||||
pages = doc.getDrawPages()
|
pages = doc.getDrawPages()
|
||||||
|
if not os.path.isdir(self.get_temp_folder()):
|
||||||
|
os.makedirs(self.get_temp_folder())
|
||||||
for idx in range(pages.getCount()):
|
for idx in range(pages.getCount()):
|
||||||
page = pages.getByIndex(idx)
|
page = pages.getByIndex(idx)
|
||||||
doc.getCurrentController().setCurrentPage(page)
|
doc.getCurrentController().setCurrentPage(page)
|
||||||
path = u'%s/%s%s.png' % (thumbdir, self.controller.thumbnailprefix,
|
urlpath = u'%s/%s.png' % (thumbdirurl, unicode(idx + 1))
|
||||||
unicode(idx + 1))
|
path = os.path.join(self.get_temp_folder(),
|
||||||
|
unicode(idx + 1) + u'.png')
|
||||||
try:
|
try:
|
||||||
doc.storeToURL(path , props)
|
doc.storeToURL(urlpath, props)
|
||||||
preview = resize_image(path, 640, 480)
|
self.convert_thumbnail(path, idx + 1)
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
os.remove(path)
|
os.remove(path)
|
||||||
preview.save(path, u'png')
|
|
||||||
except:
|
except:
|
||||||
log.exception(u'%s - Unable to store openoffice preview' % path)
|
log.exception(u'%s - Unable to store openoffice preview' % path)
|
||||||
|
|
||||||
def create_property(self, name, value):
|
def create_property(self, name, value):
|
||||||
|
"""
|
||||||
|
Create an OOo style property object which are passed into some
|
||||||
|
Uno methods
|
||||||
|
"""
|
||||||
log.debug(u'create property OpenOffice')
|
log.debug(u'create property OpenOffice')
|
||||||
if os.name == u'nt':
|
if os.name == u'nt':
|
||||||
prop = self.controller.manager.\
|
prop = self.controller.manager.\
|
||||||
@ -288,6 +316,9 @@ class ImpressDocument(PresentationDocument):
|
|||||||
self.controller.remove_doc(self)
|
self.controller.remove_doc(self)
|
||||||
|
|
||||||
def is_loaded(self):
|
def is_loaded(self):
|
||||||
|
"""
|
||||||
|
Returns true if a presentation is loaded
|
||||||
|
"""
|
||||||
log.debug(u'is loaded OpenOffice')
|
log.debug(u'is loaded OpenOffice')
|
||||||
#print "is_loaded "
|
#print "is_loaded "
|
||||||
if self.presentation is None or self.document is None:
|
if self.presentation is None or self.document is None:
|
||||||
@ -302,6 +333,9 @@ class ImpressDocument(PresentationDocument):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def is_active(self):
|
def is_active(self):
|
||||||
|
"""
|
||||||
|
Returns true if a presentation is active and running
|
||||||
|
"""
|
||||||
log.debug(u'is active OpenOffice')
|
log.debug(u'is active OpenOffice')
|
||||||
#print "is_active "
|
#print "is_active "
|
||||||
if not self.is_loaded():
|
if not self.is_loaded():
|
||||||
@ -313,10 +347,16 @@ class ImpressDocument(PresentationDocument):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def unblank_screen(self):
|
def unblank_screen(self):
|
||||||
|
"""
|
||||||
|
Unblanks the screen
|
||||||
|
"""
|
||||||
log.debug(u'unblank screen OpenOffice')
|
log.debug(u'unblank screen OpenOffice')
|
||||||
return self.control.resume()
|
return self.control.resume()
|
||||||
|
|
||||||
def blank_screen(self):
|
def blank_screen(self):
|
||||||
|
"""
|
||||||
|
Blanks the screen
|
||||||
|
"""
|
||||||
log.debug(u'blank screen OpenOffice')
|
log.debug(u'blank screen OpenOffice')
|
||||||
self.control.blankScreen(0)
|
self.control.blankScreen(0)
|
||||||
|
|
||||||
@ -331,6 +371,9 @@ class ImpressDocument(PresentationDocument):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def stop_presentation(self):
|
def stop_presentation(self):
|
||||||
|
"""
|
||||||
|
Stop the presentation, remove from screen
|
||||||
|
"""
|
||||||
log.debug(u'stop presentation OpenOffice')
|
log.debug(u'stop presentation OpenOffice')
|
||||||
# deactivate should hide the screen according to docs, but doesn't
|
# deactivate should hide the screen according to docs, but doesn't
|
||||||
#self.control.deactivate()
|
#self.control.deactivate()
|
||||||
@ -338,6 +381,9 @@ class ImpressDocument(PresentationDocument):
|
|||||||
self.control = None
|
self.control = None
|
||||||
|
|
||||||
def start_presentation(self):
|
def start_presentation(self):
|
||||||
|
"""
|
||||||
|
Start the presentation from the beginning
|
||||||
|
"""
|
||||||
log.debug(u'start presentation OpenOffice')
|
log.debug(u'start presentation OpenOffice')
|
||||||
if self.control is None or not self.control.isRunning():
|
if self.control is None or not self.control.isRunning():
|
||||||
self.presentation.start()
|
self.presentation.start()
|
||||||
@ -354,12 +400,21 @@ class ImpressDocument(PresentationDocument):
|
|||||||
self.goto_slide(1)
|
self.goto_slide(1)
|
||||||
|
|
||||||
def get_slide_number(self):
|
def get_slide_number(self):
|
||||||
|
"""
|
||||||
|
Return the current slide number on the screen, from 1
|
||||||
|
"""
|
||||||
return self.control.getCurrentSlideIndex() + 1
|
return self.control.getCurrentSlideIndex() + 1
|
||||||
|
|
||||||
def get_slide_count(self):
|
def get_slide_count(self):
|
||||||
|
"""
|
||||||
|
Return the total number of slides
|
||||||
|
"""
|
||||||
return self.document.getDrawPages().getCount()
|
return self.document.getDrawPages().getCount()
|
||||||
|
|
||||||
def goto_slide(self, slideno):
|
def goto_slide(self, slideno):
|
||||||
|
"""
|
||||||
|
Go to a specific slide (from 1)
|
||||||
|
"""
|
||||||
self.control.gotoSlideIndex(slideno-1)
|
self.control.gotoSlideIndex(slideno-1)
|
||||||
|
|
||||||
def next_step(self):
|
def next_step(self):
|
||||||
|
@ -30,14 +30,17 @@ from PyQt4 import QtCore, QtGui
|
|||||||
|
|
||||||
from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \
|
from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \
|
||||||
SettingsManager, translate, check_item_selected
|
SettingsManager, translate, check_item_selected
|
||||||
from openlp.core.utils import AppLocation
|
|
||||||
from openlp.plugins.presentations.lib import MessageListener
|
from openlp.plugins.presentations.lib import MessageListener
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
# We have to explicitly create separate classes for each plugin
|
|
||||||
# in order for DnD to the Service manager to work correctly.
|
|
||||||
class PresentationListView(BaseListWithDnD):
|
class PresentationListView(BaseListWithDnD):
|
||||||
|
"""
|
||||||
|
Class for the list of Presentations
|
||||||
|
|
||||||
|
We have to explicitly create separate classes for each plugin
|
||||||
|
in order for DnD to the Service manager to work correctly.
|
||||||
|
"""
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
self.PluginName = u'Presentations'
|
self.PluginName = u'Presentations'
|
||||||
BaseListWithDnD.__init__(self, parent)
|
BaseListWithDnD.__init__(self, parent)
|
||||||
@ -45,11 +48,14 @@ class PresentationListView(BaseListWithDnD):
|
|||||||
class PresentationMediaItem(MediaManagerItem):
|
class PresentationMediaItem(MediaManagerItem):
|
||||||
"""
|
"""
|
||||||
This is the Presentation media manager item for Presentation Items.
|
This is the Presentation media manager item for Presentation Items.
|
||||||
It can present files using Openoffice
|
It can present files using Openoffice and Powerpoint
|
||||||
"""
|
"""
|
||||||
log.info(u'Presentations Media Item loaded')
|
log.info(u'Presentations Media Item loaded')
|
||||||
|
|
||||||
def __init__(self, parent, icon, title, controllers):
|
def __init__(self, parent, icon, title, controllers):
|
||||||
|
"""
|
||||||
|
Constructor. Setup defaults
|
||||||
|
"""
|
||||||
self.controllers = controllers
|
self.controllers = controllers
|
||||||
self.PluginNameShort = u'Presentation'
|
self.PluginNameShort = u'Presentation'
|
||||||
self.pluginNameVisible = translate('PresentationPlugin.MediaItem',
|
self.pluginNameVisible = translate('PresentationPlugin.MediaItem',
|
||||||
@ -63,6 +69,9 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
self.message_listener = MessageListener(self)
|
self.message_listener = MessageListener(self)
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslateUi(self):
|
||||||
|
"""
|
||||||
|
The name of the plugin media displayed in UI
|
||||||
|
"""
|
||||||
self.OnNewPrompt = translate('PresentationPlugin.MediaItem',
|
self.OnNewPrompt = translate('PresentationPlugin.MediaItem',
|
||||||
'Select Presentation(s)')
|
'Select Presentation(s)')
|
||||||
self.Automatic = translate('PresentationPlugin.MediaItem',
|
self.Automatic = translate('PresentationPlugin.MediaItem',
|
||||||
@ -80,12 +89,18 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
'Presentations (%s)' % fileType)
|
'Presentations (%s)' % fileType)
|
||||||
|
|
||||||
def requiredIcons(self):
|
def requiredIcons(self):
|
||||||
|
"""
|
||||||
|
Set which icons the media manager tab should show
|
||||||
|
"""
|
||||||
MediaManagerItem.requiredIcons(self)
|
MediaManagerItem.requiredIcons(self)
|
||||||
self.hasFileIcon = True
|
self.hasFileIcon = True
|
||||||
self.hasNewIcon = False
|
self.hasNewIcon = False
|
||||||
self.hasEditIcon = False
|
self.hasEditIcon = False
|
||||||
|
|
||||||
def addEndHeaderBar(self):
|
def addEndHeaderBar(self):
|
||||||
|
"""
|
||||||
|
Display custom media manager items for presentations
|
||||||
|
"""
|
||||||
self.PresentationWidget = QtGui.QWidget(self)
|
self.PresentationWidget = QtGui.QWidget(self)
|
||||||
sizePolicy = QtGui.QSizePolicy(
|
sizePolicy = QtGui.QSizePolicy(
|
||||||
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||||
@ -109,15 +124,13 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
self.pageLayout.addWidget(self.PresentationWidget)
|
self.pageLayout.addWidget(self.PresentationWidget)
|
||||||
|
|
||||||
def initialise(self):
|
def initialise(self):
|
||||||
self.servicePath = os.path.join(
|
"""
|
||||||
AppLocation.get_section_data_path(self.settingsSection),
|
Populate the media manager tab
|
||||||
u'thumbnails')
|
"""
|
||||||
self.listView.setIconSize(QtCore.QSize(88, 50))
|
self.listView.setIconSize(QtCore.QSize(88, 50))
|
||||||
if not os.path.exists(self.servicePath):
|
|
||||||
os.mkdir(self.servicePath)
|
|
||||||
list = SettingsManager.load_list(
|
list = SettingsManager.load_list(
|
||||||
self.settingsSection, u'presentations')
|
self.settingsSection, u'presentations')
|
||||||
self.loadList(list)
|
self.loadList(list, True)
|
||||||
for item in self.controllers:
|
for item in self.controllers:
|
||||||
#load the drop down selection
|
#load the drop down selection
|
||||||
if self.controllers[item].enabled:
|
if self.controllers[item].enabled:
|
||||||
@ -126,7 +139,12 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
self.DisplayTypeComboBox.insertItem(0, self.Automatic)
|
self.DisplayTypeComboBox.insertItem(0, self.Automatic)
|
||||||
self.DisplayTypeComboBox.setCurrentIndex(0)
|
self.DisplayTypeComboBox.setCurrentIndex(0)
|
||||||
|
|
||||||
def loadList(self, list):
|
def loadList(self, list, initialLoad=False):
|
||||||
|
"""
|
||||||
|
Add presentations into the media manager
|
||||||
|
This is called both on initial load of the plugin to populate with
|
||||||
|
existing files, and when the user adds new files via the media manager
|
||||||
|
"""
|
||||||
currlist = self.getFileList()
|
currlist = self.getFileList()
|
||||||
titles = []
|
titles = []
|
||||||
for file in currlist:
|
for file in currlist:
|
||||||
@ -136,40 +154,43 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
continue
|
continue
|
||||||
filename = os.path.split(unicode(file))[1]
|
filename = os.path.split(unicode(file))[1]
|
||||||
if titles.count(filename) > 0:
|
if titles.count(filename) > 0:
|
||||||
QtGui.QMessageBox.critical(
|
if not initialLoad:
|
||||||
self, translate('PresentationPlugin.MediaItem',
|
QtGui.QMessageBox.critical(
|
||||||
'File exists'),
|
self, translate('PresentationPlugin.MediaItem',
|
||||||
|
'File exists'),
|
||||||
translate('PresentationPlugin.MediaItem',
|
translate('PresentationPlugin.MediaItem',
|
||||||
'A presentation with that filename already exists.'),
|
'A presentation with that filename already exists.'),
|
||||||
QtGui.QMessageBox.Ok)
|
QtGui.QMessageBox.Ok)
|
||||||
else:
|
continue
|
||||||
icon = None
|
controller_name = self.findControllerByType(filename)
|
||||||
for controller in self.controllers:
|
if controller_name:
|
||||||
thumbPath = os.path.join(
|
controller = self.controllers[controller_name]
|
||||||
AppLocation.get_section_data_path(
|
doc = controller.add_doc(unicode(file))
|
||||||
self.settingsSection),
|
thumb = os.path.join(doc.get_thumbnail_folder(), u'icon.png')
|
||||||
u'thumbnails', controller, filename)
|
preview = doc.get_thumbnail_path(1, True)
|
||||||
thumb = os.path.join(thumbPath, u'slide1.png')
|
if not preview and not initialLoad:
|
||||||
preview = os.path.join(
|
doc.load_presentation()
|
||||||
AppLocation.get_section_data_path(
|
preview = doc.get_thumbnail_path(1, True)
|
||||||
self.settingsSection),
|
doc.close_presentation()
|
||||||
controller, u'thumbnails', filename, u'slide1.png')
|
if preview and self.validate(preview, thumb):
|
||||||
if os.path.exists(preview):
|
icon = build_icon(thumb)
|
||||||
if os.path.exists(thumb):
|
else:
|
||||||
if self.validate(preview, thumb):
|
|
||||||
icon = build_icon(thumb)
|
|
||||||
else:
|
|
||||||
icon = build_icon(
|
|
||||||
u':/general/general_delete.png')
|
|
||||||
else:
|
|
||||||
os.makedirs(thumbPath)
|
|
||||||
icon = self.iconFromFile(preview, thumb)
|
|
||||||
if not icon:
|
|
||||||
icon = build_icon(u':/general/general_delete.png')
|
icon = build_icon(u':/general/general_delete.png')
|
||||||
item_name = QtGui.QListWidgetItem(filename)
|
else:
|
||||||
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
|
if initialLoad:
|
||||||
item_name.setIcon(icon)
|
icon = build_icon(u':/general/general_delete.png')
|
||||||
self.listView.addItem(item_name)
|
else:
|
||||||
|
QtGui.QMessageBox.critical(
|
||||||
|
self, translate('PresentationPlugin.MediaItem',
|
||||||
|
'Unsupported file'),
|
||||||
|
translate('PresentationPlugin.MediaItem',
|
||||||
|
'This type of presentation is not supported'),
|
||||||
|
QtGui.QMessageBox.Ok)
|
||||||
|
continue
|
||||||
|
item_name = QtGui.QListWidgetItem(filename)
|
||||||
|
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
|
||||||
|
item_name.setIcon(icon)
|
||||||
|
self.listView.addItem(item_name)
|
||||||
|
|
||||||
def onDeleteClick(self):
|
def onDeleteClick(self):
|
||||||
"""
|
"""
|
||||||
@ -184,8 +205,6 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
for item in items:
|
for item in items:
|
||||||
filepath = unicode(item.data(
|
filepath = unicode(item.data(
|
||||||
QtCore.Qt.UserRole).toString())
|
QtCore.Qt.UserRole).toString())
|
||||||
#not sure of this has errors
|
|
||||||
#John please can you look at .
|
|
||||||
for cidx in self.controllers:
|
for cidx in self.controllers:
|
||||||
doc = self.controllers[cidx].add_doc(filepath)
|
doc = self.controllers[cidx].add_doc(filepath)
|
||||||
doc.presentation_deleted()
|
doc.presentation_deleted()
|
||||||
@ -196,6 +215,11 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
self.settingsSection, self.getFileList())
|
self.settingsSection, self.getFileList())
|
||||||
|
|
||||||
def generateSlideData(self, service_item, item=None):
|
def generateSlideData(self, service_item, item=None):
|
||||||
|
"""
|
||||||
|
Load the relevant information for displaying the presentation
|
||||||
|
in the slidecontroller. In the case of powerpoints, an image
|
||||||
|
for each slide
|
||||||
|
"""
|
||||||
items = self.listView.selectedIndexes()
|
items = self.listView.selectedIndexes()
|
||||||
if len(items) > 1:
|
if len(items) > 1:
|
||||||
return False
|
return False
|
||||||
@ -213,20 +237,27 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
controller = self.controllers[service_item.shortname]
|
controller = self.controllers[service_item.shortname]
|
||||||
(path, name) = os.path.split(filename)
|
(path, name) = os.path.split(filename)
|
||||||
doc = controller.add_doc(filename)
|
doc = controller.add_doc(filename)
|
||||||
if doc.get_slide_preview_file(1) is None:
|
if doc.get_thumbnail_path(1, True) is None:
|
||||||
doc.load_presentation()
|
doc.load_presentation()
|
||||||
i = 1
|
i = 1
|
||||||
img = doc.get_slide_preview_file(i)
|
img = doc.get_thumbnail_path(i, True)
|
||||||
while img:
|
while img:
|
||||||
service_item.add_from_command(path, name, img)
|
service_item.add_from_command(path, name, img)
|
||||||
i = i + 1
|
i = i + 1
|
||||||
img = doc.get_slide_preview_file(i)
|
img = doc.get_thumbnail_path(i, True)
|
||||||
doc.close_presentation()
|
doc.close_presentation()
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def findControllerByType(self, filename):
|
def findControllerByType(self, filename):
|
||||||
|
"""
|
||||||
|
Determine the default application controller to use for the selected
|
||||||
|
file type. This is used if "Automatic" is set as the preferred
|
||||||
|
controller. Find the first (alphabetic) enabled controller which
|
||||||
|
"supports" the extension. If none found, then look for a controller
|
||||||
|
which "alsosupports" it instead.
|
||||||
|
"""
|
||||||
filetype = os.path.splitext(filename)[1]
|
filetype = os.path.splitext(filename)[1]
|
||||||
if not filetype:
|
if not filetype:
|
||||||
return None
|
return None
|
||||||
|
@ -41,17 +41,28 @@ class Controller(object):
|
|||||||
log.info(u'Controller loaded')
|
log.info(u'Controller loaded')
|
||||||
|
|
||||||
def __init__(self, live):
|
def __init__(self, live):
|
||||||
|
"""
|
||||||
|
Constructor
|
||||||
|
"""
|
||||||
self.is_live = live
|
self.is_live = live
|
||||||
self.doc = None
|
self.doc = None
|
||||||
log.info(u'%s controller loaded' % live)
|
log.info(u'%s controller loaded' % live)
|
||||||
|
|
||||||
def add_handler(self, controller, file, is_blank):
|
def add_handler(self, controller, file, is_blank):
|
||||||
|
"""
|
||||||
|
Add a handler, which is an instance of a presentation and
|
||||||
|
slidecontroller combination. If the slidecontroller has a display
|
||||||
|
then load the presentation.
|
||||||
|
"""
|
||||||
log.debug(u'Live = %s, add_handler %s' % (self.is_live, file))
|
log.debug(u'Live = %s, add_handler %s' % (self.is_live, file))
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
if self.doc is not None:
|
if self.doc is not None:
|
||||||
self.shutdown()
|
self.shutdown()
|
||||||
self.doc = self.controller.add_doc(file)
|
self.doc = self.controller.add_doc(file)
|
||||||
self.doc.load_presentation()
|
if not self.doc.load_presentation():
|
||||||
|
# Display error message to user
|
||||||
|
# Inform slidecontroller that the action failed?
|
||||||
|
return
|
||||||
if self.is_live:
|
if self.is_live:
|
||||||
self.doc.start_presentation()
|
self.doc.start_presentation()
|
||||||
if is_blank:
|
if is_blank:
|
||||||
@ -60,6 +71,10 @@ class Controller(object):
|
|||||||
self.doc.slidenumber = 0
|
self.doc.slidenumber = 0
|
||||||
|
|
||||||
def activate(self):
|
def activate(self):
|
||||||
|
"""
|
||||||
|
Active the presentation, and show it on the screen.
|
||||||
|
Use the last slide number.
|
||||||
|
"""
|
||||||
log.debug(u'Live = %s, activate' % self.is_live)
|
log.debug(u'Live = %s, activate' % self.is_live)
|
||||||
if self.doc.is_active():
|
if self.doc.is_active():
|
||||||
return
|
return
|
||||||
@ -71,6 +86,9 @@ class Controller(object):
|
|||||||
self.doc.goto_slide(self.doc.slidenumber)
|
self.doc.goto_slide(self.doc.slidenumber)
|
||||||
|
|
||||||
def slide(self, slide):
|
def slide(self, slide):
|
||||||
|
"""
|
||||||
|
Go to a specific slide
|
||||||
|
"""
|
||||||
log.debug(u'Live = %s, slide' % self.is_live)
|
log.debug(u'Live = %s, slide' % self.is_live)
|
||||||
if not self.is_live:
|
if not self.is_live:
|
||||||
return
|
return
|
||||||
@ -152,6 +170,9 @@ class Controller(object):
|
|||||||
#self.timer.stop()
|
#self.timer.stop()
|
||||||
|
|
||||||
def blank(self):
|
def blank(self):
|
||||||
|
"""
|
||||||
|
Instruct the controller to blank the presentation
|
||||||
|
"""
|
||||||
log.debug(u'Live = %s, blank' % self.is_live)
|
log.debug(u'Live = %s, blank' % self.is_live)
|
||||||
if not self.is_live:
|
if not self.is_live:
|
||||||
return
|
return
|
||||||
@ -162,6 +183,9 @@ class Controller(object):
|
|||||||
self.doc.blank_screen()
|
self.doc.blank_screen()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
"""
|
||||||
|
Instruct the controller to stop and hide the presentation
|
||||||
|
"""
|
||||||
log.debug(u'Live = %s, stop' % self.is_live)
|
log.debug(u'Live = %s, stop' % self.is_live)
|
||||||
if not self.is_live:
|
if not self.is_live:
|
||||||
return
|
return
|
||||||
@ -172,6 +196,9 @@ class Controller(object):
|
|||||||
self.doc.stop_presentation()
|
self.doc.stop_presentation()
|
||||||
|
|
||||||
def unblank(self):
|
def unblank(self):
|
||||||
|
"""
|
||||||
|
Instruct the controller to unblank the presentation
|
||||||
|
"""
|
||||||
log.debug(u'Live = %s, unblank' % self.is_live)
|
log.debug(u'Live = %s, unblank' % self.is_live)
|
||||||
if not self.is_live:
|
if not self.is_live:
|
||||||
return
|
return
|
||||||
@ -246,6 +273,9 @@ class MessageListener(object):
|
|||||||
controller.add_handler(self.controllers[self.handler], file, is_blank)
|
controller.add_handler(self.controllers[self.handler], file, is_blank)
|
||||||
|
|
||||||
def slide(self, message):
|
def slide(self, message):
|
||||||
|
"""
|
||||||
|
React to the message to move to a specific slide
|
||||||
|
"""
|
||||||
is_live = message[1]
|
is_live = message[1]
|
||||||
slide = message[2]
|
slide = message[2]
|
||||||
if is_live:
|
if is_live:
|
||||||
@ -254,6 +284,9 @@ class MessageListener(object):
|
|||||||
self.preview_handler.slide(slide)
|
self.preview_handler.slide(slide)
|
||||||
|
|
||||||
def first(self, message):
|
def first(self, message):
|
||||||
|
"""
|
||||||
|
React to the message to move to the first slide
|
||||||
|
"""
|
||||||
is_live = message[1]
|
is_live = message[1]
|
||||||
if is_live:
|
if is_live:
|
||||||
self.live_handler.first()
|
self.live_handler.first()
|
||||||
@ -261,6 +294,9 @@ class MessageListener(object):
|
|||||||
self.preview_handler.first()
|
self.preview_handler.first()
|
||||||
|
|
||||||
def last(self, message):
|
def last(self, message):
|
||||||
|
"""
|
||||||
|
React to the message to move to the last slide
|
||||||
|
"""
|
||||||
is_live = message[1]
|
is_live = message[1]
|
||||||
if is_live:
|
if is_live:
|
||||||
self.live_handler.last()
|
self.live_handler.last()
|
||||||
@ -268,6 +304,9 @@ class MessageListener(object):
|
|||||||
self.preview_handler.last()
|
self.preview_handler.last()
|
||||||
|
|
||||||
def next(self, message):
|
def next(self, message):
|
||||||
|
"""
|
||||||
|
React to the message to move to the next animation/slide
|
||||||
|
"""
|
||||||
is_live = message[1]
|
is_live = message[1]
|
||||||
if is_live:
|
if is_live:
|
||||||
self.live_handler.next()
|
self.live_handler.next()
|
||||||
@ -275,6 +314,9 @@ class MessageListener(object):
|
|||||||
self.preview_handler.next()
|
self.preview_handler.next()
|
||||||
|
|
||||||
def previous(self, message):
|
def previous(self, message):
|
||||||
|
"""
|
||||||
|
React to the message to move to the previous animation/slide
|
||||||
|
"""
|
||||||
is_live = message[1]
|
is_live = message[1]
|
||||||
if is_live:
|
if is_live:
|
||||||
self.live_handler.previous()
|
self.live_handler.previous()
|
||||||
@ -282,6 +324,10 @@ class MessageListener(object):
|
|||||||
self.preview_handler.previous()
|
self.preview_handler.previous()
|
||||||
|
|
||||||
def shutdown(self, message):
|
def shutdown(self, message):
|
||||||
|
"""
|
||||||
|
React to message to shutdown the presentation. I.e. end the show
|
||||||
|
and close the file
|
||||||
|
"""
|
||||||
is_live = message[1]
|
is_live = message[1]
|
||||||
if is_live:
|
if is_live:
|
||||||
Receiver.send_message(u'maindisplay_show')
|
Receiver.send_message(u'maindisplay_show')
|
||||||
@ -290,19 +336,34 @@ class MessageListener(object):
|
|||||||
self.preview_handler.shutdown()
|
self.preview_handler.shutdown()
|
||||||
|
|
||||||
def hide(self, message):
|
def hide(self, message):
|
||||||
|
"""
|
||||||
|
React to the message to show the desktop
|
||||||
|
"""
|
||||||
is_live = message[1]
|
is_live = message[1]
|
||||||
if is_live:
|
if is_live:
|
||||||
self.live_handler.stop()
|
self.live_handler.stop()
|
||||||
|
|
||||||
def blank(self, message):
|
def blank(self, message):
|
||||||
|
"""
|
||||||
|
React to the message to blank the display
|
||||||
|
"""
|
||||||
is_live = message[1]
|
is_live = message[1]
|
||||||
if is_live:
|
if is_live:
|
||||||
self.live_handler.blank()
|
self.live_handler.blank()
|
||||||
|
|
||||||
def unblank(self, message):
|
def unblank(self, message):
|
||||||
|
"""
|
||||||
|
React to the message to unblank the display
|
||||||
|
"""
|
||||||
is_live = message[1]
|
is_live = message[1]
|
||||||
if is_live:
|
if is_live:
|
||||||
self.live_handler.unblank()
|
self.live_handler.unblank()
|
||||||
|
|
||||||
def timeout(self):
|
def timeout(self):
|
||||||
|
"""
|
||||||
|
The presentation may be timed or might be controlled by the
|
||||||
|
application directly, rather than through OpenLP. Poll occassionally
|
||||||
|
to check which slide is currently displayed so the slidecontroller
|
||||||
|
view can be updated
|
||||||
|
"""
|
||||||
self.live_handler.poll()
|
self.live_handler.poll()
|
||||||
|
@ -97,13 +97,23 @@ class PowerpointController(PresentationController):
|
|||||||
self.process = None
|
self.process = None
|
||||||
|
|
||||||
def add_doc(self, name):
|
def add_doc(self, name):
|
||||||
|
"""
|
||||||
|
Called when a new powerpoint document is opened
|
||||||
|
"""
|
||||||
log.debug(u'Add Doc PowerPoint')
|
log.debug(u'Add Doc PowerPoint')
|
||||||
doc = PowerpointDocument(self, name)
|
doc = PowerpointDocument(self, name)
|
||||||
self.docs.append(doc)
|
self.docs.append(doc)
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
class PowerpointDocument(PresentationDocument):
|
class PowerpointDocument(PresentationDocument):
|
||||||
|
"""
|
||||||
|
Class which holds information and controls a single presentation
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, controller, presentation):
|
def __init__(self, controller, presentation):
|
||||||
|
"""
|
||||||
|
Constructor, store information about the file and initialise
|
||||||
|
"""
|
||||||
log.debug(u'Init Presentation Powerpoint')
|
log.debug(u'Init Presentation Powerpoint')
|
||||||
PresentationDocument.__init__(self, controller, presentation)
|
PresentationDocument.__init__(self, controller, presentation)
|
||||||
self.presentation = None
|
self.presentation = None
|
||||||
@ -111,22 +121,23 @@ class PowerpointDocument(PresentationDocument):
|
|||||||
def load_presentation(self):
|
def load_presentation(self):
|
||||||
"""
|
"""
|
||||||
Called when a presentation is added to the SlideController.
|
Called when a presentation is added to the SlideController.
|
||||||
It builds the environment, starts communcations with the background
|
Opens the PowerPoint file using the process created earlier
|
||||||
OpenOffice task started earlier. If OpenOffice is not present is is
|
|
||||||
started. Once the environment is available the presentation is loaded
|
|
||||||
and started.
|
|
||||||
|
|
||||||
``presentation``
|
``presentation``
|
||||||
The file name of the presentations to run.
|
The file name of the presentations to run.
|
||||||
"""
|
"""
|
||||||
log.debug(u'LoadPresentation')
|
log.debug(u'LoadPresentation')
|
||||||
if not self.controller.process.Visible:
|
if not self.controller.process or not self.controller.process.Visible:
|
||||||
self.controller.start_process()
|
self.controller.start_process()
|
||||||
self.controller.process.Presentations.Open(self.filepath, False, False,
|
try:
|
||||||
True)
|
self.controller.process.Presentations.Open(self.filepath, False,
|
||||||
|
False, True)
|
||||||
|
except pywintypes.com_error:
|
||||||
|
return False
|
||||||
self.presentation = self.controller.process.Presentations(
|
self.presentation = self.controller.process.Presentations(
|
||||||
self.controller.process.Presentations.Count)
|
self.controller.process.Presentations.Count)
|
||||||
self.create_thumbnails()
|
self.create_thumbnails()
|
||||||
|
return True
|
||||||
|
|
||||||
def create_thumbnails(self):
|
def create_thumbnails(self):
|
||||||
"""
|
"""
|
||||||
@ -139,8 +150,8 @@ class PowerpointDocument(PresentationDocument):
|
|||||||
"""
|
"""
|
||||||
if self.check_thumbnails():
|
if self.check_thumbnails():
|
||||||
return
|
return
|
||||||
self.presentation.Export(os.path.join(self.thumbnailpath, ''), 'png',
|
self.presentation.Export(os.path.join(self.get_thumbnail_folder(), ''),
|
||||||
320, 240)
|
'png', 320, 240)
|
||||||
|
|
||||||
def close_presentation(self):
|
def close_presentation(self):
|
||||||
"""
|
"""
|
||||||
@ -298,4 +309,4 @@ class PowerpointDocument(PresentationDocument):
|
|||||||
shape = shapes(idx + 1)
|
shape = shapes(idx + 1)
|
||||||
if shape.HasTextFrame:
|
if shape.HasTextFrame:
|
||||||
text += shape.TextFrame.TextRange.Text + '\n'
|
text += shape.TextFrame.TextRange.Text + '\n'
|
||||||
return text
|
return text
|
||||||
|
@ -93,13 +93,22 @@ class PptviewController(PresentationController):
|
|||||||
self.docs[0].close_presentation()
|
self.docs[0].close_presentation()
|
||||||
|
|
||||||
def add_doc(self, name):
|
def add_doc(self, name):
|
||||||
|
"""
|
||||||
|
Called when a new powerpoint document is opened
|
||||||
|
"""
|
||||||
log.debug(u'Add Doc PPTView')
|
log.debug(u'Add Doc PPTView')
|
||||||
doc = PptviewDocument(self, name)
|
doc = PptviewDocument(self, name)
|
||||||
self.docs.append(doc)
|
self.docs.append(doc)
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
class PptviewDocument(PresentationDocument):
|
class PptviewDocument(PresentationDocument):
|
||||||
|
"""
|
||||||
|
Class which holds information and controls a single presentation
|
||||||
|
"""
|
||||||
def __init__(self, controller, presentation):
|
def __init__(self, controller, presentation):
|
||||||
|
"""
|
||||||
|
Constructor, store information about the file and initialise
|
||||||
|
"""
|
||||||
log.debug(u'Init Presentation PowerPoint')
|
log.debug(u'Init Presentation PowerPoint')
|
||||||
PresentationDocument.__init__(self, controller, presentation)
|
PresentationDocument.__init__(self, controller, presentation)
|
||||||
self.presentation = None
|
self.presentation = None
|
||||||
@ -117,17 +126,31 @@ class PptviewDocument(PresentationDocument):
|
|||||||
The file name of the presentations to run.
|
The file name of the presentations to run.
|
||||||
"""
|
"""
|
||||||
log.debug(u'LoadPresentation')
|
log.debug(u'LoadPresentation')
|
||||||
#if self.pptid >= 0:
|
|
||||||
# self.close_presentation()
|
|
||||||
rendermanager = self.controller.plugin.renderManager
|
rendermanager = self.controller.plugin.renderManager
|
||||||
rect = rendermanager.screens.current[u'size']
|
rect = rendermanager.screens.current[u'size']
|
||||||
rect = RECT(rect.x(), rect.y(), rect.right(), rect.bottom())
|
rect = RECT(rect.x(), rect.y(), rect.right(), rect.bottom())
|
||||||
filepath = str(self.filepath.replace(u'/', u'\\'))
|
filepath = str(self.filepath.replace(u'/', u'\\'))
|
||||||
|
if not os.path.isdir(self.get_temp_folder()):
|
||||||
|
os.makedirs(self.get_temp_folder())
|
||||||
self.pptid = self.controller.process.OpenPPT(filepath, None, rect,
|
self.pptid = self.controller.process.OpenPPT(filepath, None, rect,
|
||||||
str(os.path.join(self.thumbnailpath,
|
str(self.get_temp_folder()) + '\\slide')
|
||||||
self.controller.thumbnailprefix)))
|
if self.pptid >= 0:
|
||||||
if self.pptid:
|
self.create_thumbnails()
|
||||||
self.stop_presentation()
|
self.stop_presentation()
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def create_thumbnails(self):
|
||||||
|
"""
|
||||||
|
PPTviewLib creates large BMP's, but we want small PNG's for consistency.
|
||||||
|
Convert them here.
|
||||||
|
"""
|
||||||
|
if self.check_thumbnails():
|
||||||
|
return
|
||||||
|
for idx in range(self.get_slide_count()):
|
||||||
|
path = u'%s\\slide%s.bmp' % (self.get_temp_folder(), unicode(idx + 1))
|
||||||
|
self.convert_thumbnail(path, idx + 1)
|
||||||
|
|
||||||
def close_presentation(self):
|
def close_presentation(self):
|
||||||
"""
|
"""
|
||||||
@ -224,17 +247,3 @@ class PptviewDocument(PresentationDocument):
|
|||||||
"""
|
"""
|
||||||
self.controller.process.PrevStep(self.pptid)
|
self.controller.process.PrevStep(self.pptid)
|
||||||
|
|
||||||
def get_slide_preview_file(self, slide_no):
|
|
||||||
"""
|
|
||||||
Returns an image path containing a preview for the requested slide
|
|
||||||
|
|
||||||
``slide_no``
|
|
||||||
The slide an image is required for, starting at 1
|
|
||||||
"""
|
|
||||||
path = os.path.join(self.thumbnailpath,
|
|
||||||
self.controller.thumbnailprefix + unicode(slide_no) + u'.bmp')
|
|
||||||
if os.path.isfile(path):
|
|
||||||
return path
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ import shutil
|
|||||||
|
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
from openlp.core.lib import Receiver
|
from openlp.core.lib import Receiver, resize_image
|
||||||
from openlp.core.utils import AppLocation
|
from openlp.core.utils import AppLocation
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -63,6 +63,13 @@ class PresentationController(object):
|
|||||||
``plugin``
|
``plugin``
|
||||||
The presentationplugin object
|
The presentationplugin object
|
||||||
|
|
||||||
|
``supports``
|
||||||
|
The primary native file types this application supports
|
||||||
|
|
||||||
|
``alsosupports``
|
||||||
|
Other file types the application can import, although not necessarily
|
||||||
|
the first choice due to potential incompatibilities
|
||||||
|
|
||||||
**Hook Functions**
|
**Hook Functions**
|
||||||
|
|
||||||
``kill()``
|
``kill()``
|
||||||
@ -109,12 +116,16 @@ class PresentationController(object):
|
|||||||
QtCore.Qt.Checked
|
QtCore.Qt.Checked
|
||||||
else:
|
else:
|
||||||
self.enabled = False
|
self.enabled = False
|
||||||
self.thumbnailroot = os.path.join(
|
self.temp_folder = os.path.join(
|
||||||
|
AppLocation.get_section_data_path(self.settings_section), name)
|
||||||
|
self.thumbnail_folder = os.path.join(
|
||||||
AppLocation.get_section_data_path(self.settings_section),
|
AppLocation.get_section_data_path(self.settings_section),
|
||||||
name, u'thumbnails')
|
u'thumbnails')
|
||||||
self.thumbnailprefix = u'slide'
|
self.thumbnail_prefix = u'slide'
|
||||||
if not os.path.isdir(self.thumbnailroot):
|
if not os.path.isdir(self.thumbnail_folder):
|
||||||
os.makedirs(self.thumbnailroot)
|
os.makedirs(self.thumbnail_folder)
|
||||||
|
if not os.path.isdir(self.temp_folder):
|
||||||
|
os.makedirs(self.temp_folder)
|
||||||
|
|
||||||
def check_available(self):
|
def check_available(self):
|
||||||
"""
|
"""
|
||||||
@ -208,14 +219,19 @@ class PresentationDocument(object):
|
|||||||
``previous_step()``
|
``previous_step()``
|
||||||
Triggers the previous slide on the running presentation
|
Triggers the previous slide on the running presentation
|
||||||
|
|
||||||
``get_slide_preview_file(slide_no)``
|
``get_thumbnail_path(slide_no, check_exists)``
|
||||||
Returns a path to an image containing a preview for the requested slide
|
Returns a path to an image containing a preview for the requested slide
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, controller, name):
|
def __init__(self, controller, name):
|
||||||
|
"""
|
||||||
|
Constructor for the PresentationController class
|
||||||
|
"""
|
||||||
self.slidenumber = 0
|
self.slidenumber = 0
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.store_filename(name)
|
self.filepath = name
|
||||||
|
if not os.path.isdir(self.get_thumbnail_folder()):
|
||||||
|
os.mkdir(self.get_thumbnail_folder())
|
||||||
|
|
||||||
def load_presentation(self):
|
def load_presentation(self):
|
||||||
"""
|
"""
|
||||||
@ -224,9 +240,10 @@ class PresentationDocument(object):
|
|||||||
|
|
||||||
``presentation``
|
``presentation``
|
||||||
The file name of the presentations to the run.
|
The file name of the presentations to the run.
|
||||||
|
|
||||||
|
Returns False if the file could not be opened
|
||||||
"""
|
"""
|
||||||
pass
|
return False
|
||||||
|
|
||||||
def presentation_deleted(self):
|
def presentation_deleted(self):
|
||||||
"""
|
"""
|
||||||
@ -234,33 +251,37 @@ class PresentationDocument(object):
|
|||||||
a file, e.g. thumbnails
|
a file, e.g. thumbnails
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(self.thumbnailpath)
|
shutil.rmtree(self.get_thumbnail_folder())
|
||||||
|
shutil.rmtree(self.get_temp_folder())
|
||||||
except OSError:
|
except OSError:
|
||||||
log.exception(u'Failed to delete presentation controller files')
|
log.exception(u'Failed to delete presentation controller files')
|
||||||
|
|
||||||
def store_filename(self, presentation):
|
def get_file_name(self):
|
||||||
"""
|
"""
|
||||||
Set properties for the filename and thumbnail paths
|
Return just the filename of the presention, without the directory
|
||||||
"""
|
"""
|
||||||
self.filepath = presentation
|
return os.path.split(self.filepath)[1]
|
||||||
self.filename = self.get_file_name(presentation)
|
|
||||||
self.thumbnailpath = self.get_thumbnail_path(presentation)
|
|
||||||
if not os.path.isdir(self.thumbnailpath):
|
|
||||||
os.mkdir(self.thumbnailpath)
|
|
||||||
|
|
||||||
def get_file_name(self, presentation):
|
def get_thumbnail_folder(self):
|
||||||
return os.path.split(presentation)[1]
|
"""
|
||||||
|
The location where thumbnail images will be stored
|
||||||
def get_thumbnail_path(self, presentation):
|
"""
|
||||||
return os.path.join(
|
return os.path.join(
|
||||||
self.controller.thumbnailroot, self.get_file_name(presentation))
|
self.controller.thumbnail_folder, self.get_file_name())
|
||||||
|
|
||||||
|
def get_temp_folder(self):
|
||||||
|
"""
|
||||||
|
The location where thumbnail images will be stored
|
||||||
|
"""
|
||||||
|
return os.path.join(
|
||||||
|
self.controller.temp_folder, self.get_file_name())
|
||||||
|
|
||||||
def check_thumbnails(self):
|
def check_thumbnails(self):
|
||||||
"""
|
"""
|
||||||
Returns true if the thumbnail images look to exist and are more
|
Returns true if the thumbnail images look to exist and are more
|
||||||
recent than the powerpoint
|
recent than the powerpoint
|
||||||
"""
|
"""
|
||||||
lastimage = self.get_slide_preview_file(self.get_slide_count())
|
lastimage = self.get_thumbnail_path(self.get_slide_count(), True)
|
||||||
if not (lastimage and os.path.isfile(lastimage)):
|
if not (lastimage and os.path.isfile(lastimage)):
|
||||||
return False
|
return False
|
||||||
imgdate = os.stat(lastimage).st_mtime
|
imgdate = os.stat(lastimage).st_mtime
|
||||||
@ -350,16 +371,27 @@ class PresentationDocument(object):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_slide_preview_file(self, slide_no):
|
def convert_thumbnail(self, file, idx):
|
||||||
|
"""
|
||||||
|
Convert the slide image the application made to a standard 320x240
|
||||||
|
.png image.
|
||||||
|
"""
|
||||||
|
if self.check_thumbnails():
|
||||||
|
return
|
||||||
|
if os.path.isfile(file):
|
||||||
|
img = resize_image(file, 320, 240)
|
||||||
|
img.save(self.get_thumbnail_path(idx, False))
|
||||||
|
|
||||||
|
def get_thumbnail_path(self, slide_no, check_exists):
|
||||||
"""
|
"""
|
||||||
Returns an image path containing a preview for the requested slide
|
Returns an image path containing a preview for the requested slide
|
||||||
|
|
||||||
``slide_no``
|
``slide_no``
|
||||||
The slide an image is required for, starting at 1
|
The slide an image is required for, starting at 1
|
||||||
"""
|
"""
|
||||||
path = os.path.join(self.thumbnailpath,
|
path = os.path.join(self.get_thumbnail_folder(),
|
||||||
self.controller.thumbnailprefix + unicode(slide_no) + u'.png')
|
self.controller.thumbnail_prefix + unicode(slide_no) + u'.png')
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path) or not check_exists:
|
||||||
return path
|
return path
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
@ -32,10 +32,16 @@ class PresentationTab(SettingsTab):
|
|||||||
PresentationsTab is the Presentations settings tab in the settings dialog.
|
PresentationsTab is the Presentations settings tab in the settings dialog.
|
||||||
"""
|
"""
|
||||||
def __init__(self, title, controllers):
|
def __init__(self, title, controllers):
|
||||||
|
"""
|
||||||
|
Constructor
|
||||||
|
"""
|
||||||
self.controllers = controllers
|
self.controllers = controllers
|
||||||
SettingsTab.__init__(self, title)
|
SettingsTab.__init__(self, title)
|
||||||
|
|
||||||
def setupUi(self):
|
def setupUi(self):
|
||||||
|
"""
|
||||||
|
Create the controls for the settings tab
|
||||||
|
"""
|
||||||
self.setObjectName(u'PresentationTab')
|
self.setObjectName(u'PresentationTab')
|
||||||
self.tabTitleVisible = translate('PresentationPlugin.PresentationTab',
|
self.tabTitleVisible = translate('PresentationPlugin.PresentationTab',
|
||||||
'Presentations')
|
'Presentations')
|
||||||
@ -89,6 +95,9 @@ class PresentationTab(SettingsTab):
|
|||||||
self.PresentationLayout.addWidget(self.PresentationRightWidget)
|
self.PresentationLayout.addWidget(self.PresentationRightWidget)
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslateUi(self):
|
||||||
|
"""
|
||||||
|
Make any translation changes
|
||||||
|
"""
|
||||||
self.VerseDisplayGroupBox.setTitle(
|
self.VerseDisplayGroupBox.setTitle(
|
||||||
translate('PresentationPlugin.PresentationTab',
|
translate('PresentationPlugin.PresentationTab',
|
||||||
'Available Controllers'))
|
'Available Controllers'))
|
||||||
@ -100,6 +109,9 @@ class PresentationTab(SettingsTab):
|
|||||||
translate('PresentationPlugin.PresentationTab', 'available')))
|
translate('PresentationPlugin.PresentationTab', 'available')))
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
|
"""
|
||||||
|
Load the settings.
|
||||||
|
"""
|
||||||
for key in self.controllers:
|
for key in self.controllers:
|
||||||
controller = self.controllers[key]
|
controller = self.controllers[key]
|
||||||
if controller.available:
|
if controller.available:
|
||||||
@ -109,6 +121,9 @@ class PresentationTab(SettingsTab):
|
|||||||
QtCore.QVariant(0)).toInt()[0])
|
QtCore.QVariant(0)).toInt()[0])
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
|
"""
|
||||||
|
Save the settings.
|
||||||
|
"""
|
||||||
for key in self.controllers:
|
for key in self.controllers:
|
||||||
controller = self.controllers[key]
|
controller = self.controllers[key]
|
||||||
checkbox = self.PresenterCheckboxes[controller.name]
|
checkbox = self.PresenterCheckboxes[controller.name]
|
||||||
|
@ -33,14 +33,23 @@ from openlp.plugins.presentations.lib import *
|
|||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
class PresentationPlugin(Plugin):
|
class PresentationPlugin(Plugin):
|
||||||
|
"""
|
||||||
|
This plugin allowed a Presentation to be opened, controlled and displayed
|
||||||
|
on the output display. The plugin controls third party applications such
|
||||||
|
as OpenOffice.org Impress, Microsoft PowerPoint and the PowerPoint viewer
|
||||||
|
"""
|
||||||
log = logging.getLogger(u'PresentationPlugin')
|
log = logging.getLogger(u'PresentationPlugin')
|
||||||
|
|
||||||
def __init__(self, plugin_helpers):
|
def __init__(self, plugin_helpers):
|
||||||
|
"""
|
||||||
|
PluginPresentation constructor.
|
||||||
|
"""
|
||||||
log.debug(u'Initialised')
|
log.debug(u'Initialised')
|
||||||
self.controllers = {}
|
self.controllers = {}
|
||||||
Plugin.__init__(self, u'Presentations', u'1.9.2', plugin_helpers)
|
Plugin.__init__(self, u'Presentations', u'1.9.2', plugin_helpers)
|
||||||
self.weight = -8
|
self.weight = -8
|
||||||
self.icon = build_icon(u':/plugins/plugin_presentations.png')
|
self.icon_path = u':/plugins/plugin_presentations.png'
|
||||||
|
self.icon = build_icon(self.icon_path)
|
||||||
self.status = PluginStatus.Active
|
self.status = PluginStatus.Active
|
||||||
|
|
||||||
def getSettingsTab(self):
|
def getSettingsTab(self):
|
||||||
@ -50,6 +59,10 @@ class PresentationPlugin(Plugin):
|
|||||||
return PresentationTab(self.name, self.controllers)
|
return PresentationTab(self.name, self.controllers)
|
||||||
|
|
||||||
def initialise(self):
|
def initialise(self):
|
||||||
|
"""
|
||||||
|
Initialise the plugin. Determine which controllers are enabled
|
||||||
|
are start their processes.
|
||||||
|
"""
|
||||||
log.info(u'Presentations Initialising')
|
log.info(u'Presentations Initialising')
|
||||||
Plugin.initialise(self)
|
Plugin.initialise(self)
|
||||||
self.insertToolboxItem()
|
self.insertToolboxItem()
|
||||||
@ -58,6 +71,10 @@ class PresentationPlugin(Plugin):
|
|||||||
self.controllers[controller].start_process()
|
self.controllers[controller].start_process()
|
||||||
|
|
||||||
def finalise(self):
|
def finalise(self):
|
||||||
|
"""
|
||||||
|
Finalise the plugin. Ask all the enabled presentation applications
|
||||||
|
to close down their applications and release resources.
|
||||||
|
"""
|
||||||
log.info(u'Plugin Finalise')
|
log.info(u'Plugin Finalise')
|
||||||
#Ask each controller to tidy up
|
#Ask each controller to tidy up
|
||||||
for key in self.controllers:
|
for key in self.controllers:
|
||||||
@ -74,6 +91,10 @@ class PresentationPlugin(Plugin):
|
|||||||
self, self.icon, self.name, self.controllers)
|
self, self.icon, self.name, self.controllers)
|
||||||
|
|
||||||
def registerControllers(self, controller):
|
def registerControllers(self, controller):
|
||||||
|
"""
|
||||||
|
Register each presentation controller (Impress, PPT etc) and
|
||||||
|
store for later use
|
||||||
|
"""
|
||||||
self.controllers[controller.name] = controller
|
self.controllers[controller.name] = controller
|
||||||
|
|
||||||
def checkPreConditions(self):
|
def checkPreConditions(self):
|
||||||
@ -108,9 +129,13 @@ class PresentationPlugin(Plugin):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def about(self):
|
def about(self):
|
||||||
|
"""
|
||||||
|
Return information about this plugin
|
||||||
|
"""
|
||||||
about_text = translate('PresentationPlugin',
|
about_text = translate('PresentationPlugin',
|
||||||
'<b>Presentation Plugin</b> <br> Delivers '
|
'<b>Presentation Plugin</b> <br> Delivers '
|
||||||
'the ability to show presentations using a number of different '
|
'the ability to show presentations using a number of different '
|
||||||
'programs. The choice of available presentation programs is '
|
'programs. The choice of available presentation programs is '
|
||||||
'available to the user in a drop down box.')
|
'available to the user in a drop down box.')
|
||||||
return about_text
|
return about_text
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
from PyQt4 import QtGui, QtCore
|
from PyQt4 import QtGui, QtCore
|
||||||
|
from sqlalchemy.sql import and_
|
||||||
|
|
||||||
from openlp.core.lib import translate
|
from openlp.core.lib import translate
|
||||||
from openlp.plugins.songs.forms import AuthorsForm, TopicsForm, SongBookForm
|
from openlp.plugins.songs.forms import AuthorsForm, TopicsForm, SongBookForm
|
||||||
@ -97,6 +98,9 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
QtGui.QMessageBox.critical(self, dlg_title, sel_text)
|
QtGui.QMessageBox.critical(self, dlg_title, sel_text)
|
||||||
|
|
||||||
def resetAuthors(self):
|
def resetAuthors(self):
|
||||||
|
"""
|
||||||
|
Reloads the Authors list.
|
||||||
|
"""
|
||||||
self.AuthorsListWidget.clear()
|
self.AuthorsListWidget.clear()
|
||||||
authors = self.songmanager.get_all_objects(Author, Author.display_name)
|
authors = self.songmanager.get_all_objects(Author, Author.display_name)
|
||||||
for author in authors:
|
for author in authors:
|
||||||
@ -109,6 +113,9 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
self.AuthorsListWidget.addItem(author_name)
|
self.AuthorsListWidget.addItem(author_name)
|
||||||
|
|
||||||
def resetTopics(self):
|
def resetTopics(self):
|
||||||
|
"""
|
||||||
|
Reloads the Topics list.
|
||||||
|
"""
|
||||||
self.TopicsListWidget.clear()
|
self.TopicsListWidget.clear()
|
||||||
topics = self.songmanager.get_all_objects(Topic, Topic.name)
|
topics = self.songmanager.get_all_objects(Topic, Topic.name)
|
||||||
for topic in topics:
|
for topic in topics:
|
||||||
@ -117,13 +124,88 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
self.TopicsListWidget.addItem(topic_name)
|
self.TopicsListWidget.addItem(topic_name)
|
||||||
|
|
||||||
def resetBooks(self):
|
def resetBooks(self):
|
||||||
|
"""
|
||||||
|
Reloads the Books list.
|
||||||
|
"""
|
||||||
self.BooksListWidget.clear()
|
self.BooksListWidget.clear()
|
||||||
books = self.songmanager.get_all_objects(Book, Book.name)
|
books = self.songmanager.get_all_objects(Book, Book.name)
|
||||||
for book in books:
|
for book in books:
|
||||||
book_name = QtGui.QListWidgetItem(book.name)
|
book_name = QtGui.QListWidgetItem(u'%s (%s)' % (book.name,
|
||||||
|
book.publisher))
|
||||||
book_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(book.id))
|
book_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(book.id))
|
||||||
self.BooksListWidget.addItem(book_name)
|
self.BooksListWidget.addItem(book_name)
|
||||||
|
|
||||||
|
def checkAuthor(self, new_author, edit=False):
|
||||||
|
"""
|
||||||
|
Returns False when the given Author is already in the list elsewise
|
||||||
|
True.
|
||||||
|
"""
|
||||||
|
authors = self.songmanager.get_all_objects_filtered(Author,
|
||||||
|
and_(
|
||||||
|
Author.first_name == new_author.first_name,
|
||||||
|
Author.last_name == new_author.last_name,
|
||||||
|
Author.display_name == new_author.display_name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if len(authors) > 0:
|
||||||
|
# If we edit an existing Author, we need to make sure that we do
|
||||||
|
# not return False when nothing has changed (because this would
|
||||||
|
# cause an error message later on).
|
||||||
|
if edit:
|
||||||
|
if authors[0].id == new_author.id:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def checkTopic(self, new_topic, edit=False):
|
||||||
|
"""
|
||||||
|
Returns False when the given Topic is already in the list elsewise True.
|
||||||
|
"""
|
||||||
|
topics = self.songmanager.get_all_objects_filtered(Topic,
|
||||||
|
Topic.name == new_topic.name
|
||||||
|
)
|
||||||
|
if len(topics) > 0:
|
||||||
|
# If we edit an existing Topic, we need to make sure that we do
|
||||||
|
# not return False when nothing has changed (because this would
|
||||||
|
# cause an error message later on).
|
||||||
|
if edit:
|
||||||
|
if topics[0].id == new_topic.id:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def checkBook(self, new_book, edit=False):
|
||||||
|
"""
|
||||||
|
Returns False when the given Book is already in the list elsewise True.
|
||||||
|
"""
|
||||||
|
books = self.songmanager.get_all_objects_filtered(Book,
|
||||||
|
and_(
|
||||||
|
Book.name == new_book.name,
|
||||||
|
Book.publisher == new_book.publisher
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if len(books) > 0:
|
||||||
|
# If we edit an existing Book, we need to make sure that we do
|
||||||
|
# not return False when nothing has changed (because this would
|
||||||
|
# cause an error message later on).
|
||||||
|
if edit:
|
||||||
|
if books[0].id == new_book.id:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
def onAuthorAddButtonClick(self):
|
def onAuthorAddButtonClick(self):
|
||||||
self.authorform.setAutoDisplayName(True)
|
self.authorform.setAutoDisplayName(True)
|
||||||
if self.authorform.exec_():
|
if self.authorform.exec_():
|
||||||
@ -131,86 +213,93 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
first_name=unicode(self.authorform.FirstNameEdit.text()),
|
first_name=unicode(self.authorform.FirstNameEdit.text()),
|
||||||
last_name=unicode(self.authorform.LastNameEdit.text()),
|
last_name=unicode(self.authorform.LastNameEdit.text()),
|
||||||
display_name=unicode(self.authorform.DisplayEdit.text()))
|
display_name=unicode(self.authorform.DisplayEdit.text()))
|
||||||
if self.songmanager.save_object(author):
|
if self.checkAuthor(author):
|
||||||
self.resetAuthors()
|
if self.songmanager.save_object(author):
|
||||||
|
self.resetAuthors()
|
||||||
else:
|
else:
|
||||||
QtGui.QMessageBox.critical(
|
QtGui.QMessageBox.critical(self,
|
||||||
self, translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm', 'Error'),
|
||||||
'Error'),
|
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm',
|
||||||
'Couldn\'t add your author.'))
|
'Could not add your author.'))
|
||||||
|
|
||||||
def onTopicAddButtonClick(self):
|
def onTopicAddButtonClick(self):
|
||||||
if self.topicform.exec_():
|
if self.topicform.exec_():
|
||||||
topic = Topic.populate(name=unicode(self.topicform.NameEdit.text()))
|
topic = Topic.populate(name=unicode(self.topicform.NameEdit.text()))
|
||||||
if self.songmanager.save_object(topic):
|
if self.checkTopic(topic):
|
||||||
self.resetTopics()
|
if self.songmanager.save_object(topic):
|
||||||
|
self.resetTopics()
|
||||||
else:
|
else:
|
||||||
QtGui.QMessageBox.critical(
|
QtGui.QMessageBox.critical(self,
|
||||||
self, translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm', 'Error'),
|
||||||
'Error'),
|
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm',
|
||||||
'Couldn\'t add your topic.'))
|
'Could not add your topic.'))
|
||||||
|
|
||||||
def onBookAddButtonClick(self):
|
def onBookAddButtonClick(self):
|
||||||
if self.bookform.exec_():
|
if self.bookform.exec_():
|
||||||
book = Book.populate(
|
book = Book.populate(
|
||||||
name=unicode(self.bookform.NameEdit.text()),
|
name=unicode(self.bookform.NameEdit.text()),
|
||||||
publisher=unicode(self.bookform.PublisherEdit.text()))
|
publisher=unicode(self.bookform.PublisherEdit.text()))
|
||||||
if self.songmanager.save_object(book):
|
if self.checkBook(book):
|
||||||
self.resetBooks()
|
if self.songmanager.save_object(book):
|
||||||
|
self.resetBooks()
|
||||||
else:
|
else:
|
||||||
QtGui.QMessageBox.critical(
|
QtGui.QMessageBox.critical(self,
|
||||||
self, translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm', 'Error'),
|
||||||
'Error'),
|
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm',
|
||||||
'Couldn\'t add your book.'))
|
'Could not add your book.'))
|
||||||
|
|
||||||
def onAuthorEditButtonClick(self):
|
def onAuthorEditButtonClick(self):
|
||||||
author_id = self._getCurrentItemId(self.AuthorsListWidget)
|
author_id = self._getCurrentItemId(self.AuthorsListWidget)
|
||||||
if author_id != -1:
|
if author_id != -1:
|
||||||
author = self.songmanager.get_object(Author, author_id)
|
author = self.songmanager.get_object(Author, author_id)
|
||||||
# Just make sure none of the fields is None
|
|
||||||
if author.first_name is None:
|
|
||||||
author.first_name = u''
|
|
||||||
if author.last_name is None:
|
|
||||||
author.last_name = u''
|
|
||||||
if author.display_name is None:
|
|
||||||
author.display_name = u''
|
|
||||||
self.authorform.setAutoDisplayName(False)
|
self.authorform.setAutoDisplayName(False)
|
||||||
self.authorform.FirstNameEdit.setText(author.first_name)
|
self.authorform.FirstNameEdit.setText(author.first_name)
|
||||||
self.authorform.LastNameEdit.setText(author.last_name)
|
self.authorform.LastNameEdit.setText(author.last_name)
|
||||||
self.authorform.DisplayEdit.setText(author.display_name)
|
self.authorform.DisplayEdit.setText(author.display_name)
|
||||||
|
# Save the author's first and last name as well as the display name
|
||||||
|
# for the case that they have to be restored.
|
||||||
|
temp_first_name = author.first_name
|
||||||
|
temp_last_name = author.last_name
|
||||||
|
temp_display_name = author.display_name
|
||||||
if self.authorform.exec_(False):
|
if self.authorform.exec_(False):
|
||||||
author.first_name = unicode(
|
author.first_name = unicode(
|
||||||
self.authorform.FirstNameEdit.text())
|
self.authorform.FirstNameEdit.text())
|
||||||
author.last_name = unicode(self.authorform.LastNameEdit.text())
|
author.last_name = unicode(self.authorform.LastNameEdit.text())
|
||||||
author.display_name = unicode(
|
author.display_name = unicode(
|
||||||
self.authorform.DisplayEdit.text())
|
self.authorform.DisplayEdit.text())
|
||||||
if self.songmanager.save_object(author):
|
if self.checkAuthor(author, True):
|
||||||
self.resetAuthors()
|
if self.songmanager.save_object(author):
|
||||||
|
self.resetAuthors()
|
||||||
else:
|
else:
|
||||||
QtGui.QMessageBox.critical(
|
# We restore the author's old first and last name as well as
|
||||||
self, translate('SongsPlugin.SongMaintenanceForm',
|
# his display name.
|
||||||
'Error'),
|
author.first_name = temp_first_name
|
||||||
|
author.last_name = temp_last_name
|
||||||
|
author.display_name = temp_display_name
|
||||||
|
QtGui.QMessageBox.critical(self,
|
||||||
|
translate('SongsPlugin.SongMaintenanceForm', 'Error'),
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm',
|
||||||
'Couldn\'t save your author.'))
|
'Could not save your author.'))
|
||||||
|
|
||||||
def onTopicEditButtonClick(self):
|
def onTopicEditButtonClick(self):
|
||||||
topic_id = self._getCurrentItemId(self.TopicsListWidget)
|
topic_id = self._getCurrentItemId(self.TopicsListWidget)
|
||||||
if topic_id != -1:
|
if topic_id != -1:
|
||||||
topic = self.songmanager.get_object(Topic, topic_id)
|
topic = self.songmanager.get_object(Topic, topic_id)
|
||||||
self.topicform.NameEdit.setText(topic.name)
|
self.topicform.NameEdit.setText(topic.name)
|
||||||
|
# Save the topic's name for the case that he has to be restored.
|
||||||
|
temp_name = topic.name
|
||||||
if self.topicform.exec_(False):
|
if self.topicform.exec_(False):
|
||||||
topic.name = unicode(self.topicform.NameEdit.text())
|
topic.name = unicode(self.topicform.NameEdit.text())
|
||||||
if self.songmanager.save_object(topic):
|
if self.checkTopic(topic, True):
|
||||||
self.resetTopics()
|
if self.songmanager.save_object(topic):
|
||||||
|
self.resetTopics()
|
||||||
else:
|
else:
|
||||||
QtGui.QMessageBox.critical(
|
# We restore the topics's old name.
|
||||||
self, translate('SongsPlugin.SongMaintenanceForm',
|
topic.name = temp_name
|
||||||
'Error'),
|
QtGui.QMessageBox.critical(self,
|
||||||
|
translate('SongsPlugin.SongMaintenanceForm', 'Error'),
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm',
|
||||||
'Couldn\'t save your topic.'))
|
'Could not save your topic.'))
|
||||||
|
|
||||||
def onBookEditButtonClick(self):
|
def onBookEditButtonClick(self):
|
||||||
book_id = self._getCurrentItemId(self.BooksListWidget)
|
book_id = self._getCurrentItemId(self.BooksListWidget)
|
||||||
@ -218,17 +307,24 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
book = self.songmanager.get_object(Book, book_id)
|
book = self.songmanager.get_object(Book, book_id)
|
||||||
self.bookform.NameEdit.setText(book.name)
|
self.bookform.NameEdit.setText(book.name)
|
||||||
self.bookform.PublisherEdit.setText(book.publisher)
|
self.bookform.PublisherEdit.setText(book.publisher)
|
||||||
|
# Save the book's name and publisher for the case that they have to
|
||||||
|
# be restored.
|
||||||
|
temp_name = book.name
|
||||||
|
temp_publisher = book.publisher
|
||||||
if self.bookform.exec_(False):
|
if self.bookform.exec_(False):
|
||||||
book.name = unicode(self.bookform.NameEdit.text())
|
book.name = unicode(self.bookform.NameEdit.text())
|
||||||
book.publisher = unicode(self.bookform.PublisherEdit.text())
|
book.publisher = unicode(self.bookform.PublisherEdit.text())
|
||||||
if self.songmanager.save_object(book):
|
if self.checkBook(book, True):
|
||||||
self.resetBooks()
|
if self.songmanager.save_object(book):
|
||||||
|
self.resetBooks()
|
||||||
else:
|
else:
|
||||||
QtGui.QMessageBox.critical(
|
# We restore the book's old name and publisher.
|
||||||
self, translate('SongsPlugin.SongMaintenanceForm',
|
book.name = temp_name
|
||||||
'Error'),
|
book.publisher = temp_publisher
|
||||||
|
QtGui.QMessageBox.critical(self,
|
||||||
|
translate('SongsPlugin.SongMaintenanceForm', 'Error'),
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm',
|
||||||
'Couldn\'t save your book.'))
|
'Could not save your book.'))
|
||||||
|
|
||||||
def onAuthorDeleteButtonClick(self):
|
def onAuthorDeleteButtonClick(self):
|
||||||
"""
|
"""
|
||||||
@ -236,13 +332,12 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
"""
|
"""
|
||||||
self._deleteItem(Author, self.AuthorsListWidget, self.resetAuthors,
|
self._deleteItem(Author, self.AuthorsListWidget, self.resetAuthors,
|
||||||
translate('SongsPlugin.SongMaintenanceForm', 'Delete Author'),
|
translate('SongsPlugin.SongMaintenanceForm', 'Delete Author'),
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm',
|
||||||
'Are you sure you want to delete the selected author?'),
|
'Are you sure you want to delete the selected author?'),
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm',
|
||||||
'This author can\'t be deleted, they are currently '
|
'This author cannot be deleted, they are currently '
|
||||||
'assigned to at least one song.'),
|
'assigned to at least one song.'),
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm', 'No author selected!'))
|
||||||
'No author selected!'))
|
|
||||||
|
|
||||||
def onTopicDeleteButtonClick(self):
|
def onTopicDeleteButtonClick(self):
|
||||||
"""
|
"""
|
||||||
@ -250,13 +345,12 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
"""
|
"""
|
||||||
self._deleteItem(Topic, self.TopicsListWidget, self.resetTopics,
|
self._deleteItem(Topic, self.TopicsListWidget, self.resetTopics,
|
||||||
translate('SongsPlugin.SongMaintenanceForm', 'Delete Topic'),
|
translate('SongsPlugin.SongMaintenanceForm', 'Delete Topic'),
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
|
||||||
'Are you sure you want to delete the selected topic?'),
|
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
|
||||||
'This topic can\'t be deleted, it is currently '
|
|
||||||
'assigned to at least one song.'),
|
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm',
|
||||||
'No topic selected!'))
|
'Are you sure you want to delete the selected topic?'),
|
||||||
|
translate('SongsPlugin.SongMaintenanceForm',
|
||||||
|
'This topic cannot be deleted, it is currently '
|
||||||
|
'assigned to at least one song.'),
|
||||||
|
translate('SongsPlugin.SongMaintenanceForm', 'No topic selected!'))
|
||||||
|
|
||||||
def onBookDeleteButtonClick(self):
|
def onBookDeleteButtonClick(self):
|
||||||
"""
|
"""
|
||||||
@ -266,7 +360,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||||||
translate('SongsPlugin.SongMaintenanceForm', 'Delete Book'),
|
translate('SongsPlugin.SongMaintenanceForm', 'Delete Book'),
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm',
|
||||||
'Are you sure you want to delete the selected book?'),
|
'Are you sure you want to delete the selected book?'),
|
||||||
translate('SongsPlugin.SongMaintenanceForm',
|
translate('SongsPlugin.SongMaintenanceForm',
|
||||||
'This book can\'t be deleted, it is currently '
|
'This book cannot be deleted, it is currently '
|
||||||
'assigned to at least one song.'),
|
'assigned to at least one song.'),
|
||||||
translate('SongsPlugin.SongMaintenanceForm', u'No book selected!'))
|
translate('SongsPlugin.SongMaintenanceForm', 'No book selected!'))
|
||||||
|
@ -60,7 +60,8 @@ class SongsPlugin(Plugin):
|
|||||||
Plugin.__init__(self, u'Songs', u'1.9.2', plugin_helpers)
|
Plugin.__init__(self, u'Songs', u'1.9.2', plugin_helpers)
|
||||||
self.weight = -10
|
self.weight = -10
|
||||||
self.manager = Manager(u'songs', init_schema)
|
self.manager = Manager(u'songs', init_schema)
|
||||||
self.icon = build_icon(u':/plugins/plugin_songs.png')
|
self.icon_path = u':/plugins/plugin_songs.png'
|
||||||
|
self.icon = build_icon(self.icon_path)
|
||||||
self.status = PluginStatus.Active
|
self.status = PluginStatus.Active
|
||||||
|
|
||||||
def getSettingsTab(self):
|
def getSettingsTab(self):
|
||||||
@ -235,5 +236,31 @@ class SongsPlugin(Plugin):
|
|||||||
def canDeleteTheme(self, theme_name):
|
def canDeleteTheme(self, theme_name):
|
||||||
if not self.manager.get_all_objects_filtered(Song,
|
if not self.manager.get_all_objects_filtered(Song,
|
||||||
Song.theme_name == theme_name):
|
Song.theme_name == theme_name):
|
||||||
|
|
||||||
|
def usesTheme(self, theme):
|
||||||
|
"""
|
||||||
|
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):
|
||||||
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user