forked from openlp/openlp
Head
This commit is contained in:
commit
0f0cf5987c
@ -85,6 +85,14 @@ class PluginManager(object):
|
||||
log.debug(u'finding plugins in %s at depth %d',
|
||||
unicode(plugin_dir), startdepth)
|
||||
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:
|
||||
if name.endswith(u'.py') and not name.startswith(u'__'):
|
||||
path = os.path.abspath(os.path.join(root, name))
|
||||
|
@ -177,8 +177,10 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
return FirstTimePage.Progress
|
||||
elif self.currentId() == FirstTimePage.Themes:
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
while not self.themeScreenshotThread.isFinished():
|
||||
time.sleep(0.1)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
# Build the screenshot icons, as this can not be done in the thread.
|
||||
self._buildThemeScreenshots()
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
@ -188,10 +190,11 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
|
||||
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
|
||||
# to be a -1.
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
if pageId != -1:
|
||||
self.lastId = pageId
|
||||
if pageId == FirstTimePage.Plugins:
|
||||
@ -227,10 +230,12 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
self.cancelButton.setVisible(False)
|
||||
elif pageId == FirstTimePage.Progress:
|
||||
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()
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self._performWizard()
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self._postWizard()
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
@ -263,8 +268,8 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
"""
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self._performWizard()
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
Settings().setValue(u'general/has run wizard',
|
||||
QtCore.QVariant(True))
|
||||
self.close()
|
||||
@ -344,6 +349,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
# Loop through the songs list and increase for each selected item
|
||||
for i in xrange(self.songsListWidget.count()):
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
item = self.songsListWidget.item(i)
|
||||
if item.checkState() == QtCore.Qt.Checked:
|
||||
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
|
||||
iterator = QtGui.QTreeWidgetItemIterator(self.biblesTreeWidget)
|
||||
while iterator.value():
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
item = iterator.value()
|
||||
if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
|
||||
filename = item.data(0, QtCore.Qt.UserRole).toString()
|
||||
@ -360,6 +367,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
iterator += 1
|
||||
# Loop through the themes list and increase for each selected item
|
||||
for i in xrange(self.themesListWidget.count()):
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
item = self.themesListWidget.item(i)
|
||||
if item.checkState() == QtCore.Qt.Checked:
|
||||
filename = item.data(QtCore.Qt.UserRole).toString()
|
||||
@ -381,6 +389,10 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
self.progressPage.setTitle(translate('OpenLP.FirstTimeWizard',
|
||||
'Setting Up'))
|
||||
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):
|
||||
"""
|
||||
|
@ -82,13 +82,13 @@ class Ui_FirstTimeWizard(object):
|
||||
self.imageCheckBox.setChecked(True)
|
||||
self.imageCheckBox.setObjectName(u'imageCheckBox')
|
||||
self.pluginLayout.addWidget(self.imageCheckBox)
|
||||
self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage)
|
||||
if sys.platform == "darwin":
|
||||
self.presentationCheckBox.setChecked(False)
|
||||
else:
|
||||
# TODO Presentation plugin is not yet working on Mac OS X.
|
||||
# For now just ignore it.
|
||||
if sys.platform != 'darwin':
|
||||
self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage)
|
||||
self.presentationCheckBox.setChecked(True)
|
||||
self.presentationCheckBox.setObjectName(u'presentationCheckBox')
|
||||
self.pluginLayout.addWidget(self.presentationCheckBox)
|
||||
self.presentationCheckBox.setObjectName(u'presentationCheckBox')
|
||||
self.pluginLayout.addWidget(self.presentationCheckBox)
|
||||
self.mediaCheckBox = QtGui.QCheckBox(self.pluginPage)
|
||||
self.mediaCheckBox.setChecked(True)
|
||||
self.mediaCheckBox.setObjectName(u'mediaCheckBox')
|
||||
@ -214,10 +214,11 @@ class Ui_FirstTimeWizard(object):
|
||||
self.bibleCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Bible'))
|
||||
self.imageCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
||||
'Images'))
|
||||
self.presentationCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
||||
'Presentations'))
|
||||
if sys.platform == "darwin":
|
||||
self.presentationCheckBox.setEnabled(False)
|
||||
# TODO Presentation plugin is not yet working on Mac OS X.
|
||||
# For now just ignore it.
|
||||
if sys.platform != 'darwin':
|
||||
self.presentationCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
||||
'Presentations'))
|
||||
self.mediaCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
||||
'Media (Audio and Video)'))
|
||||
self.remoteCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
||||
|
@ -30,7 +30,6 @@ import os
|
||||
import zipfile
|
||||
import shutil
|
||||
import logging
|
||||
import locale
|
||||
import re
|
||||
|
||||
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
|
||||
from openlp.core.theme import Theme
|
||||
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__)
|
||||
|
||||
@ -284,6 +284,7 @@ class ThemeManager(QtGui.QWidget):
|
||||
plugin.renameTheme(old_theme_name, new_theme_name)
|
||||
self.mainwindow.renderer.update_theme(
|
||||
new_theme_name, old_theme_name)
|
||||
self.loadThemes()
|
||||
|
||||
def onCopyTheme(self):
|
||||
"""
|
||||
@ -457,9 +458,8 @@ class ThemeManager(QtGui.QWidget):
|
||||
self.configUpdated()
|
||||
files = SettingsManager.get_files(self.settingsSection, u'.png')
|
||||
# Sort the themes by its name considering language specific characters.
|
||||
# lower() is needed for windows!
|
||||
files.sort(key=lambda file_name: unicode(file_name).lower(),
|
||||
cmp=locale.strcoll)
|
||||
files.sort(key=lambda file_name: unicode(file_name),
|
||||
cmp=locale_compare)
|
||||
# now process the file list of png files
|
||||
for name in files:
|
||||
# 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)
|
||||
|
||||
|
||||
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 actions import ActionList
|
||||
|
||||
__all__ = [u'AppLocation', u'get_application_version', u'check_latest_version',
|
||||
u'add_actions', u'get_filesystem_encoding', u'LanguageManager',
|
||||
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']
|
||||
|
@ -30,7 +30,6 @@ The bible import functions for OpenLP
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
import locale
|
||||
|
||||
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.settings import Settings
|
||||
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.db import BiblesResourcesDB, clean_filename
|
||||
|
||||
@ -523,7 +522,7 @@ class BibleImportForm(OpenLPWizard):
|
||||
"""
|
||||
self.webTranslationComboBox.clear()
|
||||
bibles = self.web_bible_list[index].keys()
|
||||
bibles.sort(cmp=locale.strcoll)
|
||||
bibles.sort(cmp=locale_compare)
|
||||
self.webTranslationComboBox.addItems(bibles)
|
||||
|
||||
def onOsisBrowseButtonClicked(self):
|
||||
|
@ -27,7 +27,6 @@
|
||||
###############################################################################
|
||||
|
||||
import logging
|
||||
import locale
|
||||
|
||||
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, \
|
||||
create_horizontal_adjusting_combo_box, critical_error_message_box, \
|
||||
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.lib import LayoutStyle, DisplayStyle, \
|
||||
VerseReferenceList, get_reference_separator, LanguageSelection, \
|
||||
@ -381,7 +381,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
# Get all bibles and sort the list.
|
||||
bibles = self.plugin.manager.get_bibles().keys()
|
||||
bibles = filter(None, bibles)
|
||||
bibles.sort(cmp=locale.strcoll)
|
||||
bibles.sort(cmp=locale_compare)
|
||||
# Load the bibles into the combo boxes.
|
||||
self.quickVersionComboBox.addItems(bibles)
|
||||
self.quickSecondComboBox.addItems(bibles)
|
||||
@ -538,7 +538,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
data = BiblesResourcesDB.get_book_by_id(
|
||||
book.book_reference_id)
|
||||
books.append(data[u'name'] + u' ')
|
||||
books.sort(cmp=locale.strcoll)
|
||||
books.sort(cmp=locale_compare)
|
||||
set_case_insensitive_completer(books, self.quickSearchEdit)
|
||||
|
||||
def onImportClick(self):
|
||||
|
@ -34,12 +34,21 @@ from sqlalchemy import Column, Table, types
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from openlp.core.lib.db import BaseModel, init_db
|
||||
from openlp.core.utils import locale_compare
|
||||
|
||||
class CustomSlide(BaseModel):
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
|
@ -27,7 +27,6 @@
|
||||
###############################################################################
|
||||
|
||||
import logging
|
||||
import locale
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
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.
|
||||
self.saveAutoSelectId()
|
||||
self.listView.clear()
|
||||
# Sort the customs by its title considering language specific
|
||||
# characters. lower() is needed for windows!
|
||||
custom_slides.sort(
|
||||
cmp=locale.strcoll, key=lambda custom: custom.title.lower())
|
||||
custom_slides.sort()
|
||||
for custom_slide in custom_slides:
|
||||
custom_name = QtGui.QListWidgetItem(custom_slide.title)
|
||||
custom_name.setData(
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
import logging
|
||||
import os
|
||||
import locale
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
@ -37,7 +36,8 @@ from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \
|
||||
Receiver, create_thumb, validate_thumb
|
||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||
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__)
|
||||
|
||||
@ -126,10 +126,10 @@ class ImageMediaItem(MediaManagerItem):
|
||||
if not initialLoad:
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self.plugin.formParent.displayProgressBar(len(images))
|
||||
# Sort the themes by its filename considering language specific
|
||||
# characters. lower() is needed for windows!
|
||||
images.sort(cmp=locale.strcoll,
|
||||
key=lambda filename: os.path.split(unicode(filename))[1].lower())
|
||||
# Sort the images by its filename considering language specific
|
||||
# characters.
|
||||
images.sort(cmp=locale_compare,
|
||||
key=lambda filename: os.path.split(unicode(filename))[1])
|
||||
for imageFile in images:
|
||||
filename = os.path.split(unicode(imageFile))[1]
|
||||
thumb = os.path.join(self.servicePath, filename)
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
import logging
|
||||
import os
|
||||
import locale
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
@ -39,6 +38,7 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
|
||||
create_horizontal_adjusting_combo_box
|
||||
from openlp.core.ui import Controller, Display
|
||||
from openlp.core.ui.media import get_media_players, set_media_players
|
||||
from openlp.core.utils import locale_compare
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -285,10 +285,10 @@ class MediaMediaItem(MediaManagerItem):
|
||||
u'media', self.getFileList())
|
||||
|
||||
def loadList(self, media):
|
||||
# Sort the themes by its filename considering language specific
|
||||
# characters. lower() is needed for windows!
|
||||
media.sort(cmp=locale.strcoll,
|
||||
key=lambda filename: os.path.split(unicode(filename))[1].lower())
|
||||
# Sort the media by its filename considering language specific
|
||||
# characters.
|
||||
media.sort(cmp=locale_compare,
|
||||
key=lambda filename: os.path.split(unicode(filename))[1])
|
||||
for track in media:
|
||||
track_info = QtCore.QFileInfo(track)
|
||||
if track_info.isFile():
|
||||
@ -307,8 +307,8 @@ class MediaMediaItem(MediaManagerItem):
|
||||
|
||||
def getList(self, type=MediaType.Audio):
|
||||
media = SettingsManager.load_list(self.settingsSection, u'media')
|
||||
media.sort(cmp=locale.strcoll,
|
||||
key=lambda filename: os.path.split(unicode(filename))[1].lower())
|
||||
media.sort(cmp=locale_compare,
|
||||
key=lambda filename: os.path.split(unicode(filename))[1])
|
||||
ext = []
|
||||
if type == MediaType.Audio:
|
||||
ext = self.plugin.audio_extensions_list
|
||||
|
@ -153,7 +153,7 @@ class ImpressController(PresentationController):
|
||||
desktop = None
|
||||
try:
|
||||
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')
|
||||
return desktop if desktop else None
|
||||
|
||||
@ -284,6 +284,8 @@ class ImpressDocument(PresentationDocument):
|
||||
props = tuple(props)
|
||||
doc = self.document
|
||||
pages = doc.getDrawPages()
|
||||
if not pages:
|
||||
return
|
||||
if not os.path.isdir(self.get_temp_folder()):
|
||||
os.makedirs(self.get_temp_folder())
|
||||
for idx in range(pages.getCount()):
|
||||
@ -359,7 +361,7 @@ class ImpressDocument(PresentationDocument):
|
||||
log.debug(u'is active OpenOffice')
|
||||
if not self.is_loaded():
|
||||
return False
|
||||
return self.control is not None
|
||||
return self.control.isRunning() if self.control else False
|
||||
|
||||
def unblank_screen(self):
|
||||
"""
|
||||
@ -380,7 +382,7 @@ class ImpressDocument(PresentationDocument):
|
||||
Returns true if screen is blank
|
||||
"""
|
||||
log.debug(u'is blank OpenOffice')
|
||||
if self.control:
|
||||
if self.control and self.control.isRunning():
|
||||
return self.control.isPaused()
|
||||
else:
|
||||
return False
|
||||
@ -436,7 +438,11 @@ class ImpressDocument(PresentationDocument):
|
||||
"""
|
||||
Triggers the next effect of slide on the running presentation
|
||||
"""
|
||||
is_paused = self.control.isPaused()
|
||||
self.control.gotoNextEffect()
|
||||
time.sleep(0.1)
|
||||
if not is_paused and self.control.isPaused():
|
||||
self.control.gotoPreviousEffect()
|
||||
|
||||
def previous_step(self):
|
||||
"""
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
import logging
|
||||
import os
|
||||
import locale
|
||||
|
||||
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, \
|
||||
create_horizontal_adjusting_combo_box
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.core.utils import locale_compare
|
||||
from openlp.plugins.presentations.lib import MessageListener
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -169,10 +169,10 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
if not initialLoad:
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self.plugin.formParent.displayProgressBar(len(files))
|
||||
# Sort the themes by its filename considering language specific
|
||||
# characters. lower() is needed for windows!
|
||||
files.sort(cmp=locale.strcoll,
|
||||
key=lambda filename: os.path.split(unicode(filename))[1].lower())
|
||||
# Sort the presentations by its filename considering language specific
|
||||
# characters.
|
||||
files.sort(cmp=locale_compare,
|
||||
key=lambda filename: os.path.split(unicode(filename))[1])
|
||||
for file in files:
|
||||
if not initialLoad:
|
||||
self.plugin.formParent.incrementProgressBar()
|
||||
|
@ -49,6 +49,7 @@ class Controller(object):
|
||||
"""
|
||||
self.is_live = live
|
||||
self.doc = None
|
||||
self.hide_mode = None
|
||||
log.info(u'%s controller loaded' % live)
|
||||
|
||||
def add_handler(self, controller, file, hide_mode, slide_no):
|
||||
@ -67,6 +68,7 @@ class Controller(object):
|
||||
# Inform slidecontroller that the action failed?
|
||||
return
|
||||
self.doc.slidenumber = slide_no
|
||||
self.hide_mode = hide_mode
|
||||
if self.is_live:
|
||||
if hide_mode == HideMode.Screen:
|
||||
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||
@ -78,7 +80,7 @@ class Controller(object):
|
||||
else:
|
||||
self.doc.start_presentation()
|
||||
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||
self.doc.slidenumber = 0
|
||||
self.doc.slidenumber = 1
|
||||
if slide_no > 1:
|
||||
self.slide(slide_no)
|
||||
|
||||
@ -88,100 +90,134 @@ class Controller(object):
|
||||
Use the last slide number.
|
||||
"""
|
||||
log.debug(u'Live = %s, activate' % self.is_live)
|
||||
if not self.doc:
|
||||
return False
|
||||
if self.doc.is_active():
|
||||
return
|
||||
return True
|
||||
if not self.doc.is_loaded():
|
||||
if not self.doc.load_presentation():
|
||||
return
|
||||
log.warn(u'Failed to activate %s' % self.doc.filepath)
|
||||
return False
|
||||
if self.is_live:
|
||||
self.doc.start_presentation()
|
||||
if self.doc.slidenumber > 1:
|
||||
if self.doc.slidenumber > self.doc.get_slide_count():
|
||||
self.doc.slidenumber = self.doc.get_slide_count()
|
||||
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):
|
||||
"""
|
||||
Go to a specific slide
|
||||
"""
|
||||
log.debug(u'Live = %s, slide' % self.is_live)
|
||||
if not self.doc:
|
||||
return
|
||||
if not self.is_live:
|
||||
return
|
||||
if self.doc.is_blank():
|
||||
if self.hide_mode:
|
||||
self.doc.slidenumber = int(slide) + 1
|
||||
self.poll()
|
||||
return
|
||||
if not self.activate():
|
||||
return
|
||||
self.activate()
|
||||
self.doc.goto_slide(int(slide) + 1)
|
||||
self.doc.poll_slidenumber(self.is_live)
|
||||
self.poll()
|
||||
|
||||
def first(self):
|
||||
"""
|
||||
Based on the handler passed at startup triggers the first slide
|
||||
"""
|
||||
log.debug(u'Live = %s, first' % self.is_live)
|
||||
if not self.doc:
|
||||
return
|
||||
if not self.is_live:
|
||||
return
|
||||
if self.doc.is_blank():
|
||||
if self.hide_mode:
|
||||
self.doc.slidenumber = 1
|
||||
self.poll()
|
||||
return
|
||||
if not self.activate():
|
||||
return
|
||||
self.activate()
|
||||
self.doc.start_presentation()
|
||||
self.doc.poll_slidenumber(self.is_live)
|
||||
self.poll()
|
||||
|
||||
def last(self):
|
||||
"""
|
||||
Based on the handler passed at startup triggers the last slide
|
||||
"""
|
||||
log.debug(u'Live = %s, last' % self.is_live)
|
||||
if not self.doc:
|
||||
return
|
||||
if not self.is_live:
|
||||
return
|
||||
if self.doc.is_blank():
|
||||
if self.hide_mode:
|
||||
self.doc.slidenumber = self.doc.get_slide_count()
|
||||
self.poll()
|
||||
return
|
||||
if not self.activate():
|
||||
return
|
||||
self.activate()
|
||||
self.doc.goto_slide(self.doc.get_slide_count())
|
||||
self.doc.poll_slidenumber(self.is_live)
|
||||
self.poll()
|
||||
|
||||
def next(self):
|
||||
"""
|
||||
Based on the handler passed at startup triggers the next slide event
|
||||
"""
|
||||
log.debug(u'Live = %s, next' % self.is_live)
|
||||
if not self.doc:
|
||||
return
|
||||
if not self.is_live:
|
||||
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():
|
||||
self.doc.slidenumber = self.doc.slidenumber + 1
|
||||
self.poll()
|
||||
return
|
||||
if not self.activate():
|
||||
return
|
||||
# The "End of slideshow" screen is after the last slide
|
||||
# Note, we can't just stop on the last slide, since it may
|
||||
# contain animations that need to be stepped through.
|
||||
if self.doc.slidenumber > self.doc.get_slide_count():
|
||||
return
|
||||
self.activate()
|
||||
self.doc.next_step()
|
||||
self.doc.poll_slidenumber(self.is_live)
|
||||
self.poll()
|
||||
|
||||
def previous(self):
|
||||
"""
|
||||
Based on the handler passed at startup triggers the previous slide event
|
||||
"""
|
||||
log.debug(u'Live = %s, previous' % self.is_live)
|
||||
if not self.doc:
|
||||
return
|
||||
if not self.is_live:
|
||||
return
|
||||
if self.doc.is_blank():
|
||||
if self.hide_mode:
|
||||
if not self.doc.is_active():
|
||||
return
|
||||
if self.doc.slidenumber > 1:
|
||||
self.doc.slidenumber = self.doc.slidenumber - 1
|
||||
self.poll()
|
||||
return
|
||||
if not self.activate():
|
||||
return
|
||||
self.activate()
|
||||
self.doc.previous_step()
|
||||
self.doc.poll_slidenumber(self.is_live)
|
||||
self.poll()
|
||||
|
||||
def shutdown(self):
|
||||
"""
|
||||
Based on the handler passed at startup triggers slide show to shut down
|
||||
"""
|
||||
log.debug(u'Live = %s, shutdown' % self.is_live)
|
||||
if not self.doc:
|
||||
return
|
||||
self.doc.close_presentation()
|
||||
self.doc = None
|
||||
|
||||
@ -190,21 +226,30 @@ class Controller(object):
|
||||
Instruct the controller to blank the presentation
|
||||
"""
|
||||
log.debug(u'Live = %s, blank' % self.is_live)
|
||||
self.hide_mode = hide_mode
|
||||
if not self.doc:
|
||||
return
|
||||
if not self.is_live:
|
||||
return
|
||||
if not self.doc.is_loaded():
|
||||
return
|
||||
if not self.doc.is_active():
|
||||
return
|
||||
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)
|
||||
self.doc.blank_screen()
|
||||
elif hide_mode == HideMode.Blank:
|
||||
if not self.activate():
|
||||
return
|
||||
self.doc.blank_screen()
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Instruct the controller to stop and hide the presentation
|
||||
"""
|
||||
log.debug(u'Live = %s, stop' % self.is_live)
|
||||
self.hide_mode = HideMode.Screen
|
||||
if not self.doc:
|
||||
return
|
||||
if not self.is_live:
|
||||
return
|
||||
if not self.doc.is_loaded():
|
||||
@ -218,9 +263,13 @@ class Controller(object):
|
||||
Instruct the controller to unblank the presentation
|
||||
"""
|
||||
log.debug(u'Live = %s, unblank' % self.is_live)
|
||||
self.hide_mode = None
|
||||
if not self.doc:
|
||||
return
|
||||
if not self.is_live:
|
||||
return
|
||||
self.activate()
|
||||
if not self.activate():
|
||||
return
|
||||
if self.doc.slidenumber and \
|
||||
self.doc.slidenumber != self.doc.get_slide_number():
|
||||
self.doc.goto_slide(self.doc.slidenumber)
|
||||
@ -228,7 +277,9 @@ class Controller(object):
|
||||
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||
|
||||
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):
|
||||
|
@ -94,9 +94,9 @@ class PowerpointController(PresentationController):
|
||||
self.docs[0].close_presentation()
|
||||
if self.process is None:
|
||||
return
|
||||
if self.process.Presentations.Count > 0:
|
||||
return
|
||||
try:
|
||||
if self.process.Presentations.Count > 0:
|
||||
return
|
||||
self.process.Quit()
|
||||
except pywintypes.com_error:
|
||||
pass
|
||||
@ -210,6 +210,13 @@ class PowerpointDocument(PresentationDocument):
|
||||
self.presentation.SlideShowSettings.Run()
|
||||
self.presentation.SlideShowWindow.View.State = 1
|
||||
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):
|
||||
"""
|
||||
@ -253,6 +260,8 @@ class PowerpointDocument(PresentationDocument):
|
||||
renderer = self.controller.plugin.renderer
|
||||
rect = renderer.screens.current[u'size']
|
||||
ppt_window = self.presentation.SlideShowSettings.Run()
|
||||
if not ppt_window:
|
||||
return
|
||||
ppt_window.Top = rect.y() * 72 / dpi
|
||||
ppt_window.Height = rect.height() * 72 / dpi
|
||||
ppt_window.Left = rect.x() * 72 / dpi
|
||||
@ -286,6 +295,8 @@ class PowerpointDocument(PresentationDocument):
|
||||
"""
|
||||
log.debug(u'next_step')
|
||||
self.presentation.SlideShowWindow.View.Next()
|
||||
if self.get_slide_number() > self.get_slide_count():
|
||||
self.previous_step()
|
||||
|
||||
def previous_step(self):
|
||||
"""
|
||||
|
@ -260,16 +260,17 @@ class PresentationDocument(object):
|
||||
else:
|
||||
return None
|
||||
|
||||
def poll_slidenumber(self, is_live):
|
||||
def poll_slidenumber(self, is_live, hide_mode):
|
||||
"""
|
||||
Check the current slide number
|
||||
"""
|
||||
if not self.is_active():
|
||||
return
|
||||
current = self.get_slide_number()
|
||||
if current == self.slidenumber:
|
||||
return
|
||||
self.slidenumber = current
|
||||
if not hide_mode:
|
||||
current = self.get_slide_number()
|
||||
if current == self.slidenumber:
|
||||
return
|
||||
self.slidenumber = current
|
||||
if is_live:
|
||||
prefix = u'live'
|
||||
else:
|
||||
|
@ -29,7 +29,6 @@
|
||||
The :mod:`songexportform` module provides the wizard for exporting songs to the
|
||||
OpenLyrics format.
|
||||
"""
|
||||
import locale
|
||||
import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
@ -38,6 +37,7 @@ from openlp.core.lib import build_icon, Receiver, SettingsManager, translate, \
|
||||
create_separated_list
|
||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||
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.openlyricsexport import OpenLyricsExport
|
||||
|
||||
@ -252,7 +252,8 @@ class SongExportForm(OpenLPWizard):
|
||||
# Load the list of songs.
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
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:
|
||||
# No need to export temporary songs.
|
||||
if song.temporary:
|
||||
|
@ -31,8 +31,9 @@ the Songs plugin
|
||||
"""
|
||||
|
||||
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 PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib.db import BaseModel, init_db
|
||||
|
||||
@ -63,7 +64,22 @@ class Song(BaseModel):
|
||||
"""
|
||||
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):
|
||||
|
@ -27,7 +27,6 @@
|
||||
###############################################################################
|
||||
|
||||
import logging
|
||||
import locale
|
||||
import re
|
||||
import os
|
||||
import shutil
|
||||
@ -40,7 +39,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
|
||||
check_directory_exists
|
||||
from openlp.core.lib.ui import UiStrings, create_widget_action
|
||||
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, \
|
||||
SongImportForm, SongExportForm
|
||||
from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \
|
||||
@ -260,10 +259,8 @@ class SongMediaItem(MediaManagerItem):
|
||||
log.debug(u'display results Song')
|
||||
self.saveAutoSelectId()
|
||||
self.listView.clear()
|
||||
# Sort the songs by its title considering language specific characters.
|
||||
# lower() is needed for windows!
|
||||
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:
|
||||
# Do not display temporary songs
|
||||
if song.temporary:
|
||||
|
@ -63,10 +63,14 @@ class OpenLPSongImport(SongImport):
|
||||
SongImport.__init__(self, manager, **kwargs)
|
||||
self.sourceSession = None
|
||||
|
||||
def doImport(self):
|
||||
def doImport(self, progressDialog=None):
|
||||
"""
|
||||
Run the import for an OpenLP version 2 song database.
|
||||
|
||||
``progressDialog``
|
||||
The QProgressDialog used when importing songs from the FRW.
|
||||
"""
|
||||
|
||||
class OldAuthor(BaseModel):
|
||||
"""
|
||||
Author model
|
||||
@ -101,13 +105,14 @@ class OpenLPSongImport(SongImport):
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
# Check the file type
|
||||
if not self.importSource.endswith(u'.sqlite'):
|
||||
self.logError(self.importSource,
|
||||
translate('SongsPlugin.OpenLPSongImport',
|
||||
'Not a valid OpenLP 2.0 song database.'))
|
||||
return
|
||||
self.importSource = u'sqlite:///%s' % self.importSource
|
||||
# Load the db file
|
||||
engine = create_engine(self.importSource)
|
||||
source_meta = MetaData()
|
||||
source_meta.reflect(engine)
|
||||
@ -224,7 +229,11 @@ class OpenLPSongImport(SongImport):
|
||||
file_name=media_file.file_name))
|
||||
clean_song(self.manager, 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(
|
||||
WizardStrings.ImportingType % new_song.title)
|
||||
if self.stopImportFlag:
|
||||
|
@ -29,6 +29,7 @@
|
||||
import logging
|
||||
import os
|
||||
from tempfile import gettempdir
|
||||
import sqlite3
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
@ -82,7 +83,7 @@ class SongsPlugin(Plugin):
|
||||
unicode(UiStrings().Tools))
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'servicemanager_new_service'),
|
||||
self.clearTemporarySongs)
|
||||
self.clearTemporarySongs)
|
||||
|
||||
|
||||
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
|
||||
new songs into the database.
|
||||
"""
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.onToolsReindexItemTriggered()
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
db_dir = unicode(os.path.join(
|
||||
unicode(gettempdir(), get_filesystem_encoding()), u'openlp'))
|
||||
if not os.path.exists(db_dir):
|
||||
return
|
||||
song_dbs = []
|
||||
song_count = 0
|
||||
for sfile in os.listdir(db_dir):
|
||||
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_count += self._countSongs(os.path.join(db_dir, sfile))
|
||||
if not song_dbs:
|
||||
return
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
progress = QtGui.QProgressDialog(self.formParent)
|
||||
progress.setWindowModality(QtCore.Qt.WindowModal)
|
||||
progress.setWindowTitle(translate('OpenLP.Ui', 'Importing Songs'))
|
||||
progress.setLabelText(translate('OpenLP.Ui', 'Starting import...'))
|
||||
progress.setCancelButton(None)
|
||||
progress.setRange(0, len(song_dbs))
|
||||
progress.setRange(0, song_count)
|
||||
progress.setMinimumDuration(0)
|
||||
progress.forceShow()
|
||||
for idx, db in enumerate(song_dbs):
|
||||
progress.setValue(idx)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
for db in song_dbs:
|
||||
importer = OpenLPSongImport(self.manager, filename=db)
|
||||
importer.doImport()
|
||||
progress.setValue(len(song_dbs))
|
||||
importer.doImport(progress)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
progress.setValue(song_count)
|
||||
self.mediaItem.onSearchTextButtonClicked()
|
||||
|
||||
def finalise(self):
|
||||
@ -287,3 +294,15 @@ class SongsPlugin(Plugin):
|
||||
songs = self.manager.get_all_objects(Song, Song.temporary == True)
|
||||
for song in songs:
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user