forked from openlp/openlp
r2095
This commit is contained in:
commit
29ea9f6938
@ -85,6 +85,14 @@ class PluginManager(object):
|
|||||||
log.debug(u'finding plugins in %s at depth %d',
|
log.debug(u'finding plugins in %s at depth %d',
|
||||||
unicode(plugin_dir), startdepth)
|
unicode(plugin_dir), startdepth)
|
||||||
for root, dirs, files in os.walk(plugin_dir):
|
for root, dirs, files in os.walk(plugin_dir):
|
||||||
|
# TODO Presentation plugin is not yet working on Mac OS X.
|
||||||
|
# For now just ignore it. The following code will hide it
|
||||||
|
# in settings dialog.
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
present_plugin_dir = os.path.join(plugin_dir, 'presentations')
|
||||||
|
# Ignore files from the presentation plugin directory.
|
||||||
|
if root.startswith(present_plugin_dir):
|
||||||
|
continue
|
||||||
for name in files:
|
for name in files:
|
||||||
if name.endswith(u'.py') and not name.startswith(u'__'):
|
if name.endswith(u'.py') and not name.startswith(u'__'):
|
||||||
path = os.path.abspath(os.path.join(root, name))
|
path = os.path.abspath(os.path.join(root, name))
|
||||||
|
@ -29,12 +29,12 @@
|
|||||||
The :mod:`advancedtab` provides an advanced settings facility.
|
The :mod:`advancedtab` provides an advanced settings facility.
|
||||||
"""
|
"""
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
from openlp.core.lib import SettingsTab, translate, build_icon, Receiver
|
from openlp.core.lib import SettingsTab, translate, build_icon, Receiver
|
||||||
from openlp.core.lib.settings import Settings
|
from openlp.core.lib.settings import Settings
|
||||||
from openlp.core.lib.ui import UiStrings
|
from openlp.core.lib.ui import UiStrings
|
||||||
@ -432,8 +432,7 @@ class AdvancedTab(SettingsTab):
|
|||||||
translate('OpenLP.AdvancedTab',
|
translate('OpenLP.AdvancedTab',
|
||||||
'<strong>WARNING:</strong> New data directory location contains '
|
'<strong>WARNING:</strong> New data directory location contains '
|
||||||
'OpenLP data files. These files WILL be replaced during a copy.'))
|
'OpenLP data files. These files WILL be replaced during a copy.'))
|
||||||
self.x11GroupBox.setTitle(translate('OpenLP.AdvancedTab',
|
self.x11GroupBox.setTitle(translate('OpenLP.AdvancedTab', 'X11'))
|
||||||
'X11'))
|
|
||||||
self.x11BypassCheckBox.setText(translate('OpenLP.AdvancedTab',
|
self.x11BypassCheckBox.setText(translate('OpenLP.AdvancedTab',
|
||||||
'Bypass X11 Window Manager'))
|
'Bypass X11 Window Manager'))
|
||||||
# Slide Limits
|
# Slide Limits
|
||||||
@ -493,8 +492,14 @@ class AdvancedTab(SettingsTab):
|
|||||||
QtCore.QVariant(True)).toBool()
|
QtCore.QVariant(True)).toBool()
|
||||||
self.serviceNameCheckBox.setChecked(default_service_enabled)
|
self.serviceNameCheckBox.setChecked(default_service_enabled)
|
||||||
self.serviceNameCheckBoxToggled(default_service_enabled)
|
self.serviceNameCheckBoxToggled(default_service_enabled)
|
||||||
self.x11BypassCheckBox.setChecked(
|
# Fix for bug #1014422.
|
||||||
settings.value(u'x11 bypass wm', QtCore.QVariant(True)).toBool())
|
x11_bypass_default = True
|
||||||
|
if sys.platform.startswith(u'linux'):
|
||||||
|
# Default to False on Gnome.
|
||||||
|
x11_bypass_default = bool(not
|
||||||
|
os.environ.get(u'GNOME_DESKTOP_SESSION_ID'))
|
||||||
|
self.x11BypassCheckBox.setChecked(settings.value(
|
||||||
|
u'x11 bypass wm', QtCore.QVariant(x11_bypass_default)).toBool())
|
||||||
self.defaultColor = settings.value(u'default color',
|
self.defaultColor = settings.value(u'default color',
|
||||||
QtCore.QVariant(u'#ffffff')).toString()
|
QtCore.QVariant(u'#ffffff')).toString()
|
||||||
self.defaultFileEdit.setText(settings.value(u'default image',
|
self.defaultFileEdit.setText(settings.value(u'default image',
|
||||||
@ -766,7 +771,7 @@ class AdvancedTab(SettingsTab):
|
|||||||
self.dataExists = False
|
self.dataExists = False
|
||||||
self.dataDirectoryCopyCheckBox.setChecked(True)
|
self.dataDirectoryCopyCheckBox.setChecked(True)
|
||||||
self.newDataDirectoryHasFilesLabel.hide()
|
self.newDataDirectoryHasFilesLabel.hide()
|
||||||
|
|
||||||
def onDataDirectoryCancelButtonClicked(self):
|
def onDataDirectoryCancelButtonClicked(self):
|
||||||
"""
|
"""
|
||||||
Cancel the data directory location change
|
Cancel the data directory location change
|
||||||
|
@ -177,8 +177,10 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
return FirstTimePage.Progress
|
return FirstTimePage.Progress
|
||||||
elif self.currentId() == FirstTimePage.Themes:
|
elif self.currentId() == FirstTimePage.Themes:
|
||||||
Receiver.send_message(u'cursor_busy')
|
Receiver.send_message(u'cursor_busy')
|
||||||
|
Receiver.send_message(u'openlp_process_events')
|
||||||
while not self.themeScreenshotThread.isFinished():
|
while not self.themeScreenshotThread.isFinished():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
Receiver.send_message(u'openlp_process_events')
|
||||||
# Build the screenshot icons, as this can not be done in the thread.
|
# Build the screenshot icons, as this can not be done in the thread.
|
||||||
self._buildThemeScreenshots()
|
self._buildThemeScreenshots()
|
||||||
Receiver.send_message(u'cursor_normal')
|
Receiver.send_message(u'cursor_normal')
|
||||||
@ -188,10 +190,11 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
|
|
||||||
def onCurrentIdChanged(self, pageId):
|
def onCurrentIdChanged(self, pageId):
|
||||||
"""
|
"""
|
||||||
Detects Page changes and updates as approprate.
|
Detects Page changes and updates as appropriate.
|
||||||
"""
|
"""
|
||||||
# Keep track of the page we are at. Triggering "Cancel" causes pageId
|
# Keep track of the page we are at. Triggering "Cancel" causes pageId
|
||||||
# to be a -1.
|
# to be a -1.
|
||||||
|
Receiver.send_message(u'openlp_process_events')
|
||||||
if pageId != -1:
|
if pageId != -1:
|
||||||
self.lastId = pageId
|
self.lastId = pageId
|
||||||
if pageId == FirstTimePage.Plugins:
|
if pageId == FirstTimePage.Plugins:
|
||||||
@ -227,10 +230,12 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
self.cancelButton.setVisible(False)
|
self.cancelButton.setVisible(False)
|
||||||
elif pageId == FirstTimePage.Progress:
|
elif pageId == FirstTimePage.Progress:
|
||||||
Receiver.send_message(u'cursor_busy')
|
Receiver.send_message(u'cursor_busy')
|
||||||
|
self.repaint()
|
||||||
|
Receiver.send_message(u'openlp_process_events')
|
||||||
|
# Try to give the wizard a chance to redraw itself
|
||||||
|
time.sleep(0.2)
|
||||||
self._preWizard()
|
self._preWizard()
|
||||||
Receiver.send_message(u'openlp_process_events')
|
|
||||||
self._performWizard()
|
self._performWizard()
|
||||||
Receiver.send_message(u'openlp_process_events')
|
|
||||||
self._postWizard()
|
self._postWizard()
|
||||||
Receiver.send_message(u'cursor_normal')
|
Receiver.send_message(u'cursor_normal')
|
||||||
Receiver.send_message(u'openlp_process_events')
|
Receiver.send_message(u'openlp_process_events')
|
||||||
@ -263,8 +268,8 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
"""
|
"""
|
||||||
Receiver.send_message(u'cursor_busy')
|
Receiver.send_message(u'cursor_busy')
|
||||||
self._performWizard()
|
self._performWizard()
|
||||||
Receiver.send_message(u'openlp_process_events')
|
|
||||||
Receiver.send_message(u'cursor_normal')
|
Receiver.send_message(u'cursor_normal')
|
||||||
|
Receiver.send_message(u'openlp_process_events')
|
||||||
Settings().setValue(u'general/has run wizard',
|
Settings().setValue(u'general/has run wizard',
|
||||||
QtCore.QVariant(True))
|
QtCore.QVariant(True))
|
||||||
self.close()
|
self.close()
|
||||||
@ -344,6 +349,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
Receiver.send_message(u'openlp_process_events')
|
Receiver.send_message(u'openlp_process_events')
|
||||||
# Loop through the songs list and increase for each selected item
|
# Loop through the songs list and increase for each selected item
|
||||||
for i in xrange(self.songsListWidget.count()):
|
for i in xrange(self.songsListWidget.count()):
|
||||||
|
Receiver.send_message(u'openlp_process_events')
|
||||||
item = self.songsListWidget.item(i)
|
item = self.songsListWidget.item(i)
|
||||||
if item.checkState() == QtCore.Qt.Checked:
|
if item.checkState() == QtCore.Qt.Checked:
|
||||||
filename = item.data(QtCore.Qt.UserRole).toString()
|
filename = item.data(QtCore.Qt.UserRole).toString()
|
||||||
@ -352,6 +358,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
# Loop through the Bibles list and increase for each selected item
|
# Loop through the Bibles list and increase for each selected item
|
||||||
iterator = QtGui.QTreeWidgetItemIterator(self.biblesTreeWidget)
|
iterator = QtGui.QTreeWidgetItemIterator(self.biblesTreeWidget)
|
||||||
while iterator.value():
|
while iterator.value():
|
||||||
|
Receiver.send_message(u'openlp_process_events')
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
|
if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
|
||||||
filename = item.data(0, QtCore.Qt.UserRole).toString()
|
filename = item.data(0, QtCore.Qt.UserRole).toString()
|
||||||
@ -360,6 +367,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
iterator += 1
|
iterator += 1
|
||||||
# Loop through the themes list and increase for each selected item
|
# Loop through the themes list and increase for each selected item
|
||||||
for i in xrange(self.themesListWidget.count()):
|
for i in xrange(self.themesListWidget.count()):
|
||||||
|
Receiver.send_message(u'openlp_process_events')
|
||||||
item = self.themesListWidget.item(i)
|
item = self.themesListWidget.item(i)
|
||||||
if item.checkState() == QtCore.Qt.Checked:
|
if item.checkState() == QtCore.Qt.Checked:
|
||||||
filename = item.data(QtCore.Qt.UserRole).toString()
|
filename = item.data(QtCore.Qt.UserRole).toString()
|
||||||
@ -381,6 +389,10 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
self.progressPage.setTitle(translate('OpenLP.FirstTimeWizard',
|
self.progressPage.setTitle(translate('OpenLP.FirstTimeWizard',
|
||||||
'Setting Up'))
|
'Setting Up'))
|
||||||
self.progressPage.setSubTitle(u'Setup complete.')
|
self.progressPage.setSubTitle(u'Setup complete.')
|
||||||
|
self.repaint()
|
||||||
|
Receiver.send_message(u'openlp_process_events')
|
||||||
|
# Try to give the wizard a chance to repaint itself
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
def _postWizard(self):
|
def _postWizard(self):
|
||||||
"""
|
"""
|
||||||
@ -418,8 +430,11 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
'Enabling selected plugins...'))
|
'Enabling selected plugins...'))
|
||||||
self._setPluginStatus(self.songsCheckBox, u'songs/status')
|
self._setPluginStatus(self.songsCheckBox, u'songs/status')
|
||||||
self._setPluginStatus(self.bibleCheckBox, u'bibles/status')
|
self._setPluginStatus(self.bibleCheckBox, u'bibles/status')
|
||||||
self._setPluginStatus(self.presentationCheckBox,
|
# TODO Presentation plugin is not yet working on Mac OS X.
|
||||||
u'presentations/status')
|
# For now just ignore it.
|
||||||
|
if sys.platform != 'darwin':
|
||||||
|
self._setPluginStatus(self.presentationCheckBox,
|
||||||
|
u'presentations/status')
|
||||||
self._setPluginStatus(self.imageCheckBox, u'images/status')
|
self._setPluginStatus(self.imageCheckBox, u'images/status')
|
||||||
self._setPluginStatus(self.mediaCheckBox, u'media/status')
|
self._setPluginStatus(self.mediaCheckBox, u'media/status')
|
||||||
self._setPluginStatus(self.remoteCheckBox, u'remotes/status')
|
self._setPluginStatus(self.remoteCheckBox, u'remotes/status')
|
||||||
|
@ -82,13 +82,13 @@ class Ui_FirstTimeWizard(object):
|
|||||||
self.imageCheckBox.setChecked(True)
|
self.imageCheckBox.setChecked(True)
|
||||||
self.imageCheckBox.setObjectName(u'imageCheckBox')
|
self.imageCheckBox.setObjectName(u'imageCheckBox')
|
||||||
self.pluginLayout.addWidget(self.imageCheckBox)
|
self.pluginLayout.addWidget(self.imageCheckBox)
|
||||||
self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage)
|
# TODO Presentation plugin is not yet working on Mac OS X.
|
||||||
if sys.platform == "darwin":
|
# For now just ignore it.
|
||||||
self.presentationCheckBox.setChecked(False)
|
if sys.platform != 'darwin':
|
||||||
else:
|
self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage)
|
||||||
self.presentationCheckBox.setChecked(True)
|
self.presentationCheckBox.setChecked(True)
|
||||||
self.presentationCheckBox.setObjectName(u'presentationCheckBox')
|
self.presentationCheckBox.setObjectName(u'presentationCheckBox')
|
||||||
self.pluginLayout.addWidget(self.presentationCheckBox)
|
self.pluginLayout.addWidget(self.presentationCheckBox)
|
||||||
self.mediaCheckBox = QtGui.QCheckBox(self.pluginPage)
|
self.mediaCheckBox = QtGui.QCheckBox(self.pluginPage)
|
||||||
self.mediaCheckBox.setChecked(True)
|
self.mediaCheckBox.setChecked(True)
|
||||||
self.mediaCheckBox.setObjectName(u'mediaCheckBox')
|
self.mediaCheckBox.setObjectName(u'mediaCheckBox')
|
||||||
@ -214,10 +214,11 @@ class Ui_FirstTimeWizard(object):
|
|||||||
self.bibleCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Bible'))
|
self.bibleCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Bible'))
|
||||||
self.imageCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
self.imageCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
||||||
'Images'))
|
'Images'))
|
||||||
self.presentationCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
# TODO Presentation plugin is not yet working on Mac OS X.
|
||||||
'Presentations'))
|
# For now just ignore it.
|
||||||
if sys.platform == "darwin":
|
if sys.platform != 'darwin':
|
||||||
self.presentationCheckBox.setEnabled(False)
|
self.presentationCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
||||||
|
'Presentations'))
|
||||||
self.mediaCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
self.mediaCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
||||||
'Media (Audio and Video)'))
|
'Media (Audio and Video)'))
|
||||||
self.remoteCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
self.remoteCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
||||||
|
@ -31,6 +31,7 @@ and play multimedia within OpenLP.
|
|||||||
"""
|
"""
|
||||||
import cgi
|
import cgi
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui, QtWebKit, QtOpenGL
|
from PyQt4 import QtCore, QtGui, QtWebKit, QtOpenGL
|
||||||
@ -135,8 +136,14 @@ class MainDisplay(Display):
|
|||||||
self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;')
|
self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;')
|
||||||
windowFlags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | \
|
windowFlags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | \
|
||||||
QtCore.Qt.WindowStaysOnTopHint
|
QtCore.Qt.WindowStaysOnTopHint
|
||||||
|
# Fix for bug #1014422.
|
||||||
|
x11_bypass_default = True
|
||||||
|
if sys.platform.startswith(u'linux'):
|
||||||
|
# Default to False on Gnome.
|
||||||
|
x11_bypass_default = bool(not
|
||||||
|
os.environ.get(u'GNOME_DESKTOP_SESSION_ID'))
|
||||||
if Settings().value(u'advanced/x11 bypass wm',
|
if Settings().value(u'advanced/x11 bypass wm',
|
||||||
QtCore.QVariant(True)).toBool():
|
QtCore.QVariant(x11_bypass_default)).toBool():
|
||||||
windowFlags |= QtCore.Qt.X11BypassWindowManagerHint
|
windowFlags |= QtCore.Qt.X11BypassWindowManagerHint
|
||||||
# TODO: The following combination of windowFlags works correctly
|
# TODO: The following combination of windowFlags works correctly
|
||||||
# on Mac OS X. For next OpenLP version we should test it on other
|
# on Mac OS X. For next OpenLP version we should test it on other
|
||||||
|
@ -855,7 +855,11 @@ class SlideController(Controller):
|
|||||||
else:
|
else:
|
||||||
label = QtGui.QLabel()
|
label = QtGui.QLabel()
|
||||||
label.setMargin(4)
|
label.setMargin(4)
|
||||||
label.setScaledContents(True)
|
if serviceItem.is_media():
|
||||||
|
label.setAlignment(QtCore.Qt.AlignHCenter |
|
||||||
|
QtCore.Qt.AlignVCenter)
|
||||||
|
else:
|
||||||
|
label.setScaledContents(True)
|
||||||
if self.serviceItem.is_command():
|
if self.serviceItem.is_command():
|
||||||
label.setPixmap(QtGui.QPixmap(frame[u'image']))
|
label.setPixmap(QtGui.QPixmap(frame[u'image']))
|
||||||
else:
|
else:
|
||||||
|
@ -30,7 +30,6 @@ import os
|
|||||||
import zipfile
|
import zipfile
|
||||||
import shutil
|
import shutil
|
||||||
import logging
|
import logging
|
||||||
import locale
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from xml.etree.ElementTree import ElementTree, XML
|
from xml.etree.ElementTree import ElementTree, XML
|
||||||
@ -46,7 +45,8 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
|
|||||||
create_widget_action
|
create_widget_action
|
||||||
from openlp.core.theme import Theme
|
from openlp.core.theme import Theme
|
||||||
from openlp.core.ui import FileRenameForm, ThemeForm
|
from openlp.core.ui import FileRenameForm, ThemeForm
|
||||||
from openlp.core.utils import AppLocation, delete_file, get_filesystem_encoding
|
from openlp.core.utils import AppLocation, delete_file, locale_compare, \
|
||||||
|
get_filesystem_encoding
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -284,6 +284,7 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
plugin.renameTheme(old_theme_name, new_theme_name)
|
plugin.renameTheme(old_theme_name, new_theme_name)
|
||||||
self.mainwindow.renderer.update_theme(
|
self.mainwindow.renderer.update_theme(
|
||||||
new_theme_name, old_theme_name)
|
new_theme_name, old_theme_name)
|
||||||
|
self.loadThemes()
|
||||||
|
|
||||||
def onCopyTheme(self):
|
def onCopyTheme(self):
|
||||||
"""
|
"""
|
||||||
@ -457,9 +458,8 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
self.configUpdated()
|
self.configUpdated()
|
||||||
files = SettingsManager.get_files(self.settingsSection, u'.png')
|
files = SettingsManager.get_files(self.settingsSection, u'.png')
|
||||||
# Sort the themes by its name considering language specific characters.
|
# Sort the themes by its name considering language specific characters.
|
||||||
# lower() is needed for windows!
|
files.sort(key=lambda file_name: unicode(file_name),
|
||||||
files.sort(key=lambda file_name: unicode(file_name).lower(),
|
cmp=locale_compare)
|
||||||
cmp=locale.strcoll)
|
|
||||||
# now process the file list of png files
|
# now process the file list of png files
|
||||||
for name in files:
|
for name in files:
|
||||||
# check to see file is in theme root directory
|
# check to see file is in theme root directory
|
||||||
|
@ -488,10 +488,30 @@ def format_time(text, local_time):
|
|||||||
return re.sub('\%[a-zA-Z]', match_formatting, text)
|
return re.sub('\%[a-zA-Z]', match_formatting, text)
|
||||||
|
|
||||||
|
|
||||||
|
def locale_compare(string1, string2):
|
||||||
|
"""
|
||||||
|
Compares two strings according to the current locale settings.
|
||||||
|
|
||||||
|
As any other compare function, returns a negative, or a positive value,
|
||||||
|
or 0, depending on whether string1 collates before or after string2 or
|
||||||
|
is equal to it. Comparison is case insensitive.
|
||||||
|
"""
|
||||||
|
# Function locale.strcol() from standard Python library does not work
|
||||||
|
# properly on Windows and probably somewhere else.
|
||||||
|
return QtCore.QString.localeAwareCompare(string1.lower(), string2.lower())
|
||||||
|
|
||||||
|
|
||||||
|
# For performance reasons provide direct reference to compare function
|
||||||
|
# without wrapping it in another function making te string lowercase.
|
||||||
|
# This is needed for sorting songs.
|
||||||
|
locale_direct_compare = QtCore.QString.localeAwareCompare
|
||||||
|
|
||||||
|
|
||||||
from languagemanager import LanguageManager
|
from languagemanager import LanguageManager
|
||||||
from actions import ActionList
|
from actions import ActionList
|
||||||
|
|
||||||
__all__ = [u'AppLocation', u'get_application_version', u'check_latest_version',
|
__all__ = [u'AppLocation', u'get_application_version', u'check_latest_version',
|
||||||
u'add_actions', u'get_filesystem_encoding', u'LanguageManager',
|
u'add_actions', u'get_filesystem_encoding', u'LanguageManager',
|
||||||
u'ActionList', u'get_web_page', u'get_uno_command', u'get_uno_instance',
|
u'ActionList', u'get_web_page', u'get_uno_command', u'get_uno_instance',
|
||||||
u'delete_file', u'clean_filename', u'format_time']
|
u'delete_file', u'clean_filename', u'format_time', u'locale_compare',
|
||||||
|
u'locale_direct_compare']
|
||||||
|
@ -105,6 +105,7 @@ CSS = """
|
|||||||
font-size: %spt;
|
font-size: %spt;
|
||||||
color: %s;
|
color: %s;
|
||||||
background-color: %s;
|
background-color: %s;
|
||||||
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ class Ui_AlertDialog(object):
|
|||||||
def setupUi(self, alertDialog):
|
def setupUi(self, alertDialog):
|
||||||
alertDialog.setObjectName(u'alertDialog')
|
alertDialog.setObjectName(u'alertDialog')
|
||||||
alertDialog.resize(400, 300)
|
alertDialog.resize(400, 300)
|
||||||
alertDialog.setWindowIcon(build_icon(u':/icon/openlp.org-icon-32.bmp'))
|
alertDialog.setWindowIcon(build_icon(u':/icon/openlp-logo-16x16.png'))
|
||||||
self.alertDialogLayout = QtGui.QGridLayout(alertDialog)
|
self.alertDialogLayout = QtGui.QGridLayout(alertDialog)
|
||||||
self.alertDialogLayout.setObjectName(u'alertDialogLayout')
|
self.alertDialogLayout.setObjectName(u'alertDialogLayout')
|
||||||
self.alertTextLayout = QtGui.QFormLayout()
|
self.alertTextLayout = QtGui.QFormLayout()
|
||||||
|
@ -80,6 +80,10 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
|
|||||||
item_name = QtGui.QListWidgetItem(alert.text)
|
item_name = QtGui.QListWidgetItem(alert.text)
|
||||||
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(alert.id))
|
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(alert.id))
|
||||||
self.alertListWidget.addItem(item_name)
|
self.alertListWidget.addItem(item_name)
|
||||||
|
if alert.text == unicode(self.alertTextEdit.text()):
|
||||||
|
self.item_id = alert.id
|
||||||
|
self.alertListWidget.setCurrentRow(
|
||||||
|
self.alertListWidget.row(item_name))
|
||||||
|
|
||||||
def onDisplayClicked(self):
|
def onDisplayClicked(self):
|
||||||
self.triggerAlert(unicode(self.alertTextEdit.text()))
|
self.triggerAlert(unicode(self.alertTextEdit.text()))
|
||||||
@ -112,7 +116,6 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
|
|||||||
alert = AlertItem()
|
alert = AlertItem()
|
||||||
alert.text = unicode(self.alertTextEdit.text())
|
alert.text = unicode(self.alertTextEdit.text())
|
||||||
self.manager.save_object(alert)
|
self.manager.save_object(alert)
|
||||||
self.alertTextEdit.setText(u'')
|
|
||||||
self.loadList()
|
self.loadList()
|
||||||
|
|
||||||
def onSaveClick(self):
|
def onSaveClick(self):
|
||||||
@ -125,6 +128,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
|
|||||||
self.manager.save_object(alert)
|
self.manager.save_object(alert)
|
||||||
self.item_id = None
|
self.item_id = None
|
||||||
self.loadList()
|
self.loadList()
|
||||||
|
self.saveButton.setEnabled(False)
|
||||||
|
|
||||||
def onTextChanged(self):
|
def onTextChanged(self):
|
||||||
"""
|
"""
|
||||||
|
@ -57,8 +57,6 @@ class AlertsManager(QtCore.QObject):
|
|||||||
"""
|
"""
|
||||||
if message:
|
if message:
|
||||||
self.displayAlert(message[0])
|
self.displayAlert(message[0])
|
||||||
else:
|
|
||||||
self.displayAlert(u'')
|
|
||||||
|
|
||||||
def displayAlert(self, text=u''):
|
def displayAlert(self, text=u''):
|
||||||
"""
|
"""
|
||||||
@ -68,14 +66,15 @@ class AlertsManager(QtCore.QObject):
|
|||||||
display text
|
display text
|
||||||
"""
|
"""
|
||||||
log.debug(u'display alert called %s' % text)
|
log.debug(u'display alert called %s' % text)
|
||||||
self.alertList.append(text)
|
if text:
|
||||||
if self.timer_id != 0:
|
self.alertList.append(text)
|
||||||
Receiver.send_message(u'mainwindow_status_text',
|
if self.timer_id != 0:
|
||||||
translate('AlertsPlugin.AlertsManager',
|
Receiver.send_message(u'mainwindow_status_text',
|
||||||
'Alert message created and displayed.'))
|
translate('AlertsPlugin.AlertsManager',
|
||||||
return
|
'Alert message created and displayed.'))
|
||||||
Receiver.send_message(u'mainwindow_status_text', u'')
|
return
|
||||||
self.generateAlert()
|
Receiver.send_message(u'mainwindow_status_text', u'')
|
||||||
|
self.generateAlert()
|
||||||
|
|
||||||
def generateAlert(self):
|
def generateAlert(self):
|
||||||
"""
|
"""
|
||||||
|
@ -30,7 +30,6 @@ The bible import functions for OpenLP
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import locale
|
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
@ -39,7 +38,7 @@ from openlp.core.lib.db import delete_database
|
|||||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||||
from openlp.core.lib.settings import Settings
|
from openlp.core.lib.settings import Settings
|
||||||
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
|
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
|
||||||
from openlp.core.utils import AppLocation
|
from openlp.core.utils import AppLocation, locale_compare
|
||||||
from openlp.plugins.bibles.lib.manager import BibleFormat
|
from openlp.plugins.bibles.lib.manager import BibleFormat
|
||||||
from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename
|
from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename
|
||||||
|
|
||||||
@ -523,7 +522,7 @@ class BibleImportForm(OpenLPWizard):
|
|||||||
"""
|
"""
|
||||||
self.webTranslationComboBox.clear()
|
self.webTranslationComboBox.clear()
|
||||||
bibles = self.web_bible_list[index].keys()
|
bibles = self.web_bible_list[index].keys()
|
||||||
bibles.sort(cmp=locale.strcoll)
|
bibles.sort(cmp=locale_compare)
|
||||||
self.webTranslationComboBox.addItems(bibles)
|
self.webTranslationComboBox.addItems(bibles)
|
||||||
|
|
||||||
def onOsisBrowseButtonClicked(self):
|
def onOsisBrowseButtonClicked(self):
|
||||||
|
@ -355,37 +355,8 @@ def parse_reference(reference, bible, language_selection, book_ref_id=False):
|
|||||||
log.debug(u'Matched reference %s' % reference)
|
log.debug(u'Matched reference %s' % reference)
|
||||||
book = match.group(u'book')
|
book = match.group(u'book')
|
||||||
if not book_ref_id:
|
if not book_ref_id:
|
||||||
book_names = BibleStrings().BookNames
|
book_ref_id = bible.get_book_ref_id_by_localised_name(
|
||||||
# escape reserved characters
|
book, language_selection)
|
||||||
book_escaped = book
|
|
||||||
for character in u'\\.^$*+?{}[]()':
|
|
||||||
book_escaped = book_escaped.replace(
|
|
||||||
character, u'\\' + character)
|
|
||||||
regex_book = re.compile(u'\s*%s\s*' % u'\s*'.join(
|
|
||||||
book_escaped.split()), re.UNICODE | re.IGNORECASE)
|
|
||||||
if language_selection == LanguageSelection.Bible:
|
|
||||||
db_book = bible.get_book(book)
|
|
||||||
if db_book:
|
|
||||||
book_ref_id = db_book.book_reference_id
|
|
||||||
elif language_selection == LanguageSelection.Application:
|
|
||||||
books = filter(lambda key:
|
|
||||||
regex_book.match(unicode(book_names[key])), book_names.keys())
|
|
||||||
books = filter(None, map(BiblesResourcesDB.get_book, books))
|
|
||||||
for value in books:
|
|
||||||
if bible.get_book_by_book_ref_id(value[u'id']):
|
|
||||||
book_ref_id = value[u'id']
|
|
||||||
break
|
|
||||||
elif language_selection == LanguageSelection.English:
|
|
||||||
books = BiblesResourcesDB.get_books_like(book)
|
|
||||||
if books:
|
|
||||||
book_list = filter(
|
|
||||||
lambda value: regex_book.match(value[u'name']), books)
|
|
||||||
if not book_list:
|
|
||||||
book_list = books
|
|
||||||
for value in book_list:
|
|
||||||
if bible.get_book_by_book_ref_id(value[u'id']):
|
|
||||||
book_ref_id = value[u'id']
|
|
||||||
break
|
|
||||||
elif not bible.get_book_by_book_ref_id(book_ref_id):
|
elif not bible.get_book_by_book_ref_id(book_ref_id):
|
||||||
book_ref_id = False
|
book_ref_id = False
|
||||||
ranges = match.group(u'ranges')
|
ranges = match.group(u'ranges')
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
import chardet
|
import chardet
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
@ -44,6 +45,8 @@ import upgrade
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
RESERVED_CHARACTERS = u'\\.^$*+?{}[]()'
|
||||||
|
|
||||||
class BibleMeta(BaseModel):
|
class BibleMeta(BaseModel):
|
||||||
"""
|
"""
|
||||||
Bible Meta Data
|
Bible Meta Data
|
||||||
@ -352,6 +355,53 @@ class BibleDB(QtCore.QObject, Manager):
|
|||||||
book, book_id, language_id)
|
book, book_id, language_id)
|
||||||
return book_id
|
return book_id
|
||||||
|
|
||||||
|
def get_book_ref_id_by_localised_name(self, book,
|
||||||
|
language_selection):
|
||||||
|
"""
|
||||||
|
Return the id of a named book.
|
||||||
|
|
||||||
|
``book``
|
||||||
|
The name of the book, according to the selected language.
|
||||||
|
|
||||||
|
``language_selection``
|
||||||
|
The language selection the user has chosen in the settings
|
||||||
|
section of the Bible.
|
||||||
|
"""
|
||||||
|
log.debug(u'get_book_ref_id_by_localised_name("%s", "%s")',
|
||||||
|
book, language_selection)
|
||||||
|
from openlp.plugins.bibles.lib import LanguageSelection, \
|
||||||
|
BibleStrings
|
||||||
|
book_names = BibleStrings().BookNames
|
||||||
|
# escape reserved characters
|
||||||
|
book_escaped = book
|
||||||
|
for character in RESERVED_CHARACTERS:
|
||||||
|
book_escaped = book_escaped.replace(
|
||||||
|
character, u'\\' + character)
|
||||||
|
regex_book = re.compile(u'\s*%s\s*' % u'\s*'.join(
|
||||||
|
book_escaped.split()), re.UNICODE | re.IGNORECASE)
|
||||||
|
if language_selection == LanguageSelection.Bible:
|
||||||
|
db_book = self.get_book(book)
|
||||||
|
if db_book:
|
||||||
|
return db_book.book_reference_id
|
||||||
|
elif language_selection == LanguageSelection.Application:
|
||||||
|
books = filter(lambda key:
|
||||||
|
regex_book.match(unicode(book_names[key])), book_names.keys())
|
||||||
|
books = filter(None, map(BiblesResourcesDB.get_book, books))
|
||||||
|
for value in books:
|
||||||
|
if self.get_book_by_book_ref_id(value[u'id']):
|
||||||
|
return value[u'id']
|
||||||
|
elif language_selection == LanguageSelection.English:
|
||||||
|
books = BiblesResourcesDB.get_books_like(book)
|
||||||
|
if books:
|
||||||
|
book_list = filter(
|
||||||
|
lambda value: regex_book.match(value[u'name']), books)
|
||||||
|
if not book_list:
|
||||||
|
book_list = books
|
||||||
|
for value in book_list:
|
||||||
|
if self.get_book_by_book_ref_id(value[u'id']):
|
||||||
|
return value[u'id']
|
||||||
|
return False
|
||||||
|
|
||||||
def get_verses(self, reference_list, show_error=True):
|
def get_verses(self, reference_list, show_error=True):
|
||||||
"""
|
"""
|
||||||
This is probably the most used function. It retrieves the list of
|
This is probably the most used function. It retrieves the list of
|
||||||
|
@ -277,8 +277,9 @@ class BibleManager(object):
|
|||||||
"""
|
"""
|
||||||
log.debug(u'BibleManager.get_verse_count("%s", "%s", %s)',
|
log.debug(u'BibleManager.get_verse_count("%s", "%s", %s)',
|
||||||
bible, book, chapter)
|
bible, book, chapter)
|
||||||
db_book = self.db_cache[bible].get_book(book)
|
language_selection = self.get_language_selection(bible)
|
||||||
book_ref_id = db_book.book_reference_id
|
book_ref_id = self.db_cache[bible].get_book_ref_id_by_localised_name(
|
||||||
|
book, language_selection)
|
||||||
return self.db_cache[bible].get_verse_count(book_ref_id, chapter)
|
return self.db_cache[bible].get_verse_count(book_ref_id, chapter)
|
||||||
|
|
||||||
def get_verse_count_by_book_ref_id(self, bible, book_ref_id, chapter):
|
def get_verse_count_by_book_ref_id(self, bible, book_ref_id, chapter):
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import locale
|
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
@ -38,6 +37,7 @@ from openlp.core.lib.settings import Settings
|
|||||||
from openlp.core.lib.ui import UiStrings, set_case_insensitive_completer, \
|
from openlp.core.lib.ui import UiStrings, set_case_insensitive_completer, \
|
||||||
create_horizontal_adjusting_combo_box, critical_error_message_box, \
|
create_horizontal_adjusting_combo_box, critical_error_message_box, \
|
||||||
find_and_set_in_combo_box, build_icon
|
find_and_set_in_combo_box, build_icon
|
||||||
|
from openlp.core.utils import locale_compare
|
||||||
from openlp.plugins.bibles.forms import BibleImportForm, EditBibleForm
|
from openlp.plugins.bibles.forms import BibleImportForm, EditBibleForm
|
||||||
from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \
|
from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \
|
||||||
VerseReferenceList, get_reference_separator, LanguageSelection, \
|
VerseReferenceList, get_reference_separator, LanguageSelection, \
|
||||||
@ -381,7 +381,7 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
# Get all bibles and sort the list.
|
# Get all bibles and sort the list.
|
||||||
bibles = self.plugin.manager.get_bibles().keys()
|
bibles = self.plugin.manager.get_bibles().keys()
|
||||||
bibles = filter(None, bibles)
|
bibles = filter(None, bibles)
|
||||||
bibles.sort(cmp=locale.strcoll)
|
bibles.sort(cmp=locale_compare)
|
||||||
# Load the bibles into the combo boxes.
|
# Load the bibles into the combo boxes.
|
||||||
self.quickVersionComboBox.addItems(bibles)
|
self.quickVersionComboBox.addItems(bibles)
|
||||||
self.quickSecondComboBox.addItems(bibles)
|
self.quickSecondComboBox.addItems(bibles)
|
||||||
@ -538,7 +538,7 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
data = BiblesResourcesDB.get_book_by_id(
|
data = BiblesResourcesDB.get_book_by_id(
|
||||||
book.book_reference_id)
|
book.book_reference_id)
|
||||||
books.append(data[u'name'] + u' ')
|
books.append(data[u'name'] + u' ')
|
||||||
books.sort(cmp=locale.strcoll)
|
books.sort(cmp=locale_compare)
|
||||||
set_case_insensitive_completer(books, self.quickSearchEdit)
|
set_case_insensitive_completer(books, self.quickSearchEdit)
|
||||||
|
|
||||||
def onImportClick(self):
|
def onImportClick(self):
|
||||||
|
@ -36,7 +36,7 @@ class Ui_CustomEditDialog(object):
|
|||||||
customEditDialog.setObjectName(u'customEditDialog')
|
customEditDialog.setObjectName(u'customEditDialog')
|
||||||
customEditDialog.resize(450, 350)
|
customEditDialog.resize(450, 350)
|
||||||
customEditDialog.setWindowIcon(
|
customEditDialog.setWindowIcon(
|
||||||
build_icon(u':/icon/openlp.org-icon-32.bmp'))
|
build_icon(u':/icon/openlp-logo-16x16.png'))
|
||||||
self.dialogLayout = QtGui.QVBoxLayout(customEditDialog)
|
self.dialogLayout = QtGui.QVBoxLayout(customEditDialog)
|
||||||
self.dialogLayout.setObjectName(u'dialogLayout')
|
self.dialogLayout.setObjectName(u'dialogLayout')
|
||||||
self.titleLayout = QtGui.QHBoxLayout()
|
self.titleLayout = QtGui.QHBoxLayout()
|
||||||
|
@ -34,12 +34,21 @@ from sqlalchemy import Column, Table, types
|
|||||||
from sqlalchemy.orm import mapper
|
from sqlalchemy.orm import mapper
|
||||||
|
|
||||||
from openlp.core.lib.db import BaseModel, init_db
|
from openlp.core.lib.db import BaseModel, init_db
|
||||||
|
from openlp.core.utils import locale_compare
|
||||||
|
|
||||||
class CustomSlide(BaseModel):
|
class CustomSlide(BaseModel):
|
||||||
"""
|
"""
|
||||||
CustomSlide model
|
CustomSlide model
|
||||||
"""
|
"""
|
||||||
pass
|
# By default sort the customs by its title considering language specific
|
||||||
|
# characters.
|
||||||
|
def __lt__(self, other):
|
||||||
|
r = locale_compare(self.title, other.title)
|
||||||
|
return True if r < 0 else False
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return 0 == locale_compare(self.title, other.title)
|
||||||
|
|
||||||
|
|
||||||
def init_schema(url):
|
def init_schema(url):
|
||||||
"""
|
"""
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import locale
|
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
from sqlalchemy.sql import or_, func
|
from sqlalchemy.sql import or_, func
|
||||||
@ -109,10 +108,7 @@ class CustomMediaItem(MediaManagerItem):
|
|||||||
# Sort out what custom we want to select after loading the list.
|
# Sort out what custom we want to select after loading the list.
|
||||||
self.saveAutoSelectId()
|
self.saveAutoSelectId()
|
||||||
self.listView.clear()
|
self.listView.clear()
|
||||||
# Sort the customs by its title considering language specific
|
custom_slides.sort()
|
||||||
# characters. lower() is needed for windows!
|
|
||||||
custom_slides.sort(
|
|
||||||
cmp=locale.strcoll, key=lambda custom: custom.title.lower())
|
|
||||||
for custom_slide in custom_slides:
|
for custom_slide in custom_slides:
|
||||||
custom_name = QtGui.QListWidgetItem(custom_slide.title)
|
custom_name = QtGui.QListWidgetItem(custom_slide.title)
|
||||||
custom_name.setData(
|
custom_name.setData(
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import locale
|
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
@ -37,7 +36,8 @@ from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \
|
|||||||
Receiver, create_thumb, validate_thumb
|
Receiver, create_thumb, validate_thumb
|
||||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||||
from openlp.core.lib.settings import Settings
|
from openlp.core.lib.settings import Settings
|
||||||
from openlp.core.utils import AppLocation, delete_file, get_images_filter
|
from openlp.core.utils import AppLocation, delete_file, locale_compare, \
|
||||||
|
get_images_filter
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -126,10 +126,10 @@ class ImageMediaItem(MediaManagerItem):
|
|||||||
if not initialLoad:
|
if not initialLoad:
|
||||||
Receiver.send_message(u'cursor_busy')
|
Receiver.send_message(u'cursor_busy')
|
||||||
self.plugin.formParent.displayProgressBar(len(images))
|
self.plugin.formParent.displayProgressBar(len(images))
|
||||||
# Sort the themes by its filename considering language specific
|
# Sort the images by its filename considering language specific
|
||||||
# characters. lower() is needed for windows!
|
# characters.
|
||||||
images.sort(cmp=locale.strcoll,
|
images.sort(cmp=locale_compare,
|
||||||
key=lambda filename: os.path.split(unicode(filename))[1].lower())
|
key=lambda filename: os.path.split(unicode(filename))[1])
|
||||||
for imageFile in images:
|
for imageFile in images:
|
||||||
filename = os.path.split(unicode(imageFile))[1]
|
filename = os.path.split(unicode(imageFile))[1]
|
||||||
thumb = os.path.join(self.servicePath, filename)
|
thumb = os.path.join(self.servicePath, filename)
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import locale
|
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
@ -39,11 +38,13 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
|
|||||||
create_horizontal_adjusting_combo_box
|
create_horizontal_adjusting_combo_box
|
||||||
from openlp.core.ui import Controller, Display
|
from openlp.core.ui import Controller, Display
|
||||||
from openlp.core.ui.media import get_media_players, set_media_players
|
from openlp.core.ui.media import get_media_players, set_media_players
|
||||||
|
from openlp.core.utils import locale_compare
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
CLAPPERBOARD = QtGui.QImage(u':/media/media_video.png')
|
CLAPPERBOARD = u':/media/slidecontroller_multimedia.png'
|
||||||
#TODO: Add an appropriate Icon for DVDs, CDs, ...
|
VIDEO = QtGui.QImage(u':/media/media_video.png')
|
||||||
|
AUDIO = QtGui.QImage(u':/media/media_audio.png')
|
||||||
DVD_ICON = QtGui.QImage(u':/media/media_video.png')
|
DVD_ICON = QtGui.QImage(u':/media/media_video.png')
|
||||||
|
|
||||||
class MediaMediaItem(MediaManagerItem):
|
class MediaMediaItem(MediaManagerItem):
|
||||||
@ -218,7 +219,7 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
service_item.add_capability(ItemCapabilities.RequiresMedia)
|
service_item.add_capability(ItemCapabilities.RequiresMedia)
|
||||||
# force a non-existent theme
|
# force a non-existent theme
|
||||||
service_item.theme = -1
|
service_item.theme = -1
|
||||||
frame = u':/media/image_clapperboard.png'
|
frame = CLAPPERBOARD
|
||||||
(path, name) = os.path.split(filename)
|
(path, name) = os.path.split(filename)
|
||||||
service_item.add_from_command(path, name, frame)
|
service_item.add_from_command(path, name, frame)
|
||||||
return True
|
return True
|
||||||
@ -284,16 +285,16 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
u'media', self.getFileList())
|
u'media', self.getFileList())
|
||||||
|
|
||||||
def loadList(self, media):
|
def loadList(self, media):
|
||||||
# Sort the themes by its filename considering language specific
|
# Sort the media by its filename considering language specific
|
||||||
# characters. lower() is needed for windows!
|
# characters.
|
||||||
media.sort(cmp=locale.strcoll,
|
media.sort(cmp=locale_compare,
|
||||||
key=lambda filename: os.path.split(unicode(filename))[1].lower())
|
key=lambda filename: os.path.split(unicode(filename))[1])
|
||||||
for track in media:
|
for track in media:
|
||||||
track_info = QtCore.QFileInfo(track)
|
track_info = QtCore.QFileInfo(track)
|
||||||
if not track_info.isFile():
|
if track_info.isFile():
|
||||||
filename = os.path.split(unicode(track))[1]
|
filename = os.path.split(unicode(track))[1]
|
||||||
item_name = QtGui.QListWidgetItem(filename)
|
item_name = QtGui.QListWidgetItem(filename)
|
||||||
item_name.setIcon(build_icon(CLAPPERBOARD))
|
item_name.setIcon(build_icon(VIDEO))
|
||||||
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(track))
|
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(track))
|
||||||
else:
|
else:
|
||||||
filename = os.path.split(unicode(track))[1]
|
filename = os.path.split(unicode(track))[1]
|
||||||
@ -306,8 +307,8 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
|
|
||||||
def getList(self, type=MediaType.Audio):
|
def getList(self, type=MediaType.Audio):
|
||||||
media = SettingsManager.load_list(self.settingsSection, u'media')
|
media = SettingsManager.load_list(self.settingsSection, u'media')
|
||||||
media.sort(cmp=locale.strcoll,
|
media.sort(cmp=locale_compare,
|
||||||
key=lambda filename: os.path.split(unicode(filename))[1].lower())
|
key=lambda filename: os.path.split(unicode(filename))[1])
|
||||||
ext = []
|
ext = []
|
||||||
if type == MediaType.Audio:
|
if type == MediaType.Audio:
|
||||||
ext = self.plugin.audio_extensions_list
|
ext = self.plugin.audio_extensions_list
|
||||||
|
@ -153,7 +153,7 @@ class ImpressController(PresentationController):
|
|||||||
desktop = None
|
desktop = None
|
||||||
try:
|
try:
|
||||||
desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop')
|
desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop')
|
||||||
except AttributeError:
|
except (AttributeError, pywintypes.com_error):
|
||||||
log.warn(u'Failure to find desktop - Impress may have closed')
|
log.warn(u'Failure to find desktop - Impress may have closed')
|
||||||
return desktop if desktop else None
|
return desktop if desktop else None
|
||||||
|
|
||||||
@ -284,6 +284,8 @@ class ImpressDocument(PresentationDocument):
|
|||||||
props = tuple(props)
|
props = tuple(props)
|
||||||
doc = self.document
|
doc = self.document
|
||||||
pages = doc.getDrawPages()
|
pages = doc.getDrawPages()
|
||||||
|
if not pages:
|
||||||
|
return
|
||||||
if not os.path.isdir(self.get_temp_folder()):
|
if not os.path.isdir(self.get_temp_folder()):
|
||||||
os.makedirs(self.get_temp_folder())
|
os.makedirs(self.get_temp_folder())
|
||||||
for idx in range(pages.getCount()):
|
for idx in range(pages.getCount()):
|
||||||
@ -359,7 +361,7 @@ class ImpressDocument(PresentationDocument):
|
|||||||
log.debug(u'is active OpenOffice')
|
log.debug(u'is active OpenOffice')
|
||||||
if not self.is_loaded():
|
if not self.is_loaded():
|
||||||
return False
|
return False
|
||||||
return self.control is not None
|
return self.control.isRunning() if self.control else False
|
||||||
|
|
||||||
def unblank_screen(self):
|
def unblank_screen(self):
|
||||||
"""
|
"""
|
||||||
@ -380,7 +382,7 @@ class ImpressDocument(PresentationDocument):
|
|||||||
Returns true if screen is blank
|
Returns true if screen is blank
|
||||||
"""
|
"""
|
||||||
log.debug(u'is blank OpenOffice')
|
log.debug(u'is blank OpenOffice')
|
||||||
if self.control:
|
if self.control and self.control.isRunning():
|
||||||
return self.control.isPaused()
|
return self.control.isPaused()
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
@ -436,7 +438,11 @@ class ImpressDocument(PresentationDocument):
|
|||||||
"""
|
"""
|
||||||
Triggers the next effect of slide on the running presentation
|
Triggers the next effect of slide on the running presentation
|
||||||
"""
|
"""
|
||||||
|
is_paused = self.control.isPaused()
|
||||||
self.control.gotoNextEffect()
|
self.control.gotoNextEffect()
|
||||||
|
time.sleep(0.1)
|
||||||
|
if not is_paused and self.control.isPaused():
|
||||||
|
self.control.gotoPreviousEffect()
|
||||||
|
|
||||||
def previous_step(self):
|
def previous_step(self):
|
||||||
"""
|
"""
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import locale
|
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
@ -38,6 +37,7 @@ from openlp.core.lib import MediaManagerItem, build_icon, SettingsManager, \
|
|||||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
|
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
|
||||||
create_horizontal_adjusting_combo_box
|
create_horizontal_adjusting_combo_box
|
||||||
from openlp.core.lib.settings import Settings
|
from openlp.core.lib.settings import Settings
|
||||||
|
from openlp.core.utils import locale_compare
|
||||||
from openlp.plugins.presentations.lib import MessageListener
|
from openlp.plugins.presentations.lib import MessageListener
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -169,10 +169,10 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
if not initialLoad:
|
if not initialLoad:
|
||||||
Receiver.send_message(u'cursor_busy')
|
Receiver.send_message(u'cursor_busy')
|
||||||
self.plugin.formParent.displayProgressBar(len(files))
|
self.plugin.formParent.displayProgressBar(len(files))
|
||||||
# Sort the themes by its filename considering language specific
|
# Sort the presentations by its filename considering language specific
|
||||||
# characters. lower() is needed for windows!
|
# characters.
|
||||||
files.sort(cmp=locale.strcoll,
|
files.sort(cmp=locale_compare,
|
||||||
key=lambda filename: os.path.split(unicode(filename))[1].lower())
|
key=lambda filename: os.path.split(unicode(filename))[1])
|
||||||
for file in files:
|
for file in files:
|
||||||
if not initialLoad:
|
if not initialLoad:
|
||||||
self.plugin.formParent.incrementProgressBar()
|
self.plugin.formParent.incrementProgressBar()
|
||||||
|
@ -49,6 +49,7 @@ class Controller(object):
|
|||||||
"""
|
"""
|
||||||
self.is_live = live
|
self.is_live = live
|
||||||
self.doc = None
|
self.doc = None
|
||||||
|
self.hide_mode = None
|
||||||
log.info(u'%s controller loaded' % live)
|
log.info(u'%s controller loaded' % live)
|
||||||
|
|
||||||
def add_handler(self, controller, file, hide_mode, slide_no):
|
def add_handler(self, controller, file, hide_mode, slide_no):
|
||||||
@ -67,6 +68,7 @@ class Controller(object):
|
|||||||
# Inform slidecontroller that the action failed?
|
# Inform slidecontroller that the action failed?
|
||||||
return
|
return
|
||||||
self.doc.slidenumber = slide_no
|
self.doc.slidenumber = slide_no
|
||||||
|
self.hide_mode = hide_mode
|
||||||
if self.is_live:
|
if self.is_live:
|
||||||
if hide_mode == HideMode.Screen:
|
if hide_mode == HideMode.Screen:
|
||||||
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||||
@ -78,7 +80,7 @@ class Controller(object):
|
|||||||
else:
|
else:
|
||||||
self.doc.start_presentation()
|
self.doc.start_presentation()
|
||||||
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||||
self.doc.slidenumber = 0
|
self.doc.slidenumber = 1
|
||||||
if slide_no > 1:
|
if slide_no > 1:
|
||||||
self.slide(slide_no)
|
self.slide(slide_no)
|
||||||
|
|
||||||
@ -88,100 +90,134 @@ class Controller(object):
|
|||||||
Use the last slide number.
|
Use the last slide number.
|
||||||
"""
|
"""
|
||||||
log.debug(u'Live = %s, activate' % self.is_live)
|
log.debug(u'Live = %s, activate' % self.is_live)
|
||||||
|
if not self.doc:
|
||||||
|
return False
|
||||||
if self.doc.is_active():
|
if self.doc.is_active():
|
||||||
return
|
return True
|
||||||
if not self.doc.is_loaded():
|
if not self.doc.is_loaded():
|
||||||
if not self.doc.load_presentation():
|
if not self.doc.load_presentation():
|
||||||
return
|
log.warn(u'Failed to activate %s' % self.doc.filepath)
|
||||||
|
return False
|
||||||
if self.is_live:
|
if self.is_live:
|
||||||
self.doc.start_presentation()
|
self.doc.start_presentation()
|
||||||
if self.doc.slidenumber > 1:
|
if self.doc.slidenumber > 1:
|
||||||
if self.doc.slidenumber > self.doc.get_slide_count():
|
if self.doc.slidenumber > self.doc.get_slide_count():
|
||||||
self.doc.slidenumber = self.doc.get_slide_count()
|
self.doc.slidenumber = self.doc.get_slide_count()
|
||||||
self.doc.goto_slide(self.doc.slidenumber)
|
self.doc.goto_slide(self.doc.slidenumber)
|
||||||
|
if self.doc.is_active():
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
log.warn(u'Failed to activate %s' % self.doc.filepath)
|
||||||
|
return False
|
||||||
|
|
||||||
def slide(self, slide):
|
def slide(self, slide):
|
||||||
"""
|
"""
|
||||||
Go to a specific 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.doc:
|
||||||
|
return
|
||||||
if not self.is_live:
|
if not self.is_live:
|
||||||
return
|
return
|
||||||
if self.doc.is_blank():
|
if self.hide_mode:
|
||||||
self.doc.slidenumber = int(slide) + 1
|
self.doc.slidenumber = int(slide) + 1
|
||||||
|
self.poll()
|
||||||
|
return
|
||||||
|
if not self.activate():
|
||||||
return
|
return
|
||||||
self.activate()
|
|
||||||
self.doc.goto_slide(int(slide) + 1)
|
self.doc.goto_slide(int(slide) + 1)
|
||||||
self.doc.poll_slidenumber(self.is_live)
|
self.poll()
|
||||||
|
|
||||||
def first(self):
|
def first(self):
|
||||||
"""
|
"""
|
||||||
Based on the handler passed at startup triggers the first slide
|
Based on the handler passed at startup triggers the first slide
|
||||||
"""
|
"""
|
||||||
log.debug(u'Live = %s, first' % self.is_live)
|
log.debug(u'Live = %s, first' % self.is_live)
|
||||||
|
if not self.doc:
|
||||||
|
return
|
||||||
if not self.is_live:
|
if not self.is_live:
|
||||||
return
|
return
|
||||||
if self.doc.is_blank():
|
if self.hide_mode:
|
||||||
self.doc.slidenumber = 1
|
self.doc.slidenumber = 1
|
||||||
|
self.poll()
|
||||||
|
return
|
||||||
|
if not self.activate():
|
||||||
return
|
return
|
||||||
self.activate()
|
|
||||||
self.doc.start_presentation()
|
self.doc.start_presentation()
|
||||||
self.doc.poll_slidenumber(self.is_live)
|
self.poll()
|
||||||
|
|
||||||
def last(self):
|
def last(self):
|
||||||
"""
|
"""
|
||||||
Based on the handler passed at startup triggers the last slide
|
Based on the handler passed at startup triggers the last slide
|
||||||
"""
|
"""
|
||||||
log.debug(u'Live = %s, last' % self.is_live)
|
log.debug(u'Live = %s, last' % self.is_live)
|
||||||
|
if not self.doc:
|
||||||
|
return
|
||||||
if not self.is_live:
|
if not self.is_live:
|
||||||
return
|
return
|
||||||
if self.doc.is_blank():
|
if self.hide_mode:
|
||||||
self.doc.slidenumber = self.doc.get_slide_count()
|
self.doc.slidenumber = self.doc.get_slide_count()
|
||||||
|
self.poll()
|
||||||
|
return
|
||||||
|
if not self.activate():
|
||||||
return
|
return
|
||||||
self.activate()
|
|
||||||
self.doc.goto_slide(self.doc.get_slide_count())
|
self.doc.goto_slide(self.doc.get_slide_count())
|
||||||
self.doc.poll_slidenumber(self.is_live)
|
self.poll()
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
"""
|
"""
|
||||||
Based on the handler passed at startup triggers the next slide event
|
Based on the handler passed at startup triggers the next slide event
|
||||||
"""
|
"""
|
||||||
log.debug(u'Live = %s, next' % self.is_live)
|
log.debug(u'Live = %s, next' % self.is_live)
|
||||||
|
if not self.doc:
|
||||||
|
return
|
||||||
if not self.is_live:
|
if not self.is_live:
|
||||||
return
|
return
|
||||||
if self.doc.is_blank():
|
if self.hide_mode:
|
||||||
|
if not self.doc.is_active():
|
||||||
|
return
|
||||||
if self.doc.slidenumber < self.doc.get_slide_count():
|
if self.doc.slidenumber < self.doc.get_slide_count():
|
||||||
self.doc.slidenumber = self.doc.slidenumber + 1
|
self.doc.slidenumber = self.doc.slidenumber + 1
|
||||||
|
self.poll()
|
||||||
|
return
|
||||||
|
if not self.activate():
|
||||||
return
|
return
|
||||||
# The "End of slideshow" screen is after the last slide
|
# The "End of slideshow" screen is after the last slide
|
||||||
# Note, we can't just stop on the last slide, since it may
|
# Note, we can't just stop on the last slide, since it may
|
||||||
# contain animations that need to be stepped through.
|
# contain animations that need to be stepped through.
|
||||||
if self.doc.slidenumber > self.doc.get_slide_count():
|
if self.doc.slidenumber > self.doc.get_slide_count():
|
||||||
return
|
return
|
||||||
self.activate()
|
|
||||||
self.doc.next_step()
|
self.doc.next_step()
|
||||||
self.doc.poll_slidenumber(self.is_live)
|
self.poll()
|
||||||
|
|
||||||
def previous(self):
|
def previous(self):
|
||||||
"""
|
"""
|
||||||
Based on the handler passed at startup triggers the previous slide event
|
Based on the handler passed at startup triggers the previous slide event
|
||||||
"""
|
"""
|
||||||
log.debug(u'Live = %s, previous' % self.is_live)
|
log.debug(u'Live = %s, previous' % self.is_live)
|
||||||
|
if not self.doc:
|
||||||
|
return
|
||||||
if not self.is_live:
|
if not self.is_live:
|
||||||
return
|
return
|
||||||
if self.doc.is_blank():
|
if self.hide_mode:
|
||||||
|
if not self.doc.is_active():
|
||||||
|
return
|
||||||
if self.doc.slidenumber > 1:
|
if self.doc.slidenumber > 1:
|
||||||
self.doc.slidenumber = self.doc.slidenumber - 1
|
self.doc.slidenumber = self.doc.slidenumber - 1
|
||||||
|
self.poll()
|
||||||
|
return
|
||||||
|
if not self.activate():
|
||||||
return
|
return
|
||||||
self.activate()
|
|
||||||
self.doc.previous_step()
|
self.doc.previous_step()
|
||||||
self.doc.poll_slidenumber(self.is_live)
|
self.poll()
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
"""
|
"""
|
||||||
Based on the handler passed at startup triggers slide show to shut down
|
Based on the handler passed at startup triggers slide show to shut down
|
||||||
"""
|
"""
|
||||||
log.debug(u'Live = %s, shutdown' % self.is_live)
|
log.debug(u'Live = %s, shutdown' % self.is_live)
|
||||||
|
if not self.doc:
|
||||||
|
return
|
||||||
self.doc.close_presentation()
|
self.doc.close_presentation()
|
||||||
self.doc = None
|
self.doc = None
|
||||||
|
|
||||||
@ -190,21 +226,30 @@ class Controller(object):
|
|||||||
Instruct the controller to blank the presentation
|
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)
|
||||||
|
self.hide_mode = hide_mode
|
||||||
|
if not self.doc:
|
||||||
|
return
|
||||||
if not self.is_live:
|
if not self.is_live:
|
||||||
return
|
return
|
||||||
if not self.doc.is_loaded():
|
|
||||||
return
|
|
||||||
if not self.doc.is_active():
|
|
||||||
return
|
|
||||||
if hide_mode == HideMode.Theme:
|
if hide_mode == HideMode.Theme:
|
||||||
|
if not self.doc.is_loaded():
|
||||||
|
return
|
||||||
|
if not self.doc.is_active():
|
||||||
|
return
|
||||||
Receiver.send_message(u'live_display_hide', HideMode.Theme)
|
Receiver.send_message(u'live_display_hide', HideMode.Theme)
|
||||||
self.doc.blank_screen()
|
elif hide_mode == HideMode.Blank:
|
||||||
|
if not self.activate():
|
||||||
|
return
|
||||||
|
self.doc.blank_screen()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""
|
"""
|
||||||
Instruct the controller to stop and hide the presentation
|
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)
|
||||||
|
self.hide_mode = HideMode.Screen
|
||||||
|
if not self.doc:
|
||||||
|
return
|
||||||
if not self.is_live:
|
if not self.is_live:
|
||||||
return
|
return
|
||||||
if not self.doc.is_loaded():
|
if not self.doc.is_loaded():
|
||||||
@ -218,9 +263,13 @@ class Controller(object):
|
|||||||
Instruct the controller to unblank the presentation
|
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)
|
||||||
|
self.hide_mode = None
|
||||||
|
if not self.doc:
|
||||||
|
return
|
||||||
if not self.is_live:
|
if not self.is_live:
|
||||||
return
|
return
|
||||||
self.activate()
|
if not self.activate():
|
||||||
|
return
|
||||||
if self.doc.slidenumber and \
|
if self.doc.slidenumber and \
|
||||||
self.doc.slidenumber != self.doc.get_slide_number():
|
self.doc.slidenumber != self.doc.get_slide_number():
|
||||||
self.doc.goto_slide(self.doc.slidenumber)
|
self.doc.goto_slide(self.doc.slidenumber)
|
||||||
@ -228,7 +277,9 @@ class Controller(object):
|
|||||||
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||||
|
|
||||||
def poll(self):
|
def poll(self):
|
||||||
self.doc.poll_slidenumber(self.is_live)
|
if not self.doc:
|
||||||
|
return
|
||||||
|
self.doc.poll_slidenumber(self.is_live, self.hide_mode)
|
||||||
|
|
||||||
|
|
||||||
class MessageListener(object):
|
class MessageListener(object):
|
||||||
|
@ -94,9 +94,9 @@ class PowerpointController(PresentationController):
|
|||||||
self.docs[0].close_presentation()
|
self.docs[0].close_presentation()
|
||||||
if self.process is None:
|
if self.process is None:
|
||||||
return
|
return
|
||||||
if self.process.Presentations.Count > 0:
|
|
||||||
return
|
|
||||||
try:
|
try:
|
||||||
|
if self.process.Presentations.Count > 0:
|
||||||
|
return
|
||||||
self.process.Quit()
|
self.process.Quit()
|
||||||
except pywintypes.com_error:
|
except pywintypes.com_error:
|
||||||
pass
|
pass
|
||||||
@ -210,6 +210,13 @@ class PowerpointDocument(PresentationDocument):
|
|||||||
self.presentation.SlideShowSettings.Run()
|
self.presentation.SlideShowSettings.Run()
|
||||||
self.presentation.SlideShowWindow.View.State = 1
|
self.presentation.SlideShowWindow.View.State = 1
|
||||||
self.presentation.SlideShowWindow.Activate()
|
self.presentation.SlideShowWindow.Activate()
|
||||||
|
if self.presentation.Application.Version == u'14.0':
|
||||||
|
# Unblanking is broken in PowerPoint 2010, need to redisplay
|
||||||
|
slide = self.presentation.SlideShowWindow.View.CurrentShowPosition
|
||||||
|
click = self.presentation.SlideShowWindow.View.GetClickIndex()
|
||||||
|
self.presentation.SlideShowWindow.View.GotoSlide(slide)
|
||||||
|
if click:
|
||||||
|
self.presentation.SlideShowWindow.View.GotoClick(click)
|
||||||
|
|
||||||
def blank_screen(self):
|
def blank_screen(self):
|
||||||
"""
|
"""
|
||||||
@ -253,6 +260,8 @@ class PowerpointDocument(PresentationDocument):
|
|||||||
renderer = self.controller.plugin.renderer
|
renderer = self.controller.plugin.renderer
|
||||||
rect = renderer.screens.current[u'size']
|
rect = renderer.screens.current[u'size']
|
||||||
ppt_window = self.presentation.SlideShowSettings.Run()
|
ppt_window = self.presentation.SlideShowSettings.Run()
|
||||||
|
if not ppt_window:
|
||||||
|
return
|
||||||
ppt_window.Top = rect.y() * 72 / dpi
|
ppt_window.Top = rect.y() * 72 / dpi
|
||||||
ppt_window.Height = rect.height() * 72 / dpi
|
ppt_window.Height = rect.height() * 72 / dpi
|
||||||
ppt_window.Left = rect.x() * 72 / dpi
|
ppt_window.Left = rect.x() * 72 / dpi
|
||||||
@ -286,6 +295,8 @@ class PowerpointDocument(PresentationDocument):
|
|||||||
"""
|
"""
|
||||||
log.debug(u'next_step')
|
log.debug(u'next_step')
|
||||||
self.presentation.SlideShowWindow.View.Next()
|
self.presentation.SlideShowWindow.View.Next()
|
||||||
|
if self.get_slide_number() > self.get_slide_count():
|
||||||
|
self.previous_step()
|
||||||
|
|
||||||
def previous_step(self):
|
def previous_step(self):
|
||||||
"""
|
"""
|
||||||
|
@ -260,16 +260,17 @@ class PresentationDocument(object):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def poll_slidenumber(self, is_live):
|
def poll_slidenumber(self, is_live, hide_mode):
|
||||||
"""
|
"""
|
||||||
Check the current slide number
|
Check the current slide number
|
||||||
"""
|
"""
|
||||||
if not self.is_active():
|
if not self.is_active():
|
||||||
return
|
return
|
||||||
current = self.get_slide_number()
|
if not hide_mode:
|
||||||
if current == self.slidenumber:
|
current = self.get_slide_number()
|
||||||
return
|
if current == self.slidenumber:
|
||||||
self.slidenumber = current
|
return
|
||||||
|
self.slidenumber = current
|
||||||
if is_live:
|
if is_live:
|
||||||
prefix = u'live'
|
prefix = u'live'
|
||||||
else:
|
else:
|
||||||
|
@ -66,10 +66,10 @@
|
|||||||
<a href="#" id="service-refresh" data-role="button" data-icon="refresh">${refresh}</a>
|
<a href="#" id="service-refresh" data-role="button" data-icon="refresh">${refresh}</a>
|
||||||
<div data-role="navbar">
|
<div data-role="navbar">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#service-manager" data-theme="e">Service</a></li>
|
<li><a href="#service-manager" data-theme="e">${service}</a></li>
|
||||||
<li><a href="#slide-controller">Slides</a></li>
|
<li><a href="#slide-controller">${slides}</a></li>
|
||||||
<li><a href="#alerts">Alerts</a></li>
|
<li><a href="#alerts">${alerts}</a></li>
|
||||||
<li><a href="#search">Search</a></li>
|
<li><a href="#search">${search}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -97,10 +97,10 @@
|
|||||||
<a href="#" id="controller-refresh" data-role="button" data-icon="refresh">${refresh}</a>
|
<a href="#" id="controller-refresh" data-role="button" data-icon="refresh">${refresh}</a>
|
||||||
<div data-role="navbar">
|
<div data-role="navbar">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#service-manager">Service</a></li>
|
<li><a href="#service-manager">${service}</a></li>
|
||||||
<li><a href="#slide-controller" data-theme="e">Slides</a></li>
|
<li><a href="#slide-controller" data-theme="e">${slides}</a></li>
|
||||||
<li><a href="#alerts">Alerts</a></li>
|
<li><a href="#alerts">${alerts}</a></li>
|
||||||
<li><a href="#search">Search</a></li>
|
<li><a href="#search">${search}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -127,10 +127,10 @@
|
|||||||
<h1>${alerts}</h1>
|
<h1>${alerts}</h1>
|
||||||
<div data-role="navbar">
|
<div data-role="navbar">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#service-manager">Service</a></li>
|
<li><a href="#service-manager">${service}</a></li>
|
||||||
<li><a href="#slide-controller">Slides</a></li>
|
<li><a href="#slide-controller">${slides}</a></li>
|
||||||
<li><a href="#alerts" data-theme="e">Alerts</a></li>
|
<li><a href="#alerts" data-theme="e">${alerts}</a></li>
|
||||||
<li><a href="#search">Search</a></li>
|
<li><a href="#search">${search}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -148,10 +148,10 @@
|
|||||||
<h1>${search}</h1>
|
<h1>${search}</h1>
|
||||||
<div data-role="navbar">
|
<div data-role="navbar">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#service-manager">Service</a></li>
|
<li><a href="#service-manager">${service}</a></li>
|
||||||
<li><a href="#slide-controller">Slides</a></li>
|
<li><a href="#slide-controller">${slides}</a></li>
|
||||||
<li><a href="#alerts">Alerts</a></li>
|
<li><a href="#alerts">${alerts}</a></li>
|
||||||
<li><a href="#search" data-theme="e">Search</a></li>
|
<li><a href="#search" data-theme="e">${search}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -55,7 +55,9 @@ window.OpenLP = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
loadService: function (event) {
|
loadService: function (event) {
|
||||||
event.preventDefault();
|
if (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
$.getJSON(
|
$.getJSON(
|
||||||
"/api/service/list",
|
"/api/service/list",
|
||||||
function (data, status) {
|
function (data, status) {
|
||||||
@ -150,6 +152,10 @@ window.OpenLP = {
|
|||||||
OpenLP.currentSlide = data.results.slide;
|
OpenLP.currentSlide = data.results.slide;
|
||||||
OpenLP.currentItem = data.results.item;
|
OpenLP.currentItem = data.results.item;
|
||||||
if ($("#service-manager").is(":visible")) {
|
if ($("#service-manager").is(":visible")) {
|
||||||
|
if (OpenLP.currentService != data.results.service) {
|
||||||
|
OpenLP.currentService = data.results.service;
|
||||||
|
OpenLP.loadService();
|
||||||
|
}
|
||||||
$("#service-manager div[data-role=content] ul[data-role=listview] li").attr("data-theme", "c").removeClass("ui-btn-up-e").addClass("ui-btn-up-c");
|
$("#service-manager div[data-role=content] ul[data-role=listview] li").attr("data-theme", "c").removeClass("ui-btn-up-e").addClass("ui-btn-up-c");
|
||||||
$("#service-manager div[data-role=content] ul[data-role=listview] li a").each(function () {
|
$("#service-manager div[data-role=content] ul[data-role=listview] li a").each(function () {
|
||||||
var item = $(this);
|
var item = $(this);
|
||||||
@ -307,7 +313,7 @@ window.OpenLP = {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
escapeString: function (string) {
|
escapeString: function (string) {
|
||||||
return string.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")
|
return string.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,8 +139,10 @@ window.OpenLP = {
|
|||||||
"/api/poll",
|
"/api/poll",
|
||||||
function (data, status) {
|
function (data, status) {
|
||||||
OpenLP.updateClock(data);
|
OpenLP.updateClock(data);
|
||||||
if (OpenLP.currentItem != data.results.item) {
|
if (OpenLP.currentItem != data.results.item ||
|
||||||
|
OpenLP.currentService != data.results.service) {
|
||||||
OpenLP.currentItem = data.results.item;
|
OpenLP.currentItem = data.results.item;
|
||||||
|
OpenLP.currentService = data.results.service;
|
||||||
OpenLP.loadSlides();
|
OpenLP.loadSlides();
|
||||||
}
|
}
|
||||||
else if (OpenLP.currentSlide != data.results.slide) {
|
else if (OpenLP.currentSlide != data.results.slide) {
|
||||||
|
@ -308,7 +308,9 @@ class HttpConnection(object):
|
|||||||
'add_and_go_to_service': translate('RemotePlugin.Mobile',
|
'add_and_go_to_service': translate('RemotePlugin.Mobile',
|
||||||
'Add & Go to Service'),
|
'Add & Go to Service'),
|
||||||
'no_results': translate('RemotePlugin.Mobile', 'No Results'),
|
'no_results': translate('RemotePlugin.Mobile', 'No Results'),
|
||||||
'options': translate('RemotePlugin.Mobile', 'Options')
|
'options': translate('RemotePlugin.Mobile', 'Options'),
|
||||||
|
'service': translate('RemotePlugin.Mobile', 'Service'),
|
||||||
|
'slides': translate('RemotePlugin.Mobile', 'Slides')
|
||||||
}
|
}
|
||||||
|
|
||||||
def ready_read(self):
|
def ready_read(self):
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
The :mod:`songexportform` module provides the wizard for exporting songs to the
|
The :mod:`songexportform` module provides the wizard for exporting songs to the
|
||||||
OpenLyrics format.
|
OpenLyrics format.
|
||||||
"""
|
"""
|
||||||
import locale
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
@ -38,6 +37,7 @@ from openlp.core.lib import build_icon, Receiver, SettingsManager, translate, \
|
|||||||
create_separated_list
|
create_separated_list
|
||||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||||
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
|
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
|
||||||
|
from openlp.core.utils import locale_direct_compare
|
||||||
from openlp.plugins.songs.lib.db import Song
|
from openlp.plugins.songs.lib.db import Song
|
||||||
from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport
|
from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport
|
||||||
|
|
||||||
@ -252,7 +252,8 @@ class SongExportForm(OpenLPWizard):
|
|||||||
# Load the list of songs.
|
# Load the list of songs.
|
||||||
Receiver.send_message(u'cursor_busy')
|
Receiver.send_message(u'cursor_busy')
|
||||||
songs = self.plugin.manager.get_all_objects(Song)
|
songs = self.plugin.manager.get_all_objects(Song)
|
||||||
songs.sort(cmp=locale.strcoll, key=lambda song: song.title.lower())
|
songs.sort(
|
||||||
|
cmp=locale_direct_compare, key=lambda song: song.sort_string)
|
||||||
for song in songs:
|
for song in songs:
|
||||||
# No need to export temporary songs.
|
# No need to export temporary songs.
|
||||||
if song.temporary:
|
if song.temporary:
|
||||||
|
@ -31,8 +31,9 @@ the Songs plugin
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from sqlalchemy import Column, ForeignKey, Table, types
|
from sqlalchemy import Column, ForeignKey, Table, types
|
||||||
from sqlalchemy.orm import mapper, relation
|
from sqlalchemy.orm import mapper, relation, reconstructor
|
||||||
from sqlalchemy.sql.expression import func
|
from sqlalchemy.sql.expression import func
|
||||||
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
from openlp.core.lib.db import BaseModel, init_db
|
from openlp.core.lib.db import BaseModel, init_db
|
||||||
|
|
||||||
@ -63,7 +64,22 @@ class Song(BaseModel):
|
|||||||
"""
|
"""
|
||||||
Song model
|
Song model
|
||||||
"""
|
"""
|
||||||
pass
|
def __init__(self):
|
||||||
|
self.sort_string = ''
|
||||||
|
|
||||||
|
# This decorator tells sqlalchemy to call this method everytime
|
||||||
|
# any data on this object are updated.
|
||||||
|
@reconstructor
|
||||||
|
def init_on_load(self):
|
||||||
|
"""
|
||||||
|
Precompute string to be used for sorting.
|
||||||
|
|
||||||
|
Song sorting is performance sensitive operation.
|
||||||
|
To get maximum speed lets precompute the string
|
||||||
|
used for comparison.
|
||||||
|
"""
|
||||||
|
# Avoid the overhead of converting string to lowercase and to QString
|
||||||
|
self.sort_string = QtCore.QString(self.title.lower())
|
||||||
|
|
||||||
|
|
||||||
class Topic(BaseModel):
|
class Topic(BaseModel):
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import locale
|
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
@ -40,7 +39,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
|
|||||||
check_directory_exists
|
check_directory_exists
|
||||||
from openlp.core.lib.ui import UiStrings, create_widget_action
|
from openlp.core.lib.ui import UiStrings, create_widget_action
|
||||||
from openlp.core.lib.settings import Settings
|
from openlp.core.lib.settings import Settings
|
||||||
from openlp.core.utils import AppLocation
|
from openlp.core.utils import AppLocation, locale_direct_compare
|
||||||
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
|
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
|
||||||
SongImportForm, SongExportForm
|
SongImportForm, SongExportForm
|
||||||
from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \
|
from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \
|
||||||
@ -260,10 +259,8 @@ class SongMediaItem(MediaManagerItem):
|
|||||||
log.debug(u'display results Song')
|
log.debug(u'display results Song')
|
||||||
self.saveAutoSelectId()
|
self.saveAutoSelectId()
|
||||||
self.listView.clear()
|
self.listView.clear()
|
||||||
# Sort the songs by its title considering language specific characters.
|
|
||||||
# lower() is needed for windows!
|
|
||||||
searchresults.sort(
|
searchresults.sort(
|
||||||
cmp=locale.strcoll, key=lambda song: song.title.lower())
|
cmp=locale_direct_compare, key=lambda song: song.sort_string)
|
||||||
for song in searchresults:
|
for song in searchresults:
|
||||||
# Do not display temporary songs
|
# Do not display temporary songs
|
||||||
if song.temporary:
|
if song.temporary:
|
||||||
|
@ -63,10 +63,14 @@ class OpenLPSongImport(SongImport):
|
|||||||
SongImport.__init__(self, manager, **kwargs)
|
SongImport.__init__(self, manager, **kwargs)
|
||||||
self.sourceSession = None
|
self.sourceSession = None
|
||||||
|
|
||||||
def doImport(self):
|
def doImport(self, progressDialog=None):
|
||||||
"""
|
"""
|
||||||
Run the import for an OpenLP version 2 song database.
|
Run the import for an OpenLP version 2 song database.
|
||||||
|
|
||||||
|
``progressDialog``
|
||||||
|
The QProgressDialog used when importing songs from the FRW.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class OldAuthor(BaseModel):
|
class OldAuthor(BaseModel):
|
||||||
"""
|
"""
|
||||||
Author model
|
Author model
|
||||||
@ -101,13 +105,14 @@ class OpenLPSongImport(SongImport):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Check the file type
|
||||||
if not self.importSource.endswith(u'.sqlite'):
|
if not self.importSource.endswith(u'.sqlite'):
|
||||||
self.logError(self.importSource,
|
self.logError(self.importSource,
|
||||||
translate('SongsPlugin.OpenLPSongImport',
|
translate('SongsPlugin.OpenLPSongImport',
|
||||||
'Not a valid OpenLP 2.0 song database.'))
|
'Not a valid OpenLP 2.0 song database.'))
|
||||||
return
|
return
|
||||||
self.importSource = u'sqlite:///%s' % self.importSource
|
self.importSource = u'sqlite:///%s' % self.importSource
|
||||||
|
# Load the db file
|
||||||
engine = create_engine(self.importSource)
|
engine = create_engine(self.importSource)
|
||||||
source_meta = MetaData()
|
source_meta = MetaData()
|
||||||
source_meta.reflect(engine)
|
source_meta.reflect(engine)
|
||||||
@ -224,7 +229,11 @@ class OpenLPSongImport(SongImport):
|
|||||||
file_name=media_file.file_name))
|
file_name=media_file.file_name))
|
||||||
clean_song(self.manager, new_song)
|
clean_song(self.manager, new_song)
|
||||||
self.manager.save_object(new_song)
|
self.manager.save_object(new_song)
|
||||||
if self.importWizard:
|
if progressDialog:
|
||||||
|
progressDialog.setValue(progressDialog.value() + 1)
|
||||||
|
progressDialog.setLabelText(
|
||||||
|
WizardStrings.ImportingType % new_song.title)
|
||||||
|
else:
|
||||||
self.importWizard.incrementProgressBar(
|
self.importWizard.incrementProgressBar(
|
||||||
WizardStrings.ImportingType % new_song.title)
|
WizardStrings.ImportingType % new_song.title)
|
||||||
if self.stopImportFlag:
|
if self.stopImportFlag:
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
@ -123,6 +124,7 @@ class OooImport(SongImport):
|
|||||||
try:
|
try:
|
||||||
uno_instance = get_uno_instance(resolver)
|
uno_instance = get_uno_instance(resolver)
|
||||||
except NoConnectException:
|
except NoConnectException:
|
||||||
|
time.sleep(0.1)
|
||||||
log.exception("Failed to resolve uno connection")
|
log.exception("Failed to resolve uno connection")
|
||||||
self.startOooProcess()
|
self.startOooProcess()
|
||||||
loop += 1
|
loop += 1
|
||||||
|
@ -154,18 +154,20 @@ class SundayPlusImport(SongImport):
|
|||||||
# If any line inside any verse contains CCLI or
|
# If any line inside any verse contains CCLI or
|
||||||
# only Public Domain, we treat this as special data:
|
# only Public Domain, we treat this as special data:
|
||||||
# we remove that line and add data to specific field.
|
# we remove that line and add data to specific field.
|
||||||
|
processed_lines = []
|
||||||
for i in xrange(len(lines)):
|
for i in xrange(len(lines)):
|
||||||
lines[i] = lines[i].strip()
|
line = lines[i].strip()
|
||||||
line = lines[i]
|
if line[:3].lower() == u'ccl':
|
||||||
if line[:4].lower() == u'ccli':
|
|
||||||
m = re.search(r'[0-9]+', line)
|
m = re.search(r'[0-9]+', line)
|
||||||
if m:
|
if m:
|
||||||
self.ccliNumber = int(m.group(0))
|
self.ccliNumber = int(m.group(0))
|
||||||
lines.pop(i)
|
continue
|
||||||
elif line.lower() == u'public domain':
|
elif line.lower() == u'public domain':
|
||||||
self.copyright = u'Public Domain'
|
self.copyright = u'Public Domain'
|
||||||
lines.pop(i)
|
continue
|
||||||
self.addVerse('\n'.join(lines).strip(), verse_type)
|
processed_lines.append(line)
|
||||||
|
self.addVerse('\n'.join(processed_lines).strip(),
|
||||||
|
verse_type)
|
||||||
if end == -1:
|
if end == -1:
|
||||||
break
|
break
|
||||||
i = end + 1
|
i = end + 1
|
||||||
|
@ -260,7 +260,7 @@ class OpenLyrics(object):
|
|||||||
IMPLEMENTED_VERSION = u'0.8'
|
IMPLEMENTED_VERSION = u'0.8'
|
||||||
START_TAGS_REGEX = re.compile(r'\{(\w+)\}')
|
START_TAGS_REGEX = re.compile(r'\{(\w+)\}')
|
||||||
END_TAGS_REGEX = re.compile(r'\{\/(\w+)\}')
|
END_TAGS_REGEX = re.compile(r'\{\/(\w+)\}')
|
||||||
VERSE_NUMBER_REGEX = re.compile(u'[a-zA-Z]*')
|
VERSE_TAG_SPLITTER = re.compile(u'([a-zA-Z]+)([0-9]*)([a-zA-Z]?)')
|
||||||
|
|
||||||
def __init__(self, manager):
|
def __init__(self, manager):
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
@ -325,10 +325,22 @@ class OpenLyrics(object):
|
|||||||
# Process the song's lyrics.
|
# Process the song's lyrics.
|
||||||
lyrics = etree.SubElement(song_xml, u'lyrics')
|
lyrics = etree.SubElement(song_xml, u'lyrics')
|
||||||
verse_list = sxml.get_verses(song.lyrics)
|
verse_list = sxml.get_verses(song.lyrics)
|
||||||
|
# Add a suffix letter to each verse
|
||||||
|
verse_tags = []
|
||||||
for verse in verse_list:
|
for verse in verse_list:
|
||||||
verse_tag = verse[0][u'type'][0].lower()
|
verse_tag = verse[0][u'type'][0].lower()
|
||||||
verse_number = verse[0][u'label']
|
verse_number = verse[0][u'label']
|
||||||
verse_def = verse_tag + verse_number
|
verse_def = verse_tag + verse_number
|
||||||
|
verse_tags.append(verse_def)
|
||||||
|
# Create the letter from the number of duplicates
|
||||||
|
verse[0][u'suffix'] = chr(96 + verse_tags.count(verse_def))
|
||||||
|
# If the verse tag is a duplicate use the suffix letter
|
||||||
|
for verse in verse_list:
|
||||||
|
verse_tag = verse[0][u'type'][0].lower()
|
||||||
|
verse_number = verse[0][u'label']
|
||||||
|
verse_def = verse_tag + verse_number
|
||||||
|
if verse_tags.count(verse_def) > 1:
|
||||||
|
verse_def += verse[0][u'suffix']
|
||||||
verse_element = \
|
verse_element = \
|
||||||
self._add_text_to_element(u'verse', lyrics, None, verse_def)
|
self._add_text_to_element(u'verse', lyrics, None, verse_def)
|
||||||
if u'lang' in verse[0]:
|
if u'lang' in verse[0]:
|
||||||
@ -742,28 +754,28 @@ class OpenLyrics(object):
|
|||||||
if lines.get(u'break') is not None:
|
if lines.get(u'break') is not None:
|
||||||
text += u'\n[---]'
|
text += u'\n[---]'
|
||||||
verse_def = verse.get(u'name', u' ').lower()
|
verse_def = verse.get(u'name', u' ').lower()
|
||||||
if verse_def[0] in VerseType.Tags:
|
verse_tag, verse_number, verse_part = \
|
||||||
verse_tag = verse_def[0]
|
OpenLyrics.VERSE_TAG_SPLITTER.search(verse_def).groups()
|
||||||
else:
|
if verse_tag not in VerseType.Tags:
|
||||||
verse_tag = VerseType.Tags[VerseType.Other]
|
verse_tag = VerseType.Tags[VerseType.Other]
|
||||||
verse_number = OpenLyrics.VERSE_NUMBER_REGEX.sub(u'', verse_def)
|
|
||||||
# OpenLyrics allows e. g. "c", but we need "c1". However, this does
|
# OpenLyrics allows e. g. "c", but we need "c1". However, this does
|
||||||
# not correct the verse order.
|
# not correct the verse order.
|
||||||
if not verse_number:
|
if not verse_number:
|
||||||
verse_number = u'1'
|
verse_number = u'1'
|
||||||
lang = verse.get(u'lang')
|
lang = verse.get(u'lang')
|
||||||
|
translit = verse.get(u'translit')
|
||||||
# In OpenLP 1.9.6 we used v1a, v1b ... to represent visual slide
|
# In OpenLP 1.9.6 we used v1a, v1b ... to represent visual slide
|
||||||
# breaks. In OpenLyrics 0.7 an attribute has been added.
|
# breaks. In OpenLyrics 0.7 an attribute has been added.
|
||||||
if song_xml.get(u'modifiedIn') in (u'1.9.6', u'OpenLP 1.9.6') and \
|
if song_xml.get(u'modifiedIn') in (u'1.9.6', u'OpenLP 1.9.6') and \
|
||||||
song_xml.get(u'version') == u'0.7' and \
|
song_xml.get(u'version') == u'0.7' and \
|
||||||
(verse_tag, verse_number, lang) in verses:
|
(verse_tag, verse_number, lang, translit) in verses:
|
||||||
verses[(verse_tag, verse_number, lang)] += u'\n[---]\n' + text
|
verses[(verse_tag, verse_number, lang, translit, None)] += u'\n[---]\n' + text
|
||||||
# Merge v1a, v1b, .... to v1.
|
# Merge v1a, v1b, .... to v1.
|
||||||
elif (verse_tag, verse_number, lang) in verses:
|
elif (verse_tag, verse_number, lang, translit, verse_part) in verses:
|
||||||
verses[(verse_tag, verse_number, lang)] += u'\n' + text
|
verses[(verse_tag, verse_number, lang, translit, verse_part)] += u'\n' + text
|
||||||
else:
|
else:
|
||||||
verses[(verse_tag, verse_number, lang)] = text
|
verses[(verse_tag, verse_number, lang, translit, verse_part)] = text
|
||||||
verse_def_list.append((verse_tag, verse_number, lang))
|
verse_def_list.append((verse_tag, verse_number, lang, translit, verse_part))
|
||||||
# We have to use a list to keep the order, as dicts are not sorted.
|
# We have to use a list to keep the order, as dicts are not sorted.
|
||||||
for verse in verse_def_list:
|
for verse in verse_def_list:
|
||||||
sxml.add_verse_to_lyrics(
|
sxml.add_verse_to_lyrics(
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from tempfile import gettempdir
|
from tempfile import gettempdir
|
||||||
|
import sqlite3
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ class SongsPlugin(Plugin):
|
|||||||
unicode(UiStrings().Tools))
|
unicode(UiStrings().Tools))
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'servicemanager_new_service'),
|
QtCore.SIGNAL(u'servicemanager_new_service'),
|
||||||
self.clearTemporarySongs)
|
self.clearTemporarySongs)
|
||||||
|
|
||||||
|
|
||||||
def addImportMenuItem(self, import_menu):
|
def addImportMenuItem(self, import_menu):
|
||||||
@ -235,31 +236,37 @@ class SongsPlugin(Plugin):
|
|||||||
If the first time wizard has run, this function is run to import all the
|
If the first time wizard has run, this function is run to import all the
|
||||||
new songs into the database.
|
new songs into the database.
|
||||||
"""
|
"""
|
||||||
|
Receiver.send_message(u'openlp_process_events')
|
||||||
self.onToolsReindexItemTriggered()
|
self.onToolsReindexItemTriggered()
|
||||||
|
Receiver.send_message(u'openlp_process_events')
|
||||||
db_dir = unicode(os.path.join(
|
db_dir = unicode(os.path.join(
|
||||||
unicode(gettempdir(), get_filesystem_encoding()), u'openlp'))
|
unicode(gettempdir(), get_filesystem_encoding()), u'openlp'))
|
||||||
if not os.path.exists(db_dir):
|
if not os.path.exists(db_dir):
|
||||||
return
|
return
|
||||||
song_dbs = []
|
song_dbs = []
|
||||||
|
song_count = 0
|
||||||
for sfile in os.listdir(db_dir):
|
for sfile in os.listdir(db_dir):
|
||||||
if sfile.startswith(u'songs_') and sfile.endswith(u'.sqlite'):
|
if sfile.startswith(u'songs_') and sfile.endswith(u'.sqlite'):
|
||||||
|
Receiver.send_message(u'openlp_process_events')
|
||||||
song_dbs.append(os.path.join(db_dir, sfile))
|
song_dbs.append(os.path.join(db_dir, sfile))
|
||||||
|
song_count += self._countSongs(os.path.join(db_dir, sfile))
|
||||||
if not song_dbs:
|
if not song_dbs:
|
||||||
return
|
return
|
||||||
|
Receiver.send_message(u'openlp_process_events')
|
||||||
progress = QtGui.QProgressDialog(self.formParent)
|
progress = QtGui.QProgressDialog(self.formParent)
|
||||||
progress.setWindowModality(QtCore.Qt.WindowModal)
|
progress.setWindowModality(QtCore.Qt.WindowModal)
|
||||||
progress.setWindowTitle(translate('OpenLP.Ui', 'Importing Songs'))
|
progress.setWindowTitle(translate('OpenLP.Ui', 'Importing Songs'))
|
||||||
progress.setLabelText(translate('OpenLP.Ui', 'Starting import...'))
|
progress.setLabelText(translate('OpenLP.Ui', 'Starting import...'))
|
||||||
progress.setCancelButton(None)
|
progress.setCancelButton(None)
|
||||||
progress.setRange(0, len(song_dbs))
|
progress.setRange(0, song_count)
|
||||||
progress.setMinimumDuration(0)
|
progress.setMinimumDuration(0)
|
||||||
progress.forceShow()
|
progress.forceShow()
|
||||||
for idx, db in enumerate(song_dbs):
|
Receiver.send_message(u'openlp_process_events')
|
||||||
progress.setValue(idx)
|
for db in song_dbs:
|
||||||
Receiver.send_message(u'openlp_process_events')
|
|
||||||
importer = OpenLPSongImport(self.manager, filename=db)
|
importer = OpenLPSongImport(self.manager, filename=db)
|
||||||
importer.doImport()
|
importer.doImport(progress)
|
||||||
progress.setValue(len(song_dbs))
|
Receiver.send_message(u'openlp_process_events')
|
||||||
|
progress.setValue(song_count)
|
||||||
self.mediaItem.onSearchTextButtonClicked()
|
self.mediaItem.onSearchTextButtonClicked()
|
||||||
|
|
||||||
def finalise(self):
|
def finalise(self):
|
||||||
@ -287,3 +294,15 @@ class SongsPlugin(Plugin):
|
|||||||
songs = self.manager.get_all_objects(Song, Song.temporary == True)
|
songs = self.manager.get_all_objects(Song, Song.temporary == True)
|
||||||
for song in songs:
|
for song in songs:
|
||||||
self.manager.delete_object(Song, song.id)
|
self.manager.delete_object(Song, song.id)
|
||||||
|
|
||||||
|
def _countSongs(self, db_file):
|
||||||
|
connection = sqlite3.connect(db_file)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute(u'SELECT COUNT(id) AS song_count FROM songs')
|
||||||
|
song_count = cursor.fetchone()[0]
|
||||||
|
connection.close()
|
||||||
|
try:
|
||||||
|
song_count = int(song_count)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
song_count = 0
|
||||||
|
return song_count
|
||||||
|
BIN
resources/images/media_audio.png
Normal file
BIN
resources/images/media_audio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
resources/images/media_video.png
Normal file
BIN
resources/images/media_video.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
@ -130,7 +130,9 @@
|
|||||||
<qresource prefix="media">
|
<qresource prefix="media">
|
||||||
<file>media_time.png</file>
|
<file>media_time.png</file>
|
||||||
<file>media_stop.png</file>
|
<file>media_stop.png</file>
|
||||||
<file>image_clapperboard.png</file>
|
<file>media_audio.png</file>
|
||||||
|
<file>media_video.png</file>
|
||||||
|
<file>slidecontroller_multimedia.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="messagebox">
|
<qresource prefix="messagebox">
|
||||||
<file>messagebox_critical.png</file>
|
<file>messagebox_critical.png</file>
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 11 KiB |
BIN
resources/images/slidecontroller_multimedia.png
Normal file
BIN
resources/images/slidecontroller_multimedia.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Loading…
Reference in New Issue
Block a user