forked from openlp/openlp
r1800
This commit is contained in:
commit
380d44a522
@ -29,6 +29,7 @@ The :mod:`db` module provides the core database functionality for OpenLP
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
from urllib import quote_plus as urlquote
|
||||
|
||||
from PyQt4 import QtCore
|
||||
from sqlalchemy import Table, MetaData, Column, types, create_engine
|
||||
@ -193,10 +194,10 @@ class Manager(object):
|
||||
AppLocation.get_section_data_path(plugin_name), plugin_name)
|
||||
else:
|
||||
self.db_url = u'%s://%s:%s@%s/%s' % (db_type,
|
||||
unicode(settings.value(u'db username').toString()),
|
||||
unicode(settings.value(u'db password').toString()),
|
||||
unicode(settings.value(u'db hostname').toString()),
|
||||
unicode(settings.value(u'db database').toString()))
|
||||
urlquote(unicode(settings.value(u'db username').toString())),
|
||||
urlquote(unicode(settings.value(u'db password').toString())),
|
||||
urlquote(unicode(settings.value(u'db hostname').toString())),
|
||||
urlquote(unicode(settings.value(u'db database').toString())))
|
||||
settings.endGroup()
|
||||
if upgrade_mod:
|
||||
db_ver, up_ver = upgrade_db(self.db_url, upgrade_mod)
|
||||
|
@ -610,24 +610,3 @@ def build_footer_css(item, height):
|
||||
theme.font_footer_size, theme.font_footer_color)
|
||||
return lyrics_html
|
||||
|
||||
def build_alert_css(alertTab, width):
|
||||
"""
|
||||
Build the display of the footer
|
||||
|
||||
``alertTab``
|
||||
Details from the Alert tab for fonts etc
|
||||
"""
|
||||
style = u"""
|
||||
width: %spx;
|
||||
vertical-align: %s;
|
||||
font-family: %s;
|
||||
font-size: %spt;
|
||||
color: %s;
|
||||
background-color: %s;
|
||||
"""
|
||||
if not alertTab:
|
||||
return u''
|
||||
align = VerticalType.Names[alertTab.location]
|
||||
alert = style % (width, align, alertTab.font_face, alertTab.font_size,
|
||||
alertTab.font_color, alertTab.bg_color)
|
||||
return alert
|
||||
|
@ -250,7 +250,12 @@ class Renderer(object):
|
||||
# render the first virtual slide.
|
||||
text_contains_break = u'[---]' in text
|
||||
if text_contains_break:
|
||||
text_to_render, text = text.split(u'\n[---]\n', 1)
|
||||
try:
|
||||
text_to_render, text = \
|
||||
text.split(u'\n[---]\n', 1)
|
||||
except:
|
||||
text_to_render = text.split(u'\n[---]\n')[0]
|
||||
text = u''
|
||||
else:
|
||||
text_to_render = text
|
||||
text = u''
|
||||
|
@ -118,6 +118,7 @@ class ServiceItem(object):
|
||||
self.from_service = False
|
||||
self.image_border = u'#000000'
|
||||
self.background_audio = []
|
||||
self.theme_overwritten = False
|
||||
self._new_item()
|
||||
|
||||
def _new_item(self):
|
||||
@ -273,7 +274,8 @@ class ServiceItem(object):
|
||||
u'start_time': self.start_time,
|
||||
u'end_time': self.end_time,
|
||||
u'media_length': self.media_length,
|
||||
u'background_audio': self.background_audio
|
||||
u'background_audio': self.background_audio,
|
||||
u'theme_overwritten': self.theme_overwritten
|
||||
}
|
||||
service_data = []
|
||||
if self.service_item_type == ServiceItemType.Text:
|
||||
@ -323,6 +325,7 @@ class ServiceItem(object):
|
||||
self.media_length = header[u'media_length']
|
||||
if u'background_audio' in header:
|
||||
self.background_audio = header[u'background_audio']
|
||||
self.theme_overwritten = header.get(u'theme_overwritten', False)
|
||||
if self.service_item_type == ServiceItemType.Text:
|
||||
for slide in serviceitem[u'serviceitem'][u'data']:
|
||||
self._raw_frames.append(slide)
|
||||
@ -484,6 +487,7 @@ class ServiceItem(object):
|
||||
``theme``
|
||||
The new theme to be replaced in the service item
|
||||
"""
|
||||
self.theme_overwritten = (theme == None)
|
||||
self.theme = theme
|
||||
self._new_item()
|
||||
self.render()
|
||||
|
@ -52,6 +52,24 @@ class HideMode(object):
|
||||
Theme = 2
|
||||
Screen = 3
|
||||
|
||||
class AlertLocation(object):
|
||||
"""
|
||||
This is an enumeration class which controls where Alerts are placed on the
|
||||
screen.
|
||||
|
||||
``Top``
|
||||
Place the text at the top of the screen.
|
||||
|
||||
``Middle``
|
||||
Place the text in the middle of the screen.
|
||||
|
||||
``Bottom``
|
||||
Place the text at the bottom of the screen.
|
||||
"""
|
||||
Top = 0
|
||||
Middle = 1
|
||||
Bottom = 2
|
||||
|
||||
from firsttimeform import FirstTimeForm
|
||||
from firsttimelanguageform import FirstTimeLanguageForm
|
||||
from themelayoutform import ThemeLayoutForm
|
||||
|
@ -123,7 +123,7 @@ class Ui_AboutDialog(object):
|
||||
testers = [u'Philip "Phill" Ridout', u'Wesley "wrst" Stout',
|
||||
u'John "jseagull1" Cegalis (lead)']
|
||||
packagers = ['Thomas "tabthorpe" Abthorpe (FreeBSD)',
|
||||
u'Tim "TRB143" Bentley (Fedora)',
|
||||
u'Tim "TRB143" Bentley (Fedora and Android)',
|
||||
u'Matthias "matthub" Hub (Mac OS X)',
|
||||
u'Stevan "ElderP" Pettit (Windows)',
|
||||
u'Raoul "superfly" Snyman (Ubuntu)']
|
||||
|
@ -39,6 +39,11 @@ try:
|
||||
PHONON_VERSION = Phonon.phononVersion()
|
||||
except ImportError:
|
||||
PHONON_VERSION = u'-'
|
||||
try:
|
||||
import migrate
|
||||
MIGRATE_VERSION = getattr(migrate, u'__version__', u'< 0.7')
|
||||
except ImportError:
|
||||
MIGRATE_VERSION = u'-'
|
||||
try:
|
||||
import chardet
|
||||
CHARDET_VERSION = chardet.__version__
|
||||
@ -54,6 +59,24 @@ try:
|
||||
SQLITE_VERSION = sqlite.version
|
||||
except ImportError:
|
||||
SQLITE_VERSION = u'-'
|
||||
try:
|
||||
import mako
|
||||
MAKO_VERSION = mako.__version__
|
||||
except ImportError:
|
||||
MAKO_VERSION = u'-'
|
||||
try:
|
||||
import uno
|
||||
arg = uno.createUnoStruct(u'com.sun.star.beans.PropertyValue')
|
||||
arg.Name = u'nodepath'
|
||||
arg.Value = u'/org.openoffice.Setup/Product'
|
||||
context = uno.getComponentContext()
|
||||
provider = context.ServiceManager.createInstance(
|
||||
u'com.sun.star.configuration.ConfigurationProvider')
|
||||
node = provider.createInstanceWithArguments(
|
||||
u'com.sun.star.configuration.ConfigurationAccess', (arg,))
|
||||
UNO_VERSION = node.getByName(u'ooSetupVersion')
|
||||
except ImportError:
|
||||
UNO_VERSION = u'-'
|
||||
|
||||
from openlp.core.lib import translate, SettingsManager
|
||||
from openlp.core.lib.ui import UiStrings
|
||||
@ -89,11 +112,14 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
||||
u'Phonon: %s\n' % PHONON_VERSION + \
|
||||
u'PyQt4: %s\n' % Qt.PYQT_VERSION_STR + \
|
||||
u'SQLAlchemy: %s\n' % sqlalchemy.__version__ + \
|
||||
u'SQLAlchemy Migrate: %s\n' % MIGRATE_VERSION + \
|
||||
u'BeautifulSoup: %s\n' % BeautifulSoup.__version__ + \
|
||||
u'lxml: %s\n' % etree.__version__ + \
|
||||
u'Chardet: %s\n' % CHARDET_VERSION + \
|
||||
u'PyEnchant: %s\n' % ENCHANT_VERSION + \
|
||||
u'PySQLite: %s\n' % SQLITE_VERSION
|
||||
u'PySQLite: %s\n' % SQLITE_VERSION + \
|
||||
u'Mako: %s\n' % MAKO_VERSION + \
|
||||
u'pyUNO bridge: %s\n' % UNO_VERSION
|
||||
if platform.system() == u'Linux':
|
||||
if os.environ.get(u'KDE_FULL_SESSION') == u'true':
|
||||
system = system + u'Desktop: KDE SC\n'
|
||||
@ -152,6 +178,8 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
||||
'Please add the information that bug reports are favoured written '
|
||||
'in English.'))
|
||||
content = self._createReport()
|
||||
source = u''
|
||||
exception = u''
|
||||
for line in content[2].split(u'\n'):
|
||||
if re.search(r'[/\\]openlp[/\\]', line):
|
||||
source = re.sub(r'.*[/\\]openlp[/\\](.*)".*', r'\1', line)
|
||||
|
@ -37,7 +37,7 @@ from PyQt4.phonon import Phonon
|
||||
from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \
|
||||
translate, PluginManager
|
||||
|
||||
from openlp.core.ui import HideMode, ScreenList
|
||||
from openlp.core.ui import HideMode, ScreenList, AlertLocation
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -51,7 +51,7 @@ class MainDisplay(QtGui.QGraphicsView):
|
||||
def __init__(self, parent, imageManager, live):
|
||||
if live:
|
||||
QtGui.QGraphicsView.__init__(self)
|
||||
# Do not overwrite the parent() method.
|
||||
# Overwrite the parent() method.
|
||||
self.parent = lambda: parent
|
||||
else:
|
||||
QtGui.QGraphicsView.__init__(self, parent)
|
||||
@ -171,7 +171,7 @@ class MainDisplay(QtGui.QGraphicsView):
|
||||
serviceItem = ServiceItem()
|
||||
serviceItem.bg_image_bytes = image_to_byte(self.initialFrame)
|
||||
self.webView.setHtml(build_html(serviceItem, self.screen,
|
||||
self.isLive, None))
|
||||
self.isLive, None, plugins=self.plugins))
|
||||
self.__hideMouse()
|
||||
# To display or not to display?
|
||||
if not self.screen[u'primary']:
|
||||
@ -213,7 +213,7 @@ class MainDisplay(QtGui.QGraphicsView):
|
||||
self.frame.evaluateJavaScript(u'show_text("%s")' %
|
||||
slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
|
||||
|
||||
def alert(self, text):
|
||||
def alert(self, text, location):
|
||||
"""
|
||||
Display an alert.
|
||||
|
||||
@ -241,10 +241,10 @@ class MainDisplay(QtGui.QGraphicsView):
|
||||
alert_height = int(height.toString())
|
||||
shrinkItem.resize(self.width(), alert_height)
|
||||
shrinkItem.setVisible(True)
|
||||
if self.alertTab.location == 1:
|
||||
if location == AlertLocation.Middle:
|
||||
shrinkItem.move(self.screen[u'size'].left(),
|
||||
(self.screen[u'size'].height() - alert_height) / 2)
|
||||
elif self.alertTab.location == 2:
|
||||
elif location == AlertLocation.Bottom:
|
||||
shrinkItem.move(self.screen[u'size'].left(),
|
||||
self.screen[u'size'].height() - alert_height)
|
||||
else:
|
||||
|
@ -321,6 +321,94 @@ class SlideController(QtGui.QWidget):
|
||||
self.slidePreview.setObjectName(u'slidePreview')
|
||||
self.slideLayout.insertWidget(0, self.slidePreview)
|
||||
self.grid.addLayout(self.slideLayout, 0, 0, 1, 1)
|
||||
if self.isLive:
|
||||
self.current_shortcut = u''
|
||||
self.shortcutTimer = QtCore.QTimer()
|
||||
self.shortcutTimer.setObjectName(u'shortcutTimer')
|
||||
self.shortcutTimer.setSingleShot(True)
|
||||
self.verseShortcut = shortcut_action(self, u'verseShortcut',
|
||||
[QtGui.QKeySequence(u'V')], self.slideShortcutActivated,
|
||||
category=UiStrings().LiveToolbar,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.verseShortcut.setText(translate(
|
||||
'OpenLP.SlideController', 'Go to "Verse"'))
|
||||
self.shortcut0 = shortcut_action(self, u'0',
|
||||
[QtGui.QKeySequence(u'0')], self.slideShortcutActivated,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.shortcut1 = shortcut_action(self, u'1',
|
||||
[QtGui.QKeySequence(u'1')], self.slideShortcutActivated,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.shortcut2 = shortcut_action(self, u'2',
|
||||
[QtGui.QKeySequence(u'2')], self.slideShortcutActivated,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.shortcut3 = shortcut_action(self, u'3',
|
||||
[QtGui.QKeySequence(u'3')], self.slideShortcutActivated,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.shortcut4 = shortcut_action(self, u'4',
|
||||
[QtGui.QKeySequence(u'4')], self.slideShortcutActivated,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.shortcut5 = shortcut_action(self, u'5',
|
||||
[QtGui.QKeySequence(u'5')], self.slideShortcutActivated,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.shortcut6 = shortcut_action(self, u'6',
|
||||
[QtGui.QKeySequence(u'6')], self.slideShortcutActivated,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.shortcut7 = shortcut_action(self, u'7',
|
||||
[QtGui.QKeySequence(u'7')], self.slideShortcutActivated,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.shortcut8 = shortcut_action(self, u'8',
|
||||
[QtGui.QKeySequence(u'8')], self.slideShortcutActivated,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.shortcut9 = shortcut_action(self, u'9',
|
||||
[QtGui.QKeySequence(u'9')], self.slideShortcutActivated,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.chorusShortcut = shortcut_action(self, u'chorusShortcut',
|
||||
[QtGui.QKeySequence(u'C')], self.slideShortcutActivated,
|
||||
category=UiStrings().LiveToolbar,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.chorusShortcut.setText(translate(
|
||||
'OpenLP.SlideController', 'Go to "Chorus"'))
|
||||
self.bridgeShortcut = shortcut_action(self, u'bridgeShortcut',
|
||||
[QtGui.QKeySequence(u'B')], self.slideShortcutActivated,
|
||||
category=UiStrings().LiveToolbar,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.bridgeShortcut.setText(translate(
|
||||
'OpenLP.SlideController', 'Go to "Bridge"'))
|
||||
self.preChorusShortcut = shortcut_action(self, u'preChorusShortcut',
|
||||
[QtGui.QKeySequence(u'P')], self.slideShortcutActivated,
|
||||
category=UiStrings().LiveToolbar,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.preChorusShortcut.setText(translate(
|
||||
'OpenLP.SlideController', 'Go to "Pre-Chorus"'))
|
||||
self.introShortcut = shortcut_action(self, u'introShortcut',
|
||||
[QtGui.QKeySequence(u'I')], self.slideShortcutActivated,
|
||||
category=UiStrings().LiveToolbar,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.introShortcut.setText(translate(
|
||||
'OpenLP.SlideController', 'Go to "Intro"'))
|
||||
self.endingShortcut = shortcut_action(self, u'endingShortcut',
|
||||
[QtGui.QKeySequence(u'E')], self.slideShortcutActivated,
|
||||
category=UiStrings().LiveToolbar,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.endingShortcut.setText(translate(
|
||||
'OpenLP.SlideController', 'Go to "Ending"'))
|
||||
self.otherShortcut = shortcut_action(self, u'otherShortcut',
|
||||
[QtGui.QKeySequence(u'O')], self.slideShortcutActivated,
|
||||
category=UiStrings().LiveToolbar,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.otherShortcut.setText(translate(
|
||||
'OpenLP.SlideController', 'Go to "Other"'))
|
||||
self.previewListWidget.addActions([
|
||||
self.shortcut0, self.shortcut1, self.shortcut2, self.shortcut3,
|
||||
self.shortcut4, self.shortcut5, self.shortcut6, self.shortcut7,
|
||||
self.shortcut8, self.shortcut9, self.verseShortcut,
|
||||
self.chorusShortcut, self.bridgeShortcut,
|
||||
self.preChorusShortcut, self.introShortcut, self.endingShortcut,
|
||||
self.otherShortcut
|
||||
])
|
||||
QtCore.QObject.connect(
|
||||
self.shortcutTimer, QtCore.SIGNAL(u'timeout()'),
|
||||
self.slideShortcutActivated)
|
||||
# Signals
|
||||
QtCore.QObject.connect(self.previewListWidget,
|
||||
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
|
||||
@ -367,6 +455,90 @@ class SlideController(QtGui.QWidget):
|
||||
QtCore.SIGNAL(u'slidecontroller_%s_unblank' % self.typePrefix),
|
||||
self.onSlideUnblank)
|
||||
|
||||
def slideShortcutActivated(self):
|
||||
"""
|
||||
Called, when a shortcut has been activated to jump to a chorus, verse,
|
||||
etc.
|
||||
|
||||
**Note**: This implementation is based on shortcuts. But it rather works
|
||||
like "key sequenes". You have to press one key after the other and
|
||||
**not** at the same time.
|
||||
For example to jump to "V3" you have to press "V" and afterwards but
|
||||
within a time frame of 350ms you have to press "3".
|
||||
"""
|
||||
try:
|
||||
from openlp.plugins.songs.lib import VerseType
|
||||
SONGS_PLUGIN_AVAILABLE = True
|
||||
except ImportError:
|
||||
SONGS_PLUGIN_AVAILABLE = False
|
||||
verse_type = unicode(self.sender().objectName())
|
||||
if verse_type.startswith(u'verseShortcut'):
|
||||
if SONGS_PLUGIN_AVAILABLE:
|
||||
self.current_shortcut = \
|
||||
VerseType.TranslatedTags[VerseType.Verse]
|
||||
else:
|
||||
self.current_shortcut = u'V'
|
||||
elif verse_type.startswith(u'chorusShortcut'):
|
||||
if SONGS_PLUGIN_AVAILABLE:
|
||||
self.current_shortcut = \
|
||||
VerseType.TranslatedTags[VerseType.Chorus]
|
||||
else:
|
||||
self.current_shortcut = u'C'
|
||||
elif verse_type.startswith(u'bridgeShortcut'):
|
||||
if SONGS_PLUGIN_AVAILABLE:
|
||||
self.current_shortcut = \
|
||||
VerseType.TranslatedTags[VerseType.Bridge]
|
||||
else:
|
||||
self.current_shortcut = u'B'
|
||||
elif verse_type.startswith(u'preChorusShortcut'):
|
||||
if SONGS_PLUGIN_AVAILABLE:
|
||||
self.current_shortcut = \
|
||||
VerseType.TranslatedTags[VerseType.PreChorus]
|
||||
else:
|
||||
self.current_shortcut = u'P'
|
||||
elif verse_type.startswith(u'introShortcut'):
|
||||
if SONGS_PLUGIN_AVAILABLE:
|
||||
self.current_shortcut = \
|
||||
VerseType.TranslatedTags[VerseType.Intro]
|
||||
else:
|
||||
self.current_shortcut = u'I'
|
||||
elif verse_type.startswith(u'endingShortcut'):
|
||||
if SONGS_PLUGIN_AVAILABLE:
|
||||
self.current_shortcut = \
|
||||
VerseType.TranslatedTags[VerseType.Ending]
|
||||
else:
|
||||
self.current_shortcut = u'E'
|
||||
elif verse_type.startswith(u'otherShortcut'):
|
||||
if SONGS_PLUGIN_AVAILABLE:
|
||||
self.current_shortcut = \
|
||||
VerseType.TranslatedTags[VerseType.Other]
|
||||
else:
|
||||
self.current_shortcut = u'O'
|
||||
elif verse_type.isnumeric():
|
||||
self.current_shortcut += verse_type
|
||||
self.current_shortcut = self.current_shortcut.upper()
|
||||
keys = self.slideList.keys()
|
||||
matches = [match for match in keys
|
||||
if match.startswith(self.current_shortcut)]
|
||||
if len(matches) == 1:
|
||||
self.shortcutTimer.stop()
|
||||
self.current_shortcut = u''
|
||||
self.__checkUpdateSelectedSlide(self.slideList[matches[0]])
|
||||
self.slideSelected()
|
||||
elif verse_type != u'shortcutTimer':
|
||||
# Start the time as we did not have any match.
|
||||
self.shortcutTimer.start(350)
|
||||
else:
|
||||
# The timer timed out.
|
||||
if self.current_shortcut in keys:
|
||||
# We had more than one match for example "V1" and "V10", but
|
||||
# "V1" was the slide we wanted to go.
|
||||
self.__checkUpdateSelectedSlide(
|
||||
self.slideList[self.current_shortcut])
|
||||
self.slideSelected()
|
||||
# Reset the shortcut.
|
||||
self.current_shortcut = u''
|
||||
|
||||
def setPreviewHotkeys(self, parent=None):
|
||||
self.previousItem.setObjectName(u'previousItemPreview')
|
||||
self.nextItem.setObjectName(u'nextItemPreview')
|
||||
@ -643,13 +815,14 @@ class SlideController(QtGui.QWidget):
|
||||
verse_def = u'%s%s' % (verse_def[0], verse_def[1:])
|
||||
two_line_def = u'%s\n%s' % (verse_def[0], verse_def[1:])
|
||||
row = two_line_def
|
||||
if self.isLive:
|
||||
if verse_def not in self.slideList:
|
||||
self.slideList[verse_def] = framenumber
|
||||
if verse_def not in self.slideList:
|
||||
self.slideList[verse_def] = framenumber
|
||||
if self.isLive:
|
||||
self.songMenu.menu().addAction(verse_def,
|
||||
self.onSongBarHandler)
|
||||
else:
|
||||
row += 1
|
||||
self.slideList[unicode(row)] = row - 1
|
||||
item.setText(frame[u'text'])
|
||||
else:
|
||||
label = QtGui.QLabel()
|
||||
@ -667,6 +840,7 @@ class SlideController(QtGui.QWidget):
|
||||
self.previewListWidget.setCellWidget(framenumber, 0, label)
|
||||
slideHeight = width * self.parent().renderer.screen_ratio
|
||||
row += 1
|
||||
self.slideList[unicode(row)] = row - 1
|
||||
text.append(unicode(row))
|
||||
self.previewListWidget.setItem(framenumber, 0, item)
|
||||
if slideHeight != 0:
|
||||
|
@ -370,7 +370,7 @@ class ThemeManager(QtGui.QWidget):
|
||||
|
||||
def onExportTheme(self):
|
||||
"""
|
||||
Save the theme in a zip file
|
||||
Export the theme in a zip file
|
||||
"""
|
||||
item = self.themeListWidget.currentItem()
|
||||
if item is None:
|
||||
@ -625,7 +625,7 @@ class ThemeManager(QtGui.QWidget):
|
||||
theme_dir = os.path.join(self.path, name)
|
||||
check_directory_exists(theme_dir)
|
||||
theme_file = os.path.join(theme_dir, name + u'.xml')
|
||||
if imageTo and self.oldBackgroundImage and \
|
||||
if self.oldBackgroundImage and \
|
||||
imageTo != self.oldBackgroundImage:
|
||||
delete_file(self.oldBackgroundImage)
|
||||
outfile = None
|
||||
|
@ -71,11 +71,24 @@ JAVASCRIPT = """
|
||||
|
||||
function update_css(align, font, size, color, bgcolor){
|
||||
var text = document.getElementById('alert');
|
||||
text.style.verticalAlign = align;
|
||||
text.style.fontSize = size + "pt";
|
||||
text.style.fontFamily = font;
|
||||
text.style.color = color;
|
||||
text.style.backgroundColor = bgcolor;
|
||||
switch(align)
|
||||
{
|
||||
case 'top':
|
||||
text.style.top = '0px';
|
||||
break;
|
||||
case 'middle':
|
||||
text.style.top = ((window.innerHeight - text.clientHeight) / 2)
|
||||
+ 'px';
|
||||
break;
|
||||
case 'bottom':
|
||||
text.style.top = (window.innerHeight - text.clientHeight)
|
||||
+ 'px';
|
||||
break;
|
||||
}
|
||||
}
|
||||
"""
|
||||
CSS = """
|
||||
|
@ -85,7 +85,7 @@ class AlertsManager(QtCore.QObject):
|
||||
return
|
||||
text = self.alertList.pop(0)
|
||||
alertTab = self.parent().settings_tab
|
||||
self.parent().liveController.display.alert(text)
|
||||
self.parent().liveController.display.alert(text, alertTab.location)
|
||||
# Check to see if we have a timer running.
|
||||
if self.timer_id == 0:
|
||||
self.timer_id = self.startTimer(int(alertTab.timeout) * 1000)
|
||||
@ -100,7 +100,8 @@ class AlertsManager(QtCore.QObject):
|
||||
"""
|
||||
log.debug(u'timer event')
|
||||
if event.timerId() == self.timer_id:
|
||||
self.parent().liveController.display.alert(u'')
|
||||
alertTab = self.parent().settings_tab
|
||||
self.parent().liveController.display.alert(u'', alertTab.location)
|
||||
self.killTimer(self.timer_id)
|
||||
self.timer_id = 0
|
||||
self.generateAlert()
|
||||
|
@ -28,6 +28,7 @@
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SettingsTab, translate, Receiver
|
||||
from openlp.core.ui import AlertLocation
|
||||
from openlp.core.lib.ui import UiStrings, create_valign_combo
|
||||
|
||||
class AlertsTab(SettingsTab):
|
||||
@ -159,7 +160,7 @@ class AlertsTab(SettingsTab):
|
||||
self.font_face = unicode(settings.value(
|
||||
u'font face', QtCore.QVariant(QtGui.QFont().family())).toString())
|
||||
self.location = settings.value(
|
||||
u'location', QtCore.QVariant(1)).toInt()[0]
|
||||
u'location', QtCore.QVariant(AlertLocation.Bottom)).toInt()[0]
|
||||
settings.endGroup()
|
||||
self.fontSizeSpinBox.setValue(self.font_size)
|
||||
self.timeoutSpinBox.setValue(self.timeout)
|
||||
|
@ -411,7 +411,7 @@ class HttpConnection(object):
|
||||
``action``
|
||||
This is the action, either ``hide`` or ``show``.
|
||||
"""
|
||||
event = u'maindisplay_%s' % action
|
||||
event = u'live_display_%s' % action
|
||||
Receiver.send_message(event, HideMode.Blank)
|
||||
return HttpResponse(json.dumps({u'results': {u'success': True}}),
|
||||
{u'Content-Type': u'application/json'})
|
||||
|
@ -419,8 +419,7 @@ class SongMediaItem(MediaManagerItem):
|
||||
item_id = (self.editItem.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||
old_song = self.plugin.manager.get_object(Song, item_id)
|
||||
song_xml = self.openLyrics.song_to_xml(old_song)
|
||||
new_song_id = self.openLyrics.xml_to_song(song_xml)
|
||||
new_song = self.plugin.manager.get_object(Song, new_song_id)
|
||||
new_song = self.openLyrics.xml_to_song(song_xml)
|
||||
new_song.title = u'%s <%s>' % (new_song.title,
|
||||
translate('SongsPlugin.MediaItem', 'copy',
|
||||
'For song cloning'))
|
||||
|
@ -78,30 +78,35 @@ class OpenLP1SongImport(SongImport):
|
||||
connection = sqlite.connect(self.importSource, mode=0444,
|
||||
encoding=(encoding, 'replace'))
|
||||
cursor = connection.cursor()
|
||||
# Determine if we're using a new or an old DB.
|
||||
# Determine if the db supports linking audio to songs.
|
||||
cursor.execute(u'SELECT name FROM sqlite_master '
|
||||
u'WHERE type = \'table\' AND name = \'tracks\'')
|
||||
new_db = len(cursor.fetchall()) > 0
|
||||
db_has_tracks = len(cursor.fetchall()) > 0
|
||||
# Determine if the db contains theme information.
|
||||
cursor.execute(u'SELECT name FROM sqlite_master '
|
||||
u'WHERE type = \'table\' AND name = \'settings\'')
|
||||
db_has_themes = len(cursor.fetchall()) > 0
|
||||
# "cache" our list of authors.
|
||||
cursor.execute(u'-- types int, unicode')
|
||||
cursor.execute(u'SELECT authorid, authorname FROM authors')
|
||||
authors = cursor.fetchall()
|
||||
if new_db:
|
||||
if db_has_tracks:
|
||||
# "cache" our list of tracks.
|
||||
cursor.execute(u'-- types int, unicode')
|
||||
cursor.execute(u'SELECT trackid, fulltrackname FROM tracks')
|
||||
tracks = cursor.fetchall()
|
||||
# "cache" our list of themes.
|
||||
cursor.execute(u'-- types int, unicode')
|
||||
cursor.execute(u'SELECT settingsid, settingsname FROM settings')
|
||||
themes = {}
|
||||
for theme_id, theme_name in cursor.fetchall():
|
||||
if theme_name in self.availableThemes:
|
||||
themes[theme_id] = theme_name
|
||||
if db_has_themes:
|
||||
# "cache" our list of themes.
|
||||
themes = {}
|
||||
cursor.execute(u'-- types int, unicode')
|
||||
cursor.execute(u'SELECT settingsid, settingsname FROM settings')
|
||||
for theme_id, theme_name in cursor.fetchall():
|
||||
if theme_name in self.availableThemes:
|
||||
themes[theme_id] = theme_name
|
||||
# Import the songs.
|
||||
cursor.execute(u'-- types int, unicode, unicode, unicode, int')
|
||||
cursor.execute(u'SELECT songid, songtitle, lyrics || \'\' AS lyrics, '
|
||||
u'copyrightinfo, settingsid FROM songs')
|
||||
cursor.execute(u'-- types int, unicode, unicode, unicode')
|
||||
cursor.execute(u'SELECT songid, songtitle, lyrics || \'\' AS ' \
|
||||
u'lyrics, copyrightinfo FROM songs')
|
||||
songs = cursor.fetchall()
|
||||
self.importWizard.progressBar.setMaximum(len(songs))
|
||||
for song in songs:
|
||||
@ -112,8 +117,13 @@ class OpenLP1SongImport(SongImport):
|
||||
self.title = song[1]
|
||||
lyrics = song[2].replace(u'\r\n', u'\n')
|
||||
self.addCopyright(song[3])
|
||||
if themes.has_key(song[4]):
|
||||
self.themeName = themes[song[4]]
|
||||
if db_has_themes:
|
||||
cursor.execute(u'-- types int')
|
||||
cursor.execute(
|
||||
u'SELECT settingsid FROM songs WHERE songid = %s' % song_id)
|
||||
theme_id = cursor.fetchone()[0]
|
||||
if themes.has_key(theme_id):
|
||||
self.themeName = themes[theme_id]
|
||||
verses = lyrics.split(u'\n\n')
|
||||
for verse in verses:
|
||||
if verse.strip():
|
||||
@ -131,7 +141,7 @@ class OpenLP1SongImport(SongImport):
|
||||
break
|
||||
if self.stopImportFlag:
|
||||
break
|
||||
if new_db:
|
||||
if db_has_tracks:
|
||||
cursor.execute(u'-- types int, int')
|
||||
cursor.execute(u'SELECT trackid, listindex '
|
||||
u'FROM songtracks '
|
||||
|
@ -65,7 +65,7 @@ class OooImport(SongImport):
|
||||
if not isinstance(self.importSource, list):
|
||||
return
|
||||
try:
|
||||
self.start_ooo()
|
||||
self.startOoo()
|
||||
except NoConnectException as exc:
|
||||
self.logError(
|
||||
self.importSource[0],
|
||||
@ -145,7 +145,7 @@ class OooImport(SongImport):
|
||||
process.waitForStarted()
|
||||
self.processStarted = True
|
||||
except:
|
||||
log.exception("start_ooo_process failed")
|
||||
log.exception("startOooProcess failed")
|
||||
|
||||
def openOooFile(self, filepath):
|
||||
"""
|
||||
@ -171,7 +171,7 @@ class OooImport(SongImport):
|
||||
self.importWizard.incrementProgressBar(
|
||||
u'Processing file ' + filepath, 0)
|
||||
except AttributeError:
|
||||
log.exception("open_ooo_file failed: %s", url)
|
||||
log.exception("openOooFile failed: %s", url)
|
||||
return
|
||||
|
||||
def closeOooFile(self):
|
||||
|
@ -67,7 +67,7 @@ Name: quicklaunchicon; Description: {cm:CreateQuickLaunchIcon}; GroupDescription
|
||||
Source: ..\..\dist\OpenLP\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
; DLL used to check if the target program is running at install time
|
||||
Source: psvince.dll; flags: dontcopy
|
||||
; psvince is installed in {app} folder, so it will be loaded at
|
||||
; psvince is installed in {app} folder, so it will be loaded at
|
||||
; uninstall time to check if the target program is running
|
||||
Source: psvince.dll; DestDir: {app}
|
||||
|
||||
@ -84,10 +84,16 @@ Name: {userappdata}\Microsoft\Internet Explorer\Quick Launch\{#AppName}; Filenam
|
||||
Filename: {app}\{#AppExeName}; Description: {cm:LaunchProgram,{#AppName}}; Flags: nowait postinstall skipifsilent
|
||||
|
||||
[Registry]
|
||||
Root: HKCR; Subkey: ".osz"; ValueType: string; ValueName: ""; ValueData: "OpenLP"; Flags: uninsdeletevalue
|
||||
Root: HKCR; Subkey: "OpenLP"; ValueType: string; ValueName: ""; ValueData: "OpenLP Service"; Flags: uninsdeletekey
|
||||
Root: HKCR; Subkey: "OpenLP\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\OpenLP.exe,0"
|
||||
Root: HKCR; Subkey: "OpenLP\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\OpenLP.exe"" ""%1"""
|
||||
Root: HKCR; Subkey: .osz; ValueType: string; ValueName: ; ValueData: OpenLP; Flags: uninsdeletevalue
|
||||
Root: HKCR; Subkey: OpenLP; ValueType: string; ValueName: ; ValueData: OpenLP Service; Flags: uninsdeletekey
|
||||
Root: HKCR; Subkey: OpenLP\DefaultIcon; ValueType: string; ValueName: ; ValueData: {app}\OpenLP.exe,0
|
||||
Root: HKCR; Subkey: OpenLP\shell\open\command; ValueType: string; ValueName: ; ValueData: """{app}\OpenLP.exe"" ""%1"""
|
||||
|
||||
[UninstallDelete]
|
||||
; Remove support directory created when program is run:
|
||||
Type: filesandordirs; Name: {app}\support
|
||||
; Remove program directory if empty:
|
||||
Name: {app}; Type: dirifempty
|
||||
|
||||
[Code]
|
||||
// Function to call psvince.dll at install time
|
||||
@ -173,4 +179,6 @@ begin
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
// Unload psvince.dll, otherwise it is not deleted
|
||||
UnloadDLL(ExpandConstant('{app}\psvince.dll'));
|
||||
end;
|
||||
|
@ -73,6 +73,7 @@ MODULES = [
|
||||
'BeautifulSoup',
|
||||
'mako',
|
||||
'migrate',
|
||||
'uno',
|
||||
]
|
||||
|
||||
|
||||
|
@ -48,10 +48,10 @@ Inno Setup 5
|
||||
|
||||
Sphinx
|
||||
This is used to build the documentation. The documentation trunk must be at
|
||||
the same directory level as Openlp trunk and named "documentation"
|
||||
the same directory level as Openlp trunk and named "documentation".
|
||||
|
||||
HTML Help Workshop
|
||||
This is used to create the help file
|
||||
This is used to create the help file.
|
||||
|
||||
PyInstaller
|
||||
PyInstaller should be a checkout of revision 1470 of trunk, and in a
|
||||
@ -65,10 +65,6 @@ PyInstaller
|
||||
|
||||
http://svn.pyinstaller.org/trunk
|
||||
|
||||
Then you need to copy the two hook-*.py files from the "pyinstaller"
|
||||
subdirectory in OpenLP's "resources" directory into PyInstaller's
|
||||
"PyInstaller/hooks" directory.
|
||||
|
||||
Bazaar
|
||||
You need the command line "bzr" client installed.
|
||||
|
||||
@ -79,7 +75,7 @@ OpenLP
|
||||
|
||||
Visual C++ 2008 Express Edition
|
||||
This is to build pptviewlib.dll, the library for controlling the
|
||||
PowerPointViewer
|
||||
PowerPointViewer.
|
||||
|
||||
windows-builder.py
|
||||
This script, of course. It should be in the "scripts" directory of OpenLP.
|
||||
@ -88,15 +84,25 @@ psvince.dll
|
||||
This dll is used during the actual install of OpenLP to check if OpenLP is
|
||||
running on the users machine prior to the setup. If OpenLP is running,
|
||||
the install will fail. The dll can be obtained from here:
|
||||
http://www.vincenzo.net/isxkb/index.php?title=PSVince)
|
||||
|
||||
http://www.vincenzo.net/isxkb/index.php?title=PSVince)
|
||||
|
||||
The dll is presently included in .\\resources\\windows
|
||||
|
||||
Mako
|
||||
Mako Templates for Python. This package is required for building the
|
||||
remote plugin. It can be installed by going to your
|
||||
python_directory\scripts\.. and running "easy_install Mako". If you do not
|
||||
have easy_install, the Mako package can be obtained here:
|
||||
http://www.makotemplates.org/download.html
|
||||
|
||||
|
||||
http://www.makotemplates.org/download.html
|
||||
|
||||
Sqlalchemy Migrate
|
||||
Required for the data-bases used in OpenLP. The package can be
|
||||
obtained here:
|
||||
|
||||
http://code.google.com/p/sqlalchemy-migrate/
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
@ -149,6 +155,7 @@ build_path = os.path.join(branch_path, u'build')
|
||||
dist_path = os.path.join(branch_path, u'dist', u'OpenLP')
|
||||
pptviewlib_path = os.path.join(source_path, u'plugins', u'presentations',
|
||||
u'lib', u'pptviewlib')
|
||||
hooks_path = os.path.join(branch_path , u'resources', u'pyinstaller')
|
||||
|
||||
def update_code():
|
||||
os.chdir(branch_path)
|
||||
@ -173,7 +180,8 @@ def run_pyinstaller():
|
||||
pyinstaller = Popen((python_exe, pyi_build,
|
||||
u'--noconfirm',
|
||||
u'--windowed',
|
||||
u'--noupx',
|
||||
u'--noupx',
|
||||
u'--additional-hooks-dir', hooks_path,
|
||||
u'-o', branch_path,
|
||||
u'-i', win32_icon,
|
||||
u'-p', branch_path,
|
||||
|
Loading…
Reference in New Issue
Block a user