This commit is contained in:
Andreas Preikschat 2011-11-19 12:58:21 +01:00
commit 380d44a522
20 changed files with 333 additions and 83 deletions

View File

@ -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)

View File

@ -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

View File

@ -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''

View File

@ -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()

View File

@ -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

View File

@ -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)']

View File

@ -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)

View File

@ -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:

View File

@ -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:

View File

@ -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

View File

@ -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 = """

View File

@ -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()

View File

@ -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)

View File

@ -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'})

View File

@ -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'))

View File

@ -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 '

View File

@ -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):

View File

@ -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;

View File

@ -73,6 +73,7 @@ MODULES = [
'BeautifulSoup',
'mako',
'migrate',
'uno',
]

View File

@ -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,