forked from openlp/openlp
r1715
This commit is contained in:
commit
418802b735
@ -20,3 +20,4 @@ _eric4project
|
|||||||
openlp/core/resources.py.old
|
openlp/core/resources.py.old
|
||||||
*.qm
|
*.qm
|
||||||
resources/windows/warnOpenLP.txt
|
resources/windows/warnOpenLP.txt
|
||||||
|
openlp.cfg
|
||||||
|
18
openlp.pyw
18
openlp.pyw
@ -79,6 +79,8 @@ class OpenLP(QtGui.QApplication):
|
|||||||
class in order to provide the core of the application.
|
class in order to provide the core of the application.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
args = []
|
||||||
|
|
||||||
def exec_(self):
|
def exec_(self):
|
||||||
"""
|
"""
|
||||||
Override exec method to allow the shared memory to be released on exit
|
Override exec method to allow the shared memory to be released on exit
|
||||||
@ -92,7 +94,7 @@ class OpenLP(QtGui.QApplication):
|
|||||||
"""
|
"""
|
||||||
# On Windows, the args passed into the constructor are
|
# On Windows, the args passed into the constructor are
|
||||||
# ignored. Not very handy, so set the ones we want to use.
|
# ignored. Not very handy, so set the ones we want to use.
|
||||||
self.args = args
|
self.args.extend(args)
|
||||||
# provide a listener for widgets to reqest a screen update.
|
# provide a listener for widgets to reqest a screen update.
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
|
QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
|
||||||
@ -125,6 +127,8 @@ class OpenLP(QtGui.QApplication):
|
|||||||
# now kill the splashscreen
|
# now kill the splashscreen
|
||||||
self.splash.finish(self.mainWindow)
|
self.splash.finish(self.mainWindow)
|
||||||
log.debug(u'Splashscreen closed')
|
log.debug(u'Splashscreen closed')
|
||||||
|
# make sure Qt really display the splash screen
|
||||||
|
self.processEvents()
|
||||||
self.mainWindow.repaint()
|
self.mainWindow.repaint()
|
||||||
self.processEvents()
|
self.processEvents()
|
||||||
if not has_run_wizard:
|
if not has_run_wizard:
|
||||||
@ -180,6 +184,18 @@ class OpenLP(QtGui.QApplication):
|
|||||||
"""
|
"""
|
||||||
self.restoreOverrideCursor()
|
self.restoreOverrideCursor()
|
||||||
|
|
||||||
|
def event(self, event):
|
||||||
|
"""
|
||||||
|
Enables direct file opening on OS X
|
||||||
|
"""
|
||||||
|
if event.type() == QtCore.QEvent.FileOpen:
|
||||||
|
file_name = event.file()
|
||||||
|
log.debug(u'Got open file event for %s!', file_name)
|
||||||
|
self.args.insert(0, unicode(file_name))
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return QtGui.QApplication.event(self, event)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
"""
|
||||||
The main function which parses command line options and then runs
|
The main function which parses command line options and then runs
|
||||||
|
@ -205,7 +205,7 @@ def clean_tags(text):
|
|||||||
text = text.replace(u'<br>', u'\n')
|
text = text.replace(u'<br>', u'\n')
|
||||||
text = text.replace(u'{br}', u'\n')
|
text = text.replace(u'{br}', u'\n')
|
||||||
text = text.replace(u' ', u' ')
|
text = text.replace(u' ', u' ')
|
||||||
for tag in DisplayTags.get_html_tags():
|
for tag in FormattingTags.get_html_tags():
|
||||||
text = text.replace(tag[u'start tag'], u'')
|
text = text.replace(tag[u'start tag'], u'')
|
||||||
text = text.replace(tag[u'end tag'], u'')
|
text = text.replace(tag[u'end tag'], u'')
|
||||||
return text
|
return text
|
||||||
@ -214,7 +214,7 @@ def expand_tags(text):
|
|||||||
"""
|
"""
|
||||||
Expand tags HTML for display
|
Expand tags HTML for display
|
||||||
"""
|
"""
|
||||||
for tag in DisplayTags.get_html_tags():
|
for tag in FormattingTags.get_html_tags():
|
||||||
text = text.replace(tag[u'start tag'], tag[u'start html'])
|
text = text.replace(tag[u'start tag'], tag[u'start html'])
|
||||||
text = text.replace(tag[u'end tag'], tag[u'end html'])
|
text = text.replace(tag[u'end tag'], tag[u'end html'])
|
||||||
return text
|
return text
|
||||||
@ -233,9 +233,9 @@ def check_directory_exists(dir):
|
|||||||
except IOError:
|
except IOError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
from listwidgetwithdnd import ListWidgetWithDnD
|
|
||||||
from displaytags import DisplayTags
|
|
||||||
from eventreceiver import Receiver
|
from eventreceiver import Receiver
|
||||||
|
from listwidgetwithdnd import ListWidgetWithDnD
|
||||||
|
from formattingtags import FormattingTags
|
||||||
from spelltextedit import SpellTextEdit
|
from spelltextedit import SpellTextEdit
|
||||||
from settingsmanager import SettingsManager
|
from settingsmanager import SettingsManager
|
||||||
from plugin import PluginStatus, StringContent, Plugin
|
from plugin import PluginStatus, StringContent, Plugin
|
||||||
|
@ -25,12 +25,12 @@
|
|||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
"""
|
"""
|
||||||
Provide Html Tag management and Display Tag access class
|
Provide HTML Tag management and Formatting Tag access class
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from openlp.core.lib import translate
|
from openlp.core.lib import translate
|
||||||
|
|
||||||
class DisplayTags(object):
|
class FormattingTags(object):
|
||||||
"""
|
"""
|
||||||
Static Class to HTML Tags to be access around the code the list is managed
|
Static Class to HTML Tags to be access around the code the list is managed
|
||||||
by the Options Tab.
|
by the Options Tab.
|
||||||
@ -42,89 +42,93 @@ class DisplayTags(object):
|
|||||||
"""
|
"""
|
||||||
Provide access to the html_expands list.
|
Provide access to the html_expands list.
|
||||||
"""
|
"""
|
||||||
return DisplayTags.html_expands
|
return FormattingTags.html_expands
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def reset_html_tags():
|
def reset_html_tags():
|
||||||
"""
|
"""
|
||||||
Resets the html_expands list.
|
Resets the html_expands list.
|
||||||
"""
|
"""
|
||||||
DisplayTags.html_expands = []
|
FormattingTags.html_expands = []
|
||||||
base_tags = []
|
base_tags = []
|
||||||
# Append the base tags.
|
# Append the base tags.
|
||||||
# Hex Color tags from http://www.w3schools.com/html/html_colornames.asp
|
# Hex Color tags from http://www.w3schools.com/html/html_colornames.asp
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Red'),
|
base_tags.append({u'desc': translate('OpenLP.FormattingTags', 'Red'),
|
||||||
u'start tag': u'{r}',
|
u'start tag': u'{r}',
|
||||||
u'start html': u'<span style="-webkit-text-fill-color:red">',
|
u'start html': u'<span style="-webkit-text-fill-color:red">',
|
||||||
u'end tag': u'{/r}', u'end html': u'</span>', u'protected': True})
|
u'end tag': u'{/r}', u'end html': u'</span>', u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Black'),
|
base_tags.append({u'desc': translate('OpenLP.FormattingTags', 'Black'),
|
||||||
u'start tag': u'{b}',
|
u'start tag': u'{b}',
|
||||||
u'start html': u'<span style="-webkit-text-fill-color:black">',
|
u'start html': u'<span style="-webkit-text-fill-color:black">',
|
||||||
u'end tag': u'{/b}', u'end html': u'</span>', u'protected': True})
|
u'end tag': u'{/b}', u'end html': u'</span>', u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Blue'),
|
base_tags.append({u'desc': translate('OpenLP.FormattingTags', 'Blue'),
|
||||||
u'start tag': u'{bl}',
|
u'start tag': u'{bl}',
|
||||||
u'start html': u'<span style="-webkit-text-fill-color:blue">',
|
u'start html': u'<span style="-webkit-text-fill-color:blue">',
|
||||||
u'end tag': u'{/bl}', u'end html': u'</span>', u'protected': True})
|
u'end tag': u'{/bl}', u'end html': u'</span>', u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Yellow'),
|
base_tags.append({u'desc': translate('OpenLP.FormattingTags', 'Yellow'),
|
||||||
u'start tag': u'{y}',
|
u'start tag': u'{y}',
|
||||||
u'start html': u'<span style="-webkit-text-fill-color:yellow">',
|
u'start html': u'<span style="-webkit-text-fill-color:yellow">',
|
||||||
u'end tag': u'{/y}', u'end html': u'</span>', u'protected': True})
|
u'end tag': u'{/y}', u'end html': u'</span>', u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Green'),
|
base_tags.append({u'desc': translate('OpenLP.FormattingTags', 'Green'),
|
||||||
u'start tag': u'{g}',
|
u'start tag': u'{g}',
|
||||||
u'start html': u'<span style="-webkit-text-fill-color:green">',
|
u'start html': u'<span style="-webkit-text-fill-color:green">',
|
||||||
u'end tag': u'{/g}', u'end html': u'</span>', u'protected': True})
|
u'end tag': u'{/g}', u'end html': u'</span>', u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Pink'),
|
base_tags.append({u'desc': translate('OpenLP.FormattingTags', 'Pink'),
|
||||||
u'start tag': u'{pk}',
|
u'start tag': u'{pk}',
|
||||||
u'start html': u'<span style="-webkit-text-fill-color:#FFC0CB">',
|
u'start html': u'<span style="-webkit-text-fill-color:#FFC0CB">',
|
||||||
u'end tag': u'{/pk}', u'end html': u'</span>', u'protected': True})
|
u'end tag': u'{/pk}', u'end html': u'</span>', u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Orange'),
|
base_tags.append({u'desc': translate('OpenLP.FormattingTags', 'Orange'),
|
||||||
u'start tag': u'{o}',
|
u'start tag': u'{o}',
|
||||||
u'start html': u'<span style="-webkit-text-fill-color:#FFA500">',
|
u'start html': u'<span style="-webkit-text-fill-color:#FFA500">',
|
||||||
u'end tag': u'{/o}', u'end html': u'</span>', u'protected': True})
|
u'end tag': u'{/o}', u'end html': u'</span>', u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Purple'),
|
base_tags.append({u'desc': translate('OpenLP.FormattingTags', 'Purple'),
|
||||||
u'start tag': u'{pp}',
|
u'start tag': u'{pp}',
|
||||||
u'start html': u'<span style="-webkit-text-fill-color:#800080">',
|
u'start html': u'<span style="-webkit-text-fill-color:#800080">',
|
||||||
u'end tag': u'{/pp}', u'end html': u'</span>', u'protected': True})
|
u'end tag': u'{/pp}', u'end html': u'</span>', u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'White'),
|
base_tags.append({u'desc': translate('OpenLP.FormattingTags', 'White'),
|
||||||
u'start tag': u'{w}',
|
u'start tag': u'{w}',
|
||||||
u'start html': u'<span style="-webkit-text-fill-color:white">',
|
u'start html': u'<span style="-webkit-text-fill-color:white">',
|
||||||
u'end tag': u'{/w}', u'end html': u'</span>', u'protected': True})
|
u'end tag': u'{/w}', u'end html': u'</span>', u'protected': True})
|
||||||
base_tags.append({
|
base_tags.append({
|
||||||
u'desc': translate('OpenLP.DisplayTags', 'Superscript'),
|
u'desc': translate('OpenLP.FormattingTags', 'Superscript'),
|
||||||
u'start tag': u'{su}', u'start html': u'<sup>',
|
u'start tag': u'{su}', u'start html': u'<sup>',
|
||||||
u'end tag': u'{/su}', u'end html': u'</sup>', u'protected': True})
|
u'end tag': u'{/su}', u'end html': u'</sup>', u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Subscript'),
|
base_tags.append({
|
||||||
|
u'desc': translate('OpenLP.FormattingTags', 'Subscript'),
|
||||||
u'start tag': u'{sb}', u'start html': u'<sub>',
|
u'start tag': u'{sb}', u'start html': u'<sub>',
|
||||||
u'end tag': u'{/sb}', u'end html': u'</sub>', u'protected': True})
|
u'end tag': u'{/sb}', u'end html': u'</sub>', u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Paragraph'),
|
base_tags.append({
|
||||||
|
u'desc': translate('OpenLP.FormattingTags', 'Paragraph'),
|
||||||
u'start tag': u'{p}', u'start html': u'<p>', u'end tag': u'{/p}',
|
u'start tag': u'{p}', u'start html': u'<p>', u'end tag': u'{/p}',
|
||||||
u'end html': u'</p>', u'protected': True})
|
u'end html': u'</p>', u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Bold'),
|
base_tags.append({u'desc': translate('OpenLP.FormattingTags', 'Bold'),
|
||||||
u'start tag': u'{st}', u'start html': u'<strong>',
|
u'start tag': u'{st}', u'start html': u'<strong>',
|
||||||
u'end tag': u'{/st}', u'end html': u'</strong>',
|
u'end tag': u'{/st}', u'end html': u'</strong>',
|
||||||
u'protected': True})
|
u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Italics'),
|
base_tags.append({
|
||||||
|
u'desc': translate('OpenLP.FormattingTags', 'Italics'),
|
||||||
u'start tag': u'{it}', u'start html': u'<em>', u'end tag': u'{/it}',
|
u'start tag': u'{it}', u'start html': u'<em>', u'end tag': u'{/it}',
|
||||||
u'end html': u'</em>', u'protected': True})
|
u'end html': u'</em>', u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Underline'),
|
base_tags.append({
|
||||||
|
u'desc': translate('OpenLP.FormattingTags', 'Underline'),
|
||||||
u'start tag': u'{u}',
|
u'start tag': u'{u}',
|
||||||
u'start html': u'<span style="text-decoration: underline;">',
|
u'start html': u'<span style="text-decoration: underline;">',
|
||||||
u'end tag': u'{/u}', u'end html': u'</span>', u'protected': True})
|
u'end tag': u'{/u}', u'end html': u'</span>', u'protected': True})
|
||||||
base_tags.append({u'desc': translate('OpenLP.DisplayTags', 'Break'),
|
base_tags.append({u'desc': translate('OpenLP.FormattingTags', 'Break'),
|
||||||
u'start tag': u'{br}', u'start html': u'<br>', u'end tag': u'',
|
u'start tag': u'{br}', u'start html': u'<br>', u'end tag': u'',
|
||||||
u'end html': u'', u'protected': True})
|
u'end html': u'', u'protected': True})
|
||||||
DisplayTags.add_html_tags(base_tags)
|
FormattingTags.add_html_tags(base_tags)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add_html_tags(tags):
|
def add_html_tags(tags):
|
||||||
"""
|
"""
|
||||||
Add a list of tags to the list
|
Add a list of tags to the list
|
||||||
"""
|
"""
|
||||||
DisplayTags.html_expands.extend(tags)
|
FormattingTags.html_expands.extend(tags)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def remove_html_tag(tag_id):
|
def remove_html_tag(tag_id):
|
||||||
"""
|
"""
|
||||||
Removes an individual html_expands tag.
|
Removes an individual html_expands tag.
|
||||||
"""
|
"""
|
||||||
DisplayTags.html_expands.pop(tag_id)
|
FormattingTags.html_expands.pop(tag_id)
|
@ -34,6 +34,7 @@ from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, \
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# FIXME: Add html5 doctype. However, do not break theme gradients.
|
||||||
HTMLSRC = u"""
|
HTMLSRC = u"""
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
@ -56,44 +57,44 @@ body {
|
|||||||
height: %spx;
|
height: %spx;
|
||||||
}
|
}
|
||||||
#black {
|
#black {
|
||||||
z-index:8;
|
z-index: 8;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#bgimage {
|
#bgimage {
|
||||||
z-index:1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
#image {
|
#image {
|
||||||
z-index:2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
#video1 {
|
#video1 {
|
||||||
z-index:3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
#video2 {
|
#video2 {
|
||||||
z-index:3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
#alert {
|
#alert {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
z-index:10;
|
z-index: 10;
|
||||||
%s
|
%s
|
||||||
}
|
}
|
||||||
#footer {
|
#footer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index:6;
|
z-index: 6;
|
||||||
%s
|
%s
|
||||||
}
|
}
|
||||||
/* lyric css */
|
/* lyric css */
|
||||||
%s
|
%s
|
||||||
sup {
|
sup {
|
||||||
font-size:0.6em;
|
font-size: 0.6em;
|
||||||
vertical-align:top;
|
vertical-align: top;
|
||||||
position:relative;
|
position: relative;
|
||||||
top:-0.3em;
|
top: -0.3em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script language="javascript">
|
<script>
|
||||||
var timer = null;
|
var timer = null;
|
||||||
var video_timer = null;
|
var video_timer = null;
|
||||||
var current_video = '1';
|
var current_video = '1';
|
||||||
@ -317,10 +318,10 @@ sup {
|
|||||||
%s
|
%s
|
||||||
<div id="footer" class="footer"></div>
|
<div id="footer" class="footer"></div>
|
||||||
<div id="black" class="size"></div>
|
<div id="black" class="size"></div>
|
||||||
<div id="alert" style="visibility:hidden;"></div>
|
<div id="alert" style="visibility:hidden"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def build_html(item, screen, alert, islive, background, image=None):
|
def build_html(item, screen, alert, islive, background, image=None):
|
||||||
"""
|
"""
|
||||||
@ -446,15 +447,15 @@ def build_lyrics_css(item, webkitvers):
|
|||||||
The version of qtwebkit we're using
|
The version of qtwebkit we're using
|
||||||
|
|
||||||
"""
|
"""
|
||||||
style = """
|
style = u"""
|
||||||
.lyricstable {
|
.lyricstable {
|
||||||
z-index:5;
|
z-index: 5;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: table;
|
display: table;
|
||||||
%s
|
%s
|
||||||
}
|
}
|
||||||
.lyricscell {
|
.lyricscell {
|
||||||
display:table-cell;
|
display: table-cell;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
%s
|
%s
|
||||||
}
|
}
|
||||||
@ -558,8 +559,8 @@ def build_lyrics_format_css(theme, width, height):
|
|||||||
left_margin = 0
|
left_margin = 0
|
||||||
lyrics = u'white-space:pre-wrap; word-wrap: break-word; ' \
|
lyrics = u'white-space:pre-wrap; word-wrap: break-word; ' \
|
||||||
'text-align: %s; vertical-align: %s; font-family: %s; ' \
|
'text-align: %s; vertical-align: %s; font-family: %s; ' \
|
||||||
'font-size: %spt; color: %s; line-height: %d%%; margin:0;' \
|
'font-size: %spt; color: %s; line-height: %d%%; margin: 0;' \
|
||||||
'padding:0; padding-left:%spx; width: %spx; height: %spx; ' % \
|
'padding: 0; padding-left: %spx; width: %spx; height: %spx; ' % \
|
||||||
(align, valign, theme.font_main_name, theme.font_main_size,
|
(align, valign, theme.font_main_name, theme.font_main_size,
|
||||||
theme.font_main_color, 100 + int(theme.font_main_line_adjustment),
|
theme.font_main_color, 100 + int(theme.font_main_line_adjustment),
|
||||||
left_margin, width, height)
|
left_margin, width, height)
|
||||||
@ -608,7 +609,7 @@ def build_footer_css(item, height):
|
|||||||
``item``
|
``item``
|
||||||
Service Item to be processed.
|
Service Item to be processed.
|
||||||
"""
|
"""
|
||||||
style = """
|
style = u"""
|
||||||
left: %spx;
|
left: %spx;
|
||||||
bottom: %spx;
|
bottom: %spx;
|
||||||
width: %spx;
|
width: %spx;
|
||||||
@ -616,7 +617,7 @@ def build_footer_css(item, height):
|
|||||||
font-size: %spt;
|
font-size: %spt;
|
||||||
color: %s;
|
color: %s;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
white-space:nowrap;
|
white-space: nowrap;
|
||||||
"""
|
"""
|
||||||
theme = item.themedata
|
theme = item.themedata
|
||||||
if not theme or not item.footer:
|
if not theme or not item.footer:
|
||||||
@ -634,7 +635,7 @@ def build_alert_css(alertTab, width):
|
|||||||
``alertTab``
|
``alertTab``
|
||||||
Details from the Alert tab for fonts etc
|
Details from the Alert tab for fonts etc
|
||||||
"""
|
"""
|
||||||
style = """
|
style = u"""
|
||||||
width: %spx;
|
width: %spx;
|
||||||
vertical-align: %s;
|
vertical-align: %s;
|
||||||
font-family: %s;
|
font-family: %s;
|
||||||
|
@ -32,6 +32,7 @@ to wait for the conversion to happen.
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
import Queue
|
||||||
|
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
@ -42,8 +43,8 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class ImageThread(QtCore.QThread):
|
class ImageThread(QtCore.QThread):
|
||||||
"""
|
"""
|
||||||
A special Qt thread class to speed up the display of text based frames.
|
A special Qt thread class to speed up the display of images. This is
|
||||||
This is threaded so it loads the frames in background
|
threaded so it loads the frames and generates byte stream in background.
|
||||||
"""
|
"""
|
||||||
def __init__(self, manager):
|
def __init__(self, manager):
|
||||||
QtCore.QThread.__init__(self, None)
|
QtCore.QThread.__init__(self, None)
|
||||||
@ -53,15 +54,87 @@ class ImageThread(QtCore.QThread):
|
|||||||
"""
|
"""
|
||||||
Run the thread.
|
Run the thread.
|
||||||
"""
|
"""
|
||||||
self.imageManager.process()
|
self.imageManager._process()
|
||||||
|
|
||||||
|
|
||||||
|
class Priority(object):
|
||||||
|
"""
|
||||||
|
Enumeration class for different priorities.
|
||||||
|
|
||||||
|
``Lowest``
|
||||||
|
Only the image's byte stream has to be generated. But neither the
|
||||||
|
``QImage`` nor the byte stream has been requested yet.
|
||||||
|
|
||||||
|
``Low``
|
||||||
|
Only the image's byte stream has to be generated. Because the image's
|
||||||
|
``QImage`` has been requested previously it is reasonable to assume that
|
||||||
|
the byte stream will be needed before the byte stream of other images
|
||||||
|
whose ``QImage`` were not generated due to a request.
|
||||||
|
|
||||||
|
``Normal``
|
||||||
|
The image's byte stream as well as the image has to be generated.
|
||||||
|
Neither the ``QImage`` nor the byte stream has been requested yet.
|
||||||
|
|
||||||
|
``High``
|
||||||
|
The image's byte stream as well as the image has to be generated. The
|
||||||
|
``QImage`` for this image has been requested.
|
||||||
|
**Note**, this priority is only set when the ``QImage`` has not been
|
||||||
|
generated yet.
|
||||||
|
|
||||||
|
``Urgent``
|
||||||
|
The image's byte stream as well as the image has to be generated. The
|
||||||
|
byte stream for this image has been requested.
|
||||||
|
**Note**, this priority is only set when the byte stream has not been
|
||||||
|
generated yet.
|
||||||
|
"""
|
||||||
|
Lowest = 4
|
||||||
|
Low = 3
|
||||||
|
Normal = 2
|
||||||
|
High = 1
|
||||||
|
Urgent = 0
|
||||||
|
|
||||||
|
|
||||||
class Image(object):
|
class Image(object):
|
||||||
name = ''
|
"""
|
||||||
path = ''
|
This class represents an image. To mark an image as *dirty* set the instance
|
||||||
dirty = True
|
variables ``image`` and ``image_bytes`` to ``None`` and add the image object
|
||||||
image = None
|
to the queue of images to process.
|
||||||
image_bytes = None
|
"""
|
||||||
|
def __init__(self, name='', path=''):
|
||||||
|
self.name = name
|
||||||
|
self.path = path
|
||||||
|
self.image = None
|
||||||
|
self.image_bytes = None
|
||||||
|
self.priority = Priority.Normal
|
||||||
|
|
||||||
|
|
||||||
|
class PriorityQueue(Queue.PriorityQueue):
|
||||||
|
"""
|
||||||
|
Customised ``Queue.PriorityQueue``.
|
||||||
|
"""
|
||||||
|
def modify_priority(self, image, new_priority):
|
||||||
|
"""
|
||||||
|
Modifies the priority of the given ``image``.
|
||||||
|
|
||||||
|
``image``
|
||||||
|
The image to remove. This should be an ``Image`` instance.
|
||||||
|
|
||||||
|
``new_priority``
|
||||||
|
The image's new priority.
|
||||||
|
"""
|
||||||
|
self.remove(image)
|
||||||
|
image.priority = new_priority
|
||||||
|
self.put((image.priority, image))
|
||||||
|
|
||||||
|
def remove(self, image):
|
||||||
|
"""
|
||||||
|
Removes the given ``image`` from the queue.
|
||||||
|
|
||||||
|
``image``
|
||||||
|
The image to remove. This should be an ``Image`` instance.
|
||||||
|
"""
|
||||||
|
if (image.priority, image) in self.queue:
|
||||||
|
self.queue.remove((image.priority, image))
|
||||||
|
|
||||||
|
|
||||||
class ImageManager(QtCore.QObject):
|
class ImageManager(QtCore.QObject):
|
||||||
@ -76,96 +149,117 @@ class ImageManager(QtCore.QObject):
|
|||||||
self.width = current_screen[u'size'].width()
|
self.width = current_screen[u'size'].width()
|
||||||
self.height = current_screen[u'size'].height()
|
self.height = current_screen[u'size'].height()
|
||||||
self._cache = {}
|
self._cache = {}
|
||||||
self._thread_running = False
|
self._imageThread = ImageThread(self)
|
||||||
self._cache_dirty = False
|
self._conversion_queue = PriorityQueue()
|
||||||
self.image_thread = ImageThread(self)
|
|
||||||
|
|
||||||
def update_display(self):
|
def update_display(self):
|
||||||
"""
|
"""
|
||||||
Screen has changed size so rebuild the cache to new size
|
Screen has changed size so rebuild the cache to new size.
|
||||||
"""
|
"""
|
||||||
log.debug(u'update_display')
|
log.debug(u'update_display')
|
||||||
current_screen = ScreenList.get_instance().current
|
current_screen = ScreenList.get_instance().current
|
||||||
self.width = current_screen[u'size'].width()
|
self.width = current_screen[u'size'].width()
|
||||||
self.height = current_screen[u'size'].height()
|
self.height = current_screen[u'size'].height()
|
||||||
# mark the images as dirty for a rebuild
|
# Mark the images as dirty for a rebuild by setting the image and byte
|
||||||
for key in self._cache.keys():
|
# stream to None.
|
||||||
image = self._cache[key]
|
self._conversion_queue = PriorityQueue()
|
||||||
image.dirty = True
|
for key, image in self._cache.iteritems():
|
||||||
image.image = resize_image(image.path, self.width, self.height)
|
image.priority = Priority.Normal
|
||||||
self._cache_dirty = True
|
image.image = None
|
||||||
# only one thread please
|
image.image_bytes = None
|
||||||
if not self._thread_running:
|
self._conversion_queue.put((image.priority, image))
|
||||||
self.image_thread.start()
|
# We want only one thread.
|
||||||
|
if not self._imageThread.isRunning():
|
||||||
|
self._imageThread.start()
|
||||||
|
|
||||||
def get_image(self, name):
|
def get_image(self, name):
|
||||||
"""
|
"""
|
||||||
Return the Qimage from the cache
|
Return the ``QImage`` from the cache. If not present wait for the
|
||||||
|
background thread to process it.
|
||||||
"""
|
"""
|
||||||
log.debug(u'get_image %s' % name)
|
log.debug(u'get_image %s' % name)
|
||||||
return self._cache[name].image
|
image = self._cache[name]
|
||||||
|
if image.image is None:
|
||||||
|
self._conversion_queue.modify_priority(image, Priority.High)
|
||||||
|
while image.image is None:
|
||||||
|
log.debug(u'get_image - waiting')
|
||||||
|
time.sleep(0.1)
|
||||||
|
elif image.image_bytes is None:
|
||||||
|
# Set the priority to Low, because the image was requested but the
|
||||||
|
# byte stream was not generated yet. However, we only need to do
|
||||||
|
# this, when the image was generated before it was requested
|
||||||
|
# (otherwise this is already taken care of).
|
||||||
|
self._conversion_queue.modify_priority(image, Priority.Low)
|
||||||
|
return image.image
|
||||||
|
|
||||||
def get_image_bytes(self, name):
|
def get_image_bytes(self, name):
|
||||||
"""
|
"""
|
||||||
Returns the byte string for an image
|
Returns the byte string for an image. If not present wait for the
|
||||||
If not present wait for the background thread to process it.
|
background thread to process it.
|
||||||
"""
|
"""
|
||||||
log.debug(u'get_image_bytes %s' % name)
|
log.debug(u'get_image_bytes %s' % name)
|
||||||
if not self._cache[name].image_bytes:
|
image = self._cache[name]
|
||||||
while self._cache[name].dirty:
|
if image.image_bytes is None:
|
||||||
|
self._conversion_queue.modify_priority(image, Priority.Urgent)
|
||||||
|
while image.image_bytes is None:
|
||||||
log.debug(u'get_image_bytes - waiting')
|
log.debug(u'get_image_bytes - waiting')
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
return self._cache[name].image_bytes
|
return image.image_bytes
|
||||||
|
|
||||||
def del_image(self, name):
|
def del_image(self, name):
|
||||||
"""
|
"""
|
||||||
Delete the Image from the Cache
|
Delete the Image from the cache.
|
||||||
"""
|
"""
|
||||||
log.debug(u'del_image %s' % name)
|
log.debug(u'del_image %s' % name)
|
||||||
if name in self._cache:
|
if name in self._cache:
|
||||||
|
self._conversion_queue.remove(self._cache[name])
|
||||||
del self._cache[name]
|
del self._cache[name]
|
||||||
|
|
||||||
def add_image(self, name, path):
|
def add_image(self, name, path):
|
||||||
"""
|
"""
|
||||||
Add image to cache if it is not already there
|
Add image to cache if it is not already there.
|
||||||
"""
|
"""
|
||||||
log.debug(u'add_image %s:%s' % (name, path))
|
log.debug(u'add_image %s:%s' % (name, path))
|
||||||
if not name in self._cache:
|
if not name in self._cache:
|
||||||
image = Image()
|
image = Image(name, path)
|
||||||
image.name = name
|
|
||||||
image.path = path
|
|
||||||
image.image = resize_image(path, self.width, self.height)
|
|
||||||
self._cache[name] = image
|
self._cache[name] = image
|
||||||
|
self._conversion_queue.put((image.priority, image))
|
||||||
else:
|
else:
|
||||||
log.debug(u'Image in cache %s:%s' % (name, path))
|
log.debug(u'Image in cache %s:%s' % (name, path))
|
||||||
self._cache_dirty = True
|
# We want only one thread.
|
||||||
# only one thread please
|
if not self._imageThread.isRunning():
|
||||||
if not self._thread_running:
|
self._imageThread.start()
|
||||||
self.image_thread.start()
|
|
||||||
|
|
||||||
def process(self):
|
def _process(self):
|
||||||
"""
|
"""
|
||||||
Controls the processing called from a QThread
|
Controls the processing called from a ``QtCore.QThread``.
|
||||||
"""
|
"""
|
||||||
log.debug(u'process - started')
|
log.debug(u'_process - started')
|
||||||
self._thread_running = True
|
while not self._conversion_queue.empty():
|
||||||
self.clean_cache()
|
self._process_cache()
|
||||||
# data loaded since we started ?
|
log.debug(u'_process - ended')
|
||||||
while self._cache_dirty:
|
|
||||||
log.debug(u'process - recycle')
|
|
||||||
self.clean_cache()
|
|
||||||
self._thread_running = False
|
|
||||||
log.debug(u'process - ended')
|
|
||||||
|
|
||||||
def clean_cache(self):
|
def _process_cache(self):
|
||||||
"""
|
"""
|
||||||
Actually does the work.
|
Actually does the work.
|
||||||
"""
|
"""
|
||||||
log.debug(u'clean_cache')
|
log.debug(u'_process_cache')
|
||||||
# we will clean the cache now
|
image = self._conversion_queue.get()[1]
|
||||||
self._cache_dirty = False
|
# Generate the QImage for the image.
|
||||||
for key in self._cache.keys():
|
if image.image is None:
|
||||||
image = self._cache[key]
|
image.image = resize_image(image.path, self.width, self.height)
|
||||||
if image.dirty:
|
# Set the priority to Lowest and stop here as we need to process
|
||||||
image.image_bytes = image_to_byte(image.image)
|
# more important images first.
|
||||||
image.dirty = False
|
if image.priority == Priority.Normal:
|
||||||
|
self._conversion_queue.modify_priority(image, Priority.Lowest)
|
||||||
|
return
|
||||||
|
# For image with high priority we set the priority to Low, as the
|
||||||
|
# byte stream might be needed earlier the byte stream of image with
|
||||||
|
# Normal priority. We stop here as we need to process more important
|
||||||
|
# images first.
|
||||||
|
elif image.priority == Priority.High:
|
||||||
|
self._conversion_queue.modify_priority(image, Priority.Low)
|
||||||
|
return
|
||||||
|
# Generate the byte stream for the image.
|
||||||
|
if image.image_bytes is None:
|
||||||
|
image.image_bytes = image_to_byte(image.image)
|
||||||
|
@ -27,8 +27,12 @@
|
|||||||
"""
|
"""
|
||||||
Extend QListWidget to handle drag and drop functionality
|
Extend QListWidget to handle drag and drop functionality
|
||||||
"""
|
"""
|
||||||
|
import os.path
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
|
from openlp.core.lib import Receiver
|
||||||
|
|
||||||
class ListWidgetWithDnD(QtGui.QListWidget):
|
class ListWidgetWithDnD(QtGui.QListWidget):
|
||||||
"""
|
"""
|
||||||
Provide a list widget to store objects and handle drag and drop events
|
Provide a list widget to store objects and handle drag and drop events
|
||||||
@ -41,6 +45,16 @@ class ListWidgetWithDnD(QtGui.QListWidget):
|
|||||||
self.mimeDataText = name
|
self.mimeDataText = name
|
||||||
assert(self.mimeDataText)
|
assert(self.mimeDataText)
|
||||||
|
|
||||||
|
def activateDnD(self):
|
||||||
|
"""
|
||||||
|
Activate DnD of widget
|
||||||
|
"""
|
||||||
|
self.setAcceptDrops(True)
|
||||||
|
self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
|
||||||
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
|
QtCore.SIGNAL(u'%s_dnd' % self.mimeDataText),
|
||||||
|
self.parent().loadFile)
|
||||||
|
|
||||||
def mouseMoveEvent(self, event):
|
def mouseMoveEvent(self, event):
|
||||||
"""
|
"""
|
||||||
Drag and drop event does not care what data is selected
|
Drag and drop event does not care what data is selected
|
||||||
@ -58,3 +72,39 @@ class ListWidgetWithDnD(QtGui.QListWidget):
|
|||||||
drag.setMimeData(mimeData)
|
drag.setMimeData(mimeData)
|
||||||
mimeData.setText(self.mimeDataText)
|
mimeData.setText(self.mimeDataText)
|
||||||
drag.start(QtCore.Qt.CopyAction)
|
drag.start(QtCore.Qt.CopyAction)
|
||||||
|
|
||||||
|
def dragEnterEvent(self, event):
|
||||||
|
if event.mimeData().hasUrls():
|
||||||
|
event.accept()
|
||||||
|
else:
|
||||||
|
event.ignore()
|
||||||
|
|
||||||
|
def dragMoveEvent(self, event):
|
||||||
|
if event.mimeData().hasUrls():
|
||||||
|
event.setDropAction(QtCore.Qt.CopyAction)
|
||||||
|
event.accept()
|
||||||
|
else:
|
||||||
|
event.ignore()
|
||||||
|
|
||||||
|
def dropEvent(self, event):
|
||||||
|
"""
|
||||||
|
Receive drop event check if it is a file and process it if it is.
|
||||||
|
|
||||||
|
``event``
|
||||||
|
Handle of the event pint passed
|
||||||
|
"""
|
||||||
|
if event.mimeData().hasUrls():
|
||||||
|
event.setDropAction(QtCore.Qt.CopyAction)
|
||||||
|
event.accept()
|
||||||
|
files = []
|
||||||
|
for url in event.mimeData().urls():
|
||||||
|
localFile = unicode(url.toLocalFile())
|
||||||
|
if os.path.isfile(localFile):
|
||||||
|
files.append(localFile)
|
||||||
|
elif os.path.isdir(localFile):
|
||||||
|
listing = os.listdir(localFile)
|
||||||
|
for file in listing:
|
||||||
|
files.append(os.path.join(localFile,file))
|
||||||
|
Receiver.send_message(u'%s_dnd' % self.mimeDataText,files)
|
||||||
|
else:
|
||||||
|
event.ignore()
|
||||||
|
@ -96,7 +96,7 @@ class MediaManagerItem(QtGui.QWidget):
|
|||||||
self.plugin = plugin
|
self.plugin = plugin
|
||||||
visible_title = self.plugin.getString(StringContent.VisibleName)
|
visible_title = self.plugin.getString(StringContent.VisibleName)
|
||||||
self.title = unicode(visible_title[u'title'])
|
self.title = unicode(visible_title[u'title'])
|
||||||
self.settingsSection = self.plugin.name.lower()
|
self.settingsSection = self.plugin.name
|
||||||
self.icon = None
|
self.icon = None
|
||||||
if icon:
|
if icon:
|
||||||
self.icon = build_icon(icon)
|
self.icon = build_icon(icon)
|
||||||
@ -113,7 +113,7 @@ class MediaManagerItem(QtGui.QWidget):
|
|||||||
self.retranslateUi()
|
self.retranslateUi()
|
||||||
self.auto_select_id = -1
|
self.auto_select_id = -1
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'%s_service_load' % self.plugin.name.lower()),
|
QtCore.SIGNAL(u'%s_service_load' % self.plugin.name),
|
||||||
self.serviceLoad)
|
self.serviceLoad)
|
||||||
|
|
||||||
def requiredIcons(self):
|
def requiredIcons(self):
|
||||||
@ -252,7 +252,6 @@ class MediaManagerItem(QtGui.QWidget):
|
|||||||
self.listView.setSelectionMode(
|
self.listView.setSelectionMode(
|
||||||
QtGui.QAbstractItemView.ExtendedSelection)
|
QtGui.QAbstractItemView.ExtendedSelection)
|
||||||
self.listView.setAlternatingRowColors(True)
|
self.listView.setAlternatingRowColors(True)
|
||||||
self.listView.setDragEnabled(True)
|
|
||||||
self.listView.setObjectName(u'%sListView' % self.plugin.name)
|
self.listView.setObjectName(u'%sListView' % self.plugin.name)
|
||||||
# Add to pageLayout
|
# Add to pageLayout
|
||||||
self.pageLayout.addWidget(self.listView)
|
self.pageLayout.addWidget(self.listView)
|
||||||
@ -288,6 +287,7 @@ class MediaManagerItem(QtGui.QWidget):
|
|||||||
self.listView, u':/general/general_add.png',
|
self.listView, u':/general/general_add.png',
|
||||||
translate('OpenLP.MediaManagerItem',
|
translate('OpenLP.MediaManagerItem',
|
||||||
'&Add to selected Service Item'), self.onAddEditClick)
|
'&Add to selected Service Item'), self.onAddEditClick)
|
||||||
|
self.addCustomContextActions()
|
||||||
# Create the context menu and add all actions from the listView.
|
# Create the context menu and add all actions from the listView.
|
||||||
self.menu = QtGui.QMenu()
|
self.menu = QtGui.QMenu()
|
||||||
self.menu.addActions(self.listView.actions())
|
self.menu.addActions(self.listView.actions())
|
||||||
@ -301,6 +301,13 @@ class MediaManagerItem(QtGui.QWidget):
|
|||||||
QtCore.SIGNAL('customContextMenuRequested(QPoint)'),
|
QtCore.SIGNAL('customContextMenuRequested(QPoint)'),
|
||||||
self.contextMenu)
|
self.contextMenu)
|
||||||
|
|
||||||
|
def addCustomContextActions(self):
|
||||||
|
"""
|
||||||
|
Implement this method in your descendent media manager item to
|
||||||
|
add any context menu items. This method is called automatically.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
def initialise(self):
|
def initialise(self):
|
||||||
"""
|
"""
|
||||||
Implement this method in your descendent media manager item to
|
Implement this method in your descendent media manager item to
|
||||||
@ -331,26 +338,65 @@ class MediaManagerItem(QtGui.QWidget):
|
|||||||
log.info(u'New files(s) %s', unicode(files))
|
log.info(u'New files(s) %s', unicode(files))
|
||||||
if files:
|
if files:
|
||||||
Receiver.send_message(u'cursor_busy')
|
Receiver.send_message(u'cursor_busy')
|
||||||
names = []
|
self.validateAndLoad(files)
|
||||||
for count in range(0, self.listView.count()):
|
Receiver.send_message(u'cursor_normal')
|
||||||
names.append(self.listView.item(count).text())
|
|
||||||
newFiles = []
|
def loadFile(self, files):
|
||||||
for file in files:
|
"""
|
||||||
filename = os.path.split(unicode(file))[1]
|
Turn file from Drag and Drop into an array so the Validate code
|
||||||
if filename in names:
|
can run it.
|
||||||
|
|
||||||
|
``files``
|
||||||
|
The list of files to be loaded
|
||||||
|
"""
|
||||||
|
newFiles = []
|
||||||
|
errorShown = False
|
||||||
|
for file in files:
|
||||||
|
type = file.split(u'.')[-1]
|
||||||
|
if type.lower() not in self.onNewFileMasks:
|
||||||
|
if not errorShown:
|
||||||
critical_error_message_box(
|
critical_error_message_box(
|
||||||
UiStrings().Duplicate,
|
translate('OpenLP.MediaManagerItem',
|
||||||
|
'Invalid File Type'),
|
||||||
unicode(translate('OpenLP.MediaManagerItem',
|
unicode(translate('OpenLP.MediaManagerItem',
|
||||||
'Duplicate filename %s.\nThis filename is already in '
|
'Invalid File %s.\nSuffix not supported'))
|
||||||
'the list')) % filename)
|
% file)
|
||||||
else:
|
errorShown = True
|
||||||
newFiles.append(file)
|
else:
|
||||||
|
newFiles.append(file)
|
||||||
|
if file:
|
||||||
|
self.validateAndLoad(newFiles)
|
||||||
|
|
||||||
|
def validateAndLoad(self, files):
|
||||||
|
"""
|
||||||
|
Process a list for files either from the File Dialog or from Drag and
|
||||||
|
Drop
|
||||||
|
|
||||||
|
``files``
|
||||||
|
The files to be loaded
|
||||||
|
"""
|
||||||
|
names = []
|
||||||
|
for count in range(0, self.listView.count()):
|
||||||
|
names.append(self.listView.item(count).text())
|
||||||
|
newFiles = []
|
||||||
|
duplicatesFound = False
|
||||||
|
for file in files:
|
||||||
|
filename = os.path.split(unicode(file))[1]
|
||||||
|
if filename in names:
|
||||||
|
duplicatesFound = True
|
||||||
|
else:
|
||||||
|
newFiles.append(file)
|
||||||
|
if newFiles:
|
||||||
self.loadList(newFiles)
|
self.loadList(newFiles)
|
||||||
lastDir = os.path.split(unicode(files[0]))[0]
|
lastDir = os.path.split(unicode(files[0]))[0]
|
||||||
SettingsManager.set_last_dir(self.settingsSection, lastDir)
|
SettingsManager.set_last_dir(self.settingsSection, lastDir)
|
||||||
SettingsManager.set_list(self.settingsSection,
|
SettingsManager.set_list(self.settingsSection,
|
||||||
self.settingsSection, self.getFileList())
|
self.settingsSection, self.getFileList())
|
||||||
Receiver.send_message(u'cursor_normal')
|
if duplicatesFound:
|
||||||
|
critical_error_message_box(
|
||||||
|
UiStrings().Duplicate,
|
||||||
|
unicode(translate('OpenLP.MediaManagerItem',
|
||||||
|
'Duplicate files found on import and ignored.')))
|
||||||
|
|
||||||
def contextMenu(self, point):
|
def contextMenu(self, point):
|
||||||
item = self.listView.itemAt(point)
|
item = self.listView.itemAt(point)
|
||||||
@ -550,7 +596,7 @@ class MediaManagerItem(QtGui.QWidget):
|
|||||||
QtGui.QMessageBox.information(self, UiStrings().NISs,
|
QtGui.QMessageBox.information(self, UiStrings().NISs,
|
||||||
translate('OpenLP.MediaManagerItem',
|
translate('OpenLP.MediaManagerItem',
|
||||||
'You must select an existing service item to add to.'))
|
'You must select an existing service item to add to.'))
|
||||||
elif self.plugin.name.lower() == serviceItem.name.lower():
|
elif self.plugin.name == serviceItem.name:
|
||||||
self.generateSlideData(serviceItem)
|
self.generateSlideData(serviceItem)
|
||||||
self.plugin.serviceManager.addServiceItem(serviceItem,
|
self.plugin.serviceManager.addServiceItem(serviceItem,
|
||||||
replace=True)
|
replace=True)
|
||||||
|
@ -152,7 +152,7 @@ class Plugin(QtCore.QObject):
|
|||||||
self.version = version
|
self.version = version
|
||||||
else:
|
else:
|
||||||
self.version = get_application_version()[u'version']
|
self.version = get_application_version()[u'version']
|
||||||
self.settingsSection = self.name.lower()
|
self.settingsSection = self.name
|
||||||
self.icon = None
|
self.icon = None
|
||||||
self.media_item_class = media_item_class
|
self.media_item_class = media_item_class
|
||||||
self.settings_tab_class = settings_tab_class
|
self.settings_tab_class = settings_tab_class
|
||||||
|
@ -31,7 +31,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from openlp.core.lib import Plugin, StringContent, PluginStatus
|
from openlp.core.lib import Plugin, PluginStatus
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -46,8 +46,6 @@ VERSE = u'The Lord said to {r}Noah{/r}: \n' \
|
|||||||
'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n'
|
'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n'
|
||||||
FOOTER = [u'Arky Arky (Unknown)', u'Public Domain', u'CCLI 123456']
|
FOOTER = [u'Arky Arky (Unknown)', u'Public Domain', u'CCLI 123456']
|
||||||
|
|
||||||
HTML_END = u'</div></body></html>'
|
|
||||||
|
|
||||||
class Renderer(object):
|
class Renderer(object):
|
||||||
"""
|
"""
|
||||||
Class to pull all Renderer interactions into one place. The plugins will
|
Class to pull all Renderer interactions into one place. The plugins will
|
||||||
@ -56,20 +54,20 @@ class Renderer(object):
|
|||||||
"""
|
"""
|
||||||
log.info(u'Renderer Loaded')
|
log.info(u'Renderer Loaded')
|
||||||
|
|
||||||
def __init__(self, image_manager, theme_manager):
|
def __init__(self, imageManager, themeManager):
|
||||||
"""
|
"""
|
||||||
Initialise the render manager.
|
Initialise the render manager.
|
||||||
|
|
||||||
``image_manager``
|
``imageManager``
|
||||||
A ImageManager instance which takes care of e. g. caching and resizing
|
A ImageManager instance which takes care of e. g. caching and resizing
|
||||||
images.
|
images.
|
||||||
|
|
||||||
``theme_manager``
|
``themeManager``
|
||||||
The ThemeManager instance, used to get the current theme details.
|
The ThemeManager instance, used to get the current theme details.
|
||||||
"""
|
"""
|
||||||
log.debug(u'Initialisation started')
|
log.debug(u'Initialisation started')
|
||||||
self.theme_manager = theme_manager
|
self.themeManager = themeManager
|
||||||
self.image_manager = image_manager
|
self.imageManager = imageManager
|
||||||
self.screens = ScreenList.get_instance()
|
self.screens = ScreenList.get_instance()
|
||||||
self.service_theme = u''
|
self.service_theme = u''
|
||||||
self.theme_level = u''
|
self.theme_level = u''
|
||||||
@ -77,7 +75,7 @@ class Renderer(object):
|
|||||||
self.theme_data = None
|
self.theme_data = None
|
||||||
self.bg_frame = None
|
self.bg_frame = None
|
||||||
self.force_page = False
|
self.force_page = False
|
||||||
self.display = MainDisplay(None, self.image_manager, False)
|
self.display = MainDisplay(None, self.imageManager, False)
|
||||||
self.display.setup()
|
self.display.setup()
|
||||||
|
|
||||||
def update_display(self):
|
def update_display(self):
|
||||||
@ -85,10 +83,10 @@ class Renderer(object):
|
|||||||
Updates the render manager's information about the current screen.
|
Updates the render manager's information about the current screen.
|
||||||
"""
|
"""
|
||||||
log.debug(u'Update Display')
|
log.debug(u'Update Display')
|
||||||
self._calculate_default(self.screens.current[u'size'])
|
self._calculate_default()
|
||||||
if self.display:
|
if self.display:
|
||||||
self.display.close()
|
self.display.close()
|
||||||
self.display = MainDisplay(None, self.image_manager, False)
|
self.display = MainDisplay(None, self.imageManager, False)
|
||||||
self.display.setup()
|
self.display.setup()
|
||||||
self.bg_frame = None
|
self.bg_frame = None
|
||||||
self.theme_data = None
|
self.theme_data = None
|
||||||
@ -101,14 +99,14 @@ class Renderer(object):
|
|||||||
The global-level theme to be set.
|
The global-level theme to be set.
|
||||||
|
|
||||||
``theme_level``
|
``theme_level``
|
||||||
Defaults to *``ThemeLevel.Global``*. The theme level, can be
|
Defaults to ``ThemeLevel.Global``. The theme level, can be
|
||||||
``ThemeLevel.Global``, ``ThemeLevel.Service`` or
|
``ThemeLevel.Global``, ``ThemeLevel.Service`` or
|
||||||
``ThemeLevel.Song``.
|
``ThemeLevel.Song``.
|
||||||
"""
|
"""
|
||||||
self.global_theme = global_theme
|
self.global_theme = global_theme
|
||||||
self.theme_level = theme_level
|
self.theme_level = theme_level
|
||||||
self.global_theme_data = \
|
self.global_theme_data = \
|
||||||
self.theme_manager.getThemeData(self.global_theme)
|
self.themeManager.getThemeData(self.global_theme)
|
||||||
self.theme_data = None
|
self.theme_data = None
|
||||||
|
|
||||||
def set_service_theme(self, service_theme):
|
def set_service_theme(self, service_theme):
|
||||||
@ -162,12 +160,12 @@ class Renderer(object):
|
|||||||
if override_levels:
|
if override_levels:
|
||||||
self.theme_data = override_theme
|
self.theme_data = override_theme
|
||||||
else:
|
else:
|
||||||
self.theme_data = self.theme_manager.getThemeData(theme)
|
self.theme_data = self.themeManager.getThemeData(theme)
|
||||||
self._calculate_default(self.screens.current[u'size'])
|
self._calculate_default()
|
||||||
self._build_text_rectangle(self.theme_data)
|
self._build_text_rectangle(self.theme_data)
|
||||||
# if No file do not update cache
|
# if No file do not update cache
|
||||||
if self.theme_data.background_filename:
|
if self.theme_data.background_filename:
|
||||||
self.image_manager.add_image(self.theme_data.theme_name,
|
self.imageManager.add_image(self.theme_data.theme_name,
|
||||||
self.theme_data.background_filename)
|
self.theme_data.background_filename)
|
||||||
return self._rect, self._rect_footer
|
return self._rect, self._rect_footer
|
||||||
|
|
||||||
@ -185,7 +183,7 @@ class Renderer(object):
|
|||||||
# save value for use in format_slide
|
# save value for use in format_slide
|
||||||
self.force_page = force_page
|
self.force_page = force_page
|
||||||
# set the default image size for previews
|
# set the default image size for previews
|
||||||
self._calculate_default(self.screens.preview[u'size'])
|
self._calculate_default()
|
||||||
# build a service item to generate preview
|
# build a service item to generate preview
|
||||||
serviceItem = ServiceItem()
|
serviceItem = ServiceItem()
|
||||||
serviceItem.theme = theme_data
|
serviceItem.theme = theme_data
|
||||||
@ -193,7 +191,7 @@ class Renderer(object):
|
|||||||
# make big page for theme edit dialog to get line count
|
# make big page for theme edit dialog to get line count
|
||||||
serviceItem.add_from_text(u'', VERSE + VERSE + VERSE)
|
serviceItem.add_from_text(u'', VERSE + VERSE + VERSE)
|
||||||
else:
|
else:
|
||||||
self.image_manager.del_image(theme_data.theme_name)
|
self.imageManager.del_image(theme_data.theme_name)
|
||||||
serviceItem.add_from_text(u'', VERSE)
|
serviceItem.add_from_text(u'', VERSE)
|
||||||
serviceItem.renderer = self
|
serviceItem.renderer = self
|
||||||
serviceItem.raw_footer = FOOTER
|
serviceItem.raw_footer = FOOTER
|
||||||
@ -203,52 +201,58 @@ class Renderer(object):
|
|||||||
raw_html = serviceItem.get_rendered_frame(0)
|
raw_html = serviceItem.get_rendered_frame(0)
|
||||||
preview = self.display.text(raw_html)
|
preview = self.display.text(raw_html)
|
||||||
# Reset the real screen size for subsequent render requests
|
# Reset the real screen size for subsequent render requests
|
||||||
self._calculate_default(self.screens.current[u'size'])
|
self._calculate_default()
|
||||||
return preview
|
return preview
|
||||||
|
self.force_page = False
|
||||||
|
|
||||||
def format_slide(self, text, line_break, item):
|
def format_slide(self, text, item):
|
||||||
"""
|
"""
|
||||||
Calculate how much text can fit on a slide.
|
Calculate how much text can fit on a slide.
|
||||||
|
|
||||||
``text``
|
``text``
|
||||||
The words to go on the slides.
|
The words to go on the slides.
|
||||||
|
|
||||||
``line_break``
|
``item``
|
||||||
Add line endings after each line of text used for bibles.
|
The :class:`~openlp.core.lib.serviceitem.ServiceItem` item object.
|
||||||
"""
|
"""
|
||||||
log.debug(u'format slide')
|
log.debug(u'format slide')
|
||||||
# clean up line endings
|
# Add line endings after each line of text used for bibles.
|
||||||
lines = self._lines_split(text)
|
line_end = u'<br>'
|
||||||
pages = self._paginate_slide(lines, line_break, self.force_page)
|
if item.is_capable(ItemCapabilities.NoLineBreaks):
|
||||||
if len(pages) > 1:
|
line_end = u' '
|
||||||
# Songs and Custom
|
# Bibles
|
||||||
if item.is_capable(ItemCapabilities.AllowsVirtualSplit):
|
if item.is_capable(ItemCapabilities.AllowsWordSplit):
|
||||||
# Do not forget the line breaks !
|
pages = self._paginate_slide_words(text.split(u'\n'), line_end)
|
||||||
slides = text.split(u'[---]')
|
else:
|
||||||
pages = []
|
# Clean up line endings.
|
||||||
for slide in slides:
|
lines = self._lines_split(text)
|
||||||
lines = slide.strip(u'\n').split(u'\n')
|
pages = self._paginate_slide(lines, line_end)
|
||||||
new_pages = self._paginate_slide(lines, line_break,
|
if len(pages) > 1:
|
||||||
self.force_page)
|
# Songs and Custom
|
||||||
pages.extend(new_pages)
|
if item.is_capable(ItemCapabilities.AllowsVirtualSplit):
|
||||||
# Bibles
|
# Do not forget the line breaks!
|
||||||
elif item.is_capable(ItemCapabilities.AllowsWordSplit):
|
slides = text.split(u'[---]')
|
||||||
pages = self._paginate_slide_words(text, line_break)
|
pages = []
|
||||||
return pages
|
for slide in slides:
|
||||||
|
lines = slide.strip(u'\n').split(u'\n')
|
||||||
|
pages.extend(self._paginate_slide(lines, line_end))
|
||||||
|
new_pages = []
|
||||||
|
for page in pages:
|
||||||
|
while page.endswith(u'<br>'):
|
||||||
|
page = page[:-4]
|
||||||
|
new_pages.append(page)
|
||||||
|
return new_pages
|
||||||
|
|
||||||
def _calculate_default(self, screen):
|
def _calculate_default(self):
|
||||||
"""
|
"""
|
||||||
Calculate the default dimentions of the screen.
|
Calculate the default dimentions of the screen.
|
||||||
|
|
||||||
``screen``
|
|
||||||
The QSize of the screen.
|
|
||||||
"""
|
"""
|
||||||
log.debug(u'_calculate default %s', screen)
|
screen_size = self.screens.current[u'size']
|
||||||
self.width = screen.width()
|
self.width = screen_size.width()
|
||||||
self.height = screen.height()
|
self.height = screen_size.height()
|
||||||
self.screen_ratio = float(self.height) / float(self.width)
|
self.screen_ratio = float(self.height) / float(self.width)
|
||||||
log.debug(u'calculate default %d, %d, %f',
|
log.debug(u'_calculate default %s, %f' % (screen_size,
|
||||||
self.width, self.height, self.screen_ratio)
|
self.screen_ratio))
|
||||||
# 90% is start of footer
|
# 90% is start of footer
|
||||||
self.footer_start = int(self.height * 0.90)
|
self.footer_start = int(self.height * 0.90)
|
||||||
|
|
||||||
@ -301,177 +305,202 @@ class Renderer(object):
|
|||||||
self.web.resize(self.page_width, self.page_height)
|
self.web.resize(self.page_width, self.page_height)
|
||||||
self.web_frame = self.web.page().mainFrame()
|
self.web_frame = self.web.page().mainFrame()
|
||||||
# Adjust width and height to account for shadow. outline done in css
|
# Adjust width and height to account for shadow. outline done in css
|
||||||
self.page_shell = u'<html><head><style>' \
|
html = u"""<!DOCTYPE html><html><head><script>
|
||||||
u'*{margin: 0; padding: 0; border: 0;} '\
|
function show_text(newtext) {
|
||||||
u'#main {position:absolute; top:0px; %s %s}</style></head><body>' \
|
var main = document.getElementById('main');
|
||||||
u'<div id="main">' % \
|
main.innerHTML = newtext;
|
||||||
|
// We need to be sure that the page is loaded, that is why we
|
||||||
|
// return the element's height (even though we do not use the
|
||||||
|
// returned value).
|
||||||
|
return main.offsetHeight;
|
||||||
|
}
|
||||||
|
</script><style>*{margin: 0; padding: 0; border: 0;}
|
||||||
|
#main {position: absolute; top: 0px; %s %s}</style></head><body>
|
||||||
|
<div id="main"></div></body></html>""" % \
|
||||||
(build_lyrics_format_css(self.theme_data, self.page_width,
|
(build_lyrics_format_css(self.theme_data, self.page_width,
|
||||||
self.page_height), build_lyrics_outline_css(self.theme_data))
|
self.page_height), build_lyrics_outline_css(self.theme_data))
|
||||||
|
self.web.setHtml(html)
|
||||||
|
|
||||||
def _paginate_slide(self, lines, line_break, force_page=False):
|
def _paginate_slide(self, lines, line_end):
|
||||||
"""
|
"""
|
||||||
Figure out how much text can appear on a slide, using the current
|
Figure out how much text can appear on a slide, using the current
|
||||||
theme settings.
|
theme settings.
|
||||||
|
**Note:** The smallest possible "unit" of text for a slide is one line.
|
||||||
|
If the line is too long it will be cut off when displayed.
|
||||||
|
|
||||||
``lines``
|
``lines``
|
||||||
The words to be fitted on the slide split into lines.
|
The text to be fitted on the slide split into lines.
|
||||||
|
|
||||||
``line_break``
|
|
||||||
Add line endings after each line of text (used for bibles).
|
|
||||||
|
|
||||||
``force_page``
|
|
||||||
Flag to tell message lines in page.
|
|
||||||
|
|
||||||
|
``line_end``
|
||||||
|
The text added after each line. Either ``u' '`` or ``u'<br>``.
|
||||||
"""
|
"""
|
||||||
log.debug(u'_paginate_slide - Start')
|
log.debug(u'_paginate_slide - Start')
|
||||||
line_end = u''
|
|
||||||
if line_break:
|
|
||||||
line_end = u'<br>'
|
|
||||||
formatted = []
|
|
||||||
html_text = u''
|
|
||||||
styled_text = u''
|
|
||||||
line_count = 0
|
|
||||||
for line in lines:
|
|
||||||
if line_count != -1:
|
|
||||||
line_count += 1
|
|
||||||
styled_line = expand_tags(line) + line_end
|
|
||||||
styled_text += styled_line
|
|
||||||
html = self.page_shell + styled_text + HTML_END
|
|
||||||
self.web.setHtml(html)
|
|
||||||
# Text too long so go to next page.
|
|
||||||
if self.web_frame.contentsSize().height() > self.page_height:
|
|
||||||
if force_page and line_count > 0:
|
|
||||||
Receiver.send_message(u'theme_line_count', line_count - 1)
|
|
||||||
line_count = -1
|
|
||||||
while html_text.endswith(u'<br>'):
|
|
||||||
html_text = html_text[:-4]
|
|
||||||
formatted.append(html_text)
|
|
||||||
html_text = u''
|
|
||||||
styled_text = styled_line
|
|
||||||
html_text += line + line_end
|
|
||||||
while html_text.endswith(u'<br>'):
|
|
||||||
html_text = html_text[:-4]
|
|
||||||
formatted.append(html_text)
|
|
||||||
log.debug(u'_paginate_slide - End')
|
|
||||||
return formatted
|
|
||||||
|
|
||||||
def _paginate_slide_words(self, text, line_break):
|
|
||||||
"""
|
|
||||||
Figure out how much text can appear on a slide, using the current
|
|
||||||
theme settings. This version is to handle text which needs to be split
|
|
||||||
into words to get it to fit.
|
|
||||||
|
|
||||||
``text``
|
|
||||||
The words to be fitted on the slide split into lines.
|
|
||||||
|
|
||||||
``line_break``
|
|
||||||
Add line endings after each line of text used for bibles.
|
|
||||||
|
|
||||||
"""
|
|
||||||
log.debug(u'_paginate_slide_words - Start')
|
|
||||||
line_end = u' '
|
|
||||||
if line_break:
|
|
||||||
line_end = u'<br>'
|
|
||||||
formatted = []
|
formatted = []
|
||||||
previous_html = u''
|
previous_html = u''
|
||||||
previous_raw = u''
|
previous_raw = u''
|
||||||
lines = text.split(u'\n')
|
separator = u'<br>'
|
||||||
|
html_lines = map(expand_tags, lines)
|
||||||
|
# Text too long so go to next page.
|
||||||
|
if self._text_fits_on_slide(separator.join(html_lines)):
|
||||||
|
html_text, previous_raw = self._binary_chop(formatted,
|
||||||
|
previous_html, previous_raw, html_lines, lines, separator, u'')
|
||||||
|
else:
|
||||||
|
previous_raw = separator.join(lines)
|
||||||
|
if previous_raw:
|
||||||
|
formatted.append(previous_raw)
|
||||||
|
log.debug(u'_paginate_slide - End')
|
||||||
|
return formatted
|
||||||
|
|
||||||
|
def _paginate_slide_words(self, lines, line_end):
|
||||||
|
"""
|
||||||
|
Figure out how much text can appear on a slide, using the current
|
||||||
|
theme settings.
|
||||||
|
**Note:** The smallest possible "unit" of text for a slide is one word.
|
||||||
|
If one line is too long it will be processed word by word. This is
|
||||||
|
sometimes need for **bible** verses.
|
||||||
|
|
||||||
|
``lines``
|
||||||
|
The text to be fitted on the slide split into lines.
|
||||||
|
|
||||||
|
``line_end``
|
||||||
|
The text added after each line. Either ``u' '`` or ``u'<br>``.
|
||||||
|
This is needed for **bibles**.
|
||||||
|
"""
|
||||||
|
log.debug(u'_paginate_slide_words - Start')
|
||||||
|
formatted = []
|
||||||
|
previous_html = u''
|
||||||
|
previous_raw = u''
|
||||||
for line in lines:
|
for line in lines:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
styled_line = expand_tags(line)
|
html_line = expand_tags(line)
|
||||||
html = self.page_shell + previous_html + styled_line + HTML_END
|
|
||||||
self.web.setHtml(html)
|
|
||||||
# Text too long so go to next page.
|
# Text too long so go to next page.
|
||||||
if self.web_frame.contentsSize().height() > self.page_height:
|
if self._text_fits_on_slide(previous_html + html_line):
|
||||||
# Check if there was a verse before the current one and append
|
# Check if there was a verse before the current one and append
|
||||||
# it, when it fits on the page.
|
# it, when it fits on the page.
|
||||||
if previous_html:
|
if previous_html:
|
||||||
html = self.page_shell + previous_html + HTML_END
|
if not self._text_fits_on_slide(previous_html):
|
||||||
self.web.setHtml(html)
|
|
||||||
if self.web_frame.contentsSize().height() <= \
|
|
||||||
self.page_height:
|
|
||||||
while previous_raw.endswith(u'<br>'):
|
|
||||||
previous_raw = previous_raw[:-4]
|
|
||||||
formatted.append(previous_raw)
|
formatted.append(previous_raw)
|
||||||
previous_html = u''
|
previous_html = u''
|
||||||
previous_raw = u''
|
previous_raw = u''
|
||||||
html = self.page_shell + styled_line + HTML_END
|
|
||||||
self.web.setHtml(html)
|
|
||||||
# Now check if the current verse will fit, if it does
|
# Now check if the current verse will fit, if it does
|
||||||
# not we have to start to process the verse word by
|
# not we have to start to process the verse word by
|
||||||
# word.
|
# word.
|
||||||
if self.web_frame.contentsSize().height() <= \
|
if not self._text_fits_on_slide(html_line):
|
||||||
self.page_height:
|
previous_html = html_line + line_end
|
||||||
previous_html = styled_line + line_end
|
|
||||||
previous_raw = line + line_end
|
previous_raw = line + line_end
|
||||||
continue
|
continue
|
||||||
# Figure out how many words of the line will fit on screen by
|
# Figure out how many words of the line will fit on screen as
|
||||||
# using the algorithm known as "binary chop".
|
# the line will not fit as a whole.
|
||||||
raw_words = self._words_split(line)
|
raw_words = self._words_split(line)
|
||||||
html_words = [expand_tags(word) for word in raw_words]
|
html_words = map(expand_tags, raw_words)
|
||||||
smallest_index = 0
|
previous_html, previous_raw = self._binary_chop(
|
||||||
highest_index = len(html_words) - 1
|
formatted, previous_html, previous_raw, html_words,
|
||||||
index = int(highest_index / 2)
|
raw_words, u' ', line_end)
|
||||||
while True:
|
|
||||||
html = self.page_shell + previous_html + \
|
|
||||||
u''.join(html_words[:index + 1]).strip() + HTML_END
|
|
||||||
self.web.setHtml(html)
|
|
||||||
if self.web_frame.contentsSize().height() > \
|
|
||||||
self.page_height:
|
|
||||||
# We know that it does not fit, so change/calculate the
|
|
||||||
# new index and highest_index accordingly.
|
|
||||||
highest_index = index
|
|
||||||
index = int(index - (index - smallest_index) / 2)
|
|
||||||
else:
|
|
||||||
smallest_index = index
|
|
||||||
index = int(index + (highest_index - index) / 2)
|
|
||||||
# We found the number of words which will fit.
|
|
||||||
if smallest_index == index or highest_index == index:
|
|
||||||
index = smallest_index
|
|
||||||
formatted.append(previous_raw.rstrip(u'<br>') +
|
|
||||||
u''.join(raw_words[:index + 1]))
|
|
||||||
previous_html = u''
|
|
||||||
previous_raw = u''
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
# Check if the rest of the line fits on the slide. If it
|
|
||||||
# does we do not have to do the much more intensive "word by
|
|
||||||
# word" checking.
|
|
||||||
html = self.page_shell + \
|
|
||||||
u''.join(html_words[index + 1:]).strip() + HTML_END
|
|
||||||
self.web.setHtml(html)
|
|
||||||
if self.web_frame.contentsSize().height() <= \
|
|
||||||
self.page_height:
|
|
||||||
previous_html = \
|
|
||||||
u''.join(html_words[index + 1:]).strip() + line_end
|
|
||||||
previous_raw = \
|
|
||||||
u''.join(raw_words[index + 1:]).strip() + line_end
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# The other words do not fit, thus reset the indexes,
|
|
||||||
# create a new list and continue with "word by word".
|
|
||||||
raw_words = raw_words[index + 1:]
|
|
||||||
html_words = html_words[index + 1:]
|
|
||||||
smallest_index = 0
|
|
||||||
highest_index = len(html_words) - 1
|
|
||||||
index = int(highest_index / 2)
|
|
||||||
else:
|
else:
|
||||||
previous_html += styled_line + line_end
|
previous_html += html_line + line_end
|
||||||
previous_raw += line + line_end
|
previous_raw += line + line_end
|
||||||
while previous_raw.endswith(u'<br>'):
|
|
||||||
previous_raw = previous_raw[:-4]
|
|
||||||
formatted.append(previous_raw)
|
formatted.append(previous_raw)
|
||||||
log.debug(u'_paginate_slide_words - End')
|
log.debug(u'_paginate_slide_words - End')
|
||||||
return formatted
|
return formatted
|
||||||
|
|
||||||
|
def _binary_chop(self, formatted, previous_html, previous_raw, html_list,
|
||||||
|
raw_list, separator, line_end):
|
||||||
|
"""
|
||||||
|
This implements the binary chop algorithm for faster rendering. This
|
||||||
|
algorithm works line based (line by line) and word based (word by word).
|
||||||
|
It is assumed that this method is **only** called, when the lines/words
|
||||||
|
to be rendered do **not** fit as a whole.
|
||||||
|
|
||||||
|
``formatted``
|
||||||
|
The list to append any slides.
|
||||||
|
|
||||||
|
``previous_html``
|
||||||
|
The html text which is know to fit on a slide, but is not yet added
|
||||||
|
to the list of slides. (unicode string)
|
||||||
|
|
||||||
|
``previous_raw``
|
||||||
|
The raw text (with formatting tags) which is know to fit on a slide,
|
||||||
|
but is not yet added to the list of slides. (unicode string)
|
||||||
|
|
||||||
|
``html_list``
|
||||||
|
The elements which do not fit on a slide and needs to be processed
|
||||||
|
using the binary chop. The text contains html.
|
||||||
|
|
||||||
|
``raw_list``
|
||||||
|
The elements which do not fit on a slide and needs to be processed
|
||||||
|
using the binary chop. The elements can contain formatting tags.
|
||||||
|
|
||||||
|
``separator``
|
||||||
|
The separator for the elements. For lines this is ``u'<br>'`` and
|
||||||
|
for words this is ``u' '``.
|
||||||
|
|
||||||
|
``line_end``
|
||||||
|
The text added after each "element line". Either ``u' '`` or
|
||||||
|
``u'<br>``. This is needed for bibles.
|
||||||
|
"""
|
||||||
|
smallest_index = 0
|
||||||
|
highest_index = len(html_list) - 1
|
||||||
|
index = int(highest_index / 2)
|
||||||
|
while True:
|
||||||
|
if self._text_fits_on_slide(
|
||||||
|
previous_html + separator.join(html_list[:index + 1]).strip()):
|
||||||
|
# We know that it does not fit, so change/calculate the
|
||||||
|
# new index and highest_index accordingly.
|
||||||
|
highest_index = index
|
||||||
|
index = int(index - (index - smallest_index) / 2)
|
||||||
|
else:
|
||||||
|
smallest_index = index
|
||||||
|
index = int(index + (highest_index - index) / 2)
|
||||||
|
# We found the number of words which will fit.
|
||||||
|
if smallest_index == index or highest_index == index:
|
||||||
|
index = smallest_index
|
||||||
|
formatted.append(previous_raw.rstrip(u'<br>') +
|
||||||
|
separator.join(raw_list[:index + 1]))
|
||||||
|
previous_html = u''
|
||||||
|
previous_raw = u''
|
||||||
|
# Stop here as the theme line count was requested.
|
||||||
|
if self.force_page:
|
||||||
|
Receiver.send_message(u'theme_line_count', index + 1)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
# Check if the remaining elements fit on the slide.
|
||||||
|
if not self._text_fits_on_slide(
|
||||||
|
separator.join(html_list[index + 1:]).strip()):
|
||||||
|
previous_html = separator.join(
|
||||||
|
html_list[index + 1:]).strip() + line_end
|
||||||
|
previous_raw = separator.join(
|
||||||
|
raw_list[index + 1:]).strip() + line_end
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# The remaining elements do not fit, thus reset the indexes,
|
||||||
|
# create a new list and continue.
|
||||||
|
raw_list = raw_list[index + 1:]
|
||||||
|
html_list = html_list[index + 1:]
|
||||||
|
smallest_index = 0
|
||||||
|
highest_index = len(html_list) - 1
|
||||||
|
index = int(highest_index / 2)
|
||||||
|
return previous_html, previous_raw
|
||||||
|
|
||||||
|
def _text_fits_on_slide(self, text):
|
||||||
|
"""
|
||||||
|
Checks if the given ``text`` fits on a slide. If it does ``True`` is
|
||||||
|
returned, otherwise ``False``.
|
||||||
|
|
||||||
|
``text``
|
||||||
|
The text to check. It can contain HTML tags.
|
||||||
|
"""
|
||||||
|
self.web_frame.evaluateJavaScript(u'show_text("%s")' %
|
||||||
|
text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
|
||||||
|
return self.web_frame.contentsSize().height() > self.page_height
|
||||||
|
|
||||||
def _words_split(self, line):
|
def _words_split(self, line):
|
||||||
"""
|
"""
|
||||||
Split the slide up by word so can wrap better
|
Split the slide up by word so can wrap better
|
||||||
"""
|
"""
|
||||||
# this parse we are to be wordy
|
# this parse we are to be wordy
|
||||||
line = line.replace(u'\n', u' ')
|
line = line.replace(u'\n', u' ')
|
||||||
words = line.split(u' ')
|
return line.split(u' ')
|
||||||
return [word + u' ' for word in words]
|
|
||||||
|
|
||||||
def _lines_split(self, text):
|
def _lines_split(self, text):
|
||||||
"""
|
"""
|
||||||
@ -479,5 +508,5 @@ class Renderer(object):
|
|||||||
"""
|
"""
|
||||||
# this parse we do not want to use this so remove it
|
# this parse we do not want to use this so remove it
|
||||||
text = text.replace(u'\n[---]', u'')
|
text = text.replace(u'\n[---]', u'')
|
||||||
lines = text.split(u'\n')
|
text = text.replace(u'[---]', u'')
|
||||||
return [line.replace(u'[---]', u'') for line in lines]
|
return text.split(u'\n')
|
||||||
|
@ -35,8 +35,7 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from openlp.core.lib import build_icon, clean_tags, expand_tags
|
from openlp.core.lib import build_icon, clean_tags, expand_tags, translate
|
||||||
from openlp.core.lib.ui import UiStrings
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -165,7 +164,6 @@ class ServiceItem(object):
|
|||||||
log.debug(u'Render called')
|
log.debug(u'Render called')
|
||||||
self._display_frames = []
|
self._display_frames = []
|
||||||
self.bg_image_bytes = None
|
self.bg_image_bytes = None
|
||||||
line_break = not self.is_capable(ItemCapabilities.NoLineBreaks)
|
|
||||||
theme = self.theme if self.theme else None
|
theme = self.theme if self.theme else None
|
||||||
self.main, self.footer = \
|
self.main, self.footer = \
|
||||||
self.renderer.set_override_theme(theme, use_override)
|
self.renderer.set_override_theme(theme, use_override)
|
||||||
@ -173,9 +171,8 @@ class ServiceItem(object):
|
|||||||
if self.service_item_type == ServiceItemType.Text:
|
if self.service_item_type == ServiceItemType.Text:
|
||||||
log.debug(u'Formatting slides')
|
log.debug(u'Formatting slides')
|
||||||
for slide in self._raw_frames:
|
for slide in self._raw_frames:
|
||||||
formatted = self.renderer \
|
pages = self.renderer.format_slide(slide[u'raw_slide'], self)
|
||||||
.format_slide(slide[u'raw_slide'], line_break, self)
|
for page in pages:
|
||||||
for page in formatted:
|
|
||||||
page = page.replace(u'<br>', u'{br}')
|
page = page.replace(u'<br>', u'{br}')
|
||||||
html = expand_tags(cgi.escape(page.rstrip()))
|
html = expand_tags(cgi.escape(page.rstrip()))
|
||||||
self._display_frames.append({
|
self._display_frames.append({
|
||||||
@ -210,7 +207,7 @@ class ServiceItem(object):
|
|||||||
"""
|
"""
|
||||||
self.service_item_type = ServiceItemType.Image
|
self.service_item_type = ServiceItemType.Image
|
||||||
self._raw_frames.append({u'title': title, u'path': path})
|
self._raw_frames.append({u'title': title, u'path': path})
|
||||||
self.renderer.image_manager.add_image(title, path)
|
self.renderer.imageManager.add_image(title, path)
|
||||||
self._new_item()
|
self._new_item()
|
||||||
|
|
||||||
def add_from_text(self, title, raw_slide, verse_tag=None):
|
def add_from_text(self, title, raw_slide, verse_tag=None):
|
||||||
@ -352,6 +349,9 @@ class ServiceItem(object):
|
|||||||
Updates the _uuid with the value from the original one
|
Updates the _uuid with the value from the original one
|
||||||
The _uuid is unique for a given service item but this allows one to
|
The _uuid is unique for a given service item but this allows one to
|
||||||
replace an original version.
|
replace an original version.
|
||||||
|
|
||||||
|
``other``
|
||||||
|
The service item to be merged with
|
||||||
"""
|
"""
|
||||||
self._uuid = other._uuid
|
self._uuid = other._uuid
|
||||||
self.notes = other.notes
|
self.notes = other.notes
|
||||||
@ -447,10 +447,12 @@ class ServiceItem(object):
|
|||||||
start = None
|
start = None
|
||||||
end = None
|
end = None
|
||||||
if self.start_time != 0:
|
if self.start_time != 0:
|
||||||
start = UiStrings().StartTimeCode % \
|
start = unicode(translate('OpenLP.ServiceItem',
|
||||||
|
'<strong>Start</strong>: %s')) % \
|
||||||
unicode(datetime.timedelta(seconds=self.start_time))
|
unicode(datetime.timedelta(seconds=self.start_time))
|
||||||
if self.media_length != 0:
|
if self.media_length != 0:
|
||||||
end = UiStrings().LengthTime % \
|
end = unicode(translate('OpenLP.ServiceItem',
|
||||||
|
'<strong>Length</strong>: %s')) % \
|
||||||
unicode(datetime.timedelta(seconds=self.media_length))
|
unicode(datetime.timedelta(seconds=self.media_length))
|
||||||
if not start and not end:
|
if not start and not end:
|
||||||
return None
|
return None
|
||||||
@ -459,5 +461,16 @@ class ServiceItem(object):
|
|||||||
elif not start and end:
|
elif not start and end:
|
||||||
return end
|
return end
|
||||||
else:
|
else:
|
||||||
return u'%s : %s' % (start, end)
|
return u'%s <br>%s' % (start, end)
|
||||||
|
|
||||||
|
def update_theme(self, theme):
|
||||||
|
"""
|
||||||
|
updates the theme in the service item
|
||||||
|
|
||||||
|
``theme``
|
||||||
|
The new theme to be replaced in the service item
|
||||||
|
"""
|
||||||
|
self.theme = theme
|
||||||
|
self._new_item()
|
||||||
|
self.render()
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ except ImportError:
|
|||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
from openlp.core.lib import translate, DisplayTags
|
from openlp.core.lib import translate, FormattingTags
|
||||||
from openlp.core.lib.ui import checkable_action
|
from openlp.core.lib.ui import checkable_action
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -48,16 +48,17 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
|
|||||||
"""
|
"""
|
||||||
Spell checking widget based on QPlanTextEdit.
|
Spell checking widget based on QPlanTextEdit.
|
||||||
"""
|
"""
|
||||||
def __init__(self, *args):
|
def __init__(self, parent=None, formattingTagsAllowed=True):
|
||||||
global ENCHANT_AVAILABLE
|
global ENCHANT_AVAILABLE
|
||||||
QtGui.QPlainTextEdit.__init__(self, *args)
|
QtGui.QPlainTextEdit.__init__(self, parent)
|
||||||
|
self.formattingTagsAllowed = formattingTagsAllowed
|
||||||
# Default dictionary based on the current locale.
|
# Default dictionary based on the current locale.
|
||||||
if ENCHANT_AVAILABLE:
|
if ENCHANT_AVAILABLE:
|
||||||
try:
|
try:
|
||||||
self.dictionary = enchant.Dict()
|
self.dictionary = enchant.Dict()
|
||||||
self.highlighter = Highlighter(self.document())
|
self.highlighter = Highlighter(self.document())
|
||||||
self.highlighter.spellingDictionary = self.dictionary
|
self.highlighter.spellingDictionary = self.dictionary
|
||||||
except Error, DictNotFoundError:
|
except (Error, DictNotFoundError):
|
||||||
ENCHANT_AVAILABLE = False
|
ENCHANT_AVAILABLE = False
|
||||||
log.debug(u'Could not load default dictionary')
|
log.debug(u'Could not load default dictionary')
|
||||||
|
|
||||||
@ -110,16 +111,17 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
|
|||||||
spell_menu.addAction(action)
|
spell_menu.addAction(action)
|
||||||
# Only add the spelling suggests to the menu if there are
|
# Only add the spelling suggests to the menu if there are
|
||||||
# suggestions.
|
# suggestions.
|
||||||
if len(spell_menu.actions()):
|
if spell_menu.actions():
|
||||||
popupMenu.insertMenu(popupMenu.actions()[0], spell_menu)
|
popupMenu.insertMenu(popupMenu.actions()[0], spell_menu)
|
||||||
tagMenu = QtGui.QMenu(translate('OpenLP.SpellTextEdit',
|
tagMenu = QtGui.QMenu(translate('OpenLP.SpellTextEdit',
|
||||||
'Formatting Tags'))
|
'Formatting Tags'))
|
||||||
for html in DisplayTags.get_html_tags():
|
if self.formattingTagsAllowed:
|
||||||
action = SpellAction(html[u'desc'], tagMenu)
|
for html in FormattingTags.get_html_tags():
|
||||||
action.correct.connect(self.htmlTag)
|
action = SpellAction(html[u'desc'], tagMenu)
|
||||||
tagMenu.addAction(action)
|
action.correct.connect(self.htmlTag)
|
||||||
popupMenu.insertSeparator(popupMenu.actions()[0])
|
tagMenu.addAction(action)
|
||||||
popupMenu.insertMenu(popupMenu.actions()[0], tagMenu)
|
popupMenu.insertSeparator(popupMenu.actions()[0])
|
||||||
|
popupMenu.insertMenu(popupMenu.actions()[0], tagMenu)
|
||||||
popupMenu.exec_(event.globalPos())
|
popupMenu.exec_(event.globalPos())
|
||||||
|
|
||||||
def setLanguage(self, action):
|
def setLanguage(self, action):
|
||||||
@ -148,7 +150,7 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
|
|||||||
"""
|
"""
|
||||||
Replaces the selected text with word.
|
Replaces the selected text with word.
|
||||||
"""
|
"""
|
||||||
for html in DisplayTags.get_html_tags():
|
for html in FormattingTags.get_html_tags():
|
||||||
if tag == html[u'desc']:
|
if tag == html[u'desc']:
|
||||||
cursor = self.textCursor()
|
cursor = self.textCursor()
|
||||||
if self.textCursor().hasSelection():
|
if self.textCursor().hasSelection():
|
||||||
|
@ -34,8 +34,7 @@ import logging
|
|||||||
from xml.dom.minidom import Document
|
from xml.dom.minidom import Document
|
||||||
from lxml import etree, objectify
|
from lxml import etree, objectify
|
||||||
|
|
||||||
from openlp.core.lib import str_to_bool, translate
|
from openlp.core.lib import str_to_bool
|
||||||
from openlp.core.lib.ui import UiStrings
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ class UiStrings(object):
|
|||||||
self.Cancel = translate('OpenLP.Ui', 'Cancel')
|
self.Cancel = translate('OpenLP.Ui', 'Cancel')
|
||||||
self.CCLINumberLabel = translate('OpenLP.Ui', 'CCLI number:')
|
self.CCLINumberLabel = translate('OpenLP.Ui', 'CCLI number:')
|
||||||
self.CreateService = translate('OpenLP.Ui', 'Create a new service.')
|
self.CreateService = translate('OpenLP.Ui', 'Create a new service.')
|
||||||
|
self.ConfirmDelete = translate('OpenLP.Ui', 'Confirm Delete')
|
||||||
self.Continuous = translate('OpenLP.Ui', 'Continuous')
|
self.Continuous = translate('OpenLP.Ui', 'Continuous')
|
||||||
self.Default = unicode(translate('OpenLP.Ui', 'Default'))
|
self.Default = unicode(translate('OpenLP.Ui', 'Default'))
|
||||||
self.Delete = translate('OpenLP.Ui', '&Delete')
|
self.Delete = translate('OpenLP.Ui', '&Delete')
|
||||||
@ -82,7 +83,6 @@ class UiStrings(object):
|
|||||||
self.Image = translate('OpenLP.Ui', 'Image')
|
self.Image = translate('OpenLP.Ui', 'Image')
|
||||||
self.Import = translate('OpenLP.Ui', 'Import')
|
self.Import = translate('OpenLP.Ui', 'Import')
|
||||||
self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:')
|
self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:')
|
||||||
self.LengthTime = unicode(translate('OpenLP.Ui', 'Length %s'))
|
|
||||||
self.Live = translate('OpenLP.Ui', 'Live')
|
self.Live = translate('OpenLP.Ui', 'Live')
|
||||||
self.LiveBGError = translate('OpenLP.Ui', 'Live Background Error')
|
self.LiveBGError = translate('OpenLP.Ui', 'Live Background Error')
|
||||||
self.LiveToolbar = translate('OpenLP.Ui', 'Live Toolbar')
|
self.LiveToolbar = translate('OpenLP.Ui', 'Live Toolbar')
|
||||||
@ -102,6 +102,8 @@ class UiStrings(object):
|
|||||||
self.OpenLPStart = translate('OpenLP.Ui', 'OpenLP is already running. '
|
self.OpenLPStart = translate('OpenLP.Ui', 'OpenLP is already running. '
|
||||||
'Do you wish to continue?')
|
'Do you wish to continue?')
|
||||||
self.OpenService = translate('OpenLP.Ui', 'Open service.')
|
self.OpenService = translate('OpenLP.Ui', 'Open service.')
|
||||||
|
self.PlaySlidesInLoop = translate('OpenLP.Ui','Play Slides in Loop')
|
||||||
|
self.PlaySlidesToEnd = translate('OpenLP.Ui','Play Slides to End')
|
||||||
self.Preview = translate('OpenLP.Ui', 'Preview')
|
self.Preview = translate('OpenLP.Ui', 'Preview')
|
||||||
self.PrintService = translate('OpenLP.Ui', 'Print Service')
|
self.PrintService = translate('OpenLP.Ui', 'Print Service')
|
||||||
self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background')
|
self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background')
|
||||||
@ -123,6 +125,10 @@ class UiStrings(object):
|
|||||||
self.SplitToolTip = translate('OpenLP.Ui', 'Split a slide into two '
|
self.SplitToolTip = translate('OpenLP.Ui', 'Split a slide into two '
|
||||||
'only if it does not fit on the screen as one slide.')
|
'only if it does not fit on the screen as one slide.')
|
||||||
self.StartTimeCode = unicode(translate('OpenLP.Ui', 'Start %s'))
|
self.StartTimeCode = unicode(translate('OpenLP.Ui', 'Start %s'))
|
||||||
|
self.StopPlaySlidesInLoop = translate('OpenLP.Ui',
|
||||||
|
'Stop Play Slides in Loop')
|
||||||
|
self.StopPlaySlidesToEnd = translate('OpenLP.Ui',
|
||||||
|
'Stop Play Slides to End')
|
||||||
self.Theme = translate('OpenLP.Ui', 'Theme', 'Singular')
|
self.Theme = translate('OpenLP.Ui', 'Theme', 'Singular')
|
||||||
self.Themes = translate('OpenLP.Ui', 'Themes', 'Plural')
|
self.Themes = translate('OpenLP.Ui', 'Themes', 'Plural')
|
||||||
self.Tools = translate('OpenLP.Ui', 'Tools')
|
self.Tools = translate('OpenLP.Ui', 'Tools')
|
||||||
@ -323,8 +329,9 @@ def shortcut_action(parent, name, shortcuts, function, icon=None, checked=None,
|
|||||||
if checked is not None:
|
if checked is not None:
|
||||||
action.setCheckable(True)
|
action.setCheckable(True)
|
||||||
action.setChecked(checked)
|
action.setChecked(checked)
|
||||||
action.setShortcuts(shortcuts)
|
if shortcuts:
|
||||||
action.setShortcutContext(context)
|
action.setShortcuts(shortcuts)
|
||||||
|
action.setShortcutContext(context)
|
||||||
action_list = ActionList.get_instance()
|
action_list = ActionList.get_instance()
|
||||||
action_list.add_action(action, category)
|
action_list.add_action(action, category)
|
||||||
QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered(bool)'), function)
|
QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered(bool)'), function)
|
||||||
|
@ -69,7 +69,7 @@ from advancedtab import AdvancedTab
|
|||||||
from aboutform import AboutForm
|
from aboutform import AboutForm
|
||||||
from pluginform import PluginForm
|
from pluginform import PluginForm
|
||||||
from settingsform import SettingsForm
|
from settingsform import SettingsForm
|
||||||
from displaytagform import DisplayTagForm
|
from formattingtagform import FormattingTagForm
|
||||||
from shortcutlistform import ShortcutListForm
|
from shortcutlistform import ShortcutListForm
|
||||||
from mediadockmanager import MediaDockManager
|
from mediadockmanager import MediaDockManager
|
||||||
from servicemanager import ServiceManager
|
from servicemanager import ServiceManager
|
||||||
|
@ -61,6 +61,5 @@ class AboutForm(QtGui.QDialog, Ui_AboutDialog):
|
|||||||
Launch a web browser and go to the contribute page on the site.
|
Launch a web browser and go to the contribute page on the site.
|
||||||
"""
|
"""
|
||||||
import webbrowser
|
import webbrowser
|
||||||
url = u'http://www.openlp.org/en/documentation/introduction/' \
|
url = u'http://openlp.org/en/documentation/introduction/contributing'
|
||||||
+ u'contributing.html'
|
|
||||||
webbrowser.open_new(url)
|
webbrowser.open_new(url)
|
||||||
|
@ -129,6 +129,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
os.path.join(gettempdir(), u'openlp', screenshot)))
|
os.path.join(gettempdir(), u'openlp', screenshot)))
|
||||||
item.setCheckState(QtCore.Qt.Unchecked)
|
item.setCheckState(QtCore.Qt.Unchecked)
|
||||||
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
|
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
|
||||||
|
Receiver.send_message(u'cursor_normal')
|
||||||
|
|
||||||
def nextId(self):
|
def nextId(self):
|
||||||
"""
|
"""
|
||||||
@ -156,10 +157,27 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
item = self.themesListWidget.item(iter)
|
item = self.themesListWidget.item(iter)
|
||||||
if item.checkState() == QtCore.Qt.Checked:
|
if item.checkState() == QtCore.Qt.Checked:
|
||||||
self.themeComboBox.addItem(item.text())
|
self.themeComboBox.addItem(item.text())
|
||||||
|
# Check if this is a re-run of the wizard.
|
||||||
|
self.has_run_wizard = QtCore.QSettings().value(
|
||||||
|
u'general/has run wizard', QtCore.QVariant(False)).toBool()
|
||||||
|
if self.has_run_wizard:
|
||||||
|
# Add any existing themes to list.
|
||||||
|
for theme in self.parent().themeManagerContents.getThemes():
|
||||||
|
index = self.themeComboBox.findText(theme)
|
||||||
|
if index == -1:
|
||||||
|
self.themeComboBox.addItem(theme)
|
||||||
|
default_theme = unicode(QtCore.QSettings().value(
|
||||||
|
u'themes/global theme',
|
||||||
|
QtCore.QVariant(u'')).toString())
|
||||||
|
# Pre-select the current default theme.
|
||||||
|
index = self.themeComboBox.findText(default_theme)
|
||||||
|
self.themeComboBox.setCurrentIndex(index)
|
||||||
elif pageId == FirstTimePage.Progress:
|
elif pageId == FirstTimePage.Progress:
|
||||||
|
Receiver.send_message(u'cursor_busy')
|
||||||
self._preWizard()
|
self._preWizard()
|
||||||
self._performWizard()
|
self._performWizard()
|
||||||
self._postWizard()
|
self._postWizard()
|
||||||
|
Receiver.send_message(u'cursor_normal')
|
||||||
|
|
||||||
def updateScreenListCombo(self):
|
def updateScreenListCombo(self):
|
||||||
"""
|
"""
|
||||||
@ -248,11 +266,21 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
"""
|
"""
|
||||||
if self.max_progress:
|
if self.max_progress:
|
||||||
self.progressBar.setValue(self.progressBar.maximum())
|
self.progressBar.setValue(self.progressBar.maximum())
|
||||||
self.progressLabel.setText(translate('OpenLP.FirstTimeWizard',
|
if self.has_run_wizard:
|
||||||
'Download complete. Click the finish button to start OpenLP.'))
|
self.progressLabel.setText(translate('OpenLP.FirstTimeWizard',
|
||||||
|
'Download complete.'
|
||||||
|
' Click the finish button to return to OpenLP.'))
|
||||||
|
else:
|
||||||
|
self.progressLabel.setText(translate('OpenLP.FirstTimeWizard',
|
||||||
|
'Download complete.'
|
||||||
|
' Click the finish button to start OpenLP.'))
|
||||||
else:
|
else:
|
||||||
self.progressLabel.setText(translate('OpenLP.FirstTimeWizard',
|
if self.has_run_wizard:
|
||||||
'Click the finish button to start OpenLP.'))
|
self.progressLabel.setText(translate('OpenLP.FirstTimeWizard',
|
||||||
|
'Click the finish button to return to OpenLP.'))
|
||||||
|
else:
|
||||||
|
self.progressLabel.setText(translate('OpenLP.FirstTimeWizard',
|
||||||
|
'Click the finish button to start OpenLP.'))
|
||||||
self.finishButton.setVisible(True)
|
self.finishButton.setVisible(True)
|
||||||
self.finishButton.setEnabled(True)
|
self.finishButton.setEnabled(True)
|
||||||
self.cancelButton.setVisible(False)
|
self.cancelButton.setVisible(False)
|
||||||
|
@ -49,7 +49,7 @@ class Ui_FirstTimeWizard(object):
|
|||||||
FirstTimeWizard.resize(550, 386)
|
FirstTimeWizard.resize(550, 386)
|
||||||
FirstTimeWizard.setModal(True)
|
FirstTimeWizard.setModal(True)
|
||||||
FirstTimeWizard.setWizardStyle(QtGui.QWizard.ModernStyle)
|
FirstTimeWizard.setWizardStyle(QtGui.QWizard.ModernStyle)
|
||||||
FirstTimeWizard.setOptions(QtGui.QWizard.IndependentPages|
|
FirstTimeWizard.setOptions(QtGui.QWizard.IndependentPages |
|
||||||
QtGui.QWizard.NoBackButtonOnStartPage |
|
QtGui.QWizard.NoBackButtonOnStartPage |
|
||||||
QtGui.QWizard.NoBackButtonOnLastPage)
|
QtGui.QWizard.NoBackButtonOnLastPage)
|
||||||
self.finishButton = self.button(QtGui.QWizard.FinishButton)
|
self.finishButton = self.button(QtGui.QWizard.FinishButton)
|
||||||
@ -81,9 +81,9 @@ class Ui_FirstTimeWizard(object):
|
|||||||
self.pluginLayout.addWidget(self.imageCheckBox)
|
self.pluginLayout.addWidget(self.imageCheckBox)
|
||||||
self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage)
|
self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage)
|
||||||
if sys.platform == "darwin":
|
if sys.platform == "darwin":
|
||||||
self.presentationCheckBox.setChecked(False)
|
self.presentationCheckBox.setChecked(False)
|
||||||
else:
|
else:
|
||||||
self.presentationCheckBox.setChecked(True)
|
self.presentationCheckBox.setChecked(True)
|
||||||
self.presentationCheckBox.setObjectName(u'presentationCheckBox')
|
self.presentationCheckBox.setObjectName(u'presentationCheckBox')
|
||||||
self.pluginLayout.addWidget(self.presentationCheckBox)
|
self.pluginLayout.addWidget(self.presentationCheckBox)
|
||||||
self.mediaCheckBox = QtGui.QCheckBox(self.pluginPage)
|
self.mediaCheckBox = QtGui.QCheckBox(self.pluginPage)
|
||||||
@ -209,7 +209,7 @@ class Ui_FirstTimeWizard(object):
|
|||||||
'Select the Plugins you wish to use. '))
|
'Select the Plugins you wish to use. '))
|
||||||
self.songsCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Songs'))
|
self.songsCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Songs'))
|
||||||
self.customCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
self.customCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
||||||
'Custom Text'))
|
'Custom Slides'))
|
||||||
self.bibleCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Bible'))
|
self.bibleCheckBox.setText(translate('OpenLP.FirstTimeWizard', 'Bible'))
|
||||||
self.imageCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
self.imageCheckBox.setText(translate('OpenLP.FirstTimeWizard',
|
||||||
'Images'))
|
'Images'))
|
||||||
|
@ -28,17 +28,17 @@
|
|||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
from openlp.core.lib import translate
|
from openlp.core.lib import translate
|
||||||
from openlp.core.lib.ui import UiStrings, create_accept_reject_button_box
|
from openlp.core.lib.ui import UiStrings
|
||||||
|
|
||||||
class Ui_DisplayTagDialog(object):
|
class Ui_FormattingTagDialog(object):
|
||||||
|
|
||||||
def setupUi(self, displayTagDialog):
|
def setupUi(self, formattingTagDialog):
|
||||||
displayTagDialog.setObjectName(u'displayTagDialog')
|
formattingTagDialog.setObjectName(u'formattingTagDialog')
|
||||||
displayTagDialog.resize(725, 548)
|
formattingTagDialog.resize(725, 548)
|
||||||
self.listdataGridLayout = QtGui.QGridLayout(displayTagDialog)
|
self.listdataGridLayout = QtGui.QGridLayout(formattingTagDialog)
|
||||||
self.listdataGridLayout.setMargin(8)
|
self.listdataGridLayout.setMargin(8)
|
||||||
self.listdataGridLayout.setObjectName(u'listdataGridLayout')
|
self.listdataGridLayout.setObjectName(u'listdataGridLayout')
|
||||||
self.tagTableWidget = QtGui.QTableWidget(displayTagDialog)
|
self.tagTableWidget = QtGui.QTableWidget(formattingTagDialog)
|
||||||
self.tagTableWidget.setHorizontalScrollBarPolicy(
|
self.tagTableWidget.setHorizontalScrollBarPolicy(
|
||||||
QtCore.Qt.ScrollBarAlwaysOff)
|
QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
self.tagTableWidget.setEditTriggers(
|
self.tagTableWidget.setEditTriggers(
|
||||||
@ -67,11 +67,11 @@ class Ui_DisplayTagDialog(object):
|
|||||||
spacerItem = QtGui.QSpacerItem(40, 20,
|
spacerItem = QtGui.QSpacerItem(40, 20,
|
||||||
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||||
self.horizontalLayout.addItem(spacerItem)
|
self.horizontalLayout.addItem(spacerItem)
|
||||||
self.deletePushButton = QtGui.QPushButton(displayTagDialog)
|
self.deletePushButton = QtGui.QPushButton(formattingTagDialog)
|
||||||
self.deletePushButton.setObjectName(u'deletePushButton')
|
self.deletePushButton.setObjectName(u'deletePushButton')
|
||||||
self.horizontalLayout.addWidget(self.deletePushButton)
|
self.horizontalLayout.addWidget(self.deletePushButton)
|
||||||
self.listdataGridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1)
|
self.listdataGridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1)
|
||||||
self.editGroupBox = QtGui.QGroupBox(displayTagDialog)
|
self.editGroupBox = QtGui.QGroupBox(formattingTagDialog)
|
||||||
self.editGroupBox.setObjectName(u'editGroupBox')
|
self.editGroupBox.setObjectName(u'editGroupBox')
|
||||||
self.dataGridLayout = QtGui.QGridLayout(self.editGroupBox)
|
self.dataGridLayout = QtGui.QGridLayout(self.editGroupBox)
|
||||||
self.dataGridLayout.setObjectName(u'dataGridLayout')
|
self.dataGridLayout.setObjectName(u'dataGridLayout')
|
||||||
@ -112,38 +112,38 @@ class Ui_DisplayTagDialog(object):
|
|||||||
self.savePushButton.setObjectName(u'savePushButton')
|
self.savePushButton.setObjectName(u'savePushButton')
|
||||||
self.dataGridLayout.addWidget(self.savePushButton, 4, 2, 1, 1)
|
self.dataGridLayout.addWidget(self.savePushButton, 4, 2, 1, 1)
|
||||||
self.listdataGridLayout.addWidget(self.editGroupBox, 2, 0, 1, 1)
|
self.listdataGridLayout.addWidget(self.editGroupBox, 2, 0, 1, 1)
|
||||||
self.buttonBox = QtGui.QDialogButtonBox(displayTagDialog)
|
self.buttonBox = QtGui.QDialogButtonBox(formattingTagDialog)
|
||||||
self.buttonBox.setObjectName('displayTagDialogButtonBox')
|
self.buttonBox.setObjectName('formattingTagDialogButtonBox')
|
||||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Close)
|
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Close)
|
||||||
self.listdataGridLayout.addWidget(self.buttonBox, 3, 0, 1, 1)
|
self.listdataGridLayout.addWidget(self.buttonBox, 3, 0, 1, 1)
|
||||||
|
|
||||||
self.retranslateUi(displayTagDialog)
|
self.retranslateUi(formattingTagDialog)
|
||||||
QtCore.QMetaObject.connectSlotsByName(displayTagDialog)
|
QtCore.QMetaObject.connectSlotsByName(formattingTagDialog)
|
||||||
|
|
||||||
def retranslateUi(self, displayTagDialog):
|
def retranslateUi(self, formattingTagDialog):
|
||||||
displayTagDialog.setWindowTitle(translate('OpenLP.displayTagDialog',
|
formattingTagDialog.setWindowTitle(translate(
|
||||||
'Configure Display Tags'))
|
'OpenLP.FormattingTagDialog', 'Configure Formatting Tags'))
|
||||||
self.editGroupBox.setTitle(
|
self.editGroupBox.setTitle(
|
||||||
translate('OpenLP.DisplayTagDialog', 'Edit Selection'))
|
translate('OpenLP.FormattingTagDialog', 'Edit Selection'))
|
||||||
self.savePushButton.setText(
|
self.savePushButton.setText(
|
||||||
translate('OpenLP.DisplayTagDialog', 'Save'))
|
translate('OpenLP.FormattingTagDialog', 'Save'))
|
||||||
self.descriptionLabel.setText(
|
self.descriptionLabel.setText(
|
||||||
translate('OpenLP.DisplayTagDialog', 'Description'))
|
translate('OpenLP.FormattingTagDialog', 'Description'))
|
||||||
self.tagLabel.setText(translate('OpenLP.DisplayTagDialog', 'Tag'))
|
self.tagLabel.setText(translate('OpenLP.FormattingTagDialog', 'Tag'))
|
||||||
self.startTagLabel.setText(
|
self.startTagLabel.setText(
|
||||||
translate('OpenLP.DisplayTagDialog', 'Start tag'))
|
translate('OpenLP.FormattingTagDialog', 'Start tag'))
|
||||||
self.endTagLabel.setText(
|
self.endTagLabel.setText(
|
||||||
translate('OpenLP.DisplayTagDialog', 'End tag'))
|
translate('OpenLP.FormattingTagDialog', 'End tag'))
|
||||||
self.deletePushButton.setText(UiStrings().Delete)
|
self.deletePushButton.setText(UiStrings().Delete)
|
||||||
self.newPushButton.setText(UiStrings().New)
|
self.newPushButton.setText(UiStrings().New)
|
||||||
self.tagTableWidget.horizontalHeaderItem(0).setText(
|
self.tagTableWidget.horizontalHeaderItem(0).setText(
|
||||||
translate('OpenLP.DisplayTagDialog', 'Description'))
|
translate('OpenLP.FormattingTagDialog', 'Description'))
|
||||||
self.tagTableWidget.horizontalHeaderItem(1).setText(
|
self.tagTableWidget.horizontalHeaderItem(1).setText(
|
||||||
translate('OpenLP.DisplayTagDialog', 'Tag Id'))
|
translate('OpenLP.FormattingTagDialog', 'Tag Id'))
|
||||||
self.tagTableWidget.horizontalHeaderItem(2).setText(
|
self.tagTableWidget.horizontalHeaderItem(2).setText(
|
||||||
translate('OpenLP.DisplayTagDialog', 'Start HTML'))
|
translate('OpenLP.FormattingTagDialog', 'Start HTML'))
|
||||||
self.tagTableWidget.horizontalHeaderItem(3).setText(
|
self.tagTableWidget.horizontalHeaderItem(3).setText(
|
||||||
translate('OpenLP.DisplayTagDialog', 'End HTML'))
|
translate('OpenLP.FormattingTagDialog', 'End HTML'))
|
||||||
self.tagTableWidget.setColumnWidth(0, 120)
|
self.tagTableWidget.setColumnWidth(0, 120)
|
||||||
self.tagTableWidget.setColumnWidth(1, 80)
|
self.tagTableWidget.setColumnWidth(1, 80)
|
||||||
self.tagTableWidget.setColumnWidth(2, 330)
|
self.tagTableWidget.setColumnWidth(2, 330)
|
@ -25,22 +25,22 @@
|
|||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
"""
|
"""
|
||||||
The :mod:`DisplayTagTab` provides an Tag Edit facility. The Base set are
|
The :mod:`formattingtagform` provides an Tag Edit facility. The Base set are
|
||||||
protected and included each time loaded. Custom tags can be defined and saved.
|
protected and included each time loaded. Custom tags can be defined and saved.
|
||||||
The Custom Tag arrays are saved in a pickle so QSettings works on them. Base
|
The Custom Tag arrays are saved in a pickle so QSettings works on them. Base
|
||||||
Tags cannot be changed.
|
Tags cannot be changed.
|
||||||
"""
|
"""
|
||||||
import cPickle
|
import cPickle
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
from openlp.core.lib import translate, DisplayTags
|
from openlp.core.lib import translate, FormattingTags
|
||||||
from openlp.core.lib.ui import critical_error_message_box
|
from openlp.core.lib.ui import critical_error_message_box
|
||||||
from openlp.core.ui.displaytagdialog import Ui_DisplayTagDialog
|
from openlp.core.ui.formattingtagdialog import Ui_FormattingTagDialog
|
||||||
|
|
||||||
class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
|
class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog):
|
||||||
"""
|
"""
|
||||||
The :class:`DisplayTagTab` manages the settings tab .
|
The :class:`FormattingTagForm` manages the settings tab .
|
||||||
"""
|
"""
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
"""
|
"""
|
||||||
@ -48,7 +48,7 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
|
|||||||
"""
|
"""
|
||||||
QtGui.QDialog.__init__(self, parent)
|
QtGui.QDialog.__init__(self, parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self._loadDisplayTags()
|
self._loadFormattingTags()
|
||||||
QtCore.QObject.connect(self.tagTableWidget,
|
QtCore.QObject.connect(self.tagTableWidget,
|
||||||
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onRowSelected)
|
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onRowSelected)
|
||||||
QtCore.QObject.connect(self.newPushButton,
|
QtCore.QObject.connect(self.newPushButton,
|
||||||
@ -65,19 +65,20 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
|
|||||||
Load Display and set field state.
|
Load Display and set field state.
|
||||||
"""
|
"""
|
||||||
# Create initial copy from master
|
# Create initial copy from master
|
||||||
self._loadDisplayTags()
|
self._loadFormattingTags()
|
||||||
self._resetTable()
|
self._resetTable()
|
||||||
self.selected = -1
|
self.selected = -1
|
||||||
return QtGui.QDialog.exec_(self)
|
return QtGui.QDialog.exec_(self)
|
||||||
|
|
||||||
def _loadDisplayTags(self):
|
def _loadFormattingTags(self):
|
||||||
"""
|
"""
|
||||||
Load the Tags from store so can be used in the system or used to
|
Load the Tags from store so can be used in the system or used to
|
||||||
update the display. If Cancel was selected this is needed to reset the
|
update the display. If Cancel was selected this is needed to reset the
|
||||||
dsiplay to the correct version.
|
dsiplay to the correct version.
|
||||||
"""
|
"""
|
||||||
# Initial Load of the Tags
|
# Initial Load of the Tags
|
||||||
DisplayTags.reset_html_tags()
|
FormattingTags.reset_html_tags()
|
||||||
|
# Formatting Tags were also known as display tags.
|
||||||
user_expands = QtCore.QSettings().value(u'displayTags/html_tags',
|
user_expands = QtCore.QSettings().value(u'displayTags/html_tags',
|
||||||
QtCore.QVariant(u'')).toString()
|
QtCore.QVariant(u'')).toString()
|
||||||
# cPickle only accepts str not unicode strings
|
# cPickle only accepts str not unicode strings
|
||||||
@ -85,14 +86,14 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
|
|||||||
if user_expands_string:
|
if user_expands_string:
|
||||||
user_tags = cPickle.loads(user_expands_string)
|
user_tags = cPickle.loads(user_expands_string)
|
||||||
# If we have some user ones added them as well
|
# If we have some user ones added them as well
|
||||||
DisplayTags.add_html_tags(user_tags)
|
FormattingTags.add_html_tags(user_tags)
|
||||||
|
|
||||||
def onRowSelected(self):
|
def onRowSelected(self):
|
||||||
"""
|
"""
|
||||||
Table Row selected so display items and set field state.
|
Table Row selected so display items and set field state.
|
||||||
"""
|
"""
|
||||||
row = self.tagTableWidget.currentRow()
|
row = self.tagTableWidget.currentRow()
|
||||||
html = DisplayTags.get_html_tags()[row]
|
html = FormattingTags.get_html_tags()[row]
|
||||||
self.selected = row
|
self.selected = row
|
||||||
self.descriptionLineEdit.setText(html[u'desc'])
|
self.descriptionLineEdit.setText(html[u'desc'])
|
||||||
self.tagLineEdit.setText(self._strip(html[u'start tag']))
|
self.tagLineEdit.setText(self._strip(html[u'start tag']))
|
||||||
@ -117,23 +118,23 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
|
|||||||
"""
|
"""
|
||||||
Add a new tag to list only if it is not a duplicate.
|
Add a new tag to list only if it is not a duplicate.
|
||||||
"""
|
"""
|
||||||
for html in DisplayTags.get_html_tags():
|
for html in FormattingTags.get_html_tags():
|
||||||
if self._strip(html[u'start tag']) == u'n':
|
if self._strip(html[u'start tag']) == u'n':
|
||||||
critical_error_message_box(
|
critical_error_message_box(
|
||||||
translate('OpenLP.DisplayTagTab', 'Update Error'),
|
translate('OpenLP.FormattingTagForm', 'Update Error'),
|
||||||
translate('OpenLP.DisplayTagTab',
|
translate('OpenLP.FormattingTagForm',
|
||||||
'Tag "n" already defined.'))
|
'Tag "n" already defined.'))
|
||||||
return
|
return
|
||||||
# Add new tag to list
|
# Add new tag to list
|
||||||
tag = {
|
tag = {
|
||||||
u'desc': translate('OpenLP.DisplayTagTab', 'New Tag'),
|
u'desc': translate('OpenLP.FormattingTagForm', 'New Tag'),
|
||||||
u'start tag': u'{n}',
|
u'start tag': u'{n}',
|
||||||
u'start html': translate('OpenLP.DisplayTagTab', '<HTML here>'),
|
u'start html': translate('OpenLP.FormattingTagForm', '<HTML here>'),
|
||||||
u'end tag': u'{/n}',
|
u'end tag': u'{/n}',
|
||||||
u'end html': translate('OpenLP.DisplayTagTab', '</and here>'),
|
u'end html': translate('OpenLP.FormattingTagForm', '</and here>'),
|
||||||
u'protected': False
|
u'protected': False
|
||||||
}
|
}
|
||||||
DisplayTags.add_html_tags([tag])
|
FormattingTags.add_html_tags([tag])
|
||||||
self._resetTable()
|
self._resetTable()
|
||||||
# Highlight new row
|
# Highlight new row
|
||||||
self.tagTableWidget.selectRow(self.tagTableWidget.rowCount() - 1)
|
self.tagTableWidget.selectRow(self.tagTableWidget.rowCount() - 1)
|
||||||
@ -145,7 +146,7 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
|
|||||||
Delete selected custom tag.
|
Delete selected custom tag.
|
||||||
"""
|
"""
|
||||||
if self.selected != -1:
|
if self.selected != -1:
|
||||||
DisplayTags.remove_html_tag(self.selected)
|
FormattingTags.remove_html_tag(self.selected)
|
||||||
self.selected = -1
|
self.selected = -1
|
||||||
self._resetTable()
|
self._resetTable()
|
||||||
self._saveTable()
|
self._saveTable()
|
||||||
@ -154,7 +155,7 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
|
|||||||
"""
|
"""
|
||||||
Update Custom Tag details if not duplicate and save the data.
|
Update Custom Tag details if not duplicate and save the data.
|
||||||
"""
|
"""
|
||||||
html_expands = DisplayTags.get_html_tags()
|
html_expands = FormattingTags.get_html_tags()
|
||||||
if self.selected != -1:
|
if self.selected != -1:
|
||||||
html = html_expands[self.selected]
|
html = html_expands[self.selected]
|
||||||
tag = unicode(self.tagLineEdit.text())
|
tag = unicode(self.tagLineEdit.text())
|
||||||
@ -162,8 +163,8 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
|
|||||||
if self._strip(html1[u'start tag']) == tag and \
|
if self._strip(html1[u'start tag']) == tag and \
|
||||||
linenumber != self.selected:
|
linenumber != self.selected:
|
||||||
critical_error_message_box(
|
critical_error_message_box(
|
||||||
translate('OpenLP.DisplayTagTab', 'Update Error'),
|
translate('OpenLP.FormattingTagForm', 'Update Error'),
|
||||||
unicode(translate('OpenLP.DisplayTagTab',
|
unicode(translate('OpenLP.FormattingTagForm',
|
||||||
'Tag %s already defined.')) % tag)
|
'Tag %s already defined.')) % tag)
|
||||||
return
|
return
|
||||||
html[u'desc'] = unicode(self.descriptionLineEdit.text())
|
html[u'desc'] = unicode(self.descriptionLineEdit.text())
|
||||||
@ -177,18 +178,15 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
|
|||||||
|
|
||||||
def _saveTable(self):
|
def _saveTable(self):
|
||||||
"""
|
"""
|
||||||
Saves all display tags except protected ones.
|
Saves all formatting tags except protected ones.
|
||||||
"""
|
"""
|
||||||
tags = []
|
tags = []
|
||||||
for tag in DisplayTags.get_html_tags():
|
for tag in FormattingTags.get_html_tags():
|
||||||
if not tag[u'protected']:
|
if not tag[u'protected']:
|
||||||
tags.append(tag)
|
tags.append(tag)
|
||||||
if tags:
|
# Formatting Tags were also known as display tags.
|
||||||
QtCore.QSettings().setValue(u'displayTags/html_tags',
|
QtCore.QSettings().setValue(u'displayTags/html_tags',
|
||||||
QtCore.QVariant(cPickle.dumps(tags)))
|
QtCore.QVariant(cPickle.dumps(tags) if tags else u''))
|
||||||
else:
|
|
||||||
QtCore.QSettings().setValue(u'displayTags/html_tags',
|
|
||||||
QtCore.QVariant(u''))
|
|
||||||
|
|
||||||
def _resetTable(self):
|
def _resetTable(self):
|
||||||
"""
|
"""
|
||||||
@ -199,7 +197,7 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
|
|||||||
self.newPushButton.setEnabled(True)
|
self.newPushButton.setEnabled(True)
|
||||||
self.savePushButton.setEnabled(False)
|
self.savePushButton.setEnabled(False)
|
||||||
self.deletePushButton.setEnabled(False)
|
self.deletePushButton.setEnabled(False)
|
||||||
for linenumber, html in enumerate(DisplayTags.get_html_tags()):
|
for linenumber, html in enumerate(FormattingTags.get_html_tags()):
|
||||||
self.tagTableWidget.setRowCount(
|
self.tagTableWidget.setRowCount(
|
||||||
self.tagTableWidget.rowCount() + 1)
|
self.tagTableWidget.rowCount() + 1)
|
||||||
self.tagTableWidget.setItem(linenumber, 0,
|
self.tagTableWidget.setItem(linenumber, 0,
|
@ -44,7 +44,7 @@ class GeneralTab(SettingsTab):
|
|||||||
"""
|
"""
|
||||||
self.screens = ScreenList.get_instance()
|
self.screens = ScreenList.get_instance()
|
||||||
self.icon_path = u':/icon/openlp-logo-16x16.png'
|
self.icon_path = u':/icon/openlp-logo-16x16.png'
|
||||||
generalTranslated = translate('GeneralTab', 'General')
|
generalTranslated = translate('OpenLP.GeneralTab', 'General')
|
||||||
SettingsTab.__init__(self, parent, u'General', generalTranslated)
|
SettingsTab.__init__(self, parent, u'General', generalTranslated)
|
||||||
|
|
||||||
def setupUi(self):
|
def setupUi(self):
|
||||||
|
@ -48,13 +48,13 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
"""
|
"""
|
||||||
This is the display screen.
|
This is the display screen.
|
||||||
"""
|
"""
|
||||||
def __init__(self, parent, image_manager, live):
|
def __init__(self, parent, imageManager, live):
|
||||||
if live:
|
if live:
|
||||||
QtGui.QGraphicsView.__init__(self)
|
QtGui.QGraphicsView.__init__(self)
|
||||||
else:
|
else:
|
||||||
QtGui.QGraphicsView.__init__(self, parent)
|
QtGui.QGraphicsView.__init__(self, parent)
|
||||||
self.isLive = live
|
self.isLive = live
|
||||||
self.image_manager = image_manager
|
self.imageManager = imageManager
|
||||||
self.screens = ScreenList.get_instance()
|
self.screens = ScreenList.get_instance()
|
||||||
self.alertTab = None
|
self.alertTab = None
|
||||||
self.hideMode = None
|
self.hideMode = None
|
||||||
@ -188,7 +188,7 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
while not self.webLoaded:
|
while not self.webLoaded:
|
||||||
Receiver.send_message(u'openlp_process_events')
|
Receiver.send_message(u'openlp_process_events')
|
||||||
self.setGeometry(self.screen[u'size'])
|
self.setGeometry(self.screen[u'size'])
|
||||||
self.frame.evaluateJavaScript(u'show_text("%s")' % \
|
self.frame.evaluateJavaScript(u'show_text("%s")' %
|
||||||
slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
|
slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
|
||||||
return self.preview()
|
return self.preview()
|
||||||
|
|
||||||
@ -232,11 +232,13 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
"""
|
"""
|
||||||
API for replacement backgrounds so Images are added directly to cache
|
API for replacement backgrounds so Images are added directly to cache
|
||||||
"""
|
"""
|
||||||
self.image_manager.add_image(name, path)
|
self.imageManager.add_image(name, path)
|
||||||
self.image(name)
|
|
||||||
if hasattr(self, u'serviceItem'):
|
if hasattr(self, u'serviceItem'):
|
||||||
self.override[u'image'] = name
|
self.override[u'image'] = name
|
||||||
self.override[u'theme'] = self.serviceItem.themedata.theme_name
|
self.override[u'theme'] = self.serviceItem.themedata.theme_name
|
||||||
|
self.image(name)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def image(self, name):
|
def image(self, name):
|
||||||
"""
|
"""
|
||||||
@ -247,7 +249,7 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
The name of the image to be displayed
|
The name of the image to be displayed
|
||||||
"""
|
"""
|
||||||
log.debug(u'image to display')
|
log.debug(u'image to display')
|
||||||
image = self.image_manager.get_image_bytes(name)
|
image = self.imageManager.get_image_bytes(name)
|
||||||
self.resetVideo()
|
self.resetVideo()
|
||||||
self.displayImage(image)
|
self.displayImage(image)
|
||||||
return self.preview()
|
return self.preview()
|
||||||
@ -349,6 +351,9 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
"""
|
"""
|
||||||
Loads and starts a video to run with the option of sound
|
Loads and starts a video to run with the option of sound
|
||||||
"""
|
"""
|
||||||
|
# We request a background video but have no service Item
|
||||||
|
if isBackground and not hasattr(self, u'serviceItem'):
|
||||||
|
return None
|
||||||
if not self.mediaObject:
|
if not self.mediaObject:
|
||||||
self.createMediaObject()
|
self.createMediaObject()
|
||||||
log.debug(u'video')
|
log.debug(u'video')
|
||||||
@ -477,13 +482,13 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
self.override = {}
|
self.override = {}
|
||||||
else:
|
else:
|
||||||
# replace the background
|
# replace the background
|
||||||
background = self.image_manager. \
|
background = self.imageManager. \
|
||||||
get_image_bytes(self.override[u'image'])
|
get_image_bytes(self.override[u'image'])
|
||||||
if self.serviceItem.themedata.background_filename:
|
if self.serviceItem.themedata.background_filename:
|
||||||
self.serviceItem.bg_image_bytes = self.image_manager. \
|
self.serviceItem.bg_image_bytes = self.imageManager. \
|
||||||
get_image_bytes(self.serviceItem.themedata.theme_name)
|
get_image_bytes(self.serviceItem.themedata.theme_name)
|
||||||
if image:
|
if image:
|
||||||
image_bytes = self.image_manager.get_image_bytes(image)
|
image_bytes = self.imageManager.get_image_bytes(image)
|
||||||
else:
|
else:
|
||||||
image_bytes = None
|
image_bytes = None
|
||||||
html = build_html(self.serviceItem, self.screen, self.alertTab,
|
html = build_html(self.serviceItem, self.screen, self.alertTab,
|
||||||
|
@ -28,20 +28,23 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import shutil
|
||||||
from tempfile import gettempdir
|
from tempfile import gettempdir
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \
|
from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \
|
||||||
PluginManager, Receiver, translate, ImageManager
|
PluginManager, Receiver, translate, ImageManager, PluginStatus
|
||||||
from openlp.core.lib.ui import UiStrings, base_action, checkable_action, \
|
from openlp.core.lib.ui import UiStrings, base_action, checkable_action, \
|
||||||
icon_action, shortcut_action
|
icon_action, shortcut_action
|
||||||
from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \
|
from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \
|
||||||
ThemeManager, SlideController, PluginForm, MediaDockManager, \
|
ThemeManager, SlideController, PluginForm, MediaDockManager, \
|
||||||
ShortcutListForm, DisplayTagForm
|
ShortcutListForm, FormattingTagForm
|
||||||
from openlp.core.utils import AppLocation, add_actions, LanguageManager, \
|
from openlp.core.utils import AppLocation, add_actions, LanguageManager, \
|
||||||
get_application_version, delete_file
|
get_application_version, delete_file
|
||||||
from openlp.core.utils.actions import ActionList, CategoryOrder
|
from openlp.core.utils.actions import ActionList, CategoryOrder
|
||||||
|
from openlp.core.ui.firsttimeform import FirstTimeForm
|
||||||
|
from openlp.core.ui import ScreenList
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -65,6 +68,12 @@ MEDIA_MANAGER_STYLE = """
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
PROGRESSBAR_STYLE = """
|
||||||
|
QProgressBar{
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
class Ui_MainWindow(object):
|
class Ui_MainWindow(object):
|
||||||
def setupUi(self, mainWindow):
|
def setupUi(self, mainWindow):
|
||||||
"""
|
"""
|
||||||
@ -93,12 +102,16 @@ class Ui_MainWindow(object):
|
|||||||
self.previewController.panel.setVisible(previewVisible)
|
self.previewController.panel.setVisible(previewVisible)
|
||||||
liveVisible = QtCore.QSettings().value(u'user interface/live panel',
|
liveVisible = QtCore.QSettings().value(u'user interface/live panel',
|
||||||
QtCore.QVariant(True)).toBool()
|
QtCore.QVariant(True)).toBool()
|
||||||
|
panelLocked = QtCore.QSettings().value(u'user interface/lock panel',
|
||||||
|
QtCore.QVariant(False)).toBool()
|
||||||
self.liveController.panel.setVisible(liveVisible)
|
self.liveController.panel.setVisible(liveVisible)
|
||||||
# Create menu
|
# Create menu
|
||||||
self.menuBar = QtGui.QMenuBar(mainWindow)
|
self.menuBar = QtGui.QMenuBar(mainWindow)
|
||||||
self.menuBar.setObjectName(u'menuBar')
|
self.menuBar.setObjectName(u'menuBar')
|
||||||
self.fileMenu = QtGui.QMenu(self.menuBar)
|
self.fileMenu = QtGui.QMenu(self.menuBar)
|
||||||
self.fileMenu.setObjectName(u'fileMenu')
|
self.fileMenu.setObjectName(u'fileMenu')
|
||||||
|
self.recentFilesMenu = QtGui.QMenu(self.fileMenu)
|
||||||
|
self.recentFilesMenu.setObjectName(u'recentFilesMenu')
|
||||||
self.fileImportMenu = QtGui.QMenu(self.fileMenu)
|
self.fileImportMenu = QtGui.QMenu(self.fileMenu)
|
||||||
self.fileImportMenu.setObjectName(u'fileImportMenu')
|
self.fileImportMenu.setObjectName(u'fileImportMenu')
|
||||||
self.fileExportMenu = QtGui.QMenu(self.fileMenu)
|
self.fileExportMenu = QtGui.QMenu(self.fileMenu)
|
||||||
@ -128,6 +141,7 @@ class Ui_MainWindow(object):
|
|||||||
self.statusBar.addPermanentWidget(self.loadProgressBar)
|
self.statusBar.addPermanentWidget(self.loadProgressBar)
|
||||||
self.loadProgressBar.hide()
|
self.loadProgressBar.hide()
|
||||||
self.loadProgressBar.setValue(0)
|
self.loadProgressBar.setValue(0)
|
||||||
|
self.loadProgressBar.setStyleSheet(PROGRESSBAR_STYLE)
|
||||||
self.defaultThemeLabel = QtGui.QLabel(self.statusBar)
|
self.defaultThemeLabel = QtGui.QLabel(self.statusBar)
|
||||||
self.defaultThemeLabel.setObjectName(u'defaultThemeLabel')
|
self.defaultThemeLabel.setObjectName(u'defaultThemeLabel')
|
||||||
self.statusBar.addPermanentWidget(self.defaultThemeLabel)
|
self.statusBar.addPermanentWidget(self.defaultThemeLabel)
|
||||||
@ -213,7 +227,11 @@ class Ui_MainWindow(object):
|
|||||||
self.viewLivePanel = shortcut_action(mainWindow, u'viewLivePanel',
|
self.viewLivePanel = shortcut_action(mainWindow, u'viewLivePanel',
|
||||||
[QtGui.QKeySequence(u'F12')], self.setLivePanelVisibility,
|
[QtGui.QKeySequence(u'F12')], self.setLivePanelVisibility,
|
||||||
checked=liveVisible, category=UiStrings().View)
|
checked=liveVisible, category=UiStrings().View)
|
||||||
action_list.add_category(UiStrings().ViewMode, CategoryOrder.standardMenu)
|
self.lockPanel = shortcut_action(mainWindow, u'lockPanel',
|
||||||
|
None, self.setLockPanel,
|
||||||
|
checked=panelLocked, category=None)
|
||||||
|
action_list.add_category(UiStrings().ViewMode,
|
||||||
|
CategoryOrder.standardMenu)
|
||||||
self.modeDefaultItem = checkable_action(
|
self.modeDefaultItem = checkable_action(
|
||||||
mainWindow, u'modeDefaultItem', category=UiStrings().ViewMode)
|
mainWindow, u'modeDefaultItem', category=UiStrings().ViewMode)
|
||||||
self.modeSetupItem = checkable_action(
|
self.modeSetupItem = checkable_action(
|
||||||
@ -231,9 +249,13 @@ class Ui_MainWindow(object):
|
|||||||
self.toolsOpenDataFolder = icon_action(mainWindow,
|
self.toolsOpenDataFolder = icon_action(mainWindow,
|
||||||
u'toolsOpenDataFolder', u':/general/general_open.png',
|
u'toolsOpenDataFolder', u':/general/general_open.png',
|
||||||
category=UiStrings().Tools)
|
category=UiStrings().Tools)
|
||||||
|
self.toolsFirstTimeWizard = icon_action(mainWindow,
|
||||||
|
u'toolsFirstTimeWizard', u':/general/general_revert.png',
|
||||||
|
category=UiStrings().Tools)
|
||||||
self.updateThemeImages = base_action(mainWindow,
|
self.updateThemeImages = base_action(mainWindow,
|
||||||
u'updateThemeImages', category=UiStrings().Tools)
|
u'updateThemeImages', category=UiStrings().Tools)
|
||||||
action_list.add_category(UiStrings().Settings, CategoryOrder.standardMenu)
|
action_list.add_category(UiStrings().Settings,
|
||||||
|
CategoryOrder.standardMenu)
|
||||||
self.settingsPluginListItem = shortcut_action(mainWindow,
|
self.settingsPluginListItem = shortcut_action(mainWindow,
|
||||||
u'settingsPluginListItem', [QtGui.QKeySequence(u'Alt+F7')],
|
u'settingsPluginListItem', [QtGui.QKeySequence(u'Alt+F7')],
|
||||||
self.onPluginItemClicked, u':/system/settings_plugin_list.png',
|
self.onPluginItemClicked, u':/system/settings_plugin_list.png',
|
||||||
@ -255,40 +277,45 @@ class Ui_MainWindow(object):
|
|||||||
u'settingsShortcutsItem',
|
u'settingsShortcutsItem',
|
||||||
u':/system/system_configure_shortcuts.png',
|
u':/system/system_configure_shortcuts.png',
|
||||||
category=UiStrings().Settings)
|
category=UiStrings().Settings)
|
||||||
self.displayTagItem = icon_action(mainWindow,
|
# Formatting Tags were also known as display tags.
|
||||||
|
self.formattingTagItem = icon_action(mainWindow,
|
||||||
u'displayTagItem', u':/system/tag_editor.png',
|
u'displayTagItem', u':/system/tag_editor.png',
|
||||||
category=UiStrings().Settings)
|
category=UiStrings().Settings)
|
||||||
self.settingsConfigureItem = icon_action(mainWindow,
|
self.settingsConfigureItem = icon_action(mainWindow,
|
||||||
u'settingsConfigureItem', u':/system/system_settings.png',
|
u'settingsConfigureItem', u':/system/system_settings.png',
|
||||||
category=UiStrings().Settings)
|
category=UiStrings().Settings)
|
||||||
action_list.add_category(UiStrings().Help, CategoryOrder.standardMenu)
|
action_list.add_category(UiStrings().Help, CategoryOrder.standardMenu)
|
||||||
self.helpDocumentationItem = icon_action(mainWindow,
|
self.aboutItem = shortcut_action(mainWindow, u'aboutItem',
|
||||||
u'helpDocumentationItem', u':/system/system_help_contents.png',
|
[QtGui.QKeySequence(u'Ctrl+F1')], self.onAboutItemClicked,
|
||||||
category=None)#UiStrings().Help)
|
|
||||||
self.helpDocumentationItem.setEnabled(False)
|
|
||||||
self.helpAboutItem = shortcut_action(mainWindow, u'helpAboutItem',
|
|
||||||
[QtGui.QKeySequence(u'Ctrl+F1')], self.onHelpAboutItemClicked,
|
|
||||||
u':/system/system_about.png', category=UiStrings().Help)
|
u':/system/system_about.png', category=UiStrings().Help)
|
||||||
self.helpOnlineHelpItem = shortcut_action(
|
if os.name == u'nt':
|
||||||
mainWindow, u'helpOnlineHelpItem', [QtGui.QKeySequence(u'F1')],
|
self.localHelpFile = os.path.join(
|
||||||
self.onHelpOnlineHelpClicked, u':/system/system_online_help.png',
|
AppLocation.get_directory(AppLocation.AppDir), 'OpenLP.chm')
|
||||||
category=UiStrings().Help)
|
self.offlineHelpItem = shortcut_action(
|
||||||
self.helpWebSiteItem = base_action(
|
mainWindow, u'offlineHelpItem', [QtGui.QKeySequence(u'F1')],
|
||||||
mainWindow, u'helpWebSiteItem', category=UiStrings().Help)
|
self.onOfflineHelpClicked,
|
||||||
|
u':/system/system_help_contents.png', category=UiStrings().Help)
|
||||||
|
self.onlineHelpItem = shortcut_action(
|
||||||
|
mainWindow, u'onlineHelpItem',
|
||||||
|
[QtGui.QKeySequence(u'Alt+F1')], self.onOnlineHelpClicked,
|
||||||
|
u':/system/system_online_help.png', category=UiStrings().Help)
|
||||||
|
self.webSiteItem = base_action(
|
||||||
|
mainWindow, u'webSiteItem', category=UiStrings().Help)
|
||||||
add_actions(self.fileImportMenu,
|
add_actions(self.fileImportMenu,
|
||||||
(self.importThemeItem, self.importLanguageItem))
|
(self.importThemeItem, self.importLanguageItem))
|
||||||
add_actions(self.fileExportMenu,
|
add_actions(self.fileExportMenu,
|
||||||
(self.exportThemeItem, self.exportLanguageItem))
|
(self.exportThemeItem, self.exportLanguageItem))
|
||||||
self.fileMenuActions = (self.fileNewItem, self.fileOpenItem,
|
add_actions(self.fileMenu, (self.fileNewItem, self.fileOpenItem,
|
||||||
self.fileSaveItem, self.fileSaveAsItem, None,
|
self.fileSaveItem, self.fileSaveAsItem,
|
||||||
self.printServiceOrderItem, None, self.fileImportMenu.menuAction(),
|
self.recentFilesMenu.menuAction(), None,
|
||||||
self.fileExportMenu.menuAction(), self.fileExitItem)
|
self.fileImportMenu.menuAction(), self.fileExportMenu.menuAction(),
|
||||||
|
None, self.printServiceOrderItem, self.fileExitItem))
|
||||||
add_actions(self.viewModeMenu, (self.modeDefaultItem,
|
add_actions(self.viewModeMenu, (self.modeDefaultItem,
|
||||||
self.modeSetupItem, self.modeLiveItem))
|
self.modeSetupItem, self.modeLiveItem))
|
||||||
add_actions(self.viewMenu, (self.viewModeMenu.menuAction(),
|
add_actions(self.viewMenu, (self.viewModeMenu.menuAction(),
|
||||||
None, self.viewMediaManagerItem, self.viewServiceManagerItem,
|
None, self.viewMediaManagerItem, self.viewServiceManagerItem,
|
||||||
self.viewThemeManagerItem, None, self.viewPreviewPanel,
|
self.viewThemeManagerItem, None, self.viewPreviewPanel,
|
||||||
self.viewLivePanel))
|
self.viewLivePanel, None, self.lockPanel))
|
||||||
# i18n add Language Actions
|
# i18n add Language Actions
|
||||||
add_actions(self.settingsLanguageMenu, (self.autoLanguageItem, None))
|
add_actions(self.settingsLanguageMenu, (self.autoLanguageItem, None))
|
||||||
add_actions(self.settingsLanguageMenu, self.languageGroup.actions())
|
add_actions(self.settingsLanguageMenu, self.languageGroup.actions())
|
||||||
@ -298,18 +325,23 @@ class Ui_MainWindow(object):
|
|||||||
add_actions(self.settingsMenu, (self.settingsPluginListItem,
|
add_actions(self.settingsMenu, (self.settingsPluginListItem,
|
||||||
self.settingsLanguageMenu.menuAction(), None,
|
self.settingsLanguageMenu.menuAction(), None,
|
||||||
self.settingsConfigureItem, self.settingsShortcutsItem,
|
self.settingsConfigureItem, self.settingsShortcutsItem,
|
||||||
self.displayTagItem))
|
self.formattingTagItem))
|
||||||
else:
|
else:
|
||||||
add_actions(self.settingsMenu, (self.settingsPluginListItem,
|
add_actions(self.settingsMenu, (self.settingsPluginListItem,
|
||||||
self.settingsLanguageMenu.menuAction(), None,
|
self.settingsLanguageMenu.menuAction(), None,
|
||||||
self.displayTagItem, self.settingsShortcutsItem,
|
self.formattingTagItem, self.settingsShortcutsItem,
|
||||||
self.settingsConfigureItem))
|
self.settingsConfigureItem))
|
||||||
add_actions(self.toolsMenu, (self.toolsAddToolItem, None))
|
add_actions(self.toolsMenu, (self.toolsAddToolItem, None))
|
||||||
add_actions(self.toolsMenu, (self.toolsOpenDataFolder, None))
|
add_actions(self.toolsMenu, (self.toolsOpenDataFolder, None))
|
||||||
|
add_actions(self.toolsMenu, (self.toolsFirstTimeWizard, None))
|
||||||
add_actions(self.toolsMenu, [self.updateThemeImages])
|
add_actions(self.toolsMenu, [self.updateThemeImages])
|
||||||
add_actions(self.helpMenu, (self.helpDocumentationItem,
|
if os.name == u'nt':
|
||||||
self.helpOnlineHelpItem, None, self.helpWebSiteItem,
|
add_actions(self.helpMenu, (self.offlineHelpItem,
|
||||||
self.helpAboutItem))
|
self.onlineHelpItem, None, self.webSiteItem,
|
||||||
|
self.aboutItem))
|
||||||
|
else:
|
||||||
|
add_actions(self.helpMenu, (self.onlineHelpItem, None,
|
||||||
|
self.webSiteItem, self.aboutItem))
|
||||||
add_actions(self.menuBar, (self.fileMenu.menuAction(),
|
add_actions(self.menuBar, (self.fileMenu.menuAction(),
|
||||||
self.viewMenu.menuAction(), self.toolsMenu.menuAction(),
|
self.viewMenu.menuAction(), self.toolsMenu.menuAction(),
|
||||||
self.settingsMenu.menuAction(), self.helpMenu.menuAction()))
|
self.settingsMenu.menuAction(), self.helpMenu.menuAction()))
|
||||||
@ -318,13 +350,13 @@ class Ui_MainWindow(object):
|
|||||||
self.mediaToolBox.setCurrentIndex(0)
|
self.mediaToolBox.setCurrentIndex(0)
|
||||||
# Connect up some signals and slots
|
# Connect up some signals and slots
|
||||||
QtCore.QObject.connect(self.fileMenu,
|
QtCore.QObject.connect(self.fileMenu,
|
||||||
QtCore.SIGNAL(u'aboutToShow()'), self.updateFileMenu)
|
QtCore.SIGNAL(u'aboutToShow()'), self.updateRecentFilesMenu)
|
||||||
QtCore.QMetaObject.connectSlotsByName(mainWindow)
|
QtCore.QMetaObject.connectSlotsByName(mainWindow)
|
||||||
# Hide the entry, as it does not have any functionality yet.
|
# Hide the entry, as it does not have any functionality yet.
|
||||||
self.toolsAddToolItem.setVisible(False)
|
self.toolsAddToolItem.setVisible(False)
|
||||||
self.importLanguageItem.setVisible(False)
|
self.importLanguageItem.setVisible(False)
|
||||||
self.exportLanguageItem.setVisible(False)
|
self.exportLanguageItem.setVisible(False)
|
||||||
self.helpDocumentationItem.setVisible(False)
|
self.setLockPanel(panelLocked)
|
||||||
|
|
||||||
def retranslateUi(self, mainWindow):
|
def retranslateUi(self, mainWindow):
|
||||||
"""
|
"""
|
||||||
@ -335,6 +367,8 @@ class Ui_MainWindow(object):
|
|||||||
self.fileMenu.setTitle(translate('OpenLP.MainWindow', '&File'))
|
self.fileMenu.setTitle(translate('OpenLP.MainWindow', '&File'))
|
||||||
self.fileImportMenu.setTitle(translate('OpenLP.MainWindow', '&Import'))
|
self.fileImportMenu.setTitle(translate('OpenLP.MainWindow', '&Import'))
|
||||||
self.fileExportMenu.setTitle(translate('OpenLP.MainWindow', '&Export'))
|
self.fileExportMenu.setTitle(translate('OpenLP.MainWindow', '&Export'))
|
||||||
|
self.recentFilesMenu.setTitle(
|
||||||
|
translate('OpenLP.MainWindow', '&Recent Files'))
|
||||||
self.viewMenu.setTitle(translate('OpenLP.MainWindow', '&View'))
|
self.viewMenu.setTitle(translate('OpenLP.MainWindow', '&View'))
|
||||||
self.viewModeMenu.setTitle(translate('OpenLP.MainWindow', 'M&ode'))
|
self.viewModeMenu.setTitle(translate('OpenLP.MainWindow', 'M&ode'))
|
||||||
self.toolsMenu.setTitle(translate('OpenLP.MainWindow', '&Tools'))
|
self.toolsMenu.setTitle(translate('OpenLP.MainWindow', '&Tools'))
|
||||||
@ -382,8 +416,8 @@ class Ui_MainWindow(object):
|
|||||||
translate('OpenLP.MainWindow', '&Language'))
|
translate('OpenLP.MainWindow', '&Language'))
|
||||||
self.settingsShortcutsItem.setText(
|
self.settingsShortcutsItem.setText(
|
||||||
translate('OpenLP.MainWindow', 'Configure &Shortcuts...'))
|
translate('OpenLP.MainWindow', 'Configure &Shortcuts...'))
|
||||||
self.displayTagItem.setText(
|
self.formattingTagItem.setText(
|
||||||
translate('OpenLP.MainWindow', '&Configure Display Tags'))
|
translate('OpenLP.MainWindow', '&Configure Formatting Tags...'))
|
||||||
self.settingsConfigureItem.setText(
|
self.settingsConfigureItem.setText(
|
||||||
translate('OpenLP.MainWindow', '&Configure OpenLP...'))
|
translate('OpenLP.MainWindow', '&Configure OpenLP...'))
|
||||||
self.viewMediaManagerItem.setText(
|
self.viewMediaManagerItem.setText(
|
||||||
@ -414,20 +448,25 @@ class Ui_MainWindow(object):
|
|||||||
translate('OpenLP.MainWindow', '&Live Panel'))
|
translate('OpenLP.MainWindow', '&Live Panel'))
|
||||||
self.viewLivePanel.setToolTip(
|
self.viewLivePanel.setToolTip(
|
||||||
translate('OpenLP.MainWindow', 'Toggle Live Panel'))
|
translate('OpenLP.MainWindow', 'Toggle Live Panel'))
|
||||||
|
self.lockPanel.setText(
|
||||||
|
translate('OpenLP.MainWindow', 'L&ock Panels'))
|
||||||
|
self.lockPanel.setStatusTip(
|
||||||
|
translate('OpenLP.MainWindow', 'Prevent the panels being moved.'))
|
||||||
self.viewLivePanel.setStatusTip(translate('OpenLP.MainWindow',
|
self.viewLivePanel.setStatusTip(translate('OpenLP.MainWindow',
|
||||||
'Toggle the visibility of the live panel.'))
|
'Toggle the visibility of the live panel.'))
|
||||||
self.settingsPluginListItem.setText(translate('OpenLP.MainWindow',
|
self.settingsPluginListItem.setText(translate('OpenLP.MainWindow',
|
||||||
'&Plugin List'))
|
'&Plugin List'))
|
||||||
self.settingsPluginListItem.setStatusTip(
|
self.settingsPluginListItem.setStatusTip(
|
||||||
translate('OpenLP.MainWindow', 'List the Plugins'))
|
translate('OpenLP.MainWindow', 'List the Plugins'))
|
||||||
self.helpDocumentationItem.setText(
|
self.aboutItem.setText(translate('OpenLP.MainWindow', '&About'))
|
||||||
translate('OpenLP.MainWindow', '&User Guide'))
|
self.aboutItem.setStatusTip(
|
||||||
self.helpAboutItem.setText(translate('OpenLP.MainWindow', '&About'))
|
|
||||||
self.helpAboutItem.setStatusTip(
|
|
||||||
translate('OpenLP.MainWindow', 'More information about OpenLP'))
|
translate('OpenLP.MainWindow', 'More information about OpenLP'))
|
||||||
self.helpOnlineHelpItem.setText(
|
if os.name == u'nt':
|
||||||
|
self.offlineHelpItem.setText(
|
||||||
|
translate('OpenLP.MainWindow', '&User Guide'))
|
||||||
|
self.onlineHelpItem.setText(
|
||||||
translate('OpenLP.MainWindow', '&Online Help'))
|
translate('OpenLP.MainWindow', '&Online Help'))
|
||||||
self.helpWebSiteItem.setText(
|
self.webSiteItem.setText(
|
||||||
translate('OpenLP.MainWindow', '&Web Site'))
|
translate('OpenLP.MainWindow', '&Web Site'))
|
||||||
for item in self.languageGroup.actions():
|
for item in self.languageGroup.actions():
|
||||||
item.setText(item.objectName())
|
item.setText(item.objectName())
|
||||||
@ -445,6 +484,10 @@ class Ui_MainWindow(object):
|
|||||||
translate('OpenLP.MainWindow', 'Open &Data Folder...'))
|
translate('OpenLP.MainWindow', 'Open &Data Folder...'))
|
||||||
self.toolsOpenDataFolder.setStatusTip(translate('OpenLP.MainWindow',
|
self.toolsOpenDataFolder.setStatusTip(translate('OpenLP.MainWindow',
|
||||||
'Open the folder where songs, bibles and other data resides.'))
|
'Open the folder where songs, bibles and other data resides.'))
|
||||||
|
self.toolsFirstTimeWizard.setText(
|
||||||
|
translate('OpenLP.MainWindow', 'Re-run First Time Wizard'))
|
||||||
|
self.toolsFirstTimeWizard.setStatusTip(translate('OpenLP.MainWindow',
|
||||||
|
'Re-run the First Time Wizard, importing songs, Bibles and themes.'))
|
||||||
self.updateThemeImages.setText(
|
self.updateThemeImages.setText(
|
||||||
translate('OpenLP.MainWindow', 'Update Theme Images'))
|
translate('OpenLP.MainWindow', 'Update Theme Images'))
|
||||||
self.updateThemeImages.setStatusTip(
|
self.updateThemeImages.setStatusTip(
|
||||||
@ -485,7 +528,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
self.serviceNotSaved = False
|
self.serviceNotSaved = False
|
||||||
self.aboutForm = AboutForm(self)
|
self.aboutForm = AboutForm(self)
|
||||||
self.settingsForm = SettingsForm(self, self)
|
self.settingsForm = SettingsForm(self, self)
|
||||||
self.displayTagForm = DisplayTagForm(self)
|
self.formattingTagForm = FormattingTagForm(self)
|
||||||
self.shortcutForm = ShortcutListForm(self)
|
self.shortcutForm = ShortcutListForm(self)
|
||||||
self.recentFiles = QtCore.QStringList()
|
self.recentFiles = QtCore.QStringList()
|
||||||
# Set up the path with plugins
|
# Set up the path with plugins
|
||||||
@ -497,8 +540,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
# Load settings after setupUi so default UI sizes are overwritten
|
# Load settings after setupUi so default UI sizes are overwritten
|
||||||
self.loadSettings()
|
self.loadSettings()
|
||||||
# Once settings are loaded update FileMenu with recentFiles
|
# Once settings are loaded update the menu with the recent files.
|
||||||
self.updateFileMenu()
|
self.updateRecentFilesMenu()
|
||||||
self.pluginForm = PluginForm(self)
|
self.pluginForm = PluginForm(self)
|
||||||
# Set up signals and slots
|
# Set up signals and slots
|
||||||
QtCore.QObject.connect(self.importThemeItem,
|
QtCore.QObject.connect(self.importThemeItem,
|
||||||
@ -516,14 +559,16 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
QtCore.QObject.connect(self.themeManagerDock,
|
QtCore.QObject.connect(self.themeManagerDock,
|
||||||
QtCore.SIGNAL(u'visibilityChanged(bool)'),
|
QtCore.SIGNAL(u'visibilityChanged(bool)'),
|
||||||
self.viewThemeManagerItem.setChecked)
|
self.viewThemeManagerItem.setChecked)
|
||||||
QtCore.QObject.connect(self.helpWebSiteItem,
|
QtCore.QObject.connect(self.webSiteItem,
|
||||||
QtCore.SIGNAL(u'triggered()'), self.onHelpWebSiteClicked)
|
QtCore.SIGNAL(u'triggered()'), self.onHelpWebSiteClicked)
|
||||||
QtCore.QObject.connect(self.toolsOpenDataFolder,
|
QtCore.QObject.connect(self.toolsOpenDataFolder,
|
||||||
QtCore.SIGNAL(u'triggered()'), self.onToolsOpenDataFolderClicked)
|
QtCore.SIGNAL(u'triggered()'), self.onToolsOpenDataFolderClicked)
|
||||||
|
QtCore.QObject.connect(self.toolsFirstTimeWizard,
|
||||||
|
QtCore.SIGNAL(u'triggered()'), self.onFirstTimeWizardClicked)
|
||||||
QtCore.QObject.connect(self.updateThemeImages,
|
QtCore.QObject.connect(self.updateThemeImages,
|
||||||
QtCore.SIGNAL(u'triggered()'), self.onUpdateThemeImages)
|
QtCore.SIGNAL(u'triggered()'), self.onUpdateThemeImages)
|
||||||
QtCore.QObject.connect(self.displayTagItem,
|
QtCore.QObject.connect(self.formattingTagItem,
|
||||||
QtCore.SIGNAL(u'triggered()'), self.onDisplayTagItemClicked)
|
QtCore.SIGNAL(u'triggered()'), self.onFormattingTagItemClicked)
|
||||||
QtCore.QObject.connect(self.settingsConfigureItem,
|
QtCore.QObject.connect(self.settingsConfigureItem,
|
||||||
QtCore.SIGNAL(u'triggered()'), self.onSettingsConfigureItemClicked)
|
QtCore.SIGNAL(u'triggered()'), self.onSettingsConfigureItemClicked)
|
||||||
QtCore.QObject.connect(self.settingsShortcutsItem,
|
QtCore.QObject.connect(self.settingsShortcutsItem,
|
||||||
@ -653,7 +698,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
QtCore.QVariant(False)).toBool():
|
QtCore.QVariant(False)).toBool():
|
||||||
self.serviceManagerContents.loadLastFile()
|
self.serviceManagerContents.loadLastFile()
|
||||||
view_mode = QtCore.QSettings().value(u'%s/view mode' % \
|
view_mode = QtCore.QSettings().value(u'%s/view mode' % \
|
||||||
self.generalSettingsSection, u'default')
|
self.generalSettingsSection, u'default').toString()
|
||||||
if view_mode == u'default':
|
if view_mode == u'default':
|
||||||
self.modeDefaultItem.setChecked(True)
|
self.modeDefaultItem.setChecked(True)
|
||||||
elif view_mode == u'setup':
|
elif view_mode == u'setup':
|
||||||
@ -682,11 +727,46 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
plugin.firstTime()
|
plugin.firstTime()
|
||||||
Receiver.send_message(u'openlp_process_events')
|
Receiver.send_message(u'openlp_process_events')
|
||||||
temp_dir = os.path.join(unicode(gettempdir()), u'openlp')
|
temp_dir = os.path.join(unicode(gettempdir()), u'openlp')
|
||||||
if not os.path.exists(temp_dir):
|
shutil.rmtree(temp_dir, True)
|
||||||
|
|
||||||
|
def onFirstTimeWizardClicked(self):
|
||||||
|
"""
|
||||||
|
Re-run the first time wizard. Prompts the user for run confirmation
|
||||||
|
If wizard is run, songs, bibles and themes are imported. The default
|
||||||
|
theme is changed (if necessary). The plugins in pluginmanager are
|
||||||
|
set active/in-active to match the selection in the wizard.
|
||||||
|
"""
|
||||||
|
answer = QtGui.QMessageBox.warning(self,
|
||||||
|
translate('OpenLP.MainWindow', 'Re-run First Time Wizard?'),
|
||||||
|
translate('OpenLP.MainWindow',
|
||||||
|
'Are you sure you want to re-run the First Time Wizard?\n\n'
|
||||||
|
'Re-running this wizard may make changes to your current '
|
||||||
|
'OpenLP configuration and possibly add songs to your '
|
||||||
|
'existing songs list and change your default theme.'),
|
||||||
|
QtGui.QMessageBox.StandardButtons(
|
||||||
|
QtGui.QMessageBox.Yes |
|
||||||
|
QtGui.QMessageBox.No),
|
||||||
|
QtGui.QMessageBox.No)
|
||||||
|
if answer == QtGui.QMessageBox.No:
|
||||||
return
|
return
|
||||||
for filename in os.listdir(temp_dir):
|
Receiver.send_message(u'cursor_busy')
|
||||||
delete_file(os.path.join(temp_dir, filename))
|
screens = ScreenList.get_instance()
|
||||||
os.removedirs(temp_dir)
|
if FirstTimeForm(screens, self).exec_() == QtGui.QDialog.Accepted:
|
||||||
|
self.firstTime()
|
||||||
|
for plugin in self.pluginManager.plugins:
|
||||||
|
self.activePlugin = plugin
|
||||||
|
oldStatus = self.activePlugin.status
|
||||||
|
self.activePlugin.setStatus()
|
||||||
|
if oldStatus != self.activePlugin.status:
|
||||||
|
if self.activePlugin.status == PluginStatus.Active:
|
||||||
|
self.activePlugin.toggleStatus(PluginStatus.Active)
|
||||||
|
self.activePlugin.appStartup()
|
||||||
|
else:
|
||||||
|
self.activePlugin.toggleStatus(PluginStatus.Inactive)
|
||||||
|
self.themeManagerContents.configUpdated()
|
||||||
|
self.themeManagerContents.loadThemes(True)
|
||||||
|
Receiver.send_message(u'theme_update_global',
|
||||||
|
self.themeManagerContents.global_theme)
|
||||||
|
|
||||||
def blankCheck(self):
|
def blankCheck(self):
|
||||||
"""
|
"""
|
||||||
@ -723,14 +803,20 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
import webbrowser
|
import webbrowser
|
||||||
webbrowser.open_new(u'http://openlp.org/')
|
webbrowser.open_new(u'http://openlp.org/')
|
||||||
|
|
||||||
def onHelpOnlineHelpClicked(self):
|
def onOfflineHelpClicked(self):
|
||||||
|
"""
|
||||||
|
Load the local OpenLP help file
|
||||||
|
"""
|
||||||
|
os.startfile(self.localHelpFile)
|
||||||
|
|
||||||
|
def onOnlineHelpClicked(self):
|
||||||
"""
|
"""
|
||||||
Load the online OpenLP manual
|
Load the online OpenLP manual
|
||||||
"""
|
"""
|
||||||
import webbrowser
|
import webbrowser
|
||||||
webbrowser.open_new(u'http://manual.openlp.org/')
|
webbrowser.open_new(u'http://manual.openlp.org/')
|
||||||
|
|
||||||
def onHelpAboutItemClicked(self):
|
def onAboutItemClicked(self):
|
||||||
"""
|
"""
|
||||||
Show the About form
|
Show the About form
|
||||||
"""
|
"""
|
||||||
@ -756,11 +842,11 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
"""
|
"""
|
||||||
self.themeManagerContents.updatePreviewImages()
|
self.themeManagerContents.updatePreviewImages()
|
||||||
|
|
||||||
def onDisplayTagItemClicked(self):
|
def onFormattingTagItemClicked(self):
|
||||||
"""
|
"""
|
||||||
Show the Settings dialog
|
Show the Settings dialog
|
||||||
"""
|
"""
|
||||||
self.displayTagForm.exec_()
|
self.formattingTagForm.exec_()
|
||||||
|
|
||||||
def onSettingsConfigureItemClicked(self):
|
def onSettingsConfigureItemClicked(self):
|
||||||
"""
|
"""
|
||||||
@ -936,7 +1022,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
self.mediaManagerDock.setVisible(not self.mediaManagerDock.isVisible())
|
self.mediaManagerDock.setVisible(not self.mediaManagerDock.isVisible())
|
||||||
|
|
||||||
def toggleServiceManager(self):
|
def toggleServiceManager(self):
|
||||||
self.serviceManagerDock.setVisible(not self.serviceManagerDock.isVisible())
|
self.serviceManagerDock.setVisible(
|
||||||
|
not self.serviceManagerDock.isVisible())
|
||||||
|
|
||||||
def toggleThemeManager(self):
|
def toggleThemeManager(self):
|
||||||
self.themeManagerDock.setVisible(not self.themeManagerDock.isVisible())
|
self.themeManagerDock.setVisible(not self.themeManagerDock.isVisible())
|
||||||
@ -956,6 +1043,37 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
QtCore.QVariant(visible))
|
QtCore.QVariant(visible))
|
||||||
self.viewPreviewPanel.setChecked(visible)
|
self.viewPreviewPanel.setChecked(visible)
|
||||||
|
|
||||||
|
def setLockPanel(self, lock):
|
||||||
|
"""
|
||||||
|
Sets the ability to stop the toolbars being changed.
|
||||||
|
"""
|
||||||
|
if lock:
|
||||||
|
self.themeManagerDock.setFeatures(
|
||||||
|
QtGui.QDockWidget.NoDockWidgetFeatures)
|
||||||
|
self.serviceManagerDock.setFeatures(
|
||||||
|
QtGui.QDockWidget.NoDockWidgetFeatures)
|
||||||
|
self.mediaManagerDock.setFeatures(
|
||||||
|
QtGui.QDockWidget.NoDockWidgetFeatures)
|
||||||
|
self.viewMediaManagerItem.setEnabled(False)
|
||||||
|
self.viewServiceManagerItem.setEnabled(False)
|
||||||
|
self.viewThemeManagerItem.setEnabled(False)
|
||||||
|
self.viewPreviewPanel.setEnabled(False)
|
||||||
|
self.viewLivePanel.setEnabled(False)
|
||||||
|
else:
|
||||||
|
self.themeManagerDock.setFeatures(
|
||||||
|
QtGui.QDockWidget.AllDockWidgetFeatures)
|
||||||
|
self.serviceManagerDock.setFeatures(
|
||||||
|
QtGui.QDockWidget.AllDockWidgetFeatures)
|
||||||
|
self.mediaManagerDock.setFeatures(
|
||||||
|
QtGui.QDockWidget.AllDockWidgetFeatures)
|
||||||
|
self.viewMediaManagerItem.setEnabled(True)
|
||||||
|
self.viewServiceManagerItem.setEnabled(True)
|
||||||
|
self.viewThemeManagerItem.setEnabled(True)
|
||||||
|
self.viewPreviewPanel.setEnabled(True)
|
||||||
|
self.viewLivePanel.setEnabled(True)
|
||||||
|
QtCore.QSettings().setValue(u'user interface/lock panel',
|
||||||
|
QtCore.QVariant(lock))
|
||||||
|
|
||||||
def setLivePanelVisibility(self, visible):
|
def setLivePanelVisibility(self, visible):
|
||||||
"""
|
"""
|
||||||
Sets the visibility of the live panel including saving the setting and
|
Sets the visibility of the live panel including saving the setting and
|
||||||
@ -986,6 +1104,13 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
self.restoreGeometry(
|
self.restoreGeometry(
|
||||||
settings.value(u'main window geometry').toByteArray())
|
settings.value(u'main window geometry').toByteArray())
|
||||||
self.restoreState(settings.value(u'main window state').toByteArray())
|
self.restoreState(settings.value(u'main window state').toByteArray())
|
||||||
|
self.liveController.splitter.restoreState(
|
||||||
|
settings.value(u'live splitter geometry').toByteArray())
|
||||||
|
self.previewController.splitter.restoreState(
|
||||||
|
settings.value(u'preview splitter geometry').toByteArray())
|
||||||
|
self.controlSplitter.restoreState(
|
||||||
|
settings.value(u'mainwindow splitter geometry').toByteArray())
|
||||||
|
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
|
|
||||||
def saveSettings(self):
|
def saveSettings(self):
|
||||||
@ -1006,32 +1131,44 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
QtCore.QVariant(self.saveState()))
|
QtCore.QVariant(self.saveState()))
|
||||||
settings.setValue(u'main window geometry',
|
settings.setValue(u'main window geometry',
|
||||||
QtCore.QVariant(self.saveGeometry()))
|
QtCore.QVariant(self.saveGeometry()))
|
||||||
|
settings.setValue(u'live splitter geometry',
|
||||||
|
QtCore.QVariant(self.liveController.splitter.saveState()))
|
||||||
|
settings.setValue(u'preview splitter geometry',
|
||||||
|
QtCore.QVariant(self.previewController.splitter.saveState()))
|
||||||
|
settings.setValue(u'mainwindow splitter geometry',
|
||||||
|
QtCore.QVariant(self.controlSplitter.saveState()))
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
|
|
||||||
def updateFileMenu(self):
|
def updateRecentFilesMenu(self):
|
||||||
"""
|
"""
|
||||||
Updates the file menu with the latest list of service files accessed.
|
Updates the recent file menu with the latest list of service files
|
||||||
|
accessed.
|
||||||
"""
|
"""
|
||||||
recentFileCount = QtCore.QSettings().value(
|
recentFileCount = QtCore.QSettings().value(
|
||||||
u'advanced/recent file count', QtCore.QVariant(4)).toInt()[0]
|
u'advanced/recent file count', QtCore.QVariant(4)).toInt()[0]
|
||||||
self.fileMenu.clear()
|
|
||||||
add_actions(self.fileMenu, self.fileMenuActions[:-1])
|
|
||||||
existingRecentFiles = [recentFile for recentFile in self.recentFiles
|
existingRecentFiles = [recentFile for recentFile in self.recentFiles
|
||||||
if QtCore.QFile.exists(recentFile)]
|
if QtCore.QFile.exists(recentFile)]
|
||||||
recentFilesToDisplay = existingRecentFiles[0:recentFileCount]
|
recentFilesToDisplay = existingRecentFiles[0:recentFileCount]
|
||||||
if recentFilesToDisplay:
|
self.recentFilesMenu.clear()
|
||||||
self.fileMenu.addSeparator()
|
for fileId, filename in enumerate(recentFilesToDisplay):
|
||||||
for fileId, filename in enumerate(recentFilesToDisplay):
|
log.debug('Recent file name: %s', filename)
|
||||||
log.debug('Recent file name: %s', filename)
|
action = base_action(self, u'')
|
||||||
action = base_action(self, u'')
|
action.setText(u'&%d %s' %
|
||||||
action.setText(u'&%d %s' %
|
(fileId + 1, QtCore.QFileInfo(filename).fileName()))
|
||||||
(fileId + 1, QtCore.QFileInfo(filename).fileName()))
|
action.setData(QtCore.QVariant(filename))
|
||||||
action.setData(QtCore.QVariant(filename))
|
self.connect(action, QtCore.SIGNAL(u'triggered()'),
|
||||||
self.connect(action, QtCore.SIGNAL(u'triggered()'),
|
self.serviceManagerContents.onRecentServiceClicked)
|
||||||
self.serviceManagerContents.onRecentServiceClicked)
|
self.recentFilesMenu.addAction(action)
|
||||||
self.fileMenu.addAction(action)
|
clearRecentFilesAction = base_action(self, u'')
|
||||||
self.fileMenu.addSeparator()
|
clearRecentFilesAction.setText(
|
||||||
self.fileMenu.addAction(self.fileMenuActions[-1])
|
translate('OpenLP.MainWindow', 'Clear List',
|
||||||
|
'Clear List of recent files'))
|
||||||
|
clearRecentFilesAction.setStatusTip(
|
||||||
|
translate('OpenLP.MainWindow', 'Clear the list of recent files.'))
|
||||||
|
add_actions(self.recentFilesMenu, (None, clearRecentFilesAction))
|
||||||
|
self.connect(clearRecentFilesAction, QtCore.SIGNAL(u'triggered()'),
|
||||||
|
self.recentFiles.clear)
|
||||||
|
clearRecentFilesAction.setEnabled(not self.recentFiles.isEmpty())
|
||||||
|
|
||||||
def addRecentFile(self, filename):
|
def addRecentFile(self, filename):
|
||||||
"""
|
"""
|
||||||
|
@ -66,7 +66,7 @@ class MediaDockManager(object):
|
|||||||
match = False
|
match = False
|
||||||
for dock_index in range(0, self.media_dock.count()):
|
for dock_index in range(0, self.media_dock.count()):
|
||||||
if self.media_dock.widget(dock_index).settingsSection == \
|
if self.media_dock.widget(dock_index).settingsSection == \
|
||||||
media_item.plugin.name.lower():
|
media_item.plugin.name:
|
||||||
match = True
|
match = True
|
||||||
break
|
break
|
||||||
if not match:
|
if not match:
|
||||||
@ -84,6 +84,6 @@ class MediaDockManager(object):
|
|||||||
for dock_index in range(0, self.media_dock.count()):
|
for dock_index in range(0, self.media_dock.count()):
|
||||||
if self.media_dock.widget(dock_index):
|
if self.media_dock.widget(dock_index):
|
||||||
if self.media_dock.widget(dock_index).settingsSection == \
|
if self.media_dock.widget(dock_index).settingsSection == \
|
||||||
media_item.plugin.name.lower():
|
media_item.plugin.name:
|
||||||
self.media_dock.widget(dock_index).setVisible(False)
|
self.media_dock.widget(dock_index).setVisible(False)
|
||||||
self.media_dock.removeItem(dock_index)
|
self.media_dock.removeItem(dock_index)
|
||||||
|
@ -108,7 +108,7 @@ class Ui_PrintServiceDialog(object):
|
|||||||
self.footerLabel = QtGui.QLabel(self.optionsWidget)
|
self.footerLabel = QtGui.QLabel(self.optionsWidget)
|
||||||
self.footerLabel.setObjectName(u'footerLabel')
|
self.footerLabel.setObjectName(u'footerLabel')
|
||||||
self.optionsLayout.addWidget(self.footerLabel)
|
self.optionsLayout.addWidget(self.footerLabel)
|
||||||
self.footerTextEdit = SpellTextEdit(self.optionsWidget)
|
self.footerTextEdit = SpellTextEdit(self.optionsWidget, False)
|
||||||
self.footerTextEdit.setObjectName(u'footerTextEdit')
|
self.footerTextEdit.setObjectName(u'footerTextEdit')
|
||||||
self.optionsLayout.addWidget(self.footerTextEdit)
|
self.optionsLayout.addWidget(self.footerTextEdit)
|
||||||
self.optionsGroupBox = QtGui.QGroupBox()
|
self.optionsGroupBox = QtGui.QGroupBox()
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
import cgi
|
||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@ -183,7 +184,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
|||||||
self._addElement(u'style', custom_css, html_data.head,
|
self._addElement(u'style', custom_css, html_data.head,
|
||||||
attribute=(u'type', u'text/css'))
|
attribute=(u'type', u'text/css'))
|
||||||
self._addElement(u'body', parent=html_data)
|
self._addElement(u'body', parent=html_data)
|
||||||
self._addElement(u'h1', unicode(self.titleLineEdit.text()),
|
self._addElement(u'h1', cgi.escape(unicode(self.titleLineEdit.text())),
|
||||||
html_data.body, classId=u'serviceTitle')
|
html_data.body, classId=u'serviceTitle')
|
||||||
for index, item in enumerate(self.serviceManager.serviceItems):
|
for index, item in enumerate(self.serviceManager.serviceItems):
|
||||||
self._addPreviewItem(html_data.body, item[u'service_item'], index)
|
self._addPreviewItem(html_data.body, item[u'service_item'], index)
|
||||||
@ -193,8 +194,9 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
|||||||
classId=u'customNotes')
|
classId=u'customNotes')
|
||||||
self._addElement(u'span', translate('OpenLP.ServiceManager',
|
self._addElement(u'span', translate('OpenLP.ServiceManager',
|
||||||
'Custom Service Notes: '), div, classId=u'customNotesTitle')
|
'Custom Service Notes: '), div, classId=u'customNotesTitle')
|
||||||
self._addElement(u'span', self.footerTextEdit.toPlainText(), div,
|
self._addElement(u'span',
|
||||||
classId=u'customNotesText')
|
cgi.escape(self.footerTextEdit.toPlainText()),
|
||||||
|
div, classId=u'customNotesText')
|
||||||
self.document.setHtml(html.tostring(html_data))
|
self.document.setHtml(html.tostring(html_data))
|
||||||
self.previewWidget.updatePreview()
|
self.previewWidget.updatePreview()
|
||||||
|
|
||||||
@ -204,8 +206,8 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
|||||||
item_title = self._addElement(u'h2', parent=div, classId=u'itemTitle')
|
item_title = self._addElement(u'h2', parent=div, classId=u'itemTitle')
|
||||||
self._addElement(u'img', parent=item_title,
|
self._addElement(u'img', parent=item_title,
|
||||||
attribute=(u'src', item.icon))
|
attribute=(u'src', item.icon))
|
||||||
self._addElement(u'span', u' ' + item.get_display_title(),
|
self._addElement(u'span',
|
||||||
item_title)
|
u' ' + cgi.escape(item.get_display_title()), item_title)
|
||||||
if self.slideTextCheckBox.isChecked():
|
if self.slideTextCheckBox.isChecked():
|
||||||
# Add the text of the service item.
|
# Add the text of the service item.
|
||||||
if item.is_text():
|
if item.is_text():
|
||||||
@ -230,8 +232,9 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
|||||||
foot_text = item.foot_text
|
foot_text = item.foot_text
|
||||||
foot_text = foot_text.partition(u'<br>')[2]
|
foot_text = foot_text.partition(u'<br>')[2]
|
||||||
if foot_text:
|
if foot_text:
|
||||||
foot = self._addElement(u'div', foot_text, parent=div,
|
foot_text = cgi.escape(foot_text.replace(u'<br>', u'\n'))
|
||||||
classId=u'itemFooter')
|
self._addElement(u'div', foot_text.replace(u'\n', u'<br>'),
|
||||||
|
parent=div, classId=u'itemFooter')
|
||||||
# Add service items' notes.
|
# Add service items' notes.
|
||||||
if self.notesCheckBox.isChecked():
|
if self.notesCheckBox.isChecked():
|
||||||
if item.notes:
|
if item.notes:
|
||||||
@ -239,8 +242,8 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
|||||||
self._addElement(u'span',
|
self._addElement(u'span',
|
||||||
translate('OpenLP.ServiceManager', 'Notes: '), p,
|
translate('OpenLP.ServiceManager', 'Notes: '), p,
|
||||||
classId=u'itemNotesTitle')
|
classId=u'itemNotesTitle')
|
||||||
notes = self._addElement(u'span',
|
self._addElement(u'span',
|
||||||
item.notes.replace(u'\n', u'<br />'), p,
|
cgi.escape(unicode(item.notes)).replace(u'\n', u'<br>'), p,
|
||||||
classId=u'itemNotesText')
|
classId=u'itemNotesText')
|
||||||
# Add play length of media files.
|
# Add play length of media files.
|
||||||
if item.is_media() and self.metaDataCheckBox.isChecked():
|
if item.is_media() and self.metaDataCheckBox.isChecked():
|
||||||
|
@ -35,6 +35,8 @@ class Ui_ServiceItemEditDialog(object):
|
|||||||
def setupUi(self, serviceItemEditDialog):
|
def setupUi(self, serviceItemEditDialog):
|
||||||
serviceItemEditDialog.setObjectName(u'serviceItemEditDialog')
|
serviceItemEditDialog.setObjectName(u'serviceItemEditDialog')
|
||||||
self.dialogLayout = QtGui.QGridLayout(serviceItemEditDialog)
|
self.dialogLayout = QtGui.QGridLayout(serviceItemEditDialog)
|
||||||
|
self.dialogLayout.setContentsMargins(8, 8, 8, 8)
|
||||||
|
self.dialogLayout.setSpacing(8)
|
||||||
self.dialogLayout.setObjectName(u'dialogLayout')
|
self.dialogLayout.setObjectName(u'dialogLayout')
|
||||||
self.listWidget = QtGui.QListWidget(serviceItemEditDialog)
|
self.listWidget = QtGui.QListWidget(serviceItemEditDialog)
|
||||||
self.listWidget.setAlternatingRowColors(True)
|
self.listWidget.setAlternatingRowColors(True)
|
||||||
|
@ -79,7 +79,7 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
|
|||||||
if not item:
|
if not item:
|
||||||
return
|
return
|
||||||
row = self.listWidget.row(item)
|
row = self.listWidget.row(item)
|
||||||
self.itemList.remove(self.itemList[row])
|
self.itemList.pop(row)
|
||||||
self.loadData()
|
self.loadData()
|
||||||
if row == self.listWidget.count():
|
if row == self.listWidget.count():
|
||||||
self.listWidget.setCurrentRow(row - 1)
|
self.listWidget.setCurrentRow(row - 1)
|
||||||
@ -109,7 +109,7 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
|
|||||||
return
|
return
|
||||||
row = self.listWidget.row(item)
|
row = self.listWidget.row(item)
|
||||||
temp = self.itemList[row]
|
temp = self.itemList[row]
|
||||||
self.itemList.remove(self.itemList[row])
|
self.itemList.pop(row)
|
||||||
if direction == u'up':
|
if direction == u'up':
|
||||||
row -= 1
|
row -= 1
|
||||||
else:
|
else:
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
import cgi
|
||||||
import cPickle
|
import cPickle
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -48,18 +49,18 @@ class ServiceManagerList(QtGui.QTreeWidget):
|
|||||||
"""
|
"""
|
||||||
Set up key bindings and mouse behaviour for the service list
|
Set up key bindings and mouse behaviour for the service list
|
||||||
"""
|
"""
|
||||||
def __init__(self, mainwindow, parent=None, name=None):
|
def __init__(self, serviceManager, parent=None, name=None):
|
||||||
QtGui.QTreeWidget.__init__(self, parent)
|
QtGui.QTreeWidget.__init__(self, parent)
|
||||||
self.mainwindow = mainwindow
|
self.serviceManager = serviceManager
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
if isinstance(event, QtGui.QKeyEvent):
|
if isinstance(event, QtGui.QKeyEvent):
|
||||||
# here accept the event and do something
|
# here accept the event and do something
|
||||||
if event.key() == QtCore.Qt.Key_Up:
|
if event.key() == QtCore.Qt.Key_Up:
|
||||||
self.mainwindow.onMoveSelectionUp()
|
self.serviceManager.onMoveSelectionUp()
|
||||||
event.accept()
|
event.accept()
|
||||||
elif event.key() == QtCore.Qt.Key_Down:
|
elif event.key() == QtCore.Qt.Key_Down:
|
||||||
self.mainwindow.onMoveSelectionDown()
|
self.serviceManager.onMoveSelectionDown()
|
||||||
event.accept()
|
event.accept()
|
||||||
event.ignore()
|
event.ignore()
|
||||||
else:
|
else:
|
||||||
@ -408,20 +409,33 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
return False
|
return False
|
||||||
self.newFile()
|
self.newFile()
|
||||||
|
|
||||||
def onLoadServiceClicked(self):
|
def onLoadServiceClicked(self, loadFile=None):
|
||||||
|
"""
|
||||||
|
Loads the service file and saves the existing one it there is one
|
||||||
|
unchanged
|
||||||
|
|
||||||
|
``loadFile``
|
||||||
|
The service file to the loaded. Will be None is from menu so
|
||||||
|
selection will be required.
|
||||||
|
"""
|
||||||
if self.isModified():
|
if self.isModified():
|
||||||
result = self.saveModifiedService()
|
result = self.saveModifiedService()
|
||||||
if result == QtGui.QMessageBox.Cancel:
|
if result == QtGui.QMessageBox.Cancel:
|
||||||
return False
|
return False
|
||||||
elif result == QtGui.QMessageBox.Save:
|
elif result == QtGui.QMessageBox.Save:
|
||||||
self.saveFile()
|
self.saveFile()
|
||||||
fileName = unicode(QtGui.QFileDialog.getOpenFileName(self.mainwindow,
|
if not loadFile:
|
||||||
translate('OpenLP.ServiceManager', 'Open File'),
|
fileName = unicode(QtGui.QFileDialog.getOpenFileName(
|
||||||
SettingsManager.get_last_dir(
|
self.mainwindow,
|
||||||
self.mainwindow.serviceSettingsSection),
|
translate('OpenLP.ServiceManager', 'Open File'),
|
||||||
translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)')))
|
SettingsManager.get_last_dir(
|
||||||
if not fileName:
|
self.mainwindow.serviceSettingsSection),
|
||||||
return False
|
translate('OpenLP.ServiceManager',
|
||||||
|
'OpenLP Service Files (*.osz)')))
|
||||||
|
if not fileName:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
fileName = loadFile
|
||||||
SettingsManager.set_last_dir(self.mainwindow.serviceSettingsSection,
|
SettingsManager.set_last_dir(self.mainwindow.serviceSettingsSection,
|
||||||
split_filename(fileName)[0])
|
split_filename(fileName)[0])
|
||||||
self.loadFile(fileName)
|
self.loadFile(fileName)
|
||||||
@ -474,6 +488,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
item[u'service_item'].get_service_repr()})
|
item[u'service_item'].get_service_repr()})
|
||||||
if not item[u'service_item'].uses_file():
|
if not item[u'service_item'].uses_file():
|
||||||
continue
|
continue
|
||||||
|
skipMissing = False
|
||||||
for frame in item[u'service_item'].get_frames():
|
for frame in item[u'service_item'].get_frames():
|
||||||
if item[u'service_item'].is_image():
|
if item[u'service_item'].is_image():
|
||||||
path_from = frame[u'path']
|
path_from = frame[u'path']
|
||||||
@ -482,25 +497,29 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
# Only write a file once
|
# Only write a file once
|
||||||
if path_from in write_list:
|
if path_from in write_list:
|
||||||
continue
|
continue
|
||||||
file_size = os.path.getsize(path_from)
|
if not os.path.exists(path_from):
|
||||||
size_limit = 52428800 # 50MiB
|
if not skipMissing:
|
||||||
#if file_size > size_limit:
|
Receiver.send_message(u'cursor_normal')
|
||||||
# # File exeeds size_limit bytes, ask user
|
title = unicode(translate('OpenLP.ServiceManager',
|
||||||
# message = unicode(translate('OpenLP.ServiceManager',
|
'Service File Missing'))
|
||||||
# 'Do you want to include \n%.1f MB file "%s"\n'
|
message = unicode(translate('OpenLP.ServiceManager',
|
||||||
# 'into the service file?\nThis may take some time.\n\n'
|
'File missing from service\n\n %s \n\n'
|
||||||
# 'Please note that you need to\ntake care of that file'
|
'Continue saving?' % path_from ))
|
||||||
# ' yourself,\nif you leave it out.')) % \
|
answer = QtGui.QMessageBox.critical(self, title,
|
||||||
# (file_size/1048576, os.path.split(path_from)[1])
|
message,
|
||||||
# ans = QtGui.QMessageBox.question(self.mainwindow,
|
QtGui.QMessageBox.StandardButtons(
|
||||||
# translate('OpenLP.ServiceManager', 'Including Large '
|
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No |
|
||||||
# 'File'), message, QtGui.QMessageBox.StandardButtons(
|
QtGui.QMessageBox.YesToAll))
|
||||||
# QtGui.QMessageBox.Ok|QtGui.QMessageBox.Cancel),
|
if answer == QtGui.QMessageBox.No:
|
||||||
# QtGui.QMessageBox.Ok)
|
self.mainwindow.finishedProgressBar()
|
||||||
# if ans == QtGui.QMessageBox.Cancel:
|
return False
|
||||||
# continue
|
if answer == QtGui.QMessageBox.YesToAll:
|
||||||
write_list.append(path_from)
|
skipMissing = True
|
||||||
total_size += file_size
|
Receiver.send_message(u'cursor_busy')
|
||||||
|
else:
|
||||||
|
file_size = os.path.getsize(path_from)
|
||||||
|
write_list.append(path_from)
|
||||||
|
total_size += file_size
|
||||||
log.debug(u'ServiceManager.saveFile - ZIP contents size is %i bytes' %
|
log.debug(u'ServiceManager.saveFile - ZIP contents size is %i bytes' %
|
||||||
total_size)
|
total_size)
|
||||||
service_content = cPickle.dumps(service)
|
service_content = cPickle.dumps(service)
|
||||||
@ -688,7 +707,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
QtGui.QAction, serviceItem[u'service_item'].theme)
|
QtGui.QAction, serviceItem[u'service_item'].theme)
|
||||||
if themeAction is not None:
|
if themeAction is not None:
|
||||||
themeAction.setChecked(True)
|
themeAction.setChecked(True)
|
||||||
action = self.menu.exec_(self.serviceManagerList.mapToGlobal(point))
|
self.menu.exec_(self.serviceManagerList.mapToGlobal(point))
|
||||||
|
|
||||||
def onServiceItemNoteForm(self):
|
def onServiceItemNoteForm(self):
|
||||||
item = self.findServiceItem()[0]
|
item = self.findServiceItem()[0]
|
||||||
@ -701,6 +720,9 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
self.setModified()
|
self.setModified()
|
||||||
|
|
||||||
def onStartTimeForm(self):
|
def onStartTimeForm(self):
|
||||||
|
"""
|
||||||
|
Opens a dialog to type in service item notes.
|
||||||
|
"""
|
||||||
item = self.findServiceItem()[0]
|
item = self.findServiceItem()[0]
|
||||||
self.startTimeForm.item = self.serviceItems[item]
|
self.startTimeForm.item = self.serviceItems[item]
|
||||||
if self.startTimeForm.exec_():
|
if self.startTimeForm.exec_():
|
||||||
@ -781,50 +803,25 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
|
|
||||||
def onMoveSelectionUp(self):
|
def onMoveSelectionUp(self):
|
||||||
"""
|
"""
|
||||||
Moves the selection up the window. Called by the up arrow.
|
Moves the cursor selection up the window.
|
||||||
|
Called by the up arrow.
|
||||||
"""
|
"""
|
||||||
serviceIterator = QtGui.QTreeWidgetItemIterator(self.serviceManagerList)
|
item = self.serviceManagerList.currentItem()
|
||||||
tempItem = None
|
itemBefore = self.serviceManagerList.itemAbove(item)
|
||||||
setLastItem = False
|
if itemBefore is None:
|
||||||
while serviceIterator.value():
|
return
|
||||||
if serviceIterator.value().isSelected() and tempItem is None:
|
self.serviceManagerList.setCurrentItem(itemBefore)
|
||||||
setLastItem = True
|
|
||||||
serviceIterator.value().setSelected(False)
|
|
||||||
if serviceIterator.value().isSelected():
|
|
||||||
# We are on the first record
|
|
||||||
if tempItem:
|
|
||||||
tempItem.setSelected(True)
|
|
||||||
serviceIterator.value().setSelected(False)
|
|
||||||
else:
|
|
||||||
tempItem = serviceIterator.value()
|
|
||||||
lastItem = serviceIterator.value()
|
|
||||||
serviceIterator += 1
|
|
||||||
# Top Item was selected so set the last one
|
|
||||||
if setLastItem:
|
|
||||||
lastItem.setSelected(True)
|
|
||||||
self.setModified()
|
|
||||||
|
|
||||||
def onMoveSelectionDown(self):
|
def onMoveSelectionDown(self):
|
||||||
"""
|
"""
|
||||||
Moves the selection down the window. Called by the down arrow.
|
Moves the cursor selection down the window.
|
||||||
|
Called by the down arrow.
|
||||||
"""
|
"""
|
||||||
serviceIterator = QtGui.QTreeWidgetItemIterator(self.serviceManagerList)
|
item = self.serviceManagerList.currentItem()
|
||||||
firstItem = None
|
itemAfter = self.serviceManagerList.itemBelow(item)
|
||||||
setSelected = False
|
if itemAfter is None:
|
||||||
while serviceIterator.value():
|
return
|
||||||
if not firstItem:
|
self.serviceManagerList.setCurrentItem(itemAfter)
|
||||||
firstItem = serviceIterator.value()
|
|
||||||
if setSelected:
|
|
||||||
setSelected = False
|
|
||||||
serviceIterator.value().setSelected(True)
|
|
||||||
elif serviceIterator.value() and \
|
|
||||||
serviceIterator.value().isSelected():
|
|
||||||
serviceIterator.value().setSelected(False)
|
|
||||||
setSelected = True
|
|
||||||
serviceIterator += 1
|
|
||||||
if setSelected:
|
|
||||||
firstItem.setSelected(True)
|
|
||||||
self.setModified()
|
|
||||||
|
|
||||||
def onCollapseAll(self):
|
def onCollapseAll(self):
|
||||||
"""
|
"""
|
||||||
@ -832,7 +829,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
"""
|
"""
|
||||||
for item in self.serviceItems:
|
for item in self.serviceItems:
|
||||||
item[u'expanded'] = False
|
item[u'expanded'] = False
|
||||||
self.regenerateServiceItems()
|
self.serviceManagerList.collapseAll()
|
||||||
|
|
||||||
def collapsed(self, item):
|
def collapsed(self, item):
|
||||||
"""
|
"""
|
||||||
@ -848,7 +845,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
"""
|
"""
|
||||||
for item in self.serviceItems:
|
for item in self.serviceItems:
|
||||||
item[u'expanded'] = True
|
item[u'expanded'] = True
|
||||||
self.regenerateServiceItems()
|
self.serviceManagerList.expandAll()
|
||||||
|
|
||||||
def expanded(self, item):
|
def expanded(self, item):
|
||||||
"""
|
"""
|
||||||
@ -856,19 +853,19 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
correct state.
|
correct state.
|
||||||
"""
|
"""
|
||||||
pos = item.data(0, QtCore.Qt.UserRole).toInt()[0]
|
pos = item.data(0, QtCore.Qt.UserRole).toInt()[0]
|
||||||
self.serviceItems[pos -1 ][u'expanded'] = True
|
self.serviceItems[pos - 1][u'expanded'] = True
|
||||||
|
|
||||||
def onServiceTop(self):
|
def onServiceTop(self):
|
||||||
"""
|
"""
|
||||||
Move the current ServiceItem to the top of the list.
|
Move the current ServiceItem to the top of the list.
|
||||||
"""
|
"""
|
||||||
item, child = self.findServiceItem()
|
item, child = self.findServiceItem()
|
||||||
if item < len(self.serviceItems) and item is not -1:
|
if item < len(self.serviceItems) and item != -1:
|
||||||
temp = self.serviceItems[item]
|
temp = self.serviceItems[item]
|
||||||
self.serviceItems.remove(self.serviceItems[item])
|
self.serviceItems.remove(self.serviceItems[item])
|
||||||
self.serviceItems.insert(0, temp)
|
self.serviceItems.insert(0, temp)
|
||||||
self.repaintServiceList(0, child)
|
self.repaintServiceList(0, child)
|
||||||
self.setModified()
|
self.setModified()
|
||||||
|
|
||||||
def onServiceUp(self):
|
def onServiceUp(self):
|
||||||
"""
|
"""
|
||||||
@ -880,31 +877,31 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
self.serviceItems.remove(self.serviceItems[item])
|
self.serviceItems.remove(self.serviceItems[item])
|
||||||
self.serviceItems.insert(item - 1, temp)
|
self.serviceItems.insert(item - 1, temp)
|
||||||
self.repaintServiceList(item - 1, child)
|
self.repaintServiceList(item - 1, child)
|
||||||
self.setModified()
|
self.setModified()
|
||||||
|
|
||||||
def onServiceDown(self):
|
def onServiceDown(self):
|
||||||
"""
|
"""
|
||||||
Move the current ServiceItem one position down in the list.
|
Move the current ServiceItem one position down in the list.
|
||||||
"""
|
"""
|
||||||
item, child = self.findServiceItem()
|
item, child = self.findServiceItem()
|
||||||
if item < len(self.serviceItems) and item is not -1:
|
if item < len(self.serviceItems) and item != -1:
|
||||||
temp = self.serviceItems[item]
|
temp = self.serviceItems[item]
|
||||||
self.serviceItems.remove(self.serviceItems[item])
|
self.serviceItems.remove(self.serviceItems[item])
|
||||||
self.serviceItems.insert(item + 1, temp)
|
self.serviceItems.insert(item + 1, temp)
|
||||||
self.repaintServiceList(item + 1, child)
|
self.repaintServiceList(item + 1, child)
|
||||||
self.setModified()
|
self.setModified()
|
||||||
|
|
||||||
def onServiceEnd(self):
|
def onServiceEnd(self):
|
||||||
"""
|
"""
|
||||||
Move the current ServiceItem to the bottom of the list.
|
Move the current ServiceItem to the bottom of the list.
|
||||||
"""
|
"""
|
||||||
item, child = self.findServiceItem()
|
item, child = self.findServiceItem()
|
||||||
if item < len(self.serviceItems) and item is not -1:
|
if item < len(self.serviceItems) and item != -1:
|
||||||
temp = self.serviceItems[item]
|
temp = self.serviceItems[item]
|
||||||
self.serviceItems.remove(self.serviceItems[item])
|
self.serviceItems.remove(self.serviceItems[item])
|
||||||
self.serviceItems.insert(len(self.serviceItems), temp)
|
self.serviceItems.insert(len(self.serviceItems), temp)
|
||||||
self.repaintServiceList(len(self.serviceItems) - 1, child)
|
self.repaintServiceList(len(self.serviceItems) - 1, child)
|
||||||
self.setModified()
|
self.setModified()
|
||||||
|
|
||||||
def onDeleteFromService(self):
|
def onDeleteFromService(self):
|
||||||
"""
|
"""
|
||||||
@ -914,7 +911,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
if item != -1:
|
if item != -1:
|
||||||
self.serviceItems.remove(self.serviceItems[item])
|
self.serviceItems.remove(self.serviceItems[item])
|
||||||
self.repaintServiceList(item - 1, -1)
|
self.repaintServiceList(item - 1, -1)
|
||||||
self.setModified()
|
self.setModified()
|
||||||
|
|
||||||
def repaintServiceList(self, serviceItem, serviceItemChild):
|
def repaintServiceList(self, serviceItem, serviceItemChild):
|
||||||
"""
|
"""
|
||||||
@ -956,7 +953,19 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
treewidgetitem.setIcon(0,
|
treewidgetitem.setIcon(0,
|
||||||
build_icon(u':/general/general_delete.png'))
|
build_icon(u':/general/general_delete.png'))
|
||||||
treewidgetitem.setText(0, serviceitem.get_display_title())
|
treewidgetitem.setText(0, serviceitem.get_display_title())
|
||||||
treewidgetitem.setToolTip(0, serviceitem.notes)
|
tips = []
|
||||||
|
if serviceitem.theme and serviceitem.theme != -1:
|
||||||
|
tips.append(u'<strong>%s:</strong> <em>%s</em>' %
|
||||||
|
(unicode(translate('OpenLP.ServiceManager', 'Slide theme')),
|
||||||
|
serviceitem.theme))
|
||||||
|
if serviceitem.notes:
|
||||||
|
tips.append(u'<strong>%s: </strong> %s' %
|
||||||
|
(unicode(translate('OpenLP.ServiceManager', 'Notes')),
|
||||||
|
cgi.escape(unicode(serviceitem.notes))))
|
||||||
|
if item[u'service_item'] \
|
||||||
|
.is_capable(ItemCapabilities.AllowsVariableStartTime):
|
||||||
|
tips.append(item[u'service_item'].get_media_time())
|
||||||
|
treewidgetitem.setToolTip(0, u'<br>'.join(tips))
|
||||||
treewidgetitem.setData(0, QtCore.Qt.UserRole,
|
treewidgetitem.setData(0, QtCore.Qt.UserRole,
|
||||||
QtCore.QVariant(item[u'order']))
|
QtCore.QVariant(item[u'order']))
|
||||||
treewidgetitem.setSelected(item[u'selected'])
|
treewidgetitem.setSelected(item[u'selected'])
|
||||||
@ -966,11 +975,6 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
text = frame[u'title'].replace(u'\n', u' ')
|
text = frame[u'title'].replace(u'\n', u' ')
|
||||||
child.setText(0, text[:40])
|
child.setText(0, text[:40])
|
||||||
child.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(count))
|
child.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(count))
|
||||||
if item[u'service_item'] \
|
|
||||||
.is_capable(ItemCapabilities.AllowsVariableStartTime):
|
|
||||||
tip = item[u'service_item'].get_media_time()
|
|
||||||
if tip:
|
|
||||||
child.setToolTip(0, tip)
|
|
||||||
if serviceItem == itemcount:
|
if serviceItem == itemcount:
|
||||||
if item[u'expanded'] and serviceItemChild == count:
|
if item[u'expanded'] and serviceItemChild == count:
|
||||||
self.serviceManagerList.setCurrentItem(child)
|
self.serviceManagerList.setCurrentItem(child)
|
||||||
@ -1257,7 +1261,14 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
Handle of the event pint passed
|
Handle of the event pint passed
|
||||||
"""
|
"""
|
||||||
link = event.mimeData()
|
link = event.mimeData()
|
||||||
if link.hasText():
|
if event.mimeData().hasUrls():
|
||||||
|
event.setDropAction(QtCore.Qt.CopyAction)
|
||||||
|
event.accept()
|
||||||
|
for url in event.mimeData().urls():
|
||||||
|
filename = unicode(url.toLocalFile())
|
||||||
|
if filename.endswith(u'.osz'):
|
||||||
|
self.onLoadServiceClicked(filename)
|
||||||
|
elif event.mimeData().hasText():
|
||||||
plugin = unicode(event.mimeData().text())
|
plugin = unicode(event.mimeData().text())
|
||||||
item = self.serviceManagerList.itemAt(event.pos())
|
item = self.serviceManagerList.itemAt(event.pos())
|
||||||
# ServiceManager started the drag and drop
|
# ServiceManager started the drag and drop
|
||||||
@ -1338,7 +1349,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
if not theme:
|
if not theme:
|
||||||
theme = None
|
theme = None
|
||||||
item = self.findServiceItem()[0]
|
item = self.findServiceItem()[0]
|
||||||
self.serviceItems[item][u'service_item'].theme = theme
|
self.serviceItems[item][u'service_item'].update_theme(theme)
|
||||||
self.regenerateServiceItems()
|
self.regenerateServiceItems()
|
||||||
|
|
||||||
def _getParentItemData(self, item):
|
def _getParentItemData(self, item):
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
from openlp.core.lib import translate
|
from openlp.core.lib import translate, SpellTextEdit
|
||||||
from openlp.core.lib.ui import create_accept_reject_button_box
|
from openlp.core.lib.ui import create_accept_reject_button_box
|
||||||
|
|
||||||
class ServiceNoteForm(QtGui.QDialog):
|
class ServiceNoteForm(QtGui.QDialog):
|
||||||
@ -49,8 +49,10 @@ class ServiceNoteForm(QtGui.QDialog):
|
|||||||
def setupUi(self):
|
def setupUi(self):
|
||||||
self.setObjectName(u'serviceNoteEdit')
|
self.setObjectName(u'serviceNoteEdit')
|
||||||
self.dialogLayout = QtGui.QVBoxLayout(self)
|
self.dialogLayout = QtGui.QVBoxLayout(self)
|
||||||
|
self.dialogLayout.setContentsMargins(8, 8, 8, 8)
|
||||||
|
self.dialogLayout.setSpacing(8)
|
||||||
self.dialogLayout.setObjectName(u'verticalLayout')
|
self.dialogLayout.setObjectName(u'verticalLayout')
|
||||||
self.textEdit = QtGui.QTextEdit(self)
|
self.textEdit = SpellTextEdit(self, False)
|
||||||
self.textEdit.setObjectName(u'textEdit')
|
self.textEdit.setObjectName(u'textEdit')
|
||||||
self.dialogLayout.addWidget(self.textEdit)
|
self.dialogLayout.addWidget(self.textEdit)
|
||||||
self.dialogLayout.addWidget(create_accept_reject_button_box(self))
|
self.dialogLayout.addWidget(create_accept_reject_button_box(self))
|
||||||
|
@ -29,7 +29,7 @@ The :mod:`settingsform` provides a user interface for the OpenLP settings
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from PyQt4 import QtGui, QtCore
|
from PyQt4 import QtGui
|
||||||
|
|
||||||
from openlp.core.lib import Receiver, build_icon, PluginStatus
|
from openlp.core.lib import Receiver, build_icon, PluginStatus
|
||||||
from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab
|
from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab
|
||||||
|
@ -123,7 +123,7 @@ class Ui_ShortcutListDialog(object):
|
|||||||
|
|
||||||
def retranslateUi(self, shortcutListDialog):
|
def retranslateUi(self, shortcutListDialog):
|
||||||
shortcutListDialog.setWindowTitle(
|
shortcutListDialog.setWindowTitle(
|
||||||
translate('OpenLP.ShortcutListDialog', 'Customize Shortcuts'))
|
translate('OpenLP.ShortcutListDialog', 'Configure Shortcuts'))
|
||||||
self.descriptionLabel.setText(translate('OpenLP.ShortcutListDialog',
|
self.descriptionLabel.setText(translate('OpenLP.ShortcutListDialog',
|
||||||
'Select an action and click one of the buttons below to start '
|
'Select an action and click one of the buttons below to start '
|
||||||
'capturing a new primary or alternate shortcut, respectively.'))
|
'capturing a new primary or alternate shortcut, respectively.'))
|
||||||
|
@ -247,7 +247,8 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
|
|||||||
alternate_label_text = action.defaultShortcuts[1].toString()
|
alternate_label_text = action.defaultShortcuts[1].toString()
|
||||||
shortcuts = self._actionShortcuts(action)
|
shortcuts = self._actionShortcuts(action)
|
||||||
# We do not want to loose pending changes, that is why we have to
|
# We do not want to loose pending changes, that is why we have to
|
||||||
# keep the text when, this function has not been triggered by a signal.
|
# keep the text when, this function has not been triggered by a
|
||||||
|
# signal.
|
||||||
if item is None:
|
if item is None:
|
||||||
primary_text = self.primaryPushButton.text()
|
primary_text = self.primaryPushButton.text()
|
||||||
alternate_text = self.alternatePushButton.text()
|
alternate_text = self.alternatePushButton.text()
|
||||||
@ -280,7 +281,8 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
|
|||||||
"""
|
"""
|
||||||
Restores all default shortcuts.
|
Restores all default shortcuts.
|
||||||
"""
|
"""
|
||||||
if self.buttonBox.buttonRole(button) != QtGui.QDialogButtonBox.ResetRole:
|
if self.buttonBox.buttonRole(button) != \
|
||||||
|
QtGui.QDialogButtonBox.ResetRole:
|
||||||
return
|
return
|
||||||
if QtGui.QMessageBox.question(self,
|
if QtGui.QMessageBox.question(self,
|
||||||
translate('OpenLP.ShortcutListDialog', 'Restore Default Shortcuts'),
|
translate('OpenLP.ShortcutListDialog', 'Restore Default Shortcuts'),
|
||||||
|
@ -27,12 +27,14 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
import copy
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
from PyQt4.phonon import Phonon
|
from PyQt4.phonon import Phonon
|
||||||
|
|
||||||
from openlp.core.lib import OpenLPToolbar, Receiver, resize_image, \
|
from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, \
|
||||||
ItemCapabilities, translate
|
translate, build_icon
|
||||||
from openlp.core.lib.ui import UiStrings, shortcut_action
|
from openlp.core.lib.ui import UiStrings, shortcut_action
|
||||||
from openlp.core.ui import HideMode, MainDisplay, ScreenList
|
from openlp.core.ui import HideMode, MainDisplay, ScreenList
|
||||||
from openlp.core.utils.actions import ActionList, CategoryOrder
|
from openlp.core.utils.actions import ActionList, CategoryOrder
|
||||||
@ -193,13 +195,11 @@ class SlideController(QtGui.QWidget):
|
|||||||
self.playSlidesLoop = shortcut_action(self.playSlidesMenu,
|
self.playSlidesLoop = shortcut_action(self.playSlidesMenu,
|
||||||
u'playSlidesLoop', [], self.onPlaySlidesLoop,
|
u'playSlidesLoop', [], self.onPlaySlidesLoop,
|
||||||
u':/media/media_time.png', False, UiStrings().LiveToolbar)
|
u':/media/media_time.png', False, UiStrings().LiveToolbar)
|
||||||
self.playSlidesLoop.setText(
|
self.playSlidesLoop.setText(UiStrings().PlaySlidesInLoop)
|
||||||
translate('OpenLP.SlideController', 'Play Slides in Loop'))
|
|
||||||
self.playSlidesOnce = shortcut_action(self.playSlidesMenu,
|
self.playSlidesOnce = shortcut_action(self.playSlidesMenu,
|
||||||
u'playSlidesOnce', [], self.onPlaySlidesOnce,
|
u'playSlidesOnce', [], self.onPlaySlidesOnce,
|
||||||
u':/media/media_time.png', False, UiStrings().LiveToolbar)
|
u':/media/media_time.png', False, UiStrings().LiveToolbar)
|
||||||
self.playSlidesOnce.setText(
|
self.playSlidesOnce.setText(UiStrings().PlaySlidesToEnd)
|
||||||
translate('OpenLP.SlideController', 'Play Slides to End'))
|
|
||||||
if QtCore.QSettings().value(self.parent().generalSettingsSection +
|
if QtCore.QSettings().value(self.parent().generalSettingsSection +
|
||||||
u'/enable slide loop', QtCore.QVariant(True)).toBool():
|
u'/enable slide loop', QtCore.QVariant(True)).toBool():
|
||||||
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
|
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
|
||||||
@ -412,9 +412,11 @@ class SlideController(QtGui.QWidget):
|
|||||||
self.display.videoStop()
|
self.display.videoStop()
|
||||||
|
|
||||||
def servicePrevious(self):
|
def servicePrevious(self):
|
||||||
|
time.sleep(0.1)
|
||||||
Receiver.send_message('servicemanager_previous_item')
|
Receiver.send_message('servicemanager_previous_item')
|
||||||
|
|
||||||
def serviceNext(self):
|
def serviceNext(self):
|
||||||
|
time.sleep(0.1)
|
||||||
Receiver.send_message('servicemanager_next_item')
|
Receiver.send_message('servicemanager_next_item')
|
||||||
|
|
||||||
def screenSizeChanged(self):
|
def screenSizeChanged(self):
|
||||||
@ -506,6 +508,11 @@ class SlideController(QtGui.QWidget):
|
|||||||
self.mediabar.setVisible(False)
|
self.mediabar.setVisible(False)
|
||||||
self.toolbar.makeWidgetsInvisible([u'Song Menu'])
|
self.toolbar.makeWidgetsInvisible([u'Song Menu'])
|
||||||
self.toolbar.makeWidgetsInvisible(self.loopList)
|
self.toolbar.makeWidgetsInvisible(self.loopList)
|
||||||
|
# Reset the button
|
||||||
|
self.playSlidesOnce.setChecked(False)
|
||||||
|
self.playSlidesOnce.setIcon(build_icon(u':/media/media_time.png'))
|
||||||
|
self.playSlidesLoop.setChecked(False)
|
||||||
|
self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
|
||||||
if item.is_text():
|
if item.is_text():
|
||||||
if QtCore.QSettings().value(
|
if QtCore.QSettings().value(
|
||||||
self.parent().songsSettingsSection + u'/display songbar',
|
self.parent().songsSettingsSection + u'/display songbar',
|
||||||
@ -597,7 +604,8 @@ class SlideController(QtGui.QWidget):
|
|||||||
log.debug(u'processManagerItem live = %s' % self.isLive)
|
log.debug(u'processManagerItem live = %s' % self.isLive)
|
||||||
self.onStopLoop()
|
self.onStopLoop()
|
||||||
old_item = self.serviceItem
|
old_item = self.serviceItem
|
||||||
self.serviceItem = serviceItem
|
# take a copy not a link to the servicemeanager copy.
|
||||||
|
self.serviceItem = copy.copy(serviceItem)
|
||||||
if old_item and self.isLive and old_item.is_capable(
|
if old_item and self.isLive and old_item.is_capable(
|
||||||
ItemCapabilities.ProvidesOwnDisplay):
|
ItemCapabilities.ProvidesOwnDisplay):
|
||||||
self._resetBlank()
|
self._resetBlank()
|
||||||
@ -1056,6 +1064,14 @@ class SlideController(QtGui.QWidget):
|
|||||||
else:
|
else:
|
||||||
self.playSlidesLoop.setChecked(checked)
|
self.playSlidesLoop.setChecked(checked)
|
||||||
log.debug(u'onPlaySlidesLoop %s' % checked)
|
log.debug(u'onPlaySlidesLoop %s' % checked)
|
||||||
|
if checked:
|
||||||
|
self.playSlidesLoop.setIcon(build_icon(u':/media/media_stop.png'))
|
||||||
|
self.playSlidesLoop.setText(UiStrings().StopPlaySlidesInLoop)
|
||||||
|
self.playSlidesOnce.setIcon(build_icon(u':/media/media_time.png'))
|
||||||
|
self.playSlidesOnce.setText(UiStrings().PlaySlidesToEnd)
|
||||||
|
else:
|
||||||
|
self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
|
||||||
|
self.playSlidesLoop.setText(UiStrings().PlaySlidesInLoop)
|
||||||
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
|
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
|
||||||
self.playSlidesOnce.setChecked(False)
|
self.playSlidesOnce.setChecked(False)
|
||||||
self.onToggleLoop()
|
self.onToggleLoop()
|
||||||
@ -1069,6 +1085,14 @@ class SlideController(QtGui.QWidget):
|
|||||||
else:
|
else:
|
||||||
self.playSlidesOnce.setChecked(checked)
|
self.playSlidesOnce.setChecked(checked)
|
||||||
log.debug(u'onPlaySlidesOnce %s' % checked)
|
log.debug(u'onPlaySlidesOnce %s' % checked)
|
||||||
|
if checked:
|
||||||
|
self.playSlidesOnce.setIcon(build_icon(u':/media/media_stop.png'))
|
||||||
|
self.playSlidesOnce.setText(UiStrings().StopPlaySlidesToEnd)
|
||||||
|
self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
|
||||||
|
self.playSlidesLoop.setText(UiStrings().PlaySlidesInLoop)
|
||||||
|
else:
|
||||||
|
self.playSlidesOnce.setIcon(build_icon(u':/media/media_time'))
|
||||||
|
self.playSlidesOnce.setText(UiStrings().PlaySlidesToEnd)
|
||||||
self.playSlidesMenu.setDefaultAction(self.playSlidesOnce)
|
self.playSlidesMenu.setDefaultAction(self.playSlidesOnce)
|
||||||
self.playSlidesLoop.setChecked(False)
|
self.playSlidesLoop.setChecked(False)
|
||||||
self.onToggleLoop()
|
self.onToggleLoop()
|
||||||
|
@ -39,7 +39,8 @@ from openlp.core.lib import OpenLPToolbar, get_text_file_string, build_icon, \
|
|||||||
check_directory_exists
|
check_directory_exists
|
||||||
from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, \
|
from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, \
|
||||||
BackgroundGradientType
|
BackgroundGradientType
|
||||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
|
||||||
|
context_menu_action, context_menu_separator
|
||||||
from openlp.core.theme import Theme
|
from openlp.core.theme import Theme
|
||||||
from openlp.core.ui import FileRenameForm, ThemeForm
|
from openlp.core.ui import FileRenameForm, ThemeForm
|
||||||
from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \
|
from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \
|
||||||
@ -104,25 +105,29 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
self.contextMenu)
|
self.contextMenu)
|
||||||
# build the context menu
|
# build the context menu
|
||||||
self.menu = QtGui.QMenu()
|
self.menu = QtGui.QMenu()
|
||||||
self.editAction = self.menu.addAction(
|
self.editAction = context_menu_action(
|
||||||
translate('OpenLP.ThemeManager', '&Edit Theme'))
|
self.menu, u':/themes/theme_edit.png',
|
||||||
self.editAction.setIcon(build_icon(u':/themes/theme_edit.png'))
|
translate('OpenLP.ThemeManager', '&Edit Theme'), self.onEditTheme)
|
||||||
self.copyAction = self.menu.addAction(
|
self.copyAction = context_menu_action(
|
||||||
translate('OpenLP.ThemeManager', '&Copy Theme'))
|
self.menu, u':/themes/theme_edit.png',
|
||||||
self.copyAction.setIcon(build_icon(u':/themes/theme_edit.png'))
|
translate('OpenLP.ThemeManager', '&Copy Theme'), self.onCopyTheme)
|
||||||
self.renameAction = self.menu.addAction(
|
self.renameAction = context_menu_action(
|
||||||
translate('OpenLP.ThemeManager', '&Rename Theme'))
|
self.menu, u':/themes/theme_edit.png',
|
||||||
self.renameAction.setIcon(build_icon(u':/themes/theme_edit.png'))
|
translate('OpenLP.ThemeManager', '&Rename Theme'),
|
||||||
self.deleteAction = self.menu.addAction(
|
self.onRenameTheme)
|
||||||
translate('OpenLP.ThemeManager', '&Delete Theme'))
|
self.deleteAction = context_menu_action(
|
||||||
self.deleteAction.setIcon(build_icon(u':/general/general_delete.png'))
|
self.menu, u':/general/general_delete.png',
|
||||||
self.separator = self.menu.addSeparator()
|
translate('OpenLP.ThemeManager', '&Delete Theme'),
|
||||||
self.globalAction = self.menu.addAction(
|
self.onDeleteTheme)
|
||||||
translate('OpenLP.ThemeManager', 'Set As &Global Default'))
|
context_menu_separator(self.menu)
|
||||||
self.globalAction.setIcon(build_icon(u':/general/general_export.png'))
|
self.globalAction = context_menu_action(
|
||||||
self.exportAction = self.menu.addAction(
|
self.menu, u':/general/general_export.png',
|
||||||
translate('OpenLP.ThemeManager', '&Export Theme'))
|
translate('OpenLP.ThemeManager', 'Set As &Global Default'),
|
||||||
self.exportAction.setIcon(build_icon(u':/general/general_export.png'))
|
self.changeGlobalFromScreen)
|
||||||
|
self.exportAction = context_menu_action(
|
||||||
|
self.menu, u':/general/general_export.png',
|
||||||
|
translate('OpenLP.ThemeManager', '&Export Theme'),
|
||||||
|
self.onExportTheme)
|
||||||
# Signals
|
# Signals
|
||||||
QtCore.QObject.connect(self.themeListWidget,
|
QtCore.QObject.connect(self.themeListWidget,
|
||||||
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
|
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
|
||||||
@ -198,19 +203,7 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
self.deleteAction.setVisible(True)
|
self.deleteAction.setVisible(True)
|
||||||
self.renameAction.setVisible(True)
|
self.renameAction.setVisible(True)
|
||||||
self.globalAction.setVisible(True)
|
self.globalAction.setVisible(True)
|
||||||
action = self.menu.exec_(self.themeListWidget.mapToGlobal(point))
|
self.menu.exec_(self.themeListWidget.mapToGlobal(point))
|
||||||
if action == self.editAction:
|
|
||||||
self.onEditTheme()
|
|
||||||
if action == self.copyAction:
|
|
||||||
self.onCopyTheme()
|
|
||||||
if action == self.renameAction:
|
|
||||||
self.onRenameTheme()
|
|
||||||
if action == self.deleteAction:
|
|
||||||
self.onDeleteTheme()
|
|
||||||
if action == self.globalAction:
|
|
||||||
self.changeGlobalFromScreen()
|
|
||||||
if action == self.exportAction:
|
|
||||||
self.onExportTheme()
|
|
||||||
|
|
||||||
def changeGlobalFromTab(self, themeName):
|
def changeGlobalFromTab(self, themeName):
|
||||||
"""
|
"""
|
||||||
@ -298,11 +291,10 @@ class ThemeManager(QtGui.QWidget):
|
|||||||
Copies an existing theme to a new name
|
Copies an existing theme to a new name
|
||||||
"""
|
"""
|
||||||
item = self.themeListWidget.currentItem()
|
item = self.themeListWidget.currentItem()
|
||||||
oldThemeName = unicode(
|
oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||||
translate('OpenLP.ThemeManager', 'Copy of %s',
|
self.fileRenameForm.fileNameEdit.setText(
|
||||||
'Copy of <theme name>')) % unicode(
|
unicode(translate('OpenLP.ThemeManager',
|
||||||
item.data(QtCore.Qt.UserRole).toString())
|
'Copy of %s','Copy of <theme name>')) % oldThemeName)
|
||||||
self.fileRenameForm.fileNameEdit.setText(oldThemeName)
|
|
||||||
if self.fileRenameForm.exec_(True):
|
if self.fileRenameForm.exec_(True):
|
||||||
newThemeName = unicode(self.fileRenameForm.fileNameEdit.text())
|
newThemeName = unicode(self.fileRenameForm.fileNameEdit.text())
|
||||||
if self.checkIfThemeExists(newThemeName):
|
if self.checkIfThemeExists(newThemeName):
|
||||||
|
@ -37,7 +37,7 @@ class ThemesTab(SettingsTab):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, parent, mainwindow):
|
def __init__(self, parent, mainwindow):
|
||||||
self.mainwindow = mainwindow
|
self.mainwindow = mainwindow
|
||||||
generalTranslated = translate('ThemeTab', 'Themes')
|
generalTranslated = translate('OpenLP.ThemesTab', 'Themes')
|
||||||
SettingsTab.__init__(self, parent, u'Themes', generalTranslated)
|
SettingsTab.__init__(self, parent, u'Themes', generalTranslated)
|
||||||
self.icon_path = u':/themes/theme_new.png'
|
self.icon_path = u':/themes/theme_new.png'
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ APPLICATION_VERSION = {}
|
|||||||
IMAGES_FILTER = None
|
IMAGES_FILTER = None
|
||||||
UNO_CONNECTION_TYPE = u'pipe'
|
UNO_CONNECTION_TYPE = u'pipe'
|
||||||
#UNO_CONNECTION_TYPE = u'socket'
|
#UNO_CONNECTION_TYPE = u'socket'
|
||||||
|
VERSION_SPLITTER = re.compile(r'([0-9]+).([0-9]+).([0-9]+)(?:-bzr([0-9]+))?')
|
||||||
|
|
||||||
class VersionThread(QtCore.QThread):
|
class VersionThread(QtCore.QThread):
|
||||||
"""
|
"""
|
||||||
@ -61,8 +62,6 @@ class VersionThread(QtCore.QThread):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
QtCore.QThread.__init__(self, parent)
|
QtCore.QThread.__init__(self, parent)
|
||||||
self.version_splitter = re.compile(
|
|
||||||
r'([0-9]+).([0-9]+).([0-9]+)(?:-bzr([0-9]+))?')
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""
|
"""
|
||||||
@ -73,7 +72,7 @@ class VersionThread(QtCore.QThread):
|
|||||||
version = check_latest_version(app_version)
|
version = check_latest_version(app_version)
|
||||||
remote_version = {}
|
remote_version = {}
|
||||||
local_version = {}
|
local_version = {}
|
||||||
match = self.version_splitter.match(version)
|
match = VERSION_SPLITTER.match(version)
|
||||||
if match:
|
if match:
|
||||||
remote_version[u'major'] = int(match.group(1))
|
remote_version[u'major'] = int(match.group(1))
|
||||||
remote_version[u'minor'] = int(match.group(2))
|
remote_version[u'minor'] = int(match.group(2))
|
||||||
@ -82,7 +81,7 @@ class VersionThread(QtCore.QThread):
|
|||||||
remote_version[u'revision'] = int(match.group(4))
|
remote_version[u'revision'] = int(match.group(4))
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
match = self.version_splitter.match(app_version[u'full'])
|
match = VERSION_SPLITTER.match(app_version[u'full'])
|
||||||
if match:
|
if match:
|
||||||
local_version[u'major'] = int(match.group(1))
|
local_version[u'major'] = int(match.group(1))
|
||||||
local_version[u'minor'] = int(match.group(2))
|
local_version[u'minor'] = int(match.group(2))
|
||||||
@ -387,6 +386,17 @@ def split_filename(path):
|
|||||||
else:
|
else:
|
||||||
return os.path.split(path)
|
return os.path.split(path)
|
||||||
|
|
||||||
|
def clean_filename(filename):
|
||||||
|
"""
|
||||||
|
Removes invalid characters from the given ``filename``.
|
||||||
|
|
||||||
|
``filename``
|
||||||
|
The "dirty" file name to clean.
|
||||||
|
"""
|
||||||
|
if not isinstance(filename, unicode):
|
||||||
|
filename = unicode(filename, u'utf-8')
|
||||||
|
return re.sub(r'[/\\?*|<>\[\]":<>+%]+', u'_', filename).strip(u'_')
|
||||||
|
|
||||||
def delete_file(file_path_name):
|
def delete_file(file_path_name):
|
||||||
"""
|
"""
|
||||||
Deletes a file from the system.
|
Deletes a file from the system.
|
||||||
@ -460,25 +470,6 @@ def file_is_unicode(filename):
|
|||||||
return None
|
return None
|
||||||
return ucsfile
|
return ucsfile
|
||||||
|
|
||||||
def string_is_unicode(test_string):
|
|
||||||
"""
|
|
||||||
Makes sure a string is unicode.
|
|
||||||
|
|
||||||
``test_string``
|
|
||||||
The string to confirm is unicode.
|
|
||||||
"""
|
|
||||||
return_string = u''
|
|
||||||
if not test_string:
|
|
||||||
return return_string
|
|
||||||
if isinstance(test_string, unicode):
|
|
||||||
return_string = test_string
|
|
||||||
if not isinstance(test_string, unicode):
|
|
||||||
try:
|
|
||||||
return_string = unicode(test_string, u'utf-8')
|
|
||||||
except UnicodeError:
|
|
||||||
log.exception("Error encoding string to unicode")
|
|
||||||
return return_string
|
|
||||||
|
|
||||||
def get_uno_command():
|
def get_uno_command():
|
||||||
"""
|
"""
|
||||||
Returns the UNO command to launch an openoffice.org instance.
|
Returns the UNO command to launch an openoffice.org instance.
|
||||||
@ -511,5 +502,5 @@ from actions import ActionList
|
|||||||
|
|
||||||
__all__ = [u'AppLocation', u'get_application_version', u'check_latest_version',
|
__all__ = [u'AppLocation', u'get_application_version', u'check_latest_version',
|
||||||
u'add_actions', u'get_filesystem_encoding', u'LanguageManager',
|
u'add_actions', u'get_filesystem_encoding', u'LanguageManager',
|
||||||
u'ActionList', u'get_web_page', u'file_is_unicode', u'string_is_unicode',
|
u'ActionList', u'get_web_page', u'file_is_unicode', u'get_uno_command',
|
||||||
u'get_uno_command', u'get_uno_instance', u'delete_file']
|
u'get_uno_instance', u'delete_file', u'clean_filename']
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||||
from openlp.core.lib.db import Manager
|
from openlp.core.lib.db import Manager
|
||||||
@ -43,7 +43,7 @@ class AlertsPlugin(Plugin):
|
|||||||
log.info(u'Alerts Plugin loaded')
|
log.info(u'Alerts Plugin loaded')
|
||||||
|
|
||||||
def __init__(self, plugin_helpers):
|
def __init__(self, plugin_helpers):
|
||||||
Plugin.__init__(self, u'Alerts', plugin_helpers,
|
Plugin.__init__(self, u'alerts', plugin_helpers,
|
||||||
settings_tab_class=AlertsTab)
|
settings_tab_class=AlertsTab)
|
||||||
self.weight = -3
|
self.weight = -3
|
||||||
self.icon_path = u':/plugins/plugin_alerts.png'
|
self.icon_path = u':/plugins/plugin_alerts.png'
|
||||||
@ -104,7 +104,7 @@ class AlertsPlugin(Plugin):
|
|||||||
def about(self):
|
def about(self):
|
||||||
about_text = translate('AlertsPlugin', '<strong>Alerts Plugin</strong>'
|
about_text = translate('AlertsPlugin', '<strong>Alerts Plugin</strong>'
|
||||||
'<br />The alert plugin controls the displaying of nursery alerts '
|
'<br />The alert plugin controls the displaying of nursery alerts '
|
||||||
'on the display screen')
|
'on the display screen.')
|
||||||
return about_text
|
return about_text
|
||||||
|
|
||||||
def setPluginTextStrings(self):
|
def setPluginTextStrings(self):
|
||||||
|
@ -176,8 +176,8 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
|
|||||||
# We found '<>' in the alert text, but the ParameterEdit field is empty.
|
# We found '<>' in the alert text, but the ParameterEdit field is empty.
|
||||||
if text.find(u'<>') != -1 and not self.parameterEdit.text() and \
|
if text.find(u'<>') != -1 and not self.parameterEdit.text() and \
|
||||||
QtGui.QMessageBox.question(self,
|
QtGui.QMessageBox.question(self,
|
||||||
translate('AlertPlugin.AlertForm', 'No Parameter Found'),
|
translate('AlertsPlugin.AlertForm', 'No Parameter Found'),
|
||||||
translate('AlertPlugin.AlertForm', 'You have not entered a '
|
translate('AlertsPlugin.AlertForm', 'You have not entered a '
|
||||||
'parameter to be replaced.\nDo you want to continue anyway?'),
|
'parameter to be replaced.\nDo you want to continue anyway?'),
|
||||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
|
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
|
||||||
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
|
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
|
||||||
@ -187,8 +187,8 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
|
|||||||
# in the alert text.
|
# in the alert text.
|
||||||
elif text.find(u'<>') == -1 and self.parameterEdit.text() and \
|
elif text.find(u'<>') == -1 and self.parameterEdit.text() and \
|
||||||
QtGui.QMessageBox.question(self,
|
QtGui.QMessageBox.question(self,
|
||||||
translate('AlertPlugin.AlertForm', 'No Placeholder Found'),
|
translate('AlertsPlugin.AlertForm', 'No Placeholder Found'),
|
||||||
translate('AlertPlugin.AlertForm', 'The alert text does not'
|
translate('AlertsPlugin.AlertForm', 'The alert text does not'
|
||||||
' contain \'<>\'.\nDo you want to continue anyway?'),
|
' contain \'<>\'.\nDo you want to continue anyway?'),
|
||||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
|
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
|
||||||
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
|
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
|
||||||
|
@ -44,85 +44,85 @@ class AlertsTab(SettingsTab):
|
|||||||
self.fontGroupBox.setObjectName(u'fontGroupBox')
|
self.fontGroupBox.setObjectName(u'fontGroupBox')
|
||||||
self.fontLayout = QtGui.QFormLayout(self.fontGroupBox)
|
self.fontLayout = QtGui.QFormLayout(self.fontGroupBox)
|
||||||
self.fontLayout.setObjectName(u'fontLayout')
|
self.fontLayout.setObjectName(u'fontLayout')
|
||||||
self.FontLabel = QtGui.QLabel(self.fontGroupBox)
|
self.fontLabel = QtGui.QLabel(self.fontGroupBox)
|
||||||
self.FontLabel.setObjectName(u'FontLabel')
|
self.fontLabel.setObjectName(u'fontLabel')
|
||||||
self.FontComboBox = QtGui.QFontComboBox(self.fontGroupBox)
|
self.fontComboBox = QtGui.QFontComboBox(self.fontGroupBox)
|
||||||
self.FontComboBox.setObjectName(u'FontComboBox')
|
self.fontComboBox.setObjectName(u'fontComboBox')
|
||||||
self.fontLayout.addRow(self.FontLabel, self.FontComboBox)
|
self.fontLayout.addRow(self.fontLabel, self.fontComboBox)
|
||||||
self.FontColorLabel = QtGui.QLabel(self.fontGroupBox)
|
self.fontColorLabel = QtGui.QLabel(self.fontGroupBox)
|
||||||
self.FontColorLabel.setObjectName(u'FontColorLabel')
|
self.fontColorLabel.setObjectName(u'fontColorLabel')
|
||||||
self.ColorLayout = QtGui.QHBoxLayout()
|
self.colorLayout = QtGui.QHBoxLayout()
|
||||||
self.ColorLayout.setObjectName(u'ColorLayout')
|
self.colorLayout.setObjectName(u'colorLayout')
|
||||||
self.FontColorButton = QtGui.QPushButton(self.fontGroupBox)
|
self.fontColorButton = QtGui.QPushButton(self.fontGroupBox)
|
||||||
self.FontColorButton.setObjectName(u'FontColorButton')
|
self.fontColorButton.setObjectName(u'fontColorButton')
|
||||||
self.ColorLayout.addWidget(self.FontColorButton)
|
self.colorLayout.addWidget(self.fontColorButton)
|
||||||
self.ColorLayout.addSpacing(20)
|
self.colorLayout.addSpacing(20)
|
||||||
self.BackgroundColorLabel = QtGui.QLabel(self.fontGroupBox)
|
self.backgroundColorLabel = QtGui.QLabel(self.fontGroupBox)
|
||||||
self.BackgroundColorLabel.setObjectName(u'BackgroundColorLabel')
|
self.backgroundColorLabel.setObjectName(u'backgroundColorLabel')
|
||||||
self.ColorLayout.addWidget(self.BackgroundColorLabel)
|
self.colorLayout.addWidget(self.backgroundColorLabel)
|
||||||
self.BackgroundColorButton = QtGui.QPushButton(self.fontGroupBox)
|
self.backgroundColorButton = QtGui.QPushButton(self.fontGroupBox)
|
||||||
self.BackgroundColorButton.setObjectName(u'BackgroundColorButton')
|
self.backgroundColorButton.setObjectName(u'backgroundColorButton')
|
||||||
self.ColorLayout.addWidget(self.BackgroundColorButton)
|
self.colorLayout.addWidget(self.backgroundColorButton)
|
||||||
self.fontLayout.addRow(self.FontColorLabel, self.ColorLayout)
|
self.fontLayout.addRow(self.fontColorLabel, self.colorLayout)
|
||||||
self.FontSizeLabel = QtGui.QLabel(self.fontGroupBox)
|
self.fontSizeLabel = QtGui.QLabel(self.fontGroupBox)
|
||||||
self.FontSizeLabel.setObjectName(u'FontSizeLabel')
|
self.fontSizeLabel.setObjectName(u'fontSizeLabel')
|
||||||
self.FontSizeSpinBox = QtGui.QSpinBox(self.fontGroupBox)
|
self.fontSizeSpinBox = QtGui.QSpinBox(self.fontGroupBox)
|
||||||
self.FontSizeSpinBox.setObjectName(u'FontSizeSpinBox')
|
self.fontSizeSpinBox.setObjectName(u'fontSizeSpinBox')
|
||||||
self.fontLayout.addRow(self.FontSizeLabel, self.FontSizeSpinBox)
|
self.fontLayout.addRow(self.fontSizeLabel, self.fontSizeSpinBox)
|
||||||
self.TimeoutLabel = QtGui.QLabel(self.fontGroupBox)
|
self.timeoutLabel = QtGui.QLabel(self.fontGroupBox)
|
||||||
self.TimeoutLabel.setObjectName(u'TimeoutLabel')
|
self.timeoutLabel.setObjectName(u'timeoutLabel')
|
||||||
self.TimeoutSpinBox = QtGui.QSpinBox(self.fontGroupBox)
|
self.timeoutSpinBox = QtGui.QSpinBox(self.fontGroupBox)
|
||||||
self.TimeoutSpinBox.setMaximum(180)
|
self.timeoutSpinBox.setMaximum(180)
|
||||||
self.TimeoutSpinBox.setObjectName(u'TimeoutSpinBox')
|
self.timeoutSpinBox.setObjectName(u'timeoutSpinBox')
|
||||||
self.fontLayout.addRow(self.TimeoutLabel, self.TimeoutSpinBox)
|
self.fontLayout.addRow(self.timeoutLabel, self.timeoutSpinBox)
|
||||||
create_valign_combo(self, self.fontGroupBox, self.fontLayout)
|
create_valign_combo(self, self.fontGroupBox, self.fontLayout)
|
||||||
self.leftLayout.addWidget(self.fontGroupBox)
|
self.leftLayout.addWidget(self.fontGroupBox)
|
||||||
self.leftLayout.addStretch()
|
self.leftLayout.addStretch()
|
||||||
self.PreviewGroupBox = QtGui.QGroupBox(self.rightColumn)
|
self.previewGroupBox = QtGui.QGroupBox(self.rightColumn)
|
||||||
self.PreviewGroupBox.setObjectName(u'PreviewGroupBox')
|
self.previewGroupBox.setObjectName(u'previewGroupBox')
|
||||||
self.PreviewLayout = QtGui.QVBoxLayout(self.PreviewGroupBox)
|
self.previewLayout = QtGui.QVBoxLayout(self.previewGroupBox)
|
||||||
self.PreviewLayout.setObjectName(u'PreviewLayout')
|
self.previewLayout.setObjectName(u'previewLayout')
|
||||||
self.FontPreview = QtGui.QLineEdit(self.PreviewGroupBox)
|
self.fontPreview = QtGui.QLineEdit(self.previewGroupBox)
|
||||||
self.FontPreview.setObjectName(u'FontPreview')
|
self.fontPreview.setObjectName(u'fontPreview')
|
||||||
self.PreviewLayout.addWidget(self.FontPreview)
|
self.previewLayout.addWidget(self.fontPreview)
|
||||||
self.rightLayout.addWidget(self.PreviewGroupBox)
|
self.rightLayout.addWidget(self.previewGroupBox)
|
||||||
self.rightLayout.addStretch()
|
self.rightLayout.addStretch()
|
||||||
# Signals and slots
|
# Signals and slots
|
||||||
QtCore.QObject.connect(self.BackgroundColorButton,
|
QtCore.QObject.connect(self.backgroundColorButton,
|
||||||
QtCore.SIGNAL(u'pressed()'), self.onBackgroundColorButtonClicked)
|
QtCore.SIGNAL(u'pressed()'), self.onBackgroundColorButtonClicked)
|
||||||
QtCore.QObject.connect(self.FontColorButton,
|
QtCore.QObject.connect(self.fontColorButton,
|
||||||
QtCore.SIGNAL(u'pressed()'), self.onFontColorButtonClicked)
|
QtCore.SIGNAL(u'pressed()'), self.onFontColorButtonClicked)
|
||||||
QtCore.QObject.connect(self.FontComboBox,
|
QtCore.QObject.connect(self.fontComboBox,
|
||||||
QtCore.SIGNAL(u'activated(int)'), self.onFontComboBoxClicked)
|
QtCore.SIGNAL(u'activated(int)'), self.onFontComboBoxClicked)
|
||||||
QtCore.QObject.connect(self.TimeoutSpinBox,
|
QtCore.QObject.connect(self.timeoutSpinBox,
|
||||||
QtCore.SIGNAL(u'valueChanged(int)'), self.onTimeoutSpinBoxChanged)
|
QtCore.SIGNAL(u'valueChanged(int)'), self.onTimeoutSpinBoxChanged)
|
||||||
QtCore.QObject.connect(self.FontSizeSpinBox,
|
QtCore.QObject.connect(self.fontSizeSpinBox,
|
||||||
QtCore.SIGNAL(u'valueChanged(int)'), self.onFontSizeSpinBoxChanged)
|
QtCore.SIGNAL(u'valueChanged(int)'), self.onFontSizeSpinBoxChanged)
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslateUi(self):
|
||||||
self.fontGroupBox.setTitle(
|
self.fontGroupBox.setTitle(
|
||||||
translate('AlertsPlugin.AlertsTab', 'Font'))
|
translate('AlertsPlugin.AlertsTab', 'Font'))
|
||||||
self.FontLabel.setText(
|
self.fontLabel.setText(
|
||||||
translate('AlertsPlugin.AlertsTab', 'Font name:'))
|
translate('AlertsPlugin.AlertsTab', 'Font name:'))
|
||||||
self.FontColorLabel.setText(
|
self.fontColorLabel.setText(
|
||||||
translate('AlertsPlugin.AlertsTab', 'Font color:'))
|
translate('AlertsPlugin.AlertsTab', 'Font color:'))
|
||||||
self.BackgroundColorLabel.setText(
|
self.backgroundColorLabel.setText(
|
||||||
translate('AlertsPlugin.AlertsTab', 'Background color:'))
|
translate('AlertsPlugin.AlertsTab', 'Background color:'))
|
||||||
self.FontSizeLabel.setText(
|
self.fontSizeLabel.setText(
|
||||||
translate('AlertsPlugin.AlertsTab', 'Font size:'))
|
translate('AlertsPlugin.AlertsTab', 'Font size:'))
|
||||||
self.FontSizeSpinBox.setSuffix(UiStrings().FontSizePtUnit)
|
self.fontSizeSpinBox.setSuffix(UiStrings().FontSizePtUnit)
|
||||||
self.TimeoutLabel.setText(
|
self.timeoutLabel.setText(
|
||||||
translate('AlertsPlugin.AlertsTab', 'Alert timeout:'))
|
translate('AlertsPlugin.AlertsTab', 'Alert timeout:'))
|
||||||
self.TimeoutSpinBox.setSuffix(UiStrings().Seconds)
|
self.timeoutSpinBox.setSuffix(UiStrings().Seconds)
|
||||||
self.PreviewGroupBox.setTitle(UiStrings().Preview)
|
self.previewGroupBox.setTitle(UiStrings().Preview)
|
||||||
self.FontPreview.setText(UiStrings().OLPV2)
|
self.fontPreview.setText(UiStrings().OLPV2)
|
||||||
|
|
||||||
def onBackgroundColorButtonClicked(self):
|
def onBackgroundColorButtonClicked(self):
|
||||||
new_color = QtGui.QColorDialog.getColor(
|
new_color = QtGui.QColorDialog.getColor(
|
||||||
QtGui.QColor(self.bg_color), self)
|
QtGui.QColor(self.bg_color), self)
|
||||||
if new_color.isValid():
|
if new_color.isValid():
|
||||||
self.bg_color = new_color.name()
|
self.bg_color = new_color.name()
|
||||||
self.BackgroundColorButton.setStyleSheet(
|
self.backgroundColorButton.setStyleSheet(
|
||||||
u'background-color: %s' % self.bg_color)
|
u'background-color: %s' % self.bg_color)
|
||||||
self.updateDisplay()
|
self.updateDisplay()
|
||||||
|
|
||||||
@ -134,15 +134,15 @@ class AlertsTab(SettingsTab):
|
|||||||
QtGui.QColor(self.font_color), self)
|
QtGui.QColor(self.font_color), self)
|
||||||
if new_color.isValid():
|
if new_color.isValid():
|
||||||
self.font_color = new_color.name()
|
self.font_color = new_color.name()
|
||||||
self.FontColorButton.setStyleSheet(
|
self.fontColorButton.setStyleSheet(
|
||||||
u'background-color: %s' % self.font_color)
|
u'background-color: %s' % self.font_color)
|
||||||
self.updateDisplay()
|
self.updateDisplay()
|
||||||
|
|
||||||
def onTimeoutSpinBoxChanged(self):
|
def onTimeoutSpinBoxChanged(self):
|
||||||
self.timeout = self.TimeoutSpinBox.value()
|
self.timeout = self.timeoutSpinBox.value()
|
||||||
|
|
||||||
def onFontSizeSpinBoxChanged(self):
|
def onFontSizeSpinBoxChanged(self):
|
||||||
self.font_size = self.FontSizeSpinBox.value()
|
self.font_size = self.fontSizeSpinBox.value()
|
||||||
self.updateDisplay()
|
self.updateDisplay()
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
@ -160,16 +160,16 @@ class AlertsTab(SettingsTab):
|
|||||||
self.location = settings.value(
|
self.location = settings.value(
|
||||||
u'location', QtCore.QVariant(1)).toInt()[0]
|
u'location', QtCore.QVariant(1)).toInt()[0]
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
self.FontSizeSpinBox.setValue(self.font_size)
|
self.fontSizeSpinBox.setValue(self.font_size)
|
||||||
self.TimeoutSpinBox.setValue(self.timeout)
|
self.timeoutSpinBox.setValue(self.timeout)
|
||||||
self.FontColorButton.setStyleSheet(
|
self.fontColorButton.setStyleSheet(
|
||||||
u'background-color: %s' % self.font_color)
|
u'background-color: %s' % self.font_color)
|
||||||
self.BackgroundColorButton.setStyleSheet(
|
self.backgroundColorButton.setStyleSheet(
|
||||||
u'background-color: %s' % self.bg_color)
|
u'background-color: %s' % self.bg_color)
|
||||||
self.verticalComboBox.setCurrentIndex(self.location)
|
self.verticalComboBox.setCurrentIndex(self.location)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setFamily(self.font_face)
|
font.setFamily(self.font_face)
|
||||||
self.FontComboBox.setCurrentFont(font)
|
self.fontComboBox.setCurrentFont(font)
|
||||||
self.updateDisplay()
|
self.updateDisplay()
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
@ -178,7 +178,7 @@ class AlertsTab(SettingsTab):
|
|||||||
settings.setValue(u'background color', QtCore.QVariant(self.bg_color))
|
settings.setValue(u'background color', QtCore.QVariant(self.bg_color))
|
||||||
settings.setValue(u'font color', QtCore.QVariant(self.font_color))
|
settings.setValue(u'font color', QtCore.QVariant(self.font_color))
|
||||||
settings.setValue(u'font size', QtCore.QVariant(self.font_size))
|
settings.setValue(u'font size', QtCore.QVariant(self.font_size))
|
||||||
self.font_face = self.FontComboBox.currentFont().family()
|
self.font_face = self.fontComboBox.currentFont().family()
|
||||||
settings.setValue(u'font face', QtCore.QVariant(self.font_face))
|
settings.setValue(u'font face', QtCore.QVariant(self.font_face))
|
||||||
settings.setValue(u'timeout', QtCore.QVariant(self.timeout))
|
settings.setValue(u'timeout', QtCore.QVariant(self.timeout))
|
||||||
self.location = self.verticalComboBox.currentIndex()
|
self.location = self.verticalComboBox.currentIndex()
|
||||||
@ -187,10 +187,10 @@ class AlertsTab(SettingsTab):
|
|||||||
|
|
||||||
def updateDisplay(self):
|
def updateDisplay(self):
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setFamily(self.FontComboBox.currentFont().family())
|
font.setFamily(self.fontComboBox.currentFont().family())
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
font.setPointSize(self.font_size)
|
font.setPointSize(self.font_size)
|
||||||
self.FontPreview.setFont(font)
|
self.fontPreview.setFont(font)
|
||||||
self.FontPreview.setStyleSheet(u'background-color: %s; color: %s' %
|
self.fontPreview.setStyleSheet(u'background-color: %s; color: %s' %
|
||||||
(self.bg_color, self.font_color))
|
(self.bg_color, self.font_color))
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ class BiblePlugin(Plugin):
|
|||||||
log.info(u'Bible Plugin loaded')
|
log.info(u'Bible Plugin loaded')
|
||||||
|
|
||||||
def __init__(self, plugin_helpers):
|
def __init__(self, plugin_helpers):
|
||||||
Plugin.__init__(self, u'Bibles', plugin_helpers,
|
Plugin.__init__(self, u'bibles', plugin_helpers,
|
||||||
BibleMediaItem, BiblesTab)
|
BibleMediaItem, BiblesTab)
|
||||||
self.weight = -9
|
self.weight = -9
|
||||||
self.icon_path = u':/plugins/plugin_bibles.png'
|
self.icon_path = u':/plugins/plugin_bibles.png'
|
||||||
@ -117,9 +117,9 @@ class BiblePlugin(Plugin):
|
|||||||
self.toolsUpgradeItem = QtGui.QAction(tools_menu)
|
self.toolsUpgradeItem = QtGui.QAction(tools_menu)
|
||||||
self.toolsUpgradeItem.setObjectName(u'toolsUpgradeItem')
|
self.toolsUpgradeItem.setObjectName(u'toolsUpgradeItem')
|
||||||
self.toolsUpgradeItem.setText(
|
self.toolsUpgradeItem.setText(
|
||||||
translate('BiblePlugin', '&Upgrade older Bibles'))
|
translate('BiblesPlugin', '&Upgrade older Bibles'))
|
||||||
self.toolsUpgradeItem.setStatusTip(
|
self.toolsUpgradeItem.setStatusTip(
|
||||||
translate('BiblePlugin', 'Upgrade the Bible databases to the '
|
translate('BiblesPlugin', 'Upgrade the Bible databases to the '
|
||||||
'latest format.'))
|
'latest format.'))
|
||||||
tools_menu.addAction(self.toolsUpgradeItem)
|
tools_menu.addAction(self.toolsUpgradeItem)
|
||||||
QtCore.QObject.connect(self.toolsUpgradeItem,
|
QtCore.QObject.connect(self.toolsUpgradeItem,
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
"""
|
"""
|
||||||
The bible import functions for OpenLP
|
The bible import functions for OpenLP
|
||||||
"""
|
"""
|
||||||
import csv
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
@ -39,7 +38,7 @@ from openlp.core.lib import Receiver, translate
|
|||||||
from openlp.core.lib.db import delete_database
|
from openlp.core.lib.db import delete_database
|
||||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||||
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
|
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
|
||||||
from openlp.core.utils import AppLocation, string_is_unicode
|
from openlp.core.utils import AppLocation
|
||||||
from openlp.plugins.bibles.lib.manager import BibleFormat
|
from openlp.plugins.bibles.lib.manager import BibleFormat
|
||||||
from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename
|
from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename
|
||||||
|
|
||||||
|
@ -27,20 +27,19 @@
|
|||||||
The bible import functions for OpenLP
|
The bible import functions for OpenLP
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import os.path
|
import os
|
||||||
import re
|
|
||||||
import shutil
|
import shutil
|
||||||
|
from tempfile import gettempdir
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
from openlp.core.lib import Receiver, SettingsManager, translate, \
|
from openlp.core.lib import Receiver, SettingsManager, translate, \
|
||||||
check_directory_exists
|
check_directory_exists
|
||||||
from openlp.core.lib.db import delete_database
|
|
||||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||||
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
|
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
|
||||||
from openlp.core.utils import AppLocation, delete_file
|
from openlp.core.utils import AppLocation, delete_file
|
||||||
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB,\
|
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB, \
|
||||||
BiblesResourcesDB, clean_filename
|
BiblesResourcesDB
|
||||||
from openlp.plugins.bibles.lib.http import BSExtract, BGExtract, CWExtract
|
from openlp.plugins.bibles.lib.http import BSExtract, BGExtract, CWExtract
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -70,8 +69,8 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
self.mediaItem = bibleplugin.mediaItem
|
self.mediaItem = bibleplugin.mediaItem
|
||||||
self.suffix = u'.sqlite'
|
self.suffix = u'.sqlite'
|
||||||
self.settingsSection = u'bibles'
|
self.settingsSection = u'bibles'
|
||||||
self.path = AppLocation.get_section_data_path(
|
self.path = AppLocation.get_section_data_path(self.settingsSection)
|
||||||
self.settingsSection)
|
self.temp_dir = os.path.join(gettempdir(), u'openlp')
|
||||||
self.files = self.manager.old_bible_databases
|
self.files = self.manager.old_bible_databases
|
||||||
self.success = {}
|
self.success = {}
|
||||||
self.newbibles = {}
|
self.newbibles = {}
|
||||||
@ -93,20 +92,6 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
log.debug(u'Stopping import')
|
log.debug(u'Stopping import')
|
||||||
self.stop_import_flag = True
|
self.stop_import_flag = True
|
||||||
|
|
||||||
def onCheckBoxIndexChanged(self, index):
|
|
||||||
"""
|
|
||||||
Show/Hide warnings if CheckBox state has changed
|
|
||||||
"""
|
|
||||||
for number, filename in enumerate(self.files):
|
|
||||||
if not self.checkBox[number].checkState() == QtCore.Qt.Checked:
|
|
||||||
self.verticalWidget[number].hide()
|
|
||||||
self.formWidget[number].hide()
|
|
||||||
else:
|
|
||||||
version_name = unicode(self.versionNameEdit[number].text())
|
|
||||||
if self.manager.exists(version_name):
|
|
||||||
self.verticalWidget[number].show()
|
|
||||||
self.formWidget[number].show()
|
|
||||||
|
|
||||||
def reject(self):
|
def reject(self):
|
||||||
"""
|
"""
|
||||||
Stop the wizard on cancel button, close button or ESC key.
|
Stop the wizard on cancel button, close button or ESC key.
|
||||||
@ -115,8 +100,6 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
self.stop_import_flag = True
|
self.stop_import_flag = True
|
||||||
if not self.currentPage() == self.progressPage:
|
if not self.currentPage() == self.progressPage:
|
||||||
self.done(QtGui.QDialog.Rejected)
|
self.done(QtGui.QDialog.Rejected)
|
||||||
else:
|
|
||||||
self.postWizard()
|
|
||||||
|
|
||||||
def onCurrentIdChanged(self, pageId):
|
def onCurrentIdChanged(self, pageId):
|
||||||
"""
|
"""
|
||||||
@ -126,7 +109,7 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
self.preWizard()
|
self.preWizard()
|
||||||
self.performWizard()
|
self.performWizard()
|
||||||
self.postWizard()
|
self.postWizard()
|
||||||
elif self.page(pageId) == self.selectPage and self.maxBibles == 0:
|
elif self.page(pageId) == self.selectPage and not self.files:
|
||||||
self.next()
|
self.next()
|
||||||
|
|
||||||
def onBackupBrowseButtonClicked(self):
|
def onBackupBrowseButtonClicked(self):
|
||||||
@ -245,78 +228,13 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
Add the content to the scrollArea.
|
Add the content to the scrollArea.
|
||||||
"""
|
"""
|
||||||
self.checkBox = {}
|
self.checkBox = {}
|
||||||
self.versionNameEdit = {}
|
|
||||||
self.versionNameLabel = {}
|
|
||||||
self.versionInfoLabel = {}
|
|
||||||
self.versionInfoPixmap = {}
|
|
||||||
self.verticalWidget = {}
|
|
||||||
self.horizontalLayout = {}
|
|
||||||
self.formWidget = {}
|
|
||||||
self.formLayoutAttention = {}
|
|
||||||
for number, filename in enumerate(self.files):
|
for number, filename in enumerate(self.files):
|
||||||
bible = OldBibleDB(self.mediaItem, path=self.path, file=filename[0])
|
bible = OldBibleDB(self.mediaItem, path=self.path, file=filename[0])
|
||||||
self.checkBox[number] = QtGui.QCheckBox(self.scrollAreaContents)
|
self.checkBox[number] = QtGui.QCheckBox(self.scrollAreaContents)
|
||||||
checkBoxName = u'checkBox[%d]' % number
|
self.checkBox[number].setObjectName(u'checkBox[%d]' % number)
|
||||||
self.checkBox[number].setObjectName(checkBoxName)
|
|
||||||
self.checkBox[number].setText(bible.get_name())
|
self.checkBox[number].setText(bible.get_name())
|
||||||
self.checkBox[number].setCheckState(QtCore.Qt.Checked)
|
self.checkBox[number].setCheckState(QtCore.Qt.Checked)
|
||||||
self.formLayout.addWidget(self.checkBox[number])
|
self.formLayout.addWidget(self.checkBox[number])
|
||||||
self.verticalWidget[number] = QtGui.QWidget(self.scrollAreaContents)
|
|
||||||
verticalWidgetName = u'verticalWidget[%d]' % number
|
|
||||||
self.verticalWidget[number].setObjectName(verticalWidgetName)
|
|
||||||
self.horizontalLayout[number] = QtGui.QHBoxLayout(
|
|
||||||
self.verticalWidget[number])
|
|
||||||
self.horizontalLayout[number].setContentsMargins(25, 0, 0, 0)
|
|
||||||
horizontalLayoutName = u'horizontalLayout[%d]' % number
|
|
||||||
self.horizontalLayout[number].setObjectName(horizontalLayoutName)
|
|
||||||
self.versionInfoPixmap[number] = QtGui.QLabel(
|
|
||||||
self.verticalWidget[number])
|
|
||||||
versionInfoPixmapName = u'versionInfoPixmap[%d]' % number
|
|
||||||
self.versionInfoPixmap[number].setObjectName(versionInfoPixmapName)
|
|
||||||
self.versionInfoPixmap[number].setPixmap(QtGui.QPixmap(
|
|
||||||
u':/bibles/bibles_upgrade_alert.png'))
|
|
||||||
self.versionInfoPixmap[number].setAlignment(QtCore.Qt.AlignRight)
|
|
||||||
self.horizontalLayout[number].addWidget(
|
|
||||||
self.versionInfoPixmap[number])
|
|
||||||
self.versionInfoLabel[number] = QtGui.QLabel(
|
|
||||||
self.verticalWidget[number])
|
|
||||||
versionInfoLabelName = u'versionInfoLabel[%d]' % number
|
|
||||||
self.versionInfoLabel[number].setObjectName(versionInfoLabelName)
|
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,
|
|
||||||
QtGui.QSizePolicy.Preferred)
|
|
||||||
sizePolicy.setHorizontalStretch(0)
|
|
||||||
sizePolicy.setVerticalStretch(0)
|
|
||||||
sizePolicy.setHeightForWidth(
|
|
||||||
self.versionInfoLabel[number].sizePolicy().hasHeightForWidth())
|
|
||||||
self.versionInfoLabel[number].setSizePolicy(sizePolicy)
|
|
||||||
self.horizontalLayout[number].addWidget(
|
|
||||||
self.versionInfoLabel[number])
|
|
||||||
self.formLayout.addWidget(self.verticalWidget[number])
|
|
||||||
self.formWidget[number] = QtGui.QWidget(self.scrollAreaContents)
|
|
||||||
formWidgetName = u'formWidget[%d]' % number
|
|
||||||
self.formWidget[number].setObjectName(formWidgetName)
|
|
||||||
self.formLayoutAttention[number] = QtGui.QFormLayout(
|
|
||||||
self.formWidget[number])
|
|
||||||
self.formLayoutAttention[number].setContentsMargins(25, 0, 0, 5)
|
|
||||||
formLayoutAttentionName = u'formLayoutAttention[%d]' % number
|
|
||||||
self.formLayoutAttention[number].setObjectName(
|
|
||||||
formLayoutAttentionName)
|
|
||||||
self.versionNameLabel[number] = QtGui.QLabel(
|
|
||||||
self.formWidget[number])
|
|
||||||
self.versionNameLabel[number].setObjectName(u'VersionNameLabel')
|
|
||||||
self.formLayoutAttention[number].setWidget(0,
|
|
||||||
QtGui.QFormLayout.LabelRole, self.versionNameLabel[number])
|
|
||||||
self.versionNameEdit[number] = QtGui.QLineEdit(
|
|
||||||
self.formWidget[number])
|
|
||||||
self.versionNameEdit[number].setObjectName(u'VersionNameEdit')
|
|
||||||
self.formLayoutAttention[number].setWidget(0,
|
|
||||||
QtGui.QFormLayout.FieldRole, self.versionNameEdit[number])
|
|
||||||
self.versionNameEdit[number].setText(bible.get_name())
|
|
||||||
self.formLayout.addWidget(self.formWidget[number])
|
|
||||||
# Set up the Signal for the checkbox.
|
|
||||||
QtCore.QObject.connect(self.checkBox[number],
|
|
||||||
QtCore.SIGNAL(u'stateChanged(int)'),
|
|
||||||
self.onCheckBoxIndexChanged)
|
|
||||||
self.spacerItem = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum,
|
self.spacerItem = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum,
|
||||||
QtGui.QSizePolicy.Expanding)
|
QtGui.QSizePolicy.Expanding)
|
||||||
self.formLayout.addItem(self.spacerItem)
|
self.formLayout.addItem(self.spacerItem)
|
||||||
@ -329,23 +247,6 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
for number, filename in enumerate(self.files):
|
for number, filename in enumerate(self.files):
|
||||||
self.formLayout.removeWidget(self.checkBox[number])
|
self.formLayout.removeWidget(self.checkBox[number])
|
||||||
self.checkBox[number].setParent(None)
|
self.checkBox[number].setParent(None)
|
||||||
self.horizontalLayout[number].removeWidget(
|
|
||||||
self.versionInfoPixmap[number])
|
|
||||||
self.versionInfoPixmap[number].setParent(None)
|
|
||||||
self.horizontalLayout[number].removeWidget(
|
|
||||||
self.versionInfoLabel[number])
|
|
||||||
self.versionInfoLabel[number].setParent(None)
|
|
||||||
self.formLayout.removeWidget(self.verticalWidget[number])
|
|
||||||
self.verticalWidget[number].setParent(None)
|
|
||||||
self.formLayoutAttention[number].removeWidget(
|
|
||||||
self.versionNameLabel[number])
|
|
||||||
self.versionNameLabel[number].setParent(None)
|
|
||||||
self.formLayoutAttention[number].removeWidget(
|
|
||||||
self.versionNameEdit[number])
|
|
||||||
self.formLayoutAttention[number].deleteLater()
|
|
||||||
self.versionNameEdit[number].setParent(None)
|
|
||||||
self.formLayout.removeWidget(self.formWidget[number])
|
|
||||||
self.formWidget[number].setParent(None)
|
|
||||||
self.formLayout.removeItem(self.spacerItem)
|
self.formLayout.removeItem(self.spacerItem)
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslateUi(self):
|
||||||
@ -387,12 +288,6 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
self.selectPage.setSubTitle(
|
self.selectPage.setSubTitle(
|
||||||
translate('BiblesPlugin.UpgradeWizardForm',
|
translate('BiblesPlugin.UpgradeWizardForm',
|
||||||
'Please select the Bibles to upgrade'))
|
'Please select the Bibles to upgrade'))
|
||||||
for number, bible in enumerate(self.files):
|
|
||||||
self.versionNameLabel[number].setText(
|
|
||||||
translate('BiblesPlugin.UpgradeWizardForm', 'Version name:'))
|
|
||||||
self.versionInfoLabel[number].setText(
|
|
||||||
translate('BiblesPlugin.UpgradeWizardForm', 'This '
|
|
||||||
'Bible still exists. Please change the name or uncheck it.'))
|
|
||||||
self.progressPage.setTitle(translate('BiblesPlugin.UpgradeWizardForm',
|
self.progressPage.setTitle(translate('BiblesPlugin.UpgradeWizardForm',
|
||||||
'Upgrading'))
|
'Upgrading'))
|
||||||
self.progressPage.setSubTitle(
|
self.progressPage.setSubTitle(
|
||||||
@ -413,7 +308,7 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
if not backup_path:
|
if not backup_path:
|
||||||
critical_error_message_box(UiStrings().EmptyField,
|
critical_error_message_box(UiStrings().EmptyField,
|
||||||
translate('BiblesPlugin.UpgradeWizardForm',
|
translate('BiblesPlugin.UpgradeWizardForm',
|
||||||
'You need to specify a Backup Directory for your '
|
'You need to specify a backup directory for your '
|
||||||
'Bibles.'))
|
'Bibles.'))
|
||||||
self.backupDirectoryEdit.setFocus()
|
self.backupDirectoryEdit.setFocus()
|
||||||
return False
|
return False
|
||||||
@ -427,58 +322,16 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
elif self.currentPage() == self.selectPage:
|
elif self.currentPage() == self.selectPage:
|
||||||
|
check_directory_exists(self.temp_dir)
|
||||||
for number, filename in enumerate(self.files):
|
for number, filename in enumerate(self.files):
|
||||||
if not self.checkBox[number].checkState() == QtCore.Qt.Checked:
|
if not self.checkBox[number].checkState() == QtCore.Qt.Checked:
|
||||||
continue
|
continue
|
||||||
version_name = unicode(self.versionNameEdit[number].text())
|
# Move bibles to temp dir.
|
||||||
if not version_name:
|
if not os.path.exists(os.path.join(self.temp_dir, filename[0])):
|
||||||
critical_error_message_box(UiStrings().EmptyField,
|
shutil.move(
|
||||||
translate('BiblesPlugin.UpgradeWizardForm',
|
os.path.join(self.path, filename[0]), self.temp_dir)
|
||||||
'You need to specify a version name for your Bible.'))
|
else:
|
||||||
self.versionNameEdit[number].setFocus()
|
delete_file(os.path.join(self.path, filename[0]))
|
||||||
return False
|
|
||||||
elif self.manager.exists(version_name):
|
|
||||||
critical_error_message_box(
|
|
||||||
translate('BiblesPlugin.UpgradeWizardForm',
|
|
||||||
'Bible Exists'),
|
|
||||||
translate('BiblesPlugin.UpgradeWizardForm',
|
|
||||||
'This Bible already exists. Please upgrade '
|
|
||||||
'a different Bible, delete the existing one or '
|
|
||||||
'uncheck.'))
|
|
||||||
self.versionNameEdit[number].setFocus()
|
|
||||||
return False
|
|
||||||
elif os.path.exists(os.path.join(self.path, clean_filename(
|
|
||||||
version_name))) and version_name == filename[1]:
|
|
||||||
newfilename = u'old_database_%s' % filename[0]
|
|
||||||
if not os.path.exists(os.path.join(self.path,
|
|
||||||
newfilename)):
|
|
||||||
os.rename(os.path.join(self.path, filename[0]),
|
|
||||||
os.path.join(self.path, newfilename))
|
|
||||||
self.files[number] = [newfilename, filename[1]]
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
critical_error_message_box(
|
|
||||||
translate('BiblesPlugin.UpgradeWizardForm',
|
|
||||||
'Bible Exists'),
|
|
||||||
translate('BiblesPlugin.UpgradeWizardForm',
|
|
||||||
'This Bible already exists. Please upgrade '
|
|
||||||
'a different Bible, delete the existing one or '
|
|
||||||
'uncheck.'))
|
|
||||||
self.verticalWidget[number].show()
|
|
||||||
self.formWidget[number].show()
|
|
||||||
self.versionNameEdit[number].setFocus()
|
|
||||||
return False
|
|
||||||
elif os.path.exists(os.path.join(self.path,
|
|
||||||
clean_filename(version_name))):
|
|
||||||
critical_error_message_box(
|
|
||||||
translate('BiblesPlugin.UpgradeWizardForm',
|
|
||||||
'Bible Exists'),
|
|
||||||
translate('BiblesPlugin.UpgradeWizardForm',
|
|
||||||
'This Bible already exists. Please upgrade '
|
|
||||||
'a different Bible, delete the existing one or '
|
|
||||||
'uncheck.'))
|
|
||||||
self.versionNameEdit[number].setFocus()
|
|
||||||
return False
|
|
||||||
return True
|
return True
|
||||||
if self.currentPage() == self.progressPage:
|
if self.currentPage() == self.progressPage:
|
||||||
return True
|
return True
|
||||||
@ -497,16 +350,8 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
self.files = self.manager.old_bible_databases
|
self.files = self.manager.old_bible_databases
|
||||||
self.addScrollArea()
|
self.addScrollArea()
|
||||||
self.retranslateUi()
|
self.retranslateUi()
|
||||||
self.maxBibles = len(self.files)
|
|
||||||
for number, filename in enumerate(self.files):
|
for number, filename in enumerate(self.files):
|
||||||
self.checkBox[number].setCheckState(QtCore.Qt.Checked)
|
self.checkBox[number].setCheckState(QtCore.Qt.Checked)
|
||||||
oldname = filename[1]
|
|
||||||
if self.manager.exists(oldname):
|
|
||||||
self.verticalWidget[number].show()
|
|
||||||
self.formWidget[number].show()
|
|
||||||
else:
|
|
||||||
self.verticalWidget[number].hide()
|
|
||||||
self.formWidget[number].hide()
|
|
||||||
self.progressBar.show()
|
self.progressBar.show()
|
||||||
self.restart()
|
self.restart()
|
||||||
self.finishButton.setVisible(False)
|
self.finishButton.setVisible(False)
|
||||||
@ -518,9 +363,8 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
Prepare the UI for the upgrade.
|
Prepare the UI for the upgrade.
|
||||||
"""
|
"""
|
||||||
OpenLPWizard.preWizard(self)
|
OpenLPWizard.preWizard(self)
|
||||||
self.progressLabel.setText(translate(
|
self.progressLabel.setText(
|
||||||
'BiblesPlugin.UpgradeWizardForm',
|
translate('BiblesPlugin.UpgradeWizardForm', 'Starting upgrade...'))
|
||||||
'Starting Bible upgrade...'))
|
|
||||||
Receiver.send_message(u'openlp_process_events')
|
Receiver.send_message(u'openlp_process_events')
|
||||||
|
|
||||||
def performWizard(self):
|
def performWizard(self):
|
||||||
@ -529,48 +373,42 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
"""
|
"""
|
||||||
self.include_webbible = False
|
self.include_webbible = False
|
||||||
proxy_server = None
|
proxy_server = None
|
||||||
if self.maxBibles == 0:
|
if not self.files:
|
||||||
self.progressLabel.setText(
|
self.progressLabel.setText(
|
||||||
translate('BiblesPlugin.UpgradeWizardForm', 'There are no '
|
translate('BiblesPlugin.UpgradeWizardForm', 'There are no '
|
||||||
'Bibles available to upgrade.'))
|
'Bibles that need to be upgraded.'))
|
||||||
self.progressBar.hide()
|
self.progressBar.hide()
|
||||||
return
|
return
|
||||||
self.maxBibles = 0
|
max_bibles = 0
|
||||||
for number, file in enumerate(self.files):
|
for number, file in enumerate(self.files):
|
||||||
if self.checkBox[number].checkState() == QtCore.Qt.Checked:
|
if self.checkBox[number].checkState() == QtCore.Qt.Checked:
|
||||||
self.maxBibles += 1
|
max_bibles += 1
|
||||||
number = 0
|
oldBible = None
|
||||||
for biblenumber, filename in enumerate(self.files):
|
for number, filename in enumerate(self.files):
|
||||||
|
# Close the previous bible's connection.
|
||||||
|
if oldBible is not None:
|
||||||
|
oldBible.close_connection()
|
||||||
|
# Set to None to make obvious that we have already closed the
|
||||||
|
# database.
|
||||||
|
oldBible = None
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
bible_failed = True
|
self.success[number] = False
|
||||||
break
|
break
|
||||||
bible_failed = False
|
if not self.checkBox[number].checkState() == QtCore.Qt.Checked:
|
||||||
self.success[biblenumber] = False
|
self.success[number] = False
|
||||||
if not self.checkBox[biblenumber].checkState() == QtCore.Qt.Checked:
|
|
||||||
continue
|
continue
|
||||||
self.progressBar.reset()
|
self.progressBar.reset()
|
||||||
oldbible = OldBibleDB(self.mediaItem, path=self.path,
|
oldBible = OldBibleDB(self.mediaItem, path=self.temp_dir,
|
||||||
file=filename[0])
|
file=filename[0])
|
||||||
name = filename[1]
|
name = filename[1]
|
||||||
if name is None:
|
|
||||||
delete_file(os.path.join(self.path, filename[0]))
|
|
||||||
self.incrementProgressBar(unicode(translate(
|
|
||||||
'BiblesPlugin.UpgradeWizardForm',
|
|
||||||
'Upgrading Bible %s of %s: "%s"\nFailed')) %
|
|
||||||
(number + 1, self.maxBibles, name),
|
|
||||||
self.progressBar.maximum() - self.progressBar.value())
|
|
||||||
number += 1
|
|
||||||
continue
|
|
||||||
self.progressLabel.setText(unicode(translate(
|
self.progressLabel.setText(unicode(translate(
|
||||||
'BiblesPlugin.UpgradeWizardForm',
|
'BiblesPlugin.UpgradeWizardForm',
|
||||||
'Upgrading Bible %s of %s: "%s"\nUpgrading ...')) %
|
'Upgrading Bible %s of %s: "%s"\nUpgrading ...')) %
|
||||||
(number + 1, self.maxBibles, name))
|
(number + 1, max_bibles, name))
|
||||||
if os.path.exists(os.path.join(self.path, filename[0])):
|
|
||||||
name = unicode(self.versionNameEdit[biblenumber].text())
|
|
||||||
self.newbibles[number] = BibleDB(self.mediaItem, path=self.path,
|
self.newbibles[number] = BibleDB(self.mediaItem, path=self.path,
|
||||||
name=name)
|
name=name, file=filename[0])
|
||||||
self.newbibles[number].register(self.plugin.upgrade_wizard)
|
self.newbibles[number].register(self.plugin.upgrade_wizard)
|
||||||
metadata = oldbible.get_metadata()
|
metadata = oldBible.get_metadata()
|
||||||
webbible = False
|
webbible = False
|
||||||
meta_data = {}
|
meta_data = {}
|
||||||
for meta in metadata:
|
for meta in metadata:
|
||||||
@ -597,7 +435,7 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
u'name: "%s" failed' % (
|
u'name: "%s" failed' % (
|
||||||
meta_data[u'download source'],
|
meta_data[u'download source'],
|
||||||
meta_data[u'download name']))
|
meta_data[u'download name']))
|
||||||
delete_database(self.path, clean_filename(name))
|
self.newbibles[number].session.close()
|
||||||
del self.newbibles[number]
|
del self.newbibles[number]
|
||||||
critical_error_message_box(
|
critical_error_message_box(
|
||||||
translate('BiblesPlugin.UpgradeWizardForm',
|
translate('BiblesPlugin.UpgradeWizardForm',
|
||||||
@ -608,9 +446,9 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
self.incrementProgressBar(unicode(translate(
|
self.incrementProgressBar(unicode(translate(
|
||||||
'BiblesPlugin.UpgradeWizardForm',
|
'BiblesPlugin.UpgradeWizardForm',
|
||||||
'Upgrading Bible %s of %s: "%s"\nFailed')) %
|
'Upgrading Bible %s of %s: "%s"\nFailed')) %
|
||||||
(number + 1, self.maxBibles, name),
|
(number + 1, max_bibles, name),
|
||||||
self.progressBar.maximum() - self.progressBar.value())
|
self.progressBar.maximum() - self.progressBar.value())
|
||||||
number += 1
|
self.success[number] = False
|
||||||
continue
|
continue
|
||||||
bible = BiblesResourcesDB.get_webbible(
|
bible = BiblesResourcesDB.get_webbible(
|
||||||
meta_data[u'download name'],
|
meta_data[u'download name'],
|
||||||
@ -623,25 +461,25 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
language_id = self.newbibles[number].get_language(name)
|
language_id = self.newbibles[number].get_language(name)
|
||||||
if not language_id:
|
if not language_id:
|
||||||
log.warn(u'Upgrading from "%s" failed' % filename[0])
|
log.warn(u'Upgrading from "%s" failed' % filename[0])
|
||||||
delete_database(self.path, clean_filename(name))
|
self.newbibles[number].session.close()
|
||||||
del self.newbibles[number]
|
del self.newbibles[number]
|
||||||
self.incrementProgressBar(unicode(translate(
|
self.incrementProgressBar(unicode(translate(
|
||||||
'BiblesPlugin.UpgradeWizardForm',
|
'BiblesPlugin.UpgradeWizardForm',
|
||||||
'Upgrading Bible %s of %s: "%s"\nFailed')) %
|
'Upgrading Bible %s of %s: "%s"\nFailed')) %
|
||||||
(number + 1, self.maxBibles, name),
|
(number + 1, max_bibles, name),
|
||||||
self.progressBar.maximum() - self.progressBar.value())
|
self.progressBar.maximum() - self.progressBar.value())
|
||||||
number += 1
|
self.success[number] = False
|
||||||
continue
|
continue
|
||||||
self.progressBar.setMaximum(len(books))
|
self.progressBar.setMaximum(len(books))
|
||||||
for book in books:
|
for book in books:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
bible_failed = True
|
self.success[number] = False
|
||||||
break
|
break
|
||||||
self.incrementProgressBar(unicode(translate(
|
self.incrementProgressBar(unicode(translate(
|
||||||
'BiblesPlugin.UpgradeWizardForm',
|
'BiblesPlugin.UpgradeWizardForm',
|
||||||
'Upgrading Bible %s of %s: "%s"\n'
|
'Upgrading Bible %s of %s: "%s"\n'
|
||||||
'Upgrading %s ...')) %
|
'Upgrading %s ...')) %
|
||||||
(number + 1, self.maxBibles, name, book))
|
(number + 1, max_bibles, name, book))
|
||||||
book_ref_id = self.newbibles[number].\
|
book_ref_id = self.newbibles[number].\
|
||||||
get_book_ref_id_by_name(book, len(books), language_id)
|
get_book_ref_id_by_name(book, len(books), language_id)
|
||||||
if not book_ref_id:
|
if not book_ref_id:
|
||||||
@ -649,24 +487,24 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
u'name: "%s" aborted by user' % (
|
u'name: "%s" aborted by user' % (
|
||||||
meta_data[u'download source'],
|
meta_data[u'download source'],
|
||||||
meta_data[u'download name']))
|
meta_data[u'download name']))
|
||||||
delete_database(self.path, clean_filename(name))
|
self.newbibles[number].session.close()
|
||||||
del self.newbibles[number]
|
del self.newbibles[number]
|
||||||
bible_failed = True
|
self.success[number] = False
|
||||||
break
|
break
|
||||||
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
|
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
|
||||||
db_book = self.newbibles[number].create_book(book,
|
db_book = self.newbibles[number].create_book(book,
|
||||||
book_ref_id, book_details[u'testament_id'])
|
book_ref_id, book_details[u'testament_id'])
|
||||||
# Try to import still downloaded verses
|
# Try to import already downloaded verses.
|
||||||
oldbook = oldbible.get_book(book)
|
oldbook = oldBible.get_book(book)
|
||||||
if oldbook:
|
if oldbook:
|
||||||
verses = oldbible.get_verses(oldbook[u'id'])
|
verses = oldBible.get_verses(oldbook[u'id'])
|
||||||
if not verses:
|
if not verses:
|
||||||
log.warn(u'No verses found to import for book '
|
log.warn(u'No verses found to import for book '
|
||||||
u'"%s"', book)
|
u'"%s"', book)
|
||||||
continue
|
continue
|
||||||
for verse in verses:
|
for verse in verses:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
bible_failed = True
|
self.success[number] = False
|
||||||
break
|
break
|
||||||
self.newbibles[number].create_verse(db_book.id,
|
self.newbibles[number].create_verse(db_book.id,
|
||||||
int(verse[u'chapter']),
|
int(verse[u'chapter']),
|
||||||
@ -680,40 +518,40 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
language_id = self.newbibles[number].get_language(name)
|
language_id = self.newbibles[number].get_language(name)
|
||||||
if not language_id:
|
if not language_id:
|
||||||
log.warn(u'Upgrading books from "%s" failed' % name)
|
log.warn(u'Upgrading books from "%s" failed' % name)
|
||||||
delete_database(self.path, clean_filename(name))
|
self.newbibles[number].session.close()
|
||||||
del self.newbibles[number]
|
del self.newbibles[number]
|
||||||
self.incrementProgressBar(unicode(translate(
|
self.incrementProgressBar(unicode(translate(
|
||||||
'BiblesPlugin.UpgradeWizardForm',
|
'BiblesPlugin.UpgradeWizardForm',
|
||||||
'Upgrading Bible %s of %s: "%s"\nFailed')) %
|
'Upgrading Bible %s of %s: "%s"\nFailed')) %
|
||||||
(number + 1, self.maxBibles, name),
|
(number + 1, max_bibles, name),
|
||||||
self.progressBar.maximum() - self.progressBar.value())
|
self.progressBar.maximum() - self.progressBar.value())
|
||||||
number += 1
|
self.success[number] = False
|
||||||
continue
|
continue
|
||||||
books = oldbible.get_books()
|
books = oldBible.get_books()
|
||||||
self.progressBar.setMaximum(len(books))
|
self.progressBar.setMaximum(len(books))
|
||||||
for book in books:
|
for book in books:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
bible_failed = True
|
self.success[number] = False
|
||||||
break
|
break
|
||||||
self.incrementProgressBar(unicode(translate(
|
self.incrementProgressBar(unicode(translate(
|
||||||
'BiblesPlugin.UpgradeWizardForm',
|
'BiblesPlugin.UpgradeWizardForm',
|
||||||
'Upgrading Bible %s of %s: "%s"\n'
|
'Upgrading Bible %s of %s: "%s"\n'
|
||||||
'Upgrading %s ...')) %
|
'Upgrading %s ...')) %
|
||||||
(number + 1, self.maxBibles, name, book[u'name']))
|
(number + 1, max_bibles, name, book[u'name']))
|
||||||
book_ref_id = self.newbibles[number].\
|
book_ref_id = self.newbibles[number].\
|
||||||
get_book_ref_id_by_name(book[u'name'], len(books),
|
get_book_ref_id_by_name(book[u'name'], len(books),
|
||||||
language_id)
|
language_id)
|
||||||
if not book_ref_id:
|
if not book_ref_id:
|
||||||
log.warn(u'Upgrading books from %s " '\
|
log.warn(u'Upgrading books from %s " '\
|
||||||
'failed - aborted by user' % name)
|
'failed - aborted by user' % name)
|
||||||
delete_database(self.path, clean_filename(name))
|
self.newbibles[number].session.close()
|
||||||
del self.newbibles[number]
|
del self.newbibles[number]
|
||||||
bible_failed = True
|
self.success[number] = False
|
||||||
break
|
break
|
||||||
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
|
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
|
||||||
db_book = self.newbibles[number].create_book(book[u'name'],
|
db_book = self.newbibles[number].create_book(book[u'name'],
|
||||||
book_ref_id, book_details[u'testament_id'])
|
book_ref_id, book_details[u'testament_id'])
|
||||||
verses = oldbible.get_verses(book[u'id'])
|
verses = oldBible.get_verses(book[u'id'])
|
||||||
if not verses:
|
if not verses:
|
||||||
log.warn(u'No verses found to import for book '
|
log.warn(u'No verses found to import for book '
|
||||||
u'"%s"', book[u'name'])
|
u'"%s"', book[u'name'])
|
||||||
@ -721,31 +559,32 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
continue
|
continue
|
||||||
for verse in verses:
|
for verse in verses:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
bible_failed = True
|
self.success[number] = False
|
||||||
break
|
break
|
||||||
self.newbibles[number].create_verse(db_book.id,
|
self.newbibles[number].create_verse(db_book.id,
|
||||||
int(verse[u'chapter']),
|
int(verse[u'chapter']),
|
||||||
int(verse[u'verse']), unicode(verse[u'text']))
|
int(verse[u'verse']), unicode(verse[u'text']))
|
||||||
Receiver.send_message(u'openlp_process_events')
|
Receiver.send_message(u'openlp_process_events')
|
||||||
self.newbibles[number].session.commit()
|
self.newbibles[number].session.commit()
|
||||||
if not bible_failed:
|
if self.success.has_key(number) and not self.success[number]:
|
||||||
|
self.incrementProgressBar(unicode(translate(
|
||||||
|
'BiblesPlugin.UpgradeWizardForm',
|
||||||
|
'Upgrading Bible %s of %s: "%s"\nFailed')) %
|
||||||
|
(number + 1, max_bibles, name),
|
||||||
|
self.progressBar.maximum() - self.progressBar.value())
|
||||||
|
else:
|
||||||
|
self.success[number] = True
|
||||||
self.newbibles[number].create_meta(u'Version', name)
|
self.newbibles[number].create_meta(u'Version', name)
|
||||||
oldbible.close_connection()
|
|
||||||
delete_file(os.path.join(self.path, filename[0]))
|
|
||||||
self.incrementProgressBar(unicode(translate(
|
self.incrementProgressBar(unicode(translate(
|
||||||
'BiblesPlugin.UpgradeWizardForm',
|
'BiblesPlugin.UpgradeWizardForm',
|
||||||
'Upgrading Bible %s of %s: "%s"\n'
|
'Upgrading Bible %s of %s: "%s"\n'
|
||||||
'Complete')) %
|
'Complete')) %
|
||||||
(number + 1, self.maxBibles, name))
|
(number + 1, max_bibles, name))
|
||||||
self.success[biblenumber] = True
|
if self.newbibles.has_key(number):
|
||||||
else:
|
self.newbibles[number].session.close()
|
||||||
self.incrementProgressBar(unicode(translate(
|
# Close the last bible's connection if possible.
|
||||||
'BiblesPlugin.UpgradeWizardForm',
|
if oldBible is not None:
|
||||||
'Upgrading Bible %s of %s: "%s"\nFailed')) %
|
oldBible.close_connection()
|
||||||
(number + 1, self.maxBibles, name),
|
|
||||||
self.progressBar.maximum() - self.progressBar.value())
|
|
||||||
delete_database(self.path, clean_filename(name))
|
|
||||||
number += 1
|
|
||||||
|
|
||||||
def postWizard(self):
|
def postWizard(self):
|
||||||
"""
|
"""
|
||||||
@ -754,10 +593,14 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
successful_import = 0
|
successful_import = 0
|
||||||
failed_import = 0
|
failed_import = 0
|
||||||
for number, filename in enumerate(self.files):
|
for number, filename in enumerate(self.files):
|
||||||
if number in self.success and self.success[number] == True:
|
if self.success.has_key(number) and self.success[number]:
|
||||||
successful_import += 1
|
successful_import += 1
|
||||||
elif self.checkBox[number].checkState() == QtCore.Qt.Checked:
|
elif self.checkBox[number].checkState() == QtCore.Qt.Checked:
|
||||||
failed_import += 1
|
failed_import += 1
|
||||||
|
# Delete upgraded (but not complete, corrupted, ...) bible.
|
||||||
|
delete_file(os.path.join(self.path, filename[0]))
|
||||||
|
# Copy not upgraded bible back.
|
||||||
|
shutil.move(os.path.join(self.temp_dir, filename[0]), self.path)
|
||||||
if failed_import > 0:
|
if failed_import > 0:
|
||||||
failed_import_text = unicode(translate(
|
failed_import_text = unicode(translate(
|
||||||
'BiblesPlugin.UpgradeWizardForm',
|
'BiblesPlugin.UpgradeWizardForm',
|
||||||
@ -778,7 +621,8 @@ class BibleUpgradeForm(OpenLPWizard):
|
|||||||
'Bible(s): %s successful%s')) % (successful_import,
|
'Bible(s): %s successful%s')) % (successful_import,
|
||||||
failed_import_text))
|
failed_import_text))
|
||||||
else:
|
else:
|
||||||
self.progressLabel.setText(
|
self.progressLabel.setText(translate(
|
||||||
translate('BiblesPlugin.UpgradeWizardForm', 'Upgrade '
|
'BiblesPlugin.UpgradeWizardForm', 'Upgrade failed.'))
|
||||||
'failed.'))
|
# Remove temp directory.
|
||||||
|
shutil.rmtree(self.temp_dir, True)
|
||||||
OpenLPWizard.postWizard(self)
|
OpenLPWizard.postWizard(self)
|
||||||
|
@ -44,8 +44,8 @@ class LanguageForm(QDialog, Ui_LanguageDialog):
|
|||||||
Class to manage a dialog which ask the user for a language.
|
Class to manage a dialog which ask the user for a language.
|
||||||
"""
|
"""
|
||||||
log.info(u'LanguageForm loaded')
|
log.info(u'LanguageForm loaded')
|
||||||
|
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent=None):
|
||||||
"""
|
"""
|
||||||
Constructor
|
Constructor
|
||||||
"""
|
"""
|
||||||
@ -57,12 +57,11 @@ class LanguageForm(QDialog, Ui_LanguageDialog):
|
|||||||
if bible_name:
|
if bible_name:
|
||||||
self.bibleLabel.setText(unicode(bible_name))
|
self.bibleLabel.setText(unicode(bible_name))
|
||||||
items = BiblesResourcesDB.get_languages()
|
items = BiblesResourcesDB.get_languages()
|
||||||
for item in items:
|
self.languageComboBox.addItems([item[u'name'] for item in items])
|
||||||
self.languageComboBox.addItem(item[u'name'])
|
|
||||||
return QDialog.exec_(self)
|
return QDialog.exec_(self)
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
if self.languageComboBox.currentText() == u'':
|
if not self.languageComboBox.currentText():
|
||||||
critical_error_message_box(
|
critical_error_message_box(
|
||||||
message=translate('BiblesPlugin.LanguageForm',
|
message=translate('BiblesPlugin.LanguageForm',
|
||||||
'You need to choose a language.'))
|
'You need to choose a language.'))
|
||||||
|
@ -115,7 +115,8 @@ class CSVBible(BibleDB):
|
|||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
break
|
break
|
||||||
self.wizard.incrementProgressBar(unicode(
|
self.wizard.incrementProgressBar(unicode(
|
||||||
translate('BibleDB.Wizard', 'Importing books... %s')) %
|
translate('BiblesPlugin.CSVBible',
|
||||||
|
'Importing books... %s')) %
|
||||||
unicode(line[2], details['encoding']))
|
unicode(line[2], details['encoding']))
|
||||||
book_ref_id = self.get_book_ref_id_by_name(
|
book_ref_id = self.get_book_ref_id_by_name(
|
||||||
unicode(line[2], details['encoding']), 67, language_id)
|
unicode(line[2], details['encoding']), 67, language_id)
|
||||||
@ -155,7 +156,7 @@ class CSVBible(BibleDB):
|
|||||||
book = self.get_book(line_book)
|
book = self.get_book(line_book)
|
||||||
book_ptr = book.name
|
book_ptr = book.name
|
||||||
self.wizard.incrementProgressBar(unicode(translate(
|
self.wizard.incrementProgressBar(unicode(translate(
|
||||||
'BibleDB.Wizard', 'Importing verses from %s...',
|
'BiblesPlugin.CSVBible', 'Importing verses from %s...',
|
||||||
'Importing verses from <book name>...')) % book.name)
|
'Importing verses from <book name>...')) % book.name)
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
try:
|
try:
|
||||||
@ -163,7 +164,7 @@ class CSVBible(BibleDB):
|
|||||||
except UnicodeError:
|
except UnicodeError:
|
||||||
verse_text = unicode(line[3], u'cp1252')
|
verse_text = unicode(line[3], u'cp1252')
|
||||||
self.create_verse(book.id, line[1], line[2], verse_text)
|
self.create_verse(book.id, line[1], line[2], verse_text)
|
||||||
self.wizard.incrementProgressBar(translate('BibleDB.Wizard',
|
self.wizard.incrementProgressBar(translate('BiblesPlugin.CSVBible',
|
||||||
'Importing verses... done.'))
|
'Importing verses... done.'))
|
||||||
Receiver.send_message(u'openlp_process_events')
|
Receiver.send_message(u'openlp_process_events')
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
|
@ -36,10 +36,10 @@ from sqlalchemy import Column, ForeignKey, or_, Table, types
|
|||||||
from sqlalchemy.orm import class_mapper, mapper, relation
|
from sqlalchemy.orm import class_mapper, mapper, relation
|
||||||
from sqlalchemy.orm.exc import UnmappedClassError
|
from sqlalchemy.orm.exc import UnmappedClassError
|
||||||
|
|
||||||
from openlp.core.lib import Receiver, translate, check_directory_exists
|
from openlp.core.lib import Receiver, translate
|
||||||
from openlp.core.lib.db import BaseModel, init_db, Manager
|
from openlp.core.lib.db import BaseModel, init_db, Manager
|
||||||
from openlp.core.lib.ui import critical_error_message_box
|
from openlp.core.lib.ui import critical_error_message_box
|
||||||
from openlp.core.utils import AppLocation
|
from openlp.core.utils import AppLocation, clean_filename
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -63,19 +63,6 @@ class Verse(BaseModel):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def clean_filename(filename):
|
|
||||||
"""
|
|
||||||
Clean up the version name of the Bible and convert it into a valid
|
|
||||||
file name.
|
|
||||||
|
|
||||||
``filename``
|
|
||||||
The "dirty" file name or version name.
|
|
||||||
"""
|
|
||||||
if not isinstance(filename, unicode):
|
|
||||||
filename = unicode(filename, u'utf-8')
|
|
||||||
filename = re.sub(r'[^\w]+', u'_', filename).strip(u'_')
|
|
||||||
return filename + u'.sqlite'
|
|
||||||
|
|
||||||
def init_schema(url):
|
def init_schema(url):
|
||||||
"""
|
"""
|
||||||
Setup a bible database connection and initialise the database schema.
|
Setup a bible database connection and initialise the database schema.
|
||||||
@ -158,7 +145,7 @@ class BibleDB(QtCore.QObject, Manager):
|
|||||||
self.name = kwargs[u'name']
|
self.name = kwargs[u'name']
|
||||||
if not isinstance(self.name, unicode):
|
if not isinstance(self.name, unicode):
|
||||||
self.name = unicode(self.name, u'utf-8')
|
self.name = unicode(self.name, u'utf-8')
|
||||||
self.file = clean_filename(self.name)
|
self.file = clean_filename(self.name) + u'.sqlite'
|
||||||
if u'file' in kwargs:
|
if u'file' in kwargs:
|
||||||
self.file = kwargs[u'file']
|
self.file = kwargs[u'file']
|
||||||
Manager.__init__(self, u'bibles', init_schema, self.file)
|
Manager.__init__(self, u'bibles', init_schema, self.file)
|
||||||
@ -210,7 +197,7 @@ class BibleDB(QtCore.QObject, Manager):
|
|||||||
The book_reference_id from bibles_resources.sqlite of the book.
|
The book_reference_id from bibles_resources.sqlite of the book.
|
||||||
|
|
||||||
``testament``
|
``testament``
|
||||||
*Defaults to 1.* The testament_reference_id from
|
*Defaults to 1.* The testament_reference_id from
|
||||||
bibles_resources.sqlite of the testament this book belongs to.
|
bibles_resources.sqlite of the testament this book belongs to.
|
||||||
"""
|
"""
|
||||||
log.debug(u'BibleDB.create_book("%s", "%s")', name, bk_ref_id)
|
log.debug(u'BibleDB.create_book("%s", "%s")', name, bk_ref_id)
|
||||||
@ -329,7 +316,7 @@ class BibleDB(QtCore.QObject, Manager):
|
|||||||
return self.get_object_filtered(Book, Book.book_reference_id.like(id))
|
return self.get_object_filtered(Book, Book.book_reference_id.like(id))
|
||||||
|
|
||||||
def get_book_ref_id_by_name(self, book, maxbooks, language_id=None):
|
def get_book_ref_id_by_name(self, book, maxbooks, language_id=None):
|
||||||
log.debug(u'BibleDB.get_book_ref_id_by_name:("%s", "%s")', book,
|
log.debug(u'BibleDB.get_book_ref_id_by_name:("%s", "%s")', book,
|
||||||
language_id)
|
language_id)
|
||||||
if BiblesResourcesDB.get_book(book, True):
|
if BiblesResourcesDB.get_book(book, True):
|
||||||
book_temp = BiblesResourcesDB.get_book(book, True)
|
book_temp = BiblesResourcesDB.get_book(book, True)
|
||||||
@ -471,7 +458,7 @@ class BibleDB(QtCore.QObject, Manager):
|
|||||||
|
|
||||||
def get_language(self, bible_name=None):
|
def get_language(self, bible_name=None):
|
||||||
"""
|
"""
|
||||||
If no language is given it calls a dialog window where the user could
|
If no language is given it calls a dialog window where the user could
|
||||||
select the bible language.
|
select the bible language.
|
||||||
Return the language id of a bible.
|
Return the language id of a bible.
|
||||||
|
|
||||||
@ -521,9 +508,9 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
|||||||
some resources which are used in the Bibles plugin.
|
some resources which are used in the Bibles plugin.
|
||||||
A wrapper class around a small SQLite database which contains the download
|
A wrapper class around a small SQLite database which contains the download
|
||||||
resources, a biblelist from the different download resources, the books,
|
resources, a biblelist from the different download resources, the books,
|
||||||
chapter counts and verse counts for the web download Bibles, a language
|
chapter counts and verse counts for the web download Bibles, a language
|
||||||
reference, the testament reference and some alternative book names. This
|
reference, the testament reference and some alternative book names. This
|
||||||
class contains a singleton "cursor" so that only one connection to the
|
class contains a singleton "cursor" so that only one connection to the
|
||||||
SQLite database is ever used.
|
SQLite database is ever used.
|
||||||
"""
|
"""
|
||||||
cursor = None
|
cursor = None
|
||||||
@ -582,7 +569,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
|||||||
|
|
||||||
``name``
|
``name``
|
||||||
The name or abbreviation of the book.
|
The name or abbreviation of the book.
|
||||||
|
|
||||||
``lower``
|
``lower``
|
||||||
True if the comparsion should be only lowercase
|
True if the comparsion should be only lowercase
|
||||||
"""
|
"""
|
||||||
@ -592,7 +579,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
|||||||
if lower:
|
if lower:
|
||||||
books = BiblesResourcesDB.run_sql(u'SELECT id, testament_id, name, '
|
books = BiblesResourcesDB.run_sql(u'SELECT id, testament_id, name, '
|
||||||
u'abbreviation, chapters FROM book_reference WHERE '
|
u'abbreviation, chapters FROM book_reference WHERE '
|
||||||
u'LOWER(name) = ? OR LOWER(abbreviation) = ?',
|
u'LOWER(name) = ? OR LOWER(abbreviation) = ?',
|
||||||
(name.lower(), name.lower()))
|
(name.lower(), name.lower()))
|
||||||
else:
|
else:
|
||||||
books = BiblesResourcesDB.run_sql(u'SELECT id, testament_id, name, '
|
books = BiblesResourcesDB.run_sql(u'SELECT id, testament_id, name, '
|
||||||
@ -621,7 +608,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
|||||||
if not isinstance(id, int):
|
if not isinstance(id, int):
|
||||||
id = int(id)
|
id = int(id)
|
||||||
books = BiblesResourcesDB.run_sql(u'SELECT id, testament_id, name, '
|
books = BiblesResourcesDB.run_sql(u'SELECT id, testament_id, name, '
|
||||||
u'abbreviation, chapters FROM book_reference WHERE id = ?',
|
u'abbreviation, chapters FROM book_reference WHERE id = ?',
|
||||||
(id, ))
|
(id, ))
|
||||||
if books:
|
if books:
|
||||||
return {
|
return {
|
||||||
@ -645,12 +632,12 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
|||||||
``chapter``
|
``chapter``
|
||||||
The chapter number.
|
The chapter number.
|
||||||
"""
|
"""
|
||||||
log.debug(u'BiblesResourcesDB.get_chapter("%s", "%s")', book_id,
|
log.debug(u'BiblesResourcesDB.get_chapter("%s", "%s")', book_id,
|
||||||
chapter)
|
chapter)
|
||||||
if not isinstance(chapter, int):
|
if not isinstance(chapter, int):
|
||||||
chapter = int(chapter)
|
chapter = int(chapter)
|
||||||
chapters = BiblesResourcesDB.run_sql(u'SELECT id, book_reference_id, '
|
chapters = BiblesResourcesDB.run_sql(u'SELECT id, book_reference_id, '
|
||||||
u'chapter, verse_count FROM chapters WHERE book_reference_id = ?',
|
u'chapter, verse_count FROM chapters WHERE book_reference_id = ?',
|
||||||
(book_id,))
|
(book_id,))
|
||||||
if chapters:
|
if chapters:
|
||||||
return {
|
return {
|
||||||
@ -687,7 +674,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
|||||||
``chapter``
|
``chapter``
|
||||||
The number of the chapter.
|
The number of the chapter.
|
||||||
"""
|
"""
|
||||||
log.debug(u'BiblesResourcesDB.get_verse_count("%s", "%s")', book_id,
|
log.debug(u'BiblesResourcesDB.get_verse_count("%s", "%s")', book_id,
|
||||||
chapter)
|
chapter)
|
||||||
details = BiblesResourcesDB.get_chapter(book_id, chapter)
|
details = BiblesResourcesDB.get_chapter(book_id, chapter)
|
||||||
if details:
|
if details:
|
||||||
@ -715,7 +702,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
|||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_webbibles(source):
|
def get_webbibles(source):
|
||||||
"""
|
"""
|
||||||
@ -737,7 +724,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
|||||||
u'id': bible[0],
|
u'id': bible[0],
|
||||||
u'name': bible[1],
|
u'name': bible[1],
|
||||||
u'abbreviation': bible[2],
|
u'abbreviation': bible[2],
|
||||||
u'language_id': bible[3],
|
u'language_id': bible[3],
|
||||||
u'download_source_id': bible[4]
|
u'download_source_id': bible[4]
|
||||||
}
|
}
|
||||||
for bible in bibles
|
for bible in bibles
|
||||||
@ -752,11 +739,11 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
|||||||
|
|
||||||
``abbreviation``
|
``abbreviation``
|
||||||
The abbreviation of the webbible.
|
The abbreviation of the webbible.
|
||||||
|
|
||||||
``source``
|
``source``
|
||||||
The source of the webbible.
|
The source of the webbible.
|
||||||
"""
|
"""
|
||||||
log.debug(u'BiblesResourcesDB.get_webbibles("%s", "%s")', abbreviation,
|
log.debug(u'BiblesResourcesDB.get_webbibles("%s", "%s")', abbreviation,
|
||||||
source)
|
source)
|
||||||
if not isinstance(abbreviation, unicode):
|
if not isinstance(abbreviation, unicode):
|
||||||
abbreviation = unicode(abbreviation)
|
abbreviation = unicode(abbreviation)
|
||||||
@ -765,14 +752,14 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
|||||||
source = BiblesResourcesDB.get_download_source(source)
|
source = BiblesResourcesDB.get_download_source(source)
|
||||||
bible = BiblesResourcesDB.run_sql(u'SELECT id, name, abbreviation, '
|
bible = BiblesResourcesDB.run_sql(u'SELECT id, name, abbreviation, '
|
||||||
u'language_id, download_source_id FROM webbibles WHERE '
|
u'language_id, download_source_id FROM webbibles WHERE '
|
||||||
u'download_source_id = ? AND abbreviation = ?', (source[u'id'],
|
u'download_source_id = ? AND abbreviation = ?', (source[u'id'],
|
||||||
abbreviation))
|
abbreviation))
|
||||||
if bible:
|
if bible:
|
||||||
return {
|
return {
|
||||||
u'id': bible[0][0],
|
u'id': bible[0][0],
|
||||||
u'name': bible[0][1],
|
u'name': bible[0][1],
|
||||||
u'abbreviation': bible[0][2],
|
u'abbreviation': bible[0][2],
|
||||||
u'language_id': bible[0][3],
|
u'language_id': bible[0][3],
|
||||||
u'download_source_id': bible[0][4]
|
u'download_source_id': bible[0][4]
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
@ -785,11 +772,11 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
|||||||
|
|
||||||
``name``
|
``name``
|
||||||
The name to search the id.
|
The name to search the id.
|
||||||
|
|
||||||
``language_id``
|
``language_id``
|
||||||
The language_id for which language should be searched
|
The language_id for which language should be searched
|
||||||
"""
|
"""
|
||||||
log.debug(u'BiblesResourcesDB.get_alternative_book_name("%s", "%s")',
|
log.debug(u'BiblesResourcesDB.get_alternative_book_name("%s", "%s")',
|
||||||
name, language_id)
|
name, language_id)
|
||||||
if language_id:
|
if language_id:
|
||||||
books = BiblesResourcesDB.run_sql(u'SELECT book_reference_id, name '
|
books = BiblesResourcesDB.run_sql(u'SELECT book_reference_id, name '
|
||||||
@ -806,7 +793,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def get_language(name):
|
def get_language(name):
|
||||||
"""
|
"""
|
||||||
Return a dict containing the language id, name and code by name or
|
Return a dict containing the language id, name and code by name or
|
||||||
abbreviation.
|
abbreviation.
|
||||||
|
|
||||||
``name``
|
``name``
|
||||||
@ -865,7 +852,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
|||||||
|
|
||||||
class AlternativeBookNamesDB(QtCore.QObject, Manager):
|
class AlternativeBookNamesDB(QtCore.QObject, Manager):
|
||||||
"""
|
"""
|
||||||
This class represents a database-bound alternative book names system.
|
This class represents a database-bound alternative book names system.
|
||||||
"""
|
"""
|
||||||
cursor = None
|
cursor = None
|
||||||
conn = None
|
conn = None
|
||||||
@ -874,7 +861,7 @@ class AlternativeBookNamesDB(QtCore.QObject, Manager):
|
|||||||
def get_cursor():
|
def get_cursor():
|
||||||
"""
|
"""
|
||||||
Return the cursor object. Instantiate one if it doesn't exist yet.
|
Return the cursor object. Instantiate one if it doesn't exist yet.
|
||||||
If necessary loads up the database and creates the tables if the
|
If necessary loads up the database and creates the tables if the
|
||||||
database doesn't exist.
|
database doesn't exist.
|
||||||
"""
|
"""
|
||||||
if AlternativeBookNamesDB.cursor is None:
|
if AlternativeBookNamesDB.cursor is None:
|
||||||
@ -904,7 +891,7 @@ class AlternativeBookNamesDB(QtCore.QObject, Manager):
|
|||||||
|
|
||||||
``parameters``
|
``parameters``
|
||||||
Any variable parameters to add to the query
|
Any variable parameters to add to the query
|
||||||
|
|
||||||
``commit``
|
``commit``
|
||||||
If a commit statement is necessary this should be True.
|
If a commit statement is necessary this should be True.
|
||||||
"""
|
"""
|
||||||
@ -921,11 +908,11 @@ class AlternativeBookNamesDB(QtCore.QObject, Manager):
|
|||||||
|
|
||||||
``name``
|
``name``
|
||||||
The name to search the id.
|
The name to search the id.
|
||||||
|
|
||||||
``language_id``
|
``language_id``
|
||||||
The language_id for which language should be searched
|
The language_id for which language should be searched
|
||||||
"""
|
"""
|
||||||
log.debug(u'AlternativeBookNamesDB.get_book_reference_id("%s", "%s")',
|
log.debug(u'AlternativeBookNamesDB.get_book_reference_id("%s", "%s")',
|
||||||
name, language_id)
|
name, language_id)
|
||||||
if language_id:
|
if language_id:
|
||||||
books = AlternativeBookNamesDB.run_sql(u'SELECT book_reference_id, '
|
books = AlternativeBookNamesDB.run_sql(u'SELECT book_reference_id, '
|
||||||
@ -962,11 +949,11 @@ class AlternativeBookNamesDB(QtCore.QObject, Manager):
|
|||||||
|
|
||||||
class OldBibleDB(QtCore.QObject, Manager):
|
class OldBibleDB(QtCore.QObject, Manager):
|
||||||
"""
|
"""
|
||||||
This class conects to the old bible databases to reimport them to the new
|
This class conects to the old bible databases to reimport them to the new
|
||||||
database scheme.
|
database scheme.
|
||||||
"""
|
"""
|
||||||
cursor = None
|
cursor = None
|
||||||
|
|
||||||
def __init__(self, parent, **kwargs):
|
def __init__(self, parent, **kwargs):
|
||||||
"""
|
"""
|
||||||
The constructor loads up the database and creates and initialises the
|
The constructor loads up the database and creates and initialises the
|
||||||
|
@ -29,9 +29,7 @@ The :mod:`http` module enables OpenLP to retrieve scripture from bible
|
|||||||
websites.
|
websites.
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import re
|
import re
|
||||||
import sqlite3
|
|
||||||
import socket
|
import socket
|
||||||
import urllib
|
import urllib
|
||||||
from HTMLParser import HTMLParseError
|
from HTMLParser import HTMLParseError
|
||||||
@ -40,7 +38,7 @@ from BeautifulSoup import BeautifulSoup, NavigableString, Tag
|
|||||||
|
|
||||||
from openlp.core.lib import Receiver, translate
|
from openlp.core.lib import Receiver, translate
|
||||||
from openlp.core.lib.ui import critical_error_message_box
|
from openlp.core.lib.ui import critical_error_message_box
|
||||||
from openlp.core.utils import AppLocation, get_web_page
|
from openlp.core.utils import get_web_page
|
||||||
from openlp.plugins.bibles.lib import SearchResults
|
from openlp.plugins.bibles.lib import SearchResults
|
||||||
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB, \
|
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB, \
|
||||||
Book
|
Book
|
||||||
@ -69,10 +67,10 @@ class BGExtract(object):
|
|||||||
``chapter``
|
``chapter``
|
||||||
Chapter number.
|
Chapter number.
|
||||||
"""
|
"""
|
||||||
log.debug(u'BGExtract.get_bible_chapter("%s", "%s", "%s")', version,
|
log.debug(u'BGExtract.get_bible_chapter("%s", "%s", "%s")', version,
|
||||||
bookname, chapter)
|
bookname, chapter)
|
||||||
urlbookname = urllib.quote(bookname.encode("utf-8"))
|
urlbookname = urllib.quote(bookname.encode("utf-8"))
|
||||||
url_params = u'search=%s+%s&version=%s' % (urlbookname, chapter,
|
url_params = u'search=%s+%s&version=%s' % (urlbookname, chapter,
|
||||||
version)
|
version)
|
||||||
cleaner = [(re.compile(' |<br />|\'\+\''), lambda match: '')]
|
cleaner = [(re.compile(' |<br />|\'\+\''), lambda match: '')]
|
||||||
soup = get_soup_for_bible_ref(
|
soup = get_soup_for_bible_ref(
|
||||||
@ -147,7 +145,10 @@ class BGExtract(object):
|
|||||||
send_error_message(u'download')
|
send_error_message(u'download')
|
||||||
return None
|
return None
|
||||||
page_source = page.read()
|
page_source = page.read()
|
||||||
page_source = unicode(page_source, 'utf8')
|
try:
|
||||||
|
page_source = unicode(page_source, u'utf8')
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
page_source = unicode(page_source, u'cp1251')
|
||||||
page_source_temp = re.search(u'<table .*?class="infotable".*?>.*?'\
|
page_source_temp = re.search(u'<table .*?class="infotable".*?>.*?'\
|
||||||
u'</table>', page_source, re.DOTALL)
|
u'</table>', page_source, re.DOTALL)
|
||||||
if page_source_temp:
|
if page_source_temp:
|
||||||
@ -200,7 +201,7 @@ class BSExtract(object):
|
|||||||
``chapter``
|
``chapter``
|
||||||
Chapter number
|
Chapter number
|
||||||
"""
|
"""
|
||||||
log.debug(u'BSExtract.get_bible_chapter("%s", "%s", "%s")', version,
|
log.debug(u'BSExtract.get_bible_chapter("%s", "%s", "%s")', version,
|
||||||
bookname, chapter)
|
bookname, chapter)
|
||||||
urlversion = urllib.quote(version.encode("utf-8"))
|
urlversion = urllib.quote(version.encode("utf-8"))
|
||||||
urlbookname = urllib.quote(bookname.encode("utf-8"))
|
urlbookname = urllib.quote(bookname.encode("utf-8"))
|
||||||
@ -227,7 +228,7 @@ class BSExtract(object):
|
|||||||
|
|
||||||
def get_books_from_http(self, version):
|
def get_books_from_http(self, version):
|
||||||
"""
|
"""
|
||||||
Load a list of all books a Bible contains from Bibleserver mobile
|
Load a list of all books a Bible contains from Bibleserver mobile
|
||||||
website.
|
website.
|
||||||
|
|
||||||
``version``
|
``version``
|
||||||
@ -273,7 +274,7 @@ class CWExtract(object):
|
|||||||
``chapter``
|
``chapter``
|
||||||
Chapter number
|
Chapter number
|
||||||
"""
|
"""
|
||||||
log.debug(u'CWExtract.get_bible_chapter("%s", "%s", "%s")', version,
|
log.debug(u'CWExtract.get_bible_chapter("%s", "%s", "%s")', version,
|
||||||
bookname, chapter)
|
bookname, chapter)
|
||||||
urlbookname = bookname.replace(u' ', u'-')
|
urlbookname = bookname.replace(u' ', u'-')
|
||||||
urlbookname = urlbookname.lower()
|
urlbookname = urlbookname.lower()
|
||||||
@ -386,7 +387,7 @@ class HTTPBible(BibleDB):
|
|||||||
"""
|
"""
|
||||||
self.wizard.progressBar.setMaximum(68)
|
self.wizard.progressBar.setMaximum(68)
|
||||||
self.wizard.incrementProgressBar(unicode(translate(
|
self.wizard.incrementProgressBar(unicode(translate(
|
||||||
'BiblesPlugin.HTTPBible',
|
'BiblesPlugin.HTTPBible',
|
||||||
'Registering Bible and loading books...')))
|
'Registering Bible and loading books...')))
|
||||||
self.create_meta(u'download source', self.download_source)
|
self.create_meta(u'download source', self.download_source)
|
||||||
self.create_meta(u'download name', self.download_name)
|
self.create_meta(u'download name', self.download_name)
|
||||||
@ -412,7 +413,7 @@ class HTTPBible(BibleDB):
|
|||||||
self.wizard.progressBar.setMaximum(len(books)+2)
|
self.wizard.progressBar.setMaximum(len(books)+2)
|
||||||
self.wizard.incrementProgressBar(unicode(translate(
|
self.wizard.incrementProgressBar(unicode(translate(
|
||||||
'BiblesPlugin.HTTPBible', 'Registering Language...')))
|
'BiblesPlugin.HTTPBible', 'Registering Language...')))
|
||||||
bible = BiblesResourcesDB.get_webbible(self.download_name,
|
bible = BiblesResourcesDB.get_webbible(self.download_name,
|
||||||
self.download_source.lower())
|
self.download_source.lower())
|
||||||
if bible[u'language_id']:
|
if bible[u'language_id']:
|
||||||
language_id = bible[u'language_id']
|
language_id = bible[u'language_id']
|
||||||
@ -429,14 +430,14 @@ class HTTPBible(BibleDB):
|
|||||||
self.wizard.incrementProgressBar(unicode(translate(
|
self.wizard.incrementProgressBar(unicode(translate(
|
||||||
'BiblesPlugin.HTTPBible', 'Importing %s...',
|
'BiblesPlugin.HTTPBible', 'Importing %s...',
|
||||||
'Importing <book name>...')) % book)
|
'Importing <book name>...')) % book)
|
||||||
book_ref_id = self.get_book_ref_id_by_name(book, len(books),
|
book_ref_id = self.get_book_ref_id_by_name(book, len(books),
|
||||||
language_id)
|
language_id)
|
||||||
if not book_ref_id:
|
if not book_ref_id:
|
||||||
log.exception(u'Importing books from %s - download name: "%s" '\
|
log.exception(u'Importing books from %s - download name: "%s" '\
|
||||||
'failed' % (self.download_source, self.download_name))
|
'failed' % (self.download_source, self.download_name))
|
||||||
return False
|
return False
|
||||||
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
|
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
|
||||||
log.debug(u'Book details: Name:%s; id:%s; testament_id:%s',
|
log.debug(u'Book details: Name:%s; id:%s; testament_id:%s',
|
||||||
book, book_ref_id, book_details[u'testament_id'])
|
book, book_ref_id, book_details[u'testament_id'])
|
||||||
self.create_book(book, book_ref_id, book_details[u'testament_id'])
|
self.create_book(book, book_ref_id, book_details[u'testament_id'])
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
@ -521,7 +522,7 @@ class HTTPBible(BibleDB):
|
|||||||
def get_chapter_count(self, book):
|
def get_chapter_count(self, book):
|
||||||
"""
|
"""
|
||||||
Return the number of chapters in a particular book.
|
Return the number of chapters in a particular book.
|
||||||
|
|
||||||
``book``
|
``book``
|
||||||
The book object to get the chapter count for.
|
The book object to get the chapter count for.
|
||||||
"""
|
"""
|
||||||
@ -594,14 +595,14 @@ def send_error_message(error_type):
|
|||||||
"""
|
"""
|
||||||
if error_type == u'download':
|
if error_type == u'download':
|
||||||
critical_error_message_box(
|
critical_error_message_box(
|
||||||
translate('BiblePlugin.HTTPBible', 'Download Error'),
|
translate('BiblesPlugin.HTTPBible', 'Download Error'),
|
||||||
translate('BiblePlugin.HTTPBible', 'There was a '
|
translate('BiblesPlugin.HTTPBible', 'There was a '
|
||||||
'problem downloading your verse selection. Please check your '
|
'problem downloading your verse selection. Please check your '
|
||||||
'Internet connection, and if this error continues to occur '
|
'Internet connection, and if this error continues to occur '
|
||||||
'please consider reporting a bug.'))
|
'please consider reporting a bug.'))
|
||||||
elif error_type == u'parse':
|
elif error_type == u'parse':
|
||||||
critical_error_message_box(
|
critical_error_message_box(
|
||||||
translate('BiblePlugin.HTTPBible', 'Parse Error'),
|
translate('BiblesPlugin.HTTPBible', 'Parse Error'),
|
||||||
translate('BiblePlugin.HTTPBible', 'There was a '
|
translate('BiblesPlugin.HTTPBible', 'There was a '
|
||||||
'problem extracting your verse selection. If this error continues '
|
'problem extracting your verse selection. If this error continues '
|
||||||
'to occur please consider reporting a bug.'))
|
'to occur please consider reporting a bug.'))
|
||||||
|
@ -34,7 +34,7 @@ from openlp.core.lib import Receiver, SettingsManager, translate
|
|||||||
from openlp.core.lib.ui import critical_error_message_box
|
from openlp.core.lib.ui import critical_error_message_box
|
||||||
from openlp.core.utils import AppLocation, delete_file
|
from openlp.core.utils import AppLocation, delete_file
|
||||||
from openlp.plugins.bibles.lib import parse_reference
|
from openlp.plugins.bibles.lib import parse_reference
|
||||||
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB
|
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta
|
||||||
from csvbible import CSVBible
|
from csvbible import CSVBible
|
||||||
from http import HTTPBible
|
from http import HTTPBible
|
||||||
from opensong import OpenSongBible
|
from opensong import OpenSongBible
|
||||||
@ -151,9 +151,10 @@ class BibleManager(object):
|
|||||||
name = bible.get_name()
|
name = bible.get_name()
|
||||||
# Remove corrupted files.
|
# Remove corrupted files.
|
||||||
if name is None:
|
if name is None:
|
||||||
|
bible.session.close()
|
||||||
delete_file(os.path.join(self.path, filename))
|
delete_file(os.path.join(self.path, filename))
|
||||||
continue
|
continue
|
||||||
# Find old database versions
|
# Find old database versions.
|
||||||
if bible.is_old_database():
|
if bible.is_old_database():
|
||||||
self.old_bible_databases.append([filename, name])
|
self.old_bible_databases.append([filename, name])
|
||||||
bible.session.close()
|
bible.session.close()
|
||||||
@ -220,7 +221,7 @@ class BibleManager(object):
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
u'name': book.name,
|
u'name': book.name,
|
||||||
u'book_reference_id': book.book_reference_id,
|
u'book_reference_id': book.book_reference_id,
|
||||||
u'chapters': self.db_cache[bible].get_chapter_count(book)
|
u'chapters': self.db_cache[bible].get_chapter_count(book)
|
||||||
}
|
}
|
||||||
for book in self.db_cache[bible].get_books()
|
for book in self.db_cache[bible].get_books()
|
||||||
@ -229,10 +230,10 @@ class BibleManager(object):
|
|||||||
def get_chapter_count(self, bible, book):
|
def get_chapter_count(self, bible, book):
|
||||||
"""
|
"""
|
||||||
Returns the number of Chapters for a given book.
|
Returns the number of Chapters for a given book.
|
||||||
|
|
||||||
``bible``
|
``bible``
|
||||||
Unicode. The Bible to get the list of books from.
|
Unicode. The Bible to get the list of books from.
|
||||||
|
|
||||||
``book``
|
``book``
|
||||||
The book object to get the chapter count for.
|
The book object to get the chapter count for.
|
||||||
"""
|
"""
|
||||||
@ -295,7 +296,7 @@ class BibleManager(object):
|
|||||||
if db_book:
|
if db_book:
|
||||||
book_id = db_book.book_reference_id
|
book_id = db_book.book_reference_id
|
||||||
log.debug(u'Book name corrected to "%s"', db_book.name)
|
log.debug(u'Book name corrected to "%s"', db_book.name)
|
||||||
new_reflist.append((book_id, item[1], item[2],
|
new_reflist.append((book_id, item[1], item[2],
|
||||||
item[3]))
|
item[3]))
|
||||||
else:
|
else:
|
||||||
log.debug(u'OpenLP failed to find book %s', item[0])
|
log.debug(u'OpenLP failed to find book %s', item[0])
|
||||||
|
@ -34,7 +34,8 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
|
|||||||
translate
|
translate
|
||||||
from openlp.core.lib.searchedit import SearchEdit
|
from openlp.core.lib.searchedit import SearchEdit
|
||||||
from openlp.core.lib.ui import UiStrings, add_widget_completer, \
|
from openlp.core.lib.ui import UiStrings, add_widget_completer, \
|
||||||
media_item_combo_box, critical_error_message_box, find_and_set_in_combo_box
|
media_item_combo_box, critical_error_message_box, \
|
||||||
|
find_and_set_in_combo_box, build_icon
|
||||||
from openlp.plugins.bibles.forms import BibleImportForm
|
from openlp.plugins.bibles.forms import BibleImportForm
|
||||||
from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \
|
from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \
|
||||||
VerseReferenceList, get_reference_match
|
VerseReferenceList, get_reference_match
|
||||||
@ -57,8 +58,8 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
|
|
||||||
def __init__(self, parent, plugin, icon):
|
def __init__(self, parent, plugin, icon):
|
||||||
self.IconPath = u'songs/song'
|
self.IconPath = u'songs/song'
|
||||||
self.lockIcon = QtGui.QIcon(u':/bibles/bibles_search_lock.png')
|
self.lockIcon = build_icon(u':/bibles/bibles_search_lock.png')
|
||||||
self.unlockIcon = QtGui.QIcon(u':/bibles/bibles_search_unlock.png')
|
self.unlockIcon = build_icon(u':/bibles/bibles_search_unlock.png')
|
||||||
MediaManagerItem.__init__(self, parent, plugin, icon)
|
MediaManagerItem.__init__(self, parent, plugin, icon)
|
||||||
# Place to store the search results for both bibles.
|
# Place to store the search results for both bibles.
|
||||||
self.settings = self.plugin.settings_tab
|
self.settings = self.plugin.settings_tab
|
||||||
@ -86,7 +87,7 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
not second_bible:
|
not second_bible:
|
||||||
self.displayResults(bible, second_bible)
|
self.displayResults(bible, second_bible)
|
||||||
elif critical_error_message_box(
|
elif critical_error_message_box(
|
||||||
message=translate('BiblePlugin.MediaItem',
|
message=translate('BiblesPlugin.MediaItem',
|
||||||
'You cannot combine single and dual Bible verse search results. '
|
'You cannot combine single and dual Bible verse search results. '
|
||||||
'Do you want to delete your search results and start a new '
|
'Do you want to delete your search results and start a new '
|
||||||
'search?'),
|
'search?'),
|
||||||
@ -394,6 +395,7 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
log.debug(u'Reloading Bibles')
|
log.debug(u'Reloading Bibles')
|
||||||
self.plugin.manager.reload_bibles()
|
self.plugin.manager.reload_bibles()
|
||||||
self.loadBibles()
|
self.loadBibles()
|
||||||
|
self.updateAutoCompleter()
|
||||||
|
|
||||||
def initialiseAdvancedBible(self, bible):
|
def initialiseAdvancedBible(self, bible):
|
||||||
"""
|
"""
|
||||||
@ -436,7 +438,7 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
if verse_count == 0:
|
if verse_count == 0:
|
||||||
self.advancedSearchButton.setEnabled(False)
|
self.advancedSearchButton.setEnabled(False)
|
||||||
critical_error_message_box(
|
critical_error_message_box(
|
||||||
message=translate('BiblePlugin.MediaItem',
|
message=translate('BiblesPlugin.MediaItem',
|
||||||
'Bible not fully loaded.'))
|
'Bible not fully loaded.'))
|
||||||
else:
|
else:
|
||||||
self.advancedSearchButton.setEnabled(True)
|
self.advancedSearchButton.setEnabled(True)
|
||||||
@ -611,7 +613,7 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
if restore:
|
if restore:
|
||||||
old_text = unicode(combo.currentText())
|
old_text = unicode(combo.currentText())
|
||||||
combo.clear()
|
combo.clear()
|
||||||
combo.addItems([unicode(i) for i in range(range_from, range_to + 1)])
|
combo.addItems(map(unicode, range(range_from, range_to + 1)))
|
||||||
if restore and combo.findText(old_text) != -1:
|
if restore and combo.findText(old_text) != -1:
|
||||||
combo.setCurrentIndex(combo.findText(old_text))
|
combo.setCurrentIndex(combo.findText(old_text))
|
||||||
|
|
||||||
@ -693,8 +695,8 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
verse.verse, verse.verse))
|
verse.verse, verse.verse))
|
||||||
if passage_not_found:
|
if passage_not_found:
|
||||||
QtGui.QMessageBox.information(self,
|
QtGui.QMessageBox.information(self,
|
||||||
translate('BiblePlugin.MediaItem', 'Information'),
|
translate('BiblesPlugin.MediaItem', 'Information'),
|
||||||
unicode(translate('BiblePlugin.MediaItem',
|
unicode(translate('BiblesPlugin.MediaItem',
|
||||||
'The second Bible does not contain all the verses '
|
'The second Bible does not contain all the verses '
|
||||||
'that are in the main Bible. Only verses found in both '
|
'that are in the main Bible. Only verses found in both '
|
||||||
'Bibles will be shown. %d verses have not been '
|
'Bibles will be shown. %d verses have not been '
|
||||||
@ -983,7 +985,8 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
Search for some Bible verses (by reference).
|
Search for some Bible verses (by reference).
|
||||||
"""
|
"""
|
||||||
bible = unicode(self.quickVersionComboBox.currentText())
|
bible = unicode(self.quickVersionComboBox.currentText())
|
||||||
search_results = self.plugin.manager.get_verses(bible, string, False, False)
|
search_results = self.plugin.manager.get_verses(bible, string, False,
|
||||||
|
False)
|
||||||
if search_results:
|
if search_results:
|
||||||
versetext = u' '.join([verse.text for verse in search_results])
|
versetext = u' '.join([verse.text for verse in search_results])
|
||||||
return [[string, versetext]]
|
return [[string, versetext]]
|
||||||
|
Binary file not shown.
@ -46,7 +46,7 @@ class CustomPlugin(Plugin):
|
|||||||
log.info(u'Custom Plugin loaded')
|
log.info(u'Custom Plugin loaded')
|
||||||
|
|
||||||
def __init__(self, plugin_helpers):
|
def __init__(self, plugin_helpers):
|
||||||
Plugin.__init__(self, u'Custom', plugin_helpers,
|
Plugin.__init__(self, u'custom', plugin_helpers,
|
||||||
CustomMediaItem, CustomTab)
|
CustomMediaItem, CustomTab)
|
||||||
self.weight = -5
|
self.weight = -5
|
||||||
self.manager = Manager(u'custom', init_schema)
|
self.manager = Manager(u'custom', init_schema)
|
||||||
|
@ -93,7 +93,6 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
|||||||
self.titleEdit.setText(u'')
|
self.titleEdit.setText(u'')
|
||||||
self.creditEdit.setText(u'')
|
self.creditEdit.setText(u'')
|
||||||
self.themeComboBox.setCurrentIndex(0)
|
self.themeComboBox.setCurrentIndex(0)
|
||||||
self.titleEdit.setFocus(QtCore.Qt.OtherFocusReason)
|
|
||||||
else:
|
else:
|
||||||
self.customSlide = self.manager.get_object(CustomSlide, id)
|
self.customSlide = self.manager.get_object(CustomSlide, id)
|
||||||
self.titleEdit.setText(self.customSlide.title)
|
self.titleEdit.setText(self.customSlide.title)
|
||||||
@ -104,10 +103,9 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
|||||||
self.slideListView.addItem(slide[1])
|
self.slideListView.addItem(slide[1])
|
||||||
theme = self.customSlide.theme_name
|
theme = self.customSlide.theme_name
|
||||||
find_and_set_in_combo_box(self.themeComboBox, theme)
|
find_and_set_in_combo_box(self.themeComboBox, theme)
|
||||||
|
self.titleEdit.setFocus(QtCore.Qt.OtherFocusReason)
|
||||||
# If not preview hide the preview button.
|
# If not preview hide the preview button.
|
||||||
self.previewButton.setVisible(False)
|
self.previewButton.setVisible(preview)
|
||||||
if preview:
|
|
||||||
self.previewButton.setVisible(True)
|
|
||||||
|
|
||||||
def reject(self):
|
def reject(self):
|
||||||
Receiver.send_message(u'custom_edit_clear')
|
Receiver.send_message(u'custom_edit_clear')
|
||||||
|
@ -200,6 +200,17 @@ class CustomMediaItem(MediaManagerItem):
|
|||||||
Remove a custom item from the list and database
|
Remove a custom item from the list and database
|
||||||
"""
|
"""
|
||||||
if check_item_selected(self.listView, UiStrings().SelectDelete):
|
if check_item_selected(self.listView, UiStrings().SelectDelete):
|
||||||
|
items = self.listView.selectedIndexes()
|
||||||
|
if QtGui.QMessageBox.question(self,
|
||||||
|
UiStrings().ConfirmDelete,
|
||||||
|
translate('CustomPlugin.MediaItem',
|
||||||
|
'Are you sure you want to delete the %n selected custom'
|
||||||
|
' slides(s)?', '',
|
||||||
|
QtCore.QCoreApplication.CodecForTr, len(items)),
|
||||||
|
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
|
||||||
|
QtGui.QMessageBox.No),
|
||||||
|
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.No:
|
||||||
|
return
|
||||||
row_list = [item.row() for item in self.listView.selectedIndexes()]
|
row_list = [item.row() for item in self.listView.selectedIndexes()]
|
||||||
row_list.sort(reverse=True)
|
row_list.sort(reverse=True)
|
||||||
id_list = [(item.data(QtCore.Qt.UserRole)).toInt()[0]
|
id_list = [(item.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||||
|
@ -36,7 +36,7 @@ class ImagePlugin(Plugin):
|
|||||||
log.info(u'Image Plugin loaded')
|
log.info(u'Image Plugin loaded')
|
||||||
|
|
||||||
def __init__(self, plugin_helpers):
|
def __init__(self, plugin_helpers):
|
||||||
Plugin.__init__(self, u'Images', plugin_helpers, ImageMediaItem)
|
Plugin.__init__(self, u'images', plugin_helpers, ImageMediaItem)
|
||||||
self.weight = -7
|
self.weight = -7
|
||||||
self.icon_path = u':/plugins/plugin_images.png'
|
self.icon_path = u':/plugins/plugin_images.png'
|
||||||
self.icon = build_icon(self.icon_path)
|
self.icon = build_icon(self.icon_path)
|
||||||
|
@ -52,6 +52,8 @@ class ImageMediaItem(MediaManagerItem):
|
|||||||
self.hasSearch = True
|
self.hasSearch = True
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'live_theme_changed'), self.liveThemeChanged)
|
QtCore.SIGNAL(u'live_theme_changed'), self.liveThemeChanged)
|
||||||
|
# Allow DnD from the desktop
|
||||||
|
self.listView.activateDnD()
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslateUi(self):
|
||||||
self.onNewPrompt = translate('ImagePlugin.MediaItem',
|
self.onNewPrompt = translate('ImagePlugin.MediaItem',
|
||||||
@ -131,6 +133,7 @@ class ImageMediaItem(MediaManagerItem):
|
|||||||
icon = self.iconFromFile(imageFile, thumb)
|
icon = self.iconFromFile(imageFile, thumb)
|
||||||
item_name = QtGui.QListWidgetItem(filename)
|
item_name = QtGui.QListWidgetItem(filename)
|
||||||
item_name.setIcon(icon)
|
item_name.setIcon(icon)
|
||||||
|
item_name.setToolTip(imageFile)
|
||||||
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(imageFile))
|
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(imageFile))
|
||||||
self.listView.addItem(item_name)
|
self.listView.addItem(item_name)
|
||||||
if not initialLoad:
|
if not initialLoad:
|
||||||
@ -208,8 +211,13 @@ class ImageMediaItem(MediaManagerItem):
|
|||||||
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
|
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
(path, name) = os.path.split(filename)
|
(path, name) = os.path.split(filename)
|
||||||
self.plugin.liveController.display.directImage(name, filename)
|
if self.plugin.liveController.display.directImage(name,
|
||||||
self.resetAction.setVisible(True)
|
filename):
|
||||||
|
self.resetAction.setVisible(True)
|
||||||
|
else:
|
||||||
|
critical_error_message_box(UiStrings().LiveBGError,
|
||||||
|
translate('ImagePlugin.MediaItem',
|
||||||
|
'There was no display item to amend.'))
|
||||||
else:
|
else:
|
||||||
critical_error_message_box(UiStrings().LiveBGError,
|
critical_error_message_box(UiStrings().LiveBGError,
|
||||||
unicode(translate('ImagePlugin.MediaItem',
|
unicode(translate('ImagePlugin.MediaItem',
|
||||||
|
@ -39,6 +39,8 @@ from PyQt4.phonon import Phonon
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
CLAPPERBOARD = QtGui.QPixmap(u':/media/media_video.png').toImage()
|
||||||
|
|
||||||
class MediaMediaItem(MediaManagerItem):
|
class MediaMediaItem(MediaManagerItem):
|
||||||
"""
|
"""
|
||||||
This is the custom media manager item for Media Slides.
|
This is the custom media manager item for Media Slides.
|
||||||
@ -48,8 +50,7 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
def __init__(self, parent, plugin, icon):
|
def __init__(self, parent, plugin, icon):
|
||||||
self.IconPath = u'images/image'
|
self.IconPath = u'images/image'
|
||||||
self.background = False
|
self.background = False
|
||||||
self.PreviewFunction = QtGui.QPixmap(
|
self.PreviewFunction = CLAPPERBOARD
|
||||||
u':/media/media_video.png').toImage()
|
|
||||||
MediaManagerItem.__init__(self, parent, plugin, icon)
|
MediaManagerItem.__init__(self, parent, plugin, icon)
|
||||||
self.singleServiceItem = False
|
self.singleServiceItem = False
|
||||||
self.hasSearch = True
|
self.hasSearch = True
|
||||||
@ -60,6 +61,8 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'openlp_phonon_creation'),
|
QtCore.SIGNAL(u'openlp_phonon_creation'),
|
||||||
self.createPhonon)
|
self.createPhonon)
|
||||||
|
# Allow DnD from the desktop
|
||||||
|
self.listView.activateDnD()
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslateUi(self):
|
||||||
self.onNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media')
|
self.onNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media')
|
||||||
@ -114,8 +117,12 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
filename = unicode(item.data(QtCore.Qt.UserRole).toString())
|
filename = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
(path, name) = os.path.split(filename)
|
(path, name) = os.path.split(filename)
|
||||||
self.plugin.liveController.display.video(filename, 0, True)
|
if self.plugin.liveController.display.video(filename, 0, True):
|
||||||
self.resetAction.setVisible(True)
|
self.resetAction.setVisible(True)
|
||||||
|
else:
|
||||||
|
critical_error_message_box(UiStrings().LiveBGError,
|
||||||
|
translate('MediaPlugin.MediaItem',
|
||||||
|
'There was no display item to amend.'))
|
||||||
else:
|
else:
|
||||||
critical_error_message_box(UiStrings().LiveBGError,
|
critical_error_message_box(UiStrings().LiveBGError,
|
||||||
unicode(translate('MediaPlugin.MediaItem',
|
unicode(translate('MediaPlugin.MediaItem',
|
||||||
@ -197,17 +204,17 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
SettingsManager.set_list(self.settingsSection,
|
SettingsManager.set_list(self.settingsSection,
|
||||||
u'media', self.getFileList())
|
u'media', self.getFileList())
|
||||||
|
|
||||||
def loadList(self, files):
|
def loadList(self, media):
|
||||||
# Sort the themes by its filename considering language specific
|
# Sort the themes by its filename considering language specific
|
||||||
# characters. lower() is needed for windows!
|
# characters. lower() is needed for windows!
|
||||||
files.sort(cmp=locale.strcoll,
|
media.sort(cmp=locale.strcoll,
|
||||||
key=lambda filename: os.path.split(unicode(filename))[1].lower())
|
key=lambda filename: os.path.split(unicode(filename))[1].lower())
|
||||||
for file in files:
|
for track in media:
|
||||||
filename = os.path.split(unicode(file))[1]
|
filename = os.path.split(unicode(track))[1]
|
||||||
item_name = QtGui.QListWidgetItem(filename)
|
item_name = QtGui.QListWidgetItem(filename)
|
||||||
img = QtGui.QPixmap(u':/media/media_video.png').toImage()
|
item_name.setIcon(build_icon(CLAPPERBOARD))
|
||||||
item_name.setIcon(build_icon(img))
|
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(track))
|
||||||
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
|
item_name.setToolTip(track)
|
||||||
self.listView.addItem(item_name)
|
self.listView.addItem(item_name)
|
||||||
|
|
||||||
def createPhonon(self):
|
def createPhonon(self):
|
||||||
|
@ -39,7 +39,7 @@ class MediaPlugin(Plugin):
|
|||||||
log.info(u'%s MediaPlugin loaded', __name__)
|
log.info(u'%s MediaPlugin loaded', __name__)
|
||||||
|
|
||||||
def __init__(self, plugin_helpers):
|
def __init__(self, plugin_helpers):
|
||||||
Plugin.__init__(self, u'Media', plugin_helpers,
|
Plugin.__init__(self, u'media', plugin_helpers,
|
||||||
MediaMediaItem, MediaTab)
|
MediaMediaItem, MediaTab)
|
||||||
self.weight = -6
|
self.weight = -6
|
||||||
self.icon_path = u':/plugins/plugin_media.png'
|
self.icon_path = u':/plugins/plugin_media.png'
|
||||||
|
@ -58,6 +58,8 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
self.hasSearch = True
|
self.hasSearch = True
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'mediaitem_presentation_rebuild'), self.rebuild)
|
QtCore.SIGNAL(u'mediaitem_presentation_rebuild'), self.rebuild)
|
||||||
|
# Allow DnD from the desktop
|
||||||
|
self.listView.activateDnD()
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslateUi(self):
|
||||||
"""
|
"""
|
||||||
@ -205,6 +207,7 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
item_name = QtGui.QListWidgetItem(filename)
|
item_name = QtGui.QListWidgetItem(filename)
|
||||||
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
|
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
|
||||||
item_name.setIcon(icon)
|
item_name.setIcon(icon)
|
||||||
|
item_name.setToolTip(file)
|
||||||
self.listView.addItem(item_name)
|
self.listView.addItem(item_name)
|
||||||
Receiver.send_message(u'cursor_normal')
|
Receiver.send_message(u'cursor_normal')
|
||||||
if not initialLoad:
|
if not initialLoad:
|
||||||
|
@ -52,7 +52,7 @@ class PresentationPlugin(Plugin):
|
|||||||
"""
|
"""
|
||||||
log.debug(u'Initialised')
|
log.debug(u'Initialised')
|
||||||
self.controllers = {}
|
self.controllers = {}
|
||||||
Plugin.__init__(self, u'Presentations', plugin_helpers)
|
Plugin.__init__(self, u'presentations', plugin_helpers)
|
||||||
self.weight = -8
|
self.weight = -8
|
||||||
self.icon_path = u':/plugins/plugin_presentations.png'
|
self.icon_path = u':/plugins/plugin_presentations.png'
|
||||||
self.icon = build_icon(self.icon_path)
|
self.icon = build_icon(self.icon_path)
|
||||||
|
@ -150,13 +150,11 @@ class HttpResponse(object):
|
|||||||
|
|
||||||
class HttpServer(object):
|
class HttpServer(object):
|
||||||
"""
|
"""
|
||||||
Ability to control OpenLP via a webbrowser
|
Ability to control OpenLP via a web browser.
|
||||||
e.g. http://localhost:4316/send/slidecontroller_live_next
|
|
||||||
http://localhost:4316/send/alerts_text?q=your%20alert%20text
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, plugin):
|
def __init__(self, plugin):
|
||||||
"""
|
"""
|
||||||
Initialise the httpserver, and start the server
|
Initialise the httpserver, and start the server.
|
||||||
"""
|
"""
|
||||||
log.debug(u'Initialise httpserver')
|
log.debug(u'Initialise httpserver')
|
||||||
self.plugin = plugin
|
self.plugin = plugin
|
||||||
@ -170,9 +168,9 @@ class HttpServer(object):
|
|||||||
|
|
||||||
def start_tcp(self):
|
def start_tcp(self):
|
||||||
"""
|
"""
|
||||||
Start the http server, use the port in the settings default to 4316
|
Start the http server, use the port in the settings default to 4316.
|
||||||
Listen out for slide and song changes so they can be broadcast to
|
Listen out for slide and song changes so they can be broadcast to
|
||||||
clients. Listen out for socket connections
|
clients. Listen out for socket connections.
|
||||||
"""
|
"""
|
||||||
log.debug(u'Start TCP server')
|
log.debug(u'Start TCP server')
|
||||||
port = QtCore.QSettings().value(
|
port = QtCore.QSettings().value(
|
||||||
@ -195,20 +193,20 @@ class HttpServer(object):
|
|||||||
|
|
||||||
def slide_change(self, row):
|
def slide_change(self, row):
|
||||||
"""
|
"""
|
||||||
Slide change listener. Store the item and tell the clients
|
Slide change listener. Store the item and tell the clients.
|
||||||
"""
|
"""
|
||||||
self.current_slide = row
|
self.current_slide = row
|
||||||
|
|
||||||
def item_change(self, items):
|
def item_change(self, items):
|
||||||
"""
|
"""
|
||||||
Item (song) change listener. Store the slide and tell the clients
|
Item (song) change listener. Store the slide and tell the clients.
|
||||||
"""
|
"""
|
||||||
self.current_item = items[0]
|
self.current_item = items[0]
|
||||||
|
|
||||||
def new_connection(self):
|
def new_connection(self):
|
||||||
"""
|
"""
|
||||||
A new http connection has been made. Create a client object to handle
|
A new http connection has been made. Create a client object to handle
|
||||||
communication
|
communication.
|
||||||
"""
|
"""
|
||||||
log.debug(u'new http connection')
|
log.debug(u'new http connection')
|
||||||
socket = self.server.nextPendingConnection()
|
socket = self.server.nextPendingConnection()
|
||||||
@ -225,15 +223,16 @@ class HttpServer(object):
|
|||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""
|
"""
|
||||||
Close down the http server
|
Close down the http server.
|
||||||
"""
|
"""
|
||||||
log.debug(u'close http server')
|
log.debug(u'close http server')
|
||||||
self.server.close()
|
self.server.close()
|
||||||
|
|
||||||
|
|
||||||
class HttpConnection(object):
|
class HttpConnection(object):
|
||||||
"""
|
"""
|
||||||
A single connection, this handles communication between the server
|
A single connection, this handles communication between the server
|
||||||
and the client
|
and the client.
|
||||||
"""
|
"""
|
||||||
def __init__(self, parent, socket):
|
def __init__(self, parent, socket):
|
||||||
"""
|
"""
|
||||||
@ -287,9 +286,12 @@ class HttpConnection(object):
|
|||||||
"""
|
"""
|
||||||
self.template_vars = {
|
self.template_vars = {
|
||||||
'app_title': translate('RemotePlugin.Mobile', 'OpenLP 2.0 Remote'),
|
'app_title': translate('RemotePlugin.Mobile', 'OpenLP 2.0 Remote'),
|
||||||
'stage_title': translate('RemotePlugin.Mobile', 'OpenLP 2.0 Stage View'),
|
'stage_title': translate('RemotePlugin.Mobile',
|
||||||
'service_manager': translate('RemotePlugin.Mobile', 'Service Manager'),
|
'OpenLP 2.0 Stage View'),
|
||||||
'slide_controller': translate('RemotePlugin.Mobile', 'Slide Controller'),
|
'service_manager': translate('RemotePlugin.Mobile',
|
||||||
|
'Service Manager'),
|
||||||
|
'slide_controller': translate('RemotePlugin.Mobile',
|
||||||
|
'Slide Controller'),
|
||||||
'alerts': translate('RemotePlugin.Mobile', 'Alerts'),
|
'alerts': translate('RemotePlugin.Mobile', 'Alerts'),
|
||||||
'search': translate('RemotePlugin.Mobile', 'Search'),
|
'search': translate('RemotePlugin.Mobile', 'Search'),
|
||||||
'back': translate('RemotePlugin.Mobile', 'Back'),
|
'back': translate('RemotePlugin.Mobile', 'Back'),
|
||||||
@ -301,7 +303,8 @@ class HttpConnection(object):
|
|||||||
'text': translate('RemotePlugin.Mobile', 'Text'),
|
'text': translate('RemotePlugin.Mobile', 'Text'),
|
||||||
'show_alert': translate('RemotePlugin.Mobile', 'Show Alert'),
|
'show_alert': translate('RemotePlugin.Mobile', 'Show Alert'),
|
||||||
'go_live': translate('RemotePlugin.Mobile', 'Go Live'),
|
'go_live': translate('RemotePlugin.Mobile', 'Go Live'),
|
||||||
'add_to_service': translate('RemotePlugin.Mobile', 'Add To Service'),
|
'add_to_service': translate('RemotePlugin.Mobile',
|
||||||
|
'Add to Service'),
|
||||||
'no_results': translate('RemotePlugin.Mobile', 'No Results'),
|
'no_results': translate('RemotePlugin.Mobile', 'No Results'),
|
||||||
'options': translate('RemotePlugin.Mobile', 'Options')
|
'options': translate('RemotePlugin.Mobile', 'Options')
|
||||||
}
|
}
|
||||||
@ -357,7 +360,8 @@ class HttpConnection(object):
|
|||||||
if ext == u'.html':
|
if ext == u'.html':
|
||||||
mimetype = u'text/html'
|
mimetype = u'text/html'
|
||||||
variables = self.template_vars
|
variables = self.template_vars
|
||||||
html = Template(filename=path, input_encoding=u'utf-8', output_encoding=u'utf-8').render(**variables)
|
html = Template(filename=path, input_encoding=u'utf-8',
|
||||||
|
output_encoding=u'utf-8').render(**variables)
|
||||||
elif ext == u'.css':
|
elif ext == u'.css':
|
||||||
mimetype = u'text/css'
|
mimetype = u'text/css'
|
||||||
elif ext == u'.js':
|
elif ext == u'.js':
|
||||||
@ -396,7 +400,7 @@ class HttpConnection(object):
|
|||||||
if self.parent.current_item else u''
|
if self.parent.current_item else u''
|
||||||
}
|
}
|
||||||
return HttpResponse(json.dumps({u'results': result}),
|
return HttpResponse(json.dumps({u'results': result}),
|
||||||
{u'Content-Type': u'application/json'})
|
{u'Content-Type': u'application/json'})
|
||||||
|
|
||||||
def display(self, action):
|
def display(self, action):
|
||||||
"""
|
"""
|
||||||
@ -482,10 +486,11 @@ class HttpConnection(object):
|
|||||||
|
|
||||||
def pluginInfo(self, action):
|
def pluginInfo(self, action):
|
||||||
"""
|
"""
|
||||||
Return plugin related information, based on the action
|
Return plugin related information, based on the action.
|
||||||
|
|
||||||
``action`` - The action to perform
|
``action``
|
||||||
if 'search' return a list of plugin names which support search
|
The action to perform. If *search* return a list of plugin names
|
||||||
|
which support search.
|
||||||
"""
|
"""
|
||||||
if action == u'search':
|
if action == u'search':
|
||||||
searches = []
|
searches = []
|
||||||
@ -500,10 +505,10 @@ class HttpConnection(object):
|
|||||||
|
|
||||||
def search(self, type):
|
def search(self, type):
|
||||||
"""
|
"""
|
||||||
Return a list of items that match the search text
|
Return a list of items that match the search text.
|
||||||
|
|
||||||
``type``
|
``type``
|
||||||
The plugin name to search in.
|
The plugin name to search in.
|
||||||
"""
|
"""
|
||||||
text = json.loads(self.url_params[u'data'][0])[u'request'][u'text']
|
text = json.loads(self.url_params[u'data'][0])[u'request'][u'text']
|
||||||
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
|
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
|
||||||
@ -527,7 +532,7 @@ class HttpConnection(object):
|
|||||||
|
|
||||||
def add_to_service(self, type):
|
def add_to_service(self, type):
|
||||||
"""
|
"""
|
||||||
Add item of type ``type`` to the end of the service
|
Add item of type ``type`` to the end of the service.
|
||||||
"""
|
"""
|
||||||
id = json.loads(self.url_params[u'data'][0])[u'request'][u'id']
|
id = json.loads(self.url_params[u'data'][0])[u'request'][u'id']
|
||||||
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
|
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
|
||||||
|
@ -39,7 +39,7 @@ class RemotesPlugin(Plugin):
|
|||||||
"""
|
"""
|
||||||
remotes constructor
|
remotes constructor
|
||||||
"""
|
"""
|
||||||
Plugin.__init__(self, u'Remotes', plugin_helpers,
|
Plugin.__init__(self, u'remotes', plugin_helpers,
|
||||||
settings_tab_class=RemoteTab)
|
settings_tab_class=RemoteTab)
|
||||||
self.icon_path = u':/plugins/plugin_remote.png'
|
self.icon_path = u':/plugins/plugin_remote.png'
|
||||||
self.icon = build_icon(self.icon_path)
|
self.icon = build_icon(self.icon_path)
|
||||||
|
@ -90,7 +90,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
self.onVerseListViewPressed)
|
self.onVerseListViewPressed)
|
||||||
QtCore.QObject.connect(self.themeAddButton,
|
QtCore.QObject.connect(self.themeAddButton,
|
||||||
QtCore.SIGNAL(u'clicked()'),
|
QtCore.SIGNAL(u'clicked()'),
|
||||||
self.mediaitem.plugin.renderer.theme_manager.onAddTheme)
|
self.mediaitem.plugin.renderer.themeManager.onAddTheme)
|
||||||
QtCore.QObject.connect(self.maintenanceButton,
|
QtCore.QObject.connect(self.maintenanceButton,
|
||||||
QtCore.SIGNAL(u'clicked()'), self.onMaintenanceButtonClicked)
|
QtCore.SIGNAL(u'clicked()'), self.onMaintenanceButtonClicked)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
@ -209,9 +209,11 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
self.alternativeEdit.setText(u'')
|
self.alternativeEdit.setText(u'')
|
||||||
if self.song.song_book_id != 0:
|
if self.song.song_book_id != 0:
|
||||||
book_name = self.manager.get_object(Book, self.song.song_book_id)
|
book_name = self.manager.get_object(Book, self.song.song_book_id)
|
||||||
find_and_set_in_combo_box(self.songBookComboBox, unicode(book_name.name))
|
find_and_set_in_combo_box(
|
||||||
|
self.songBookComboBox, unicode(book_name.name))
|
||||||
if self.song.theme_name:
|
if self.song.theme_name:
|
||||||
find_and_set_in_combo_box(self.themeComboBox, unicode(self.song.theme_name))
|
find_and_set_in_combo_box(
|
||||||
|
self.themeComboBox, unicode(self.song.theme_name))
|
||||||
if self.song.copyright:
|
if self.song.copyright:
|
||||||
self.copyrightEdit.setText(self.song.copyright)
|
self.copyrightEdit.setText(self.song.copyright)
|
||||||
else:
|
else:
|
||||||
|
@ -37,6 +37,8 @@ from editversedialog import Ui_EditVerseDialog
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
VERSE_REGEX = re.compile(r'---\[(.+):\D*(\d*)\D*.*\]---')
|
||||||
|
|
||||||
class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
||||||
"""
|
"""
|
||||||
This is the form that is used to edit the verses of the song.
|
This is the form that is used to edit the verses of the song.
|
||||||
@ -60,7 +62,6 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
|||||||
QtCore.QObject.connect(self.verseTypeComboBox,
|
QtCore.QObject.connect(self.verseTypeComboBox,
|
||||||
QtCore.SIGNAL(u'currentIndexChanged(int)'),
|
QtCore.SIGNAL(u'currentIndexChanged(int)'),
|
||||||
self.onVerseTypeComboBoxChanged)
|
self.onVerseTypeComboBoxChanged)
|
||||||
self.verse_regex = re.compile(r'---\[(.+):\D*(\d*)\D*.*\]---')
|
|
||||||
|
|
||||||
def contextMenu(self, point):
|
def contextMenu(self, point):
|
||||||
item = self.serviceManagerList.itemAt(point)
|
item = self.serviceManagerList.itemAt(point)
|
||||||
@ -105,7 +106,7 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
|||||||
if position == -1:
|
if position == -1:
|
||||||
return
|
return
|
||||||
text = text[:position + 4]
|
text = text[:position + 4]
|
||||||
match = self.verse_regex.match(text)
|
match = VERSE_REGEX.match(text)
|
||||||
if match:
|
if match:
|
||||||
verse_tag = match.group(1)
|
verse_tag = match.group(1)
|
||||||
try:
|
try:
|
||||||
@ -136,7 +137,7 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
|||||||
if position == -1:
|
if position == -1:
|
||||||
return
|
return
|
||||||
text = text[:position + 4]
|
text = text[:position + 4]
|
||||||
match = self.verse_regex.match(text)
|
match = VERSE_REGEX.match(text)
|
||||||
if match:
|
if match:
|
||||||
verse_type = match.group(1)
|
verse_type = match.group(1)
|
||||||
verse_type_index = VerseType.from_loose_input(verse_type)
|
verse_type_index = VerseType.from_loose_input(verse_type)
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
The :mod:`songexportform` module provides the wizard for exporting songs to the
|
The :mod:`songexportform` module provides the wizard for exporting songs to the
|
||||||
OpenLyrics format.
|
OpenLyrics format.
|
||||||
"""
|
"""
|
||||||
|
import locale
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
@ -249,6 +250,7 @@ class SongExportForm(OpenLPWizard):
|
|||||||
# Load the list of songs.
|
# Load the list of songs.
|
||||||
Receiver.send_message(u'cursor_busy')
|
Receiver.send_message(u'cursor_busy')
|
||||||
songs = self.plugin.manager.get_all_objects(Song)
|
songs = self.plugin.manager.get_all_objects(Song)
|
||||||
|
songs.sort(cmp=locale.strcoll, key=lambda song: song.title.lower())
|
||||||
for song in songs:
|
for song in songs:
|
||||||
authors = u', '.join([author.display_name
|
authors = u', '.join([author.display_name
|
||||||
for author in song.authors])
|
for author in song.authors])
|
||||||
|
@ -699,7 +699,8 @@ class SongImportForm(OpenLPWizard):
|
|||||||
elif source_format == SongFormat.OpenLP1:
|
elif source_format == SongFormat.OpenLP1:
|
||||||
# Import an openlp.org database
|
# Import an openlp.org database
|
||||||
importer = self.plugin.importSongs(SongFormat.OpenLP1,
|
importer = self.plugin.importSongs(SongFormat.OpenLP1,
|
||||||
filename=unicode(self.openLP1FilenameEdit.text())
|
filename=unicode(self.openLP1FilenameEdit.text()),
|
||||||
|
plugin=self.plugin
|
||||||
)
|
)
|
||||||
elif source_format == SongFormat.OpenLyrics:
|
elif source_format == SongFormat.OpenLyrics:
|
||||||
# Import OpenLyrics songs
|
# Import OpenLyrics songs
|
||||||
|
@ -267,6 +267,12 @@ def clean_song(manager, song):
|
|||||||
``song``
|
``song``
|
||||||
The song object.
|
The song object.
|
||||||
"""
|
"""
|
||||||
|
if isinstance(song.title, buffer):
|
||||||
|
song.title = unicode(song.title)
|
||||||
|
if isinstance(song.alternate_title, buffer):
|
||||||
|
song.alternate_title = unicode(song.alternate_title)
|
||||||
|
if isinstance(song.lyrics, buffer):
|
||||||
|
song.lyrics = unicode(song.lyrics)
|
||||||
song.title = song.title.rstrip() if song.title else u''
|
song.title = song.title.rstrip() if song.title else u''
|
||||||
if song.alternate_title is None:
|
if song.alternate_title is None:
|
||||||
song.alternate_title = u''
|
song.alternate_title = u''
|
||||||
|
@ -29,7 +29,7 @@ The :mod:`db` module provides the database and schema that is the backend for
|
|||||||
the Songs plugin
|
the Songs plugin
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from sqlalchemy import Column, ForeignKey, Index, Table, types
|
from sqlalchemy import Column, ForeignKey, Table, types
|
||||||
from sqlalchemy.orm import mapper, relation
|
from sqlalchemy.orm import mapper, relation
|
||||||
|
|
||||||
from openlp.core.lib.db import BaseModel, init_db
|
from openlp.core.lib.db import BaseModel, init_db
|
||||||
|
@ -26,13 +26,10 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from lxml import etree, objectify
|
from lxml import etree, objectify
|
||||||
|
|
||||||
from openlp.core.lib import translate
|
|
||||||
from openlp.core.ui.wizard import WizardStrings
|
|
||||||
from openlp.plugins.songs.lib import VerseType
|
from openlp.plugins.songs.lib import VerseType
|
||||||
from openlp.plugins.songs.lib.songimport import SongImport
|
from openlp.plugins.songs.lib.songimport import SongImport
|
||||||
|
|
||||||
|
@ -31,18 +31,33 @@ EasyWorship song databases into the current installation database.
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import struct
|
import struct
|
||||||
|
import re
|
||||||
|
|
||||||
from openlp.core.lib import translate
|
from openlp.core.lib import translate
|
||||||
from openlp.core.ui.wizard import WizardStrings
|
|
||||||
from openlp.plugins.songs.lib import VerseType
|
from openlp.plugins.songs.lib import VerseType
|
||||||
from openlp.plugins.songs.lib import retrieve_windows_encoding
|
from openlp.plugins.songs.lib import retrieve_windows_encoding
|
||||||
from songimport import SongImport
|
from songimport import SongImport
|
||||||
|
|
||||||
|
RTF_STRIPPING_REGEX = re.compile(r'\{\\tx[^}]*\}')
|
||||||
|
# regex: at least two newlines, can have spaces between them
|
||||||
|
SLIDE_BREAK_REGEX = re.compile(r'\n *?\n[\n ]*')
|
||||||
|
NUMBER_REGEX = re.compile(r'[0-9]+')
|
||||||
|
NOTE_REGEX = re.compile(r'\(.*?\)')
|
||||||
|
|
||||||
def strip_rtf(blob, encoding):
|
def strip_rtf(blob, encoding):
|
||||||
depth = 0
|
depth = 0
|
||||||
control = False
|
control = False
|
||||||
clear_text = []
|
clear_text = []
|
||||||
control_word = []
|
control_word = []
|
||||||
|
|
||||||
|
# workaround for \tx bug: remove one pair of curly braces
|
||||||
|
# if \tx is encountered
|
||||||
|
match = RTF_STRIPPING_REGEX.search(blob)
|
||||||
|
if match:
|
||||||
|
# start and end indices of match are curly braces - filter them out
|
||||||
|
blob = ''.join([blob[i] for i in xrange(len(blob))
|
||||||
|
if i != match.start() and i !=match.end()])
|
||||||
|
|
||||||
for c in blob:
|
for c in blob:
|
||||||
if control:
|
if control:
|
||||||
# for delimiters, set control to False
|
# for delimiters, set control to False
|
||||||
@ -259,9 +274,45 @@ class EasyWorshipSongImport(SongImport):
|
|||||||
if words:
|
if words:
|
||||||
# Format the lyrics
|
# Format the lyrics
|
||||||
words = strip_rtf(words, self.encoding)
|
words = strip_rtf(words, self.encoding)
|
||||||
for verse in words.split(u'\n\n'):
|
verse_type = VerseType.Tags[VerseType.Verse]
|
||||||
|
for verse in SLIDE_BREAK_REGEX.split(words):
|
||||||
|
verse = verse.strip()
|
||||||
|
if not verse:
|
||||||
|
continue
|
||||||
|
verse_split = verse.split(u'\n', 1)
|
||||||
|
first_line_is_tag = False
|
||||||
|
# EW tags: verse, chorus, pre-chorus, bridge, tag,
|
||||||
|
# intro, ending, slide
|
||||||
|
for type in VerseType.Names+[u'tag', u'slide']:
|
||||||
|
type = type.lower()
|
||||||
|
ew_tag = verse_split[0].strip().lower()
|
||||||
|
if ew_tag.startswith(type):
|
||||||
|
verse_type = type[0]
|
||||||
|
if type == u'tag' or type == u'slide':
|
||||||
|
verse_type = VerseType.Tags[VerseType.Other]
|
||||||
|
first_line_is_tag = True
|
||||||
|
number_found = False
|
||||||
|
# check if tag is followed by number and/or note
|
||||||
|
if len(ew_tag) > len(type):
|
||||||
|
match = NUMBER_REGEX.search(ew_tag)
|
||||||
|
if match:
|
||||||
|
number = match.group()
|
||||||
|
verse_type += number
|
||||||
|
number_found = True
|
||||||
|
match = NOTE_REGEX.search(ew_tag)
|
||||||
|
if match:
|
||||||
|
self.comments += ew_tag + u'\n'
|
||||||
|
if not number_found:
|
||||||
|
verse_type += u'1'
|
||||||
|
break
|
||||||
self.add_verse(
|
self.add_verse(
|
||||||
verse.strip(), VerseType.Tags[VerseType.Verse])
|
verse_split[-1].strip() if first_line_is_tag else verse,
|
||||||
|
verse_type)
|
||||||
|
if len(self.comments) > 5:
|
||||||
|
self.comments += unicode(
|
||||||
|
translate('SongsPlugin.EasyWorshipSongImport',
|
||||||
|
'\n[above are Song Tags with notes imported from \
|
||||||
|
EasyWorship]'))
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
break
|
break
|
||||||
if not self.finish():
|
if not self.finish():
|
||||||
|
@ -35,7 +35,8 @@ from sqlalchemy.sql import or_
|
|||||||
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
|
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
|
||||||
translate, check_item_selected, PluginStatus
|
translate, check_item_selected, PluginStatus
|
||||||
from openlp.core.lib.searchedit import SearchEdit
|
from openlp.core.lib.searchedit import SearchEdit
|
||||||
from openlp.core.lib.ui import UiStrings
|
from openlp.core.lib.ui import UiStrings, context_menu_action, \
|
||||||
|
context_menu_separator
|
||||||
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
|
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
|
||||||
SongImportForm, SongExportForm
|
SongImportForm, SongExportForm
|
||||||
from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \
|
from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \
|
||||||
@ -128,6 +129,13 @@ class SongMediaItem(MediaManagerItem):
|
|||||||
QtCore.SIGNAL(u'searchTypeChanged(int)'),
|
QtCore.SIGNAL(u'searchTypeChanged(int)'),
|
||||||
self.onSearchTextButtonClick)
|
self.onSearchTextButtonClick)
|
||||||
|
|
||||||
|
def addCustomContextActions(self):
|
||||||
|
context_menu_separator(self.listView)
|
||||||
|
context_menu_action(
|
||||||
|
self.listView, u':/general/general_clone.png',
|
||||||
|
translate('OpenLP.MediaManagerItem',
|
||||||
|
'&Clone'), self.onCloneClick)
|
||||||
|
|
||||||
def onFocus(self):
|
def onFocus(self):
|
||||||
self.searchTextEdit.setFocus()
|
self.searchTextEdit.setFocus()
|
||||||
|
|
||||||
@ -353,19 +361,37 @@ class SongMediaItem(MediaManagerItem):
|
|||||||
if check_item_selected(self.listView, UiStrings().SelectDelete):
|
if check_item_selected(self.listView, UiStrings().SelectDelete):
|
||||||
items = self.listView.selectedIndexes()
|
items = self.listView.selectedIndexes()
|
||||||
if QtGui.QMessageBox.question(self,
|
if QtGui.QMessageBox.question(self,
|
||||||
translate('SongsPlugin.MediaItem', 'Delete Song(s)?'),
|
UiStrings().ConfirmDelete,
|
||||||
translate('SongsPlugin.MediaItem',
|
translate('SongsPlugin.MediaItem',
|
||||||
'Are you sure you want to delete the %n selected song(s)?', '',
|
'Are you sure you want to delete the %n selected song(s)?', '',
|
||||||
QtCore.QCoreApplication.CodecForTr, len(items)),
|
QtCore.QCoreApplication.CodecForTr, len(items)),
|
||||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok |
|
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
|
||||||
QtGui.QMessageBox.Cancel),
|
QtGui.QMessageBox.No),
|
||||||
QtGui.QMessageBox.Ok) == QtGui.QMessageBox.Cancel:
|
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.No:
|
||||||
return
|
return
|
||||||
for item in items:
|
for item in items:
|
||||||
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
|
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||||
self.plugin.manager.delete_object(Song, item_id)
|
self.plugin.manager.delete_object(Song, item_id)
|
||||||
self.onSearchTextButtonClick()
|
self.onSearchTextButtonClick()
|
||||||
|
|
||||||
|
def onCloneClick(self):
|
||||||
|
"""
|
||||||
|
Clone a Song
|
||||||
|
"""
|
||||||
|
log.debug(u'onCloneClick')
|
||||||
|
if check_item_selected(self.listView, UiStrings().SelectEdit):
|
||||||
|
self.editItem = self.listView.currentItem()
|
||||||
|
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.title = u'%s <%s>' % (new_song.title,
|
||||||
|
translate('SongsPlugin.MediaItem', 'copy',
|
||||||
|
'For song cloning'))
|
||||||
|
self.plugin.manager.save_object(new_song)
|
||||||
|
self.onSongListLoad()
|
||||||
|
|
||||||
def generateSlideData(self, service_item, item=None, xmlVersion=False):
|
def generateSlideData(self, service_item, item=None, xmlVersion=False):
|
||||||
log.debug(u'generateSlideData (%s:%s)' % (service_item, item))
|
log.debug(u'generateSlideData (%s:%s)' % (service_item, item))
|
||||||
item_id = self._getIdOfItemToGenerate(item, self.remoteSong)
|
item_id = self._getIdOfItemToGenerate(item, self.remoteSong)
|
||||||
|
@ -57,6 +57,8 @@ class OpenLP1SongImport(SongImport):
|
|||||||
The database providing the data to import.
|
The database providing the data to import.
|
||||||
"""
|
"""
|
||||||
SongImport.__init__(self, manager, **kwargs)
|
SongImport.__init__(self, manager, **kwargs)
|
||||||
|
self.available_themes = \
|
||||||
|
kwargs[u'plugin'].formparent.themeManagerContents.getThemes()
|
||||||
|
|
||||||
def do_import(self):
|
def do_import(self):
|
||||||
"""
|
"""
|
||||||
@ -70,27 +72,34 @@ class OpenLP1SongImport(SongImport):
|
|||||||
encoding = self.get_encoding()
|
encoding = self.get_encoding()
|
||||||
if not encoding:
|
if not encoding:
|
||||||
return
|
return
|
||||||
# Connect to the database
|
# Connect to the database.
|
||||||
connection = sqlite.connect(self.import_source, mode=0444,
|
connection = sqlite.connect(self.import_source, mode=0444,
|
||||||
encoding=(encoding, 'replace'))
|
encoding=(encoding, 'replace'))
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
# Determine if we're using a new or an old DB
|
# Determine if we're using a new or an old DB.
|
||||||
cursor.execute(u'SELECT name FROM sqlite_master '
|
cursor.execute(u'SELECT name FROM sqlite_master '
|
||||||
u'WHERE type = \'table\' AND name = \'tracks\'')
|
u'WHERE type = \'table\' AND name = \'tracks\'')
|
||||||
new_db = len(cursor.fetchall()) > 0
|
new_db = len(cursor.fetchall()) > 0
|
||||||
# "cache" our list of authors
|
# "cache" our list of authors.
|
||||||
cursor.execute(u'-- types int, unicode')
|
cursor.execute(u'-- types int, unicode')
|
||||||
cursor.execute(u'SELECT authorid, authorname FROM authors')
|
cursor.execute(u'SELECT authorid, authorname FROM authors')
|
||||||
authors = cursor.fetchall()
|
authors = cursor.fetchall()
|
||||||
if new_db:
|
if new_db:
|
||||||
# "cache" our list of tracks
|
# "cache" our list of tracks.
|
||||||
cursor.execute(u'-- types int, unicode')
|
cursor.execute(u'-- types int, unicode')
|
||||||
cursor.execute(u'SELECT trackid, fulltrackname FROM tracks')
|
cursor.execute(u'SELECT trackid, fulltrackname FROM tracks')
|
||||||
tracks = cursor.fetchall()
|
tracks = cursor.fetchall()
|
||||||
# Import the songs
|
# "cache" our list of themes.
|
||||||
cursor.execute(u'-- types int, unicode, unicode, unicode')
|
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.available_themes:
|
||||||
|
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, '
|
cursor.execute(u'SELECT songid, songtitle, lyrics || \'\' AS lyrics, '
|
||||||
u'copyrightinfo FROM songs')
|
u'copyrightinfo, settingsid FROM songs')
|
||||||
songs = cursor.fetchall()
|
songs = cursor.fetchall()
|
||||||
self.import_wizard.progressBar.setMaximum(len(songs))
|
self.import_wizard.progressBar.setMaximum(len(songs))
|
||||||
for song in songs:
|
for song in songs:
|
||||||
@ -101,8 +110,12 @@ class OpenLP1SongImport(SongImport):
|
|||||||
self.title = song[1]
|
self.title = song[1]
|
||||||
lyrics = song[2].replace(u'\r\n', u'\n')
|
lyrics = song[2].replace(u'\r\n', u'\n')
|
||||||
self.add_copyright(song[3])
|
self.add_copyright(song[3])
|
||||||
|
if themes.has_key(song[4]):
|
||||||
|
self.theme_name = themes[song[4]]
|
||||||
verses = lyrics.split(u'\n\n')
|
verses = lyrics.split(u'\n\n')
|
||||||
[self.add_verse(verse.strip()) for verse in verses if verse.strip()]
|
for verse in verses:
|
||||||
|
if verse.strip():
|
||||||
|
self.add_verse(verse.strip())
|
||||||
cursor.execute(u'-- types int')
|
cursor.execute(u'-- types int')
|
||||||
cursor.execute(u'SELECT authorid FROM songauthors '
|
cursor.execute(u'SELECT authorid FROM songauthors '
|
||||||
u'WHERE songid = %s' % song_id)
|
u'WHERE songid = %s' % song_id)
|
||||||
@ -137,12 +150,12 @@ class OpenLP1SongImport(SongImport):
|
|||||||
"""
|
"""
|
||||||
Detect character encoding of an openlp.org 1.x song database.
|
Detect character encoding of an openlp.org 1.x song database.
|
||||||
"""
|
"""
|
||||||
# Connect to the database
|
# Connect to the database.
|
||||||
connection = sqlite.connect(self.import_source, mode=0444)
|
connection = sqlite.connect(self.import_source, mode=0444)
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
|
||||||
detector = UniversalDetector()
|
detector = UniversalDetector()
|
||||||
# detect charset by authors
|
# Detect charset by authors.
|
||||||
cursor.execute(u'SELECT authorname FROM authors')
|
cursor.execute(u'SELECT authorname FROM authors')
|
||||||
authors = cursor.fetchall()
|
authors = cursor.fetchall()
|
||||||
for author in authors:
|
for author in authors:
|
||||||
@ -150,7 +163,7 @@ class OpenLP1SongImport(SongImport):
|
|||||||
if detector.done:
|
if detector.done:
|
||||||
detector.close()
|
detector.close()
|
||||||
return detector.result[u'encoding']
|
return detector.result[u'encoding']
|
||||||
# detect charset by songs
|
# Detect charset by songs.
|
||||||
cursor.execute(u'SELECT songtitle, copyrightinfo, '
|
cursor.execute(u'SELECT songtitle, copyrightinfo, '
|
||||||
u'lyrics || \'\' AS lyrics FROM songs')
|
u'lyrics || \'\' AS lyrics FROM songs')
|
||||||
songs = cursor.fetchall()
|
songs = cursor.fetchall()
|
||||||
@ -160,7 +173,7 @@ class OpenLP1SongImport(SongImport):
|
|||||||
if detector.done:
|
if detector.done:
|
||||||
detector.close()
|
detector.close()
|
||||||
return detector.result[u'encoding']
|
return detector.result[u'encoding']
|
||||||
# detect charset by songs
|
# Detect charset by songs.
|
||||||
cursor.execute(u'SELECT name FROM sqlite_master '
|
cursor.execute(u'SELECT name FROM sqlite_master '
|
||||||
u'WHERE type = \'table\' AND name = \'tracks\'')
|
u'WHERE type = \'table\' AND name = \'tracks\'')
|
||||||
if len(cursor.fetchall()) > 0:
|
if len(cursor.fetchall()) > 0:
|
||||||
|
@ -35,6 +35,7 @@ import re
|
|||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from openlp.core.lib import check_directory_exists, Receiver, translate
|
from openlp.core.lib import check_directory_exists, Receiver, translate
|
||||||
|
from openlp.core.utils import clean_filename
|
||||||
from openlp.plugins.songs.lib import OpenLyrics
|
from openlp.plugins.songs.lib import OpenLyrics
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -72,8 +73,7 @@ class OpenLyricsExport(object):
|
|||||||
tree = etree.ElementTree(etree.fromstring(xml))
|
tree = etree.ElementTree(etree.fromstring(xml))
|
||||||
filename = u'%s (%s)' % (song.title,
|
filename = u'%s (%s)' % (song.title,
|
||||||
u', '.join([author.display_name for author in song.authors]))
|
u', '.join([author.display_name for author in song.authors]))
|
||||||
filename = re.sub(
|
filename = clean_filename(filename)
|
||||||
r'[/\\?*|<>\[\]":<>+%]+', u'_', filename).strip(u'_')
|
|
||||||
# Ensure the filename isn't too long for some filesystems
|
# Ensure the filename isn't too long for some filesystems
|
||||||
filename = u'%s.xml' % filename[0:250 - len(self.save_path)]
|
filename = u'%s.xml' % filename[0:250 - len(self.save_path)]
|
||||||
# Pass a file object, because lxml does not cope with some special
|
# Pass a file object, because lxml does not cope with some special
|
||||||
|
@ -26,9 +26,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import re
|
import re
|
||||||
from zipfile import ZipFile
|
|
||||||
|
|
||||||
from lxml import objectify
|
from lxml import objectify
|
||||||
from lxml.etree import Error, LxmlError
|
from lxml.etree import Error, LxmlError
|
||||||
@ -110,48 +108,13 @@ class OpenSongImport(SongImport):
|
|||||||
SongImport.__init__(self, manager, **kwargs)
|
SongImport.__init__(self, manager, **kwargs)
|
||||||
|
|
||||||
def do_import(self):
|
def do_import(self):
|
||||||
"""
|
self.import_wizard.progressBar.setMaximum(len(self.import_source))
|
||||||
Import either each of the files in self.import_source - each element of
|
|
||||||
which can be either a single opensong file, or a zipfile containing
|
|
||||||
multiple opensong files.
|
|
||||||
"""
|
|
||||||
numfiles = 0
|
|
||||||
for filename in self.import_source:
|
|
||||||
ext = os.path.splitext(filename)[1]
|
|
||||||
if ext.lower() == u'.zip':
|
|
||||||
z = ZipFile(filename, u'r')
|
|
||||||
numfiles += len(z.infolist())
|
|
||||||
z.close()
|
|
||||||
else:
|
|
||||||
numfiles += 1
|
|
||||||
log.debug(u'Total number of files: %d', numfiles)
|
|
||||||
self.import_wizard.progressBar.setMaximum(numfiles)
|
|
||||||
for filename in self.import_source:
|
for filename in self.import_source:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
return
|
return
|
||||||
ext = os.path.splitext(filename)[1]
|
song_file = open(filename)
|
||||||
if ext.lower() == u'.zip':
|
self.do_import_file(song_file)
|
||||||
log.debug(u'Zipfile found %s', filename)
|
song_file.close()
|
||||||
z = ZipFile(filename, u'r')
|
|
||||||
for song in z.infolist():
|
|
||||||
if self.stop_import_flag:
|
|
||||||
z.close()
|
|
||||||
return
|
|
||||||
parts = os.path.split(song.filename)
|
|
||||||
if parts[-1] == u'':
|
|
||||||
# No final part => directory
|
|
||||||
continue
|
|
||||||
log.info(u'Zip importing %s', parts[-1])
|
|
||||||
song_file = z.open(song)
|
|
||||||
self.do_import_file(song_file)
|
|
||||||
song_file.close()
|
|
||||||
z.close()
|
|
||||||
else:
|
|
||||||
# not a zipfile
|
|
||||||
log.info(u'Direct import %s', filename)
|
|
||||||
song_file = open(filename)
|
|
||||||
self.do_import_file(song_file)
|
|
||||||
song_file.close()
|
|
||||||
|
|
||||||
def do_import_file(self, file):
|
def do_import_file(self, file):
|
||||||
"""
|
"""
|
||||||
|
@ -36,7 +36,6 @@ import re
|
|||||||
|
|
||||||
from openlp.plugins.songs.lib import VerseType
|
from openlp.plugins.songs.lib import VerseType
|
||||||
from openlp.plugins.songs.lib.songimport import SongImport
|
from openlp.plugins.songs.lib.songimport import SongImport
|
||||||
from openlp.plugins.songs.lib.ui import SongStrings
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -29,9 +29,8 @@ import re
|
|||||||
|
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
from openlp.core.lib import Receiver, translate, check_directory_exists
|
from openlp.core.lib import Receiver, translate
|
||||||
from openlp.core.ui.wizard import WizardStrings
|
from openlp.core.ui.wizard import WizardStrings
|
||||||
from openlp.core.utils import AppLocation
|
|
||||||
from openlp.plugins.songs.lib import clean_song, VerseType
|
from openlp.plugins.songs.lib import clean_song, VerseType
|
||||||
from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile
|
from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile
|
||||||
from openlp.plugins.songs.lib.ui import SongStrings
|
from openlp.plugins.songs.lib.ui import SongStrings
|
||||||
|
@ -102,7 +102,6 @@ class SongShowPlusImport(SongImport):
|
|||||||
if not isinstance(self.import_source, list):
|
if not isinstance(self.import_source, list):
|
||||||
return
|
return
|
||||||
self.import_wizard.progressBar.setMaximum(len(self.import_source))
|
self.import_wizard.progressBar.setMaximum(len(self.import_source))
|
||||||
|
|
||||||
for file in self.import_source:
|
for file in self.import_source:
|
||||||
self.sspVerseOrderList = []
|
self.sspVerseOrderList = []
|
||||||
otherCount = 0
|
otherCount = 0
|
||||||
@ -111,7 +110,6 @@ class SongShowPlusImport(SongImport):
|
|||||||
self.import_wizard.incrementProgressBar(
|
self.import_wizard.incrementProgressBar(
|
||||||
WizardStrings.ImportingType % file_name, 0)
|
WizardStrings.ImportingType % file_name, 0)
|
||||||
songData = open(file, 'rb')
|
songData = open(file, 'rb')
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
blockKey, = struct.unpack("I", songData.read(4))
|
blockKey, = struct.unpack("I", songData.read(4))
|
||||||
# The file ends with 4 NUL's
|
# The file ends with 4 NUL's
|
||||||
@ -126,8 +124,9 @@ class SongShowPlusImport(SongImport):
|
|||||||
songData.read(2))
|
songData.read(2))
|
||||||
verseName = songData.read(verseNameLength)
|
verseName = songData.read(verseNameLength)
|
||||||
lengthDescriptorSize, = struct.unpack("B", songData.read(1))
|
lengthDescriptorSize, = struct.unpack("B", songData.read(1))
|
||||||
|
log.debug(lengthDescriptorSize)
|
||||||
# Detect if/how long the length descriptor is
|
# Detect if/how long the length descriptor is
|
||||||
if lengthDescriptorSize == 12:
|
if lengthDescriptorSize == 12 or lengthDescriptorSize == 20:
|
||||||
lengthDescriptor, = struct.unpack("I", songData.read(4))
|
lengthDescriptor, = struct.unpack("I", songData.read(4))
|
||||||
elif lengthDescriptorSize == 2:
|
elif lengthDescriptorSize == 2:
|
||||||
lengthDescriptor = 1
|
lengthDescriptor = 1
|
||||||
@ -135,6 +134,7 @@ class SongShowPlusImport(SongImport):
|
|||||||
lengthDescriptor = 0
|
lengthDescriptor = 0
|
||||||
else:
|
else:
|
||||||
lengthDescriptor, = struct.unpack("B", songData.read(1))
|
lengthDescriptor, = struct.unpack("B", songData.read(1))
|
||||||
|
log.debug(lengthDescriptorSize)
|
||||||
data = songData.read(lengthDescriptor)
|
data = songData.read(lengthDescriptor)
|
||||||
if blockKey == TITLE:
|
if blockKey == TITLE:
|
||||||
self.title = unicode(data, u'cp1252')
|
self.title = unicode(data, u'cp1252')
|
||||||
|
@ -31,7 +31,6 @@ Worship songs into the OpenLP database.
|
|||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from openlp.core.ui.wizard import WizardStrings
|
|
||||||
from openlp.plugins.songs.lib.songimport import SongImport
|
from openlp.plugins.songs.lib.songimport import SongImport
|
||||||
|
|
||||||
BLOCK_TYPES = (u'V', u'C', u'B')
|
BLOCK_TYPES = (u'V', u'C', u'B')
|
||||||
|
@ -73,6 +73,8 @@ from openlp.core.utils import get_application_version
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
CHORD_REGEX = re.compile(u'<chord name=".*?"/>')
|
||||||
|
|
||||||
class SongXML(object):
|
class SongXML(object):
|
||||||
"""
|
"""
|
||||||
This class builds and parses the XML used to describe songs.
|
This class builds and parses the XML used to describe songs.
|
||||||
@ -234,7 +236,6 @@ class OpenLyrics(object):
|
|||||||
IMPLEMENTED_VERSION = u'0.7'
|
IMPLEMENTED_VERSION = u'0.7'
|
||||||
def __init__(self, manager):
|
def __init__(self, manager):
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
self.chord_regex = re.compile(u'<chord name=".*?"/>')
|
|
||||||
|
|
||||||
def song_to_xml(self, song):
|
def song_to_xml(self, song):
|
||||||
"""
|
"""
|
||||||
@ -245,8 +246,9 @@ class OpenLyrics(object):
|
|||||||
# Append the necessary meta data to the song.
|
# Append the necessary meta data to the song.
|
||||||
song_xml.set(u'xmlns', u'http://openlyrics.info/namespace/2009/song')
|
song_xml.set(u'xmlns', u'http://openlyrics.info/namespace/2009/song')
|
||||||
song_xml.set(u'version', OpenLyrics.IMPLEMENTED_VERSION)
|
song_xml.set(u'version', OpenLyrics.IMPLEMENTED_VERSION)
|
||||||
song_xml.set(u'createdIn', get_application_version()[u'version'])
|
application_name = u'OpenLP ' + get_application_version()[u'version']
|
||||||
song_xml.set(u'modifiedIn', get_application_version()[u'version'])
|
song_xml.set(u'createdIn', application_name)
|
||||||
|
song_xml.set(u'modifiedIn', application_name)
|
||||||
song_xml.set(u'modifiedDate',
|
song_xml.set(u'modifiedDate',
|
||||||
datetime.datetime.now().strftime(u'%Y-%m-%dT%H:%M:%S'))
|
datetime.datetime.now().strftime(u'%Y-%m-%dT%H:%M:%S'))
|
||||||
properties = etree.SubElement(song_xml, u'properties')
|
properties = etree.SubElement(song_xml, u'properties')
|
||||||
@ -319,7 +321,7 @@ class OpenLyrics(object):
|
|||||||
if xml[:5] == u'<?xml':
|
if xml[:5] == u'<?xml':
|
||||||
xml = xml[38:]
|
xml = xml[38:]
|
||||||
# Remove chords from xml.
|
# Remove chords from xml.
|
||||||
xml = self.chord_regex.sub(u'', xml)
|
xml = CHORD_REGEX.sub(u'', xml)
|
||||||
song_xml = objectify.fromstring(xml)
|
song_xml = objectify.fromstring(xml)
|
||||||
if hasattr(song_xml, u'properties'):
|
if hasattr(song_xml, u'properties'):
|
||||||
properties = song_xml.properties
|
properties = song_xml.properties
|
||||||
|
@ -57,7 +57,7 @@ class SongsPlugin(Plugin):
|
|||||||
"""
|
"""
|
||||||
Create and set up the Songs plugin.
|
Create and set up the Songs plugin.
|
||||||
"""
|
"""
|
||||||
Plugin.__init__(self, u'Songs', plugin_helpers, SongMediaItem, SongsTab)
|
Plugin.__init__(self, u'songs', plugin_helpers, SongMediaItem, SongsTab)
|
||||||
self.weight = -10
|
self.weight = -10
|
||||||
self.manager = Manager(u'songs', init_schema)
|
self.manager = Manager(u'songs', init_schema)
|
||||||
self.icon_path = u':/plugins/plugin_songs.png'
|
self.icon_path = u':/plugins/plugin_songs.png'
|
||||||
|
@ -33,7 +33,7 @@ from PyQt4 import QtCore, QtGui
|
|||||||
from openlp.core.lib import Plugin, StringContent, Receiver, build_icon, \
|
from openlp.core.lib import Plugin, StringContent, Receiver, build_icon, \
|
||||||
translate
|
translate
|
||||||
from openlp.core.lib.db import Manager
|
from openlp.core.lib.db import Manager
|
||||||
from openlp.core.lib.ui import base_action, shortcut_action, UiStrings
|
from openlp.core.lib.ui import base_action, shortcut_action
|
||||||
from openlp.core.utils.actions import ActionList
|
from openlp.core.utils.actions import ActionList
|
||||||
from openlp.plugins.songusage.forms import SongUsageDetailForm, \
|
from openlp.plugins.songusage.forms import SongUsageDetailForm, \
|
||||||
SongUsageDeleteForm
|
SongUsageDeleteForm
|
||||||
@ -45,11 +45,13 @@ class SongUsagePlugin(Plugin):
|
|||||||
log.info(u'SongUsage Plugin loaded')
|
log.info(u'SongUsage Plugin loaded')
|
||||||
|
|
||||||
def __init__(self, plugin_helpers):
|
def __init__(self, plugin_helpers):
|
||||||
Plugin.__init__(self, u'SongUsage', plugin_helpers)
|
Plugin.__init__(self, u'songusage', plugin_helpers)
|
||||||
self.weight = -4
|
self.weight = -4
|
||||||
self.icon = build_icon(u':/plugins/plugin_songusage.png')
|
self.icon = build_icon(u':/plugins/plugin_songusage.png')
|
||||||
|
self.activeIcon = build_icon(u':/songusage/song_usage_active.png')
|
||||||
|
self.inactiveIcon = build_icon(u':/songusage/song_usage_inactive.png')
|
||||||
self.manager = None
|
self.manager = None
|
||||||
self.songusageActive = False
|
self.songUsageActive = False
|
||||||
|
|
||||||
def addToolsMenuItem(self, tools_menu):
|
def addToolsMenuItem(self, tools_menu):
|
||||||
"""
|
"""
|
||||||
@ -84,17 +86,29 @@ class SongUsagePlugin(Plugin):
|
|||||||
self.songUsageStatus.setText(translate(
|
self.songUsageStatus.setText(translate(
|
||||||
'SongUsagePlugin', 'Toggle Tracking'))
|
'SongUsagePlugin', 'Toggle Tracking'))
|
||||||
self.songUsageStatus.setStatusTip(translate('SongUsagePlugin',
|
self.songUsageStatus.setStatusTip(translate('SongUsagePlugin',
|
||||||
'Toggle the tracking of song usage.'))
|
'Toggle the tracking of song usage.'))
|
||||||
#Add Menus together
|
# Add Menus together
|
||||||
self.toolsMenu.addAction(self.songUsageMenu.menuAction())
|
self.toolsMenu.addAction(self.songUsageMenu.menuAction())
|
||||||
self.songUsageMenu.addAction(self.songUsageStatus)
|
self.songUsageMenu.addAction(self.songUsageStatus)
|
||||||
self.songUsageMenu.addSeparator()
|
self.songUsageMenu.addSeparator()
|
||||||
self.songUsageMenu.addAction(self.songUsageDelete)
|
|
||||||
self.songUsageMenu.addAction(self.songUsageReport)
|
self.songUsageMenu.addAction(self.songUsageReport)
|
||||||
|
self.songUsageMenu.addAction(self.songUsageDelete)
|
||||||
|
self.songUsageActiveButton = QtGui.QToolButton(
|
||||||
|
self.formparent.statusBar)
|
||||||
|
self.songUsageActiveButton.setCheckable(True)
|
||||||
|
self.songUsageActiveButton.setStatusTip(translate('SongUsagePlugin',
|
||||||
|
'Toggle the tracking of song usage.'))
|
||||||
|
self.songUsageActiveButton.setObjectName(u'songUsageActiveButton')
|
||||||
|
self.formparent.statusBar.insertPermanentWidget(1,
|
||||||
|
self.songUsageActiveButton)
|
||||||
|
self.songUsageActiveButton.hide()
|
||||||
# Signals and slots
|
# Signals and slots
|
||||||
QtCore.QObject.connect(self.songUsageStatus,
|
QtCore.QObject.connect(self.songUsageStatus,
|
||||||
QtCore.SIGNAL(u'visibilityChanged(bool)'),
|
QtCore.SIGNAL(u'visibilityChanged(bool)'),
|
||||||
self.songUsageStatus.setChecked)
|
self.songUsageStatus.setChecked)
|
||||||
|
QtCore.QObject.connect(self.songUsageActiveButton,
|
||||||
|
QtCore.SIGNAL(u'toggled(bool)'),
|
||||||
|
self.toggleSongUsageState)
|
||||||
QtCore.QObject.connect(self.songUsageDelete,
|
QtCore.QObject.connect(self.songUsageDelete,
|
||||||
QtCore.SIGNAL(u'triggered()'), self.onSongUsageDelete)
|
QtCore.SIGNAL(u'triggered()'), self.onSongUsageDelete)
|
||||||
QtCore.QObject.connect(self.songUsageReport,
|
QtCore.QObject.connect(self.songUsageReport,
|
||||||
@ -107,23 +121,25 @@ class SongUsagePlugin(Plugin):
|
|||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'slidecontroller_live_started'),
|
QtCore.SIGNAL(u'slidecontroller_live_started'),
|
||||||
self.onReceiveSongUsage)
|
self.onReceiveSongUsage)
|
||||||
self.SongUsageActive = QtCore.QSettings().value(
|
self.songUsageActive = QtCore.QSettings().value(
|
||||||
self.settingsSection + u'/active',
|
self.settingsSection + u'/active',
|
||||||
QtCore.QVariant(False)).toBool()
|
QtCore.QVariant(False)).toBool()
|
||||||
self.songUsageStatus.setChecked(self.SongUsageActive)
|
# Set the button and checkbox state
|
||||||
|
self.setButtonState()
|
||||||
action_list = ActionList.get_instance()
|
action_list = ActionList.get_instance()
|
||||||
|
action_list.add_action(self.songUsageStatus,
|
||||||
|
translate('SongUsagePlugin', 'Song Usage'))
|
||||||
action_list.add_action(self.songUsageDelete,
|
action_list.add_action(self.songUsageDelete,
|
||||||
translate('SongUsagePlugin', 'Song Usage'))
|
translate('SongUsagePlugin', 'Song Usage'))
|
||||||
action_list.add_action(self.songUsageReport,
|
action_list.add_action(self.songUsageReport,
|
||||||
translate('SongUsagePlugin', 'Song Usage'))
|
translate('SongUsagePlugin', 'Song Usage'))
|
||||||
action_list.add_action(self.songUsageStatus,
|
|
||||||
translate('SongUsagePlugin', 'Song Usage'))
|
|
||||||
if self.manager is None:
|
if self.manager is None:
|
||||||
self.manager = Manager(u'songusage', init_schema)
|
self.manager = Manager(u'songusage', init_schema)
|
||||||
self.songUsageDeleteForm = SongUsageDeleteForm(self.manager,
|
self.songUsageDeleteForm = SongUsageDeleteForm(self.manager,
|
||||||
self.formparent)
|
self.formparent)
|
||||||
self.songUsageDetailForm = SongUsageDetailForm(self, self.formparent)
|
self.songUsageDetailForm = SongUsageDetailForm(self, self.formparent)
|
||||||
self.songUsageMenu.menuAction().setVisible(True)
|
self.songUsageMenu.menuAction().setVisible(True)
|
||||||
|
self.songUsageActiveButton.show()
|
||||||
|
|
||||||
def finalise(self):
|
def finalise(self):
|
||||||
"""
|
"""
|
||||||
@ -134,26 +150,55 @@ class SongUsagePlugin(Plugin):
|
|||||||
Plugin.finalise(self)
|
Plugin.finalise(self)
|
||||||
self.songUsageMenu.menuAction().setVisible(False)
|
self.songUsageMenu.menuAction().setVisible(False)
|
||||||
action_list = ActionList.get_instance()
|
action_list = ActionList.get_instance()
|
||||||
|
action_list.remove_action(self.songUsageStatus,
|
||||||
|
translate('SongUsagePlugin', 'Song Usage'))
|
||||||
action_list.remove_action(self.songUsageDelete,
|
action_list.remove_action(self.songUsageDelete,
|
||||||
translate('SongUsagePlugin', 'Song Usage'))
|
translate('SongUsagePlugin', 'Song Usage'))
|
||||||
action_list.remove_action(self.songUsageReport,
|
action_list.remove_action(self.songUsageReport,
|
||||||
translate('SongUsagePlugin', 'Song Usage'))
|
translate('SongUsagePlugin', 'Song Usage'))
|
||||||
action_list.remove_action(self.songUsageStatus,
|
self.songUsageActiveButton.hide()
|
||||||
translate('SongUsagePlugin', 'Song Usage'))
|
# stop any events being processed
|
||||||
#stop any events being processed
|
self.songUsageActive = False
|
||||||
self.SongUsageActive = False
|
|
||||||
|
|
||||||
def toggleSongUsageState(self):
|
def toggleSongUsageState(self):
|
||||||
self.SongUsageActive = not self.SongUsageActive
|
"""
|
||||||
|
Manage the state of the audit collection and amend
|
||||||
|
the UI when necessary,
|
||||||
|
"""
|
||||||
|
self.songUsageActive = not self.songUsageActive
|
||||||
QtCore.QSettings().setValue(self.settingsSection + u'/active',
|
QtCore.QSettings().setValue(self.settingsSection + u'/active',
|
||||||
QtCore.QVariant(self.SongUsageActive))
|
QtCore.QVariant(self.songUsageActive))
|
||||||
|
self.setButtonState()
|
||||||
|
|
||||||
|
def setButtonState(self):
|
||||||
|
"""
|
||||||
|
Keep buttons inline. Turn of signals to stop dead loop but we need the
|
||||||
|
button and check box set correctly.
|
||||||
|
"""
|
||||||
|
self.songUsageActiveButton.blockSignals(True)
|
||||||
|
self.songUsageStatus.blockSignals(True)
|
||||||
|
if self.songUsageActive:
|
||||||
|
self.songUsageActiveButton.setIcon(self.activeIcon)
|
||||||
|
self.songUsageStatus.setChecked(True)
|
||||||
|
self.songUsageActiveButton.setChecked(True)
|
||||||
|
self.songUsageActiveButton.setToolTip(translate('SongUsagePlugin',
|
||||||
|
'Song usage tracking is active.'))
|
||||||
|
else:
|
||||||
|
self.songUsageActiveButton.setIcon(self.inactiveIcon)
|
||||||
|
self.songUsageStatus.setChecked(False)
|
||||||
|
self.songUsageActiveButton.setChecked(False)
|
||||||
|
self.songUsageActiveButton.setToolTip(translate('SongUsagePlugin',
|
||||||
|
'Song usage tracking is inactive.'))
|
||||||
|
self.songUsageActiveButton.blockSignals(False)
|
||||||
|
self.songUsageStatus.blockSignals(False)
|
||||||
|
|
||||||
|
|
||||||
def onReceiveSongUsage(self, item):
|
def onReceiveSongUsage(self, item):
|
||||||
"""
|
"""
|
||||||
Song Usage for live song from SlideController
|
Song Usage for live song from SlideController
|
||||||
"""
|
"""
|
||||||
audit = item[0].audit
|
audit = item[0].audit
|
||||||
if self.SongUsageActive and audit:
|
if self.songUsageActive and audit:
|
||||||
song_usage_item = SongUsageItem()
|
song_usage_item = SongUsageItem()
|
||||||
song_usage_item.usagedate = datetime.today()
|
song_usage_item.usagedate = datetime.today()
|
||||||
song_usage_item.usagetime = datetime.now().time()
|
song_usage_item.usagetime = datetime.now().time()
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 97 KiB |
6
resources/images/README.txt
Normal file
6
resources/images/README.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
OpenLP.ico
|
||||||
|
|
||||||
|
This Windows icon contains several images with different resolution.
|
||||||
|
It can be recreated by command:
|
||||||
|
|
||||||
|
icotool -c -o OpenLP.ico openlp-logo-16x16.png openlp-logo-32x32.png openlp-logo-48x48.png openlp-logo-64x64.png openlp-logo-128x128.png
|
BIN
resources/images/general_clone.png
Normal file
BIN
resources/images/general_clone.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 527 B |
@ -56,6 +56,7 @@
|
|||||||
<file>general_save.png</file>
|
<file>general_save.png</file>
|
||||||
<file>general_email.png</file>
|
<file>general_email.png</file>
|
||||||
<file>general_revert.png</file>
|
<file>general_revert.png</file>
|
||||||
|
<file>general_clone.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="slides">
|
<qresource prefix="slides">
|
||||||
<file>slide_close.png</file>
|
<file>slide_close.png</file>
|
||||||
@ -137,6 +138,10 @@
|
|||||||
<file>messagebox_info.png</file>
|
<file>messagebox_info.png</file>
|
||||||
<file>messagebox_warning.png</file>
|
<file>messagebox_warning.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
|
<qresource prefix="songusage">
|
||||||
|
<file>song_usage_active.png</file>
|
||||||
|
<file>song_usage_inactive.png</file>
|
||||||
|
</qresource>
|
||||||
<qresource prefix="tools">
|
<qresource prefix="tools">
|
||||||
<file>tools_add.png</file>
|
<file>tools_add.png</file>
|
||||||
<file>tools_alert.png</file>
|
<file>tools_alert.png</file>
|
||||||
|
BIN
resources/images/song_usage_active.png
Normal file
BIN
resources/images/song_usage_active.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 757 B |
BIN
resources/images/song_usage_inactive.png
Normal file
BIN
resources/images/song_usage_inactive.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 716 B |
@ -2,6 +2,99 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
|
||||||
|
<key>CFBundleDocumentTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtension</key>
|
||||||
|
<array>
|
||||||
|
<string>osz</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeIconFiles</key>
|
||||||
|
<array>
|
||||||
|
<string>openlp-logo-with-text.icns</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>OpenLP Service</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
<key>LSHandlerRank</key>
|
||||||
|
<string>Owner</string>
|
||||||
|
<key>LSItemContentTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>org.openlp.osz</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtension</key>
|
||||||
|
<array>
|
||||||
|
<string>otz</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeIconFiles</key>
|
||||||
|
<array>
|
||||||
|
<string>openlp-logo-with-text.icns</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>OpenLP Theme</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
<key>LSHandlerRank</key>
|
||||||
|
<string>Owner</string>
|
||||||
|
<key>LSItemContentTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>org.openlp.otz</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<key>UTExportedTypeDeclarations</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>UTTypeIdentifier</key>
|
||||||
|
<string>org.openlp.osz</string>
|
||||||
|
<key>UTTypeDescription</key>
|
||||||
|
<string>OpenLP Service</string>
|
||||||
|
<key>UTTypeConformsTo</key>
|
||||||
|
<array>
|
||||||
|
<string>public.data</string>
|
||||||
|
<string>public.content</string>
|
||||||
|
</array>
|
||||||
|
<key>UTTypeTagSpecification</key>
|
||||||
|
<dict>
|
||||||
|
<key>public.filename-extension</key>
|
||||||
|
<array>
|
||||||
|
<string>osz</string>
|
||||||
|
</array>
|
||||||
|
<key>public.mime-type</key>
|
||||||
|
<array>
|
||||||
|
<string>application/x-openlp-service</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>UTTypeIdentifier</key>
|
||||||
|
<string>org.openlp.otz</string>
|
||||||
|
<key>UTTypeDescription</key>
|
||||||
|
<string>OpenLP Theme</string>
|
||||||
|
<key>UTTypeConformsTo</key>
|
||||||
|
<array>
|
||||||
|
<string>public.data</string>
|
||||||
|
<string>public.content</string>
|
||||||
|
</array>
|
||||||
|
<key>UTTypeTagSpecification</key>
|
||||||
|
<dict>
|
||||||
|
<key>public.filename-extension</key>
|
||||||
|
<array>
|
||||||
|
<string>otz</string>
|
||||||
|
</array>
|
||||||
|
<key>public.mime-type</key>
|
||||||
|
<array>
|
||||||
|
<string>application/x-openlp-theme</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>org.openlp</string>
|
<string>org.openlp</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
|
@ -48,7 +48,7 @@ on run
|
|||||||
set theViewOptions to the icon view options of container window
|
set theViewOptions to the icon view options of container window
|
||||||
set arrangement of theViewOptions to not arranged
|
set arrangement of theViewOptions to not arranged
|
||||||
set icon size of theViewOptions to 128
|
set icon size of theViewOptions to 128
|
||||||
set background picture of theViewOptions to file ".installer-background.png"
|
set background picture of theViewOptions to file ".background:installer-background.png"
|
||||||
if not exists file "Applications" then
|
if not exists file "Applications" then
|
||||||
make new alias file at container window to POSIX file "/Applications" with properties {name:"Applications"}
|
make new alias file at container window to POSIX file "/Applications" with properties {name:"Applications"}
|
||||||
end if
|
end if
|
||||||
|
@ -49,15 +49,19 @@ on run
|
|||||||
set theViewOptions to the icon view options of container window
|
set theViewOptions to the icon view options of container window
|
||||||
set arrangement of theViewOptions to not arranged
|
set arrangement of theViewOptions to not arranged
|
||||||
set icon size of theViewOptions to 128
|
set icon size of theViewOptions to 128
|
||||||
set background picture of theViewOptions to file ".installer-background.png"
|
set background picture of theViewOptions to file ".background:installer-background.png"
|
||||||
make new alias file at container window to POSIX file "/Applications" with properties {name:"Applications"}
|
if not exists file "Applications" then
|
||||||
delay 5
|
make new alias file at container window to POSIX file "/Applications" with properties {name:"Applications"}
|
||||||
|
end if
|
||||||
|
delay 1
|
||||||
set position of item "%s" of container window to {160, 200}
|
set position of item "%s" of container window to {160, 200}
|
||||||
set position of item ".Trashes" of container window to {100, 500}
|
set position of item ".Trashes" of container window to {100, 500}
|
||||||
set position of item ".installer-background.png" of container window to {200, 500}
|
set position of item ".background" of container window to {200, 500}
|
||||||
set position of item ".DS_Store" of container window to {400, 500}
|
set position of item ".DS_Store" of container window to {400, 500}
|
||||||
set position of item "Applications" of container window to {550, 200}
|
set position of item "Applications" of container window to {550, 200}
|
||||||
set position of item ".VolumeIcon.icns" of container window to {500, 500}
|
if exists file ".VolumeIcon.icns" then
|
||||||
|
set position of item ".VolumeIcon.icns" of container window to {500, 500}
|
||||||
|
end if
|
||||||
set position of item ".fseventsd" of container window to {300, 500}
|
set position of item ".fseventsd" of container window to {300, 500}
|
||||||
if exists POSIX file ".SymAVx86QSFile" then
|
if exists POSIX file ".SymAVx86QSFile" then
|
||||||
set position of item ".SymAVx86QSFile" of container window to {600, 500}
|
set position of item ".SymAVx86QSFile" of container window to {600, 500}
|
||||||
|
@ -93,8 +93,12 @@ script_name = "build"
|
|||||||
def build_application(settings, app_name_lower, app_dir):
|
def build_application(settings, app_name_lower, app_dir):
|
||||||
logging.info('[%s] now building the app with pyinstaller at "%s"...',
|
logging.info('[%s] now building the app with pyinstaller at "%s"...',
|
||||||
script_name, settings['pyinstaller_basedir'])
|
script_name, settings['pyinstaller_basedir'])
|
||||||
result = os.system('python %s/pyinstaller.py openlp.spec' \
|
full_python_dir = os.path.join('/opt/local/Library/Frameworks',
|
||||||
% settings['pyinstaller_basedir'])
|
'Python.framework/Versions/2.6/Resources/',
|
||||||
|
'Python.app/Contents/MacOS/Python')
|
||||||
|
result = os.system('arch -i386 %s %s/pyinstaller.py openlp.spec' \
|
||||||
|
% ( full_python_dir,
|
||||||
|
settings['pyinstaller_basedir']) )
|
||||||
if (result != 0):
|
if (result != 0):
|
||||||
logging.error('[%s] The pyinstaller build reported an error, cannot \
|
logging.error('[%s] The pyinstaller build reported an error, cannot \
|
||||||
continue!', script_name)
|
continue!', script_name)
|
||||||
@ -219,10 +223,10 @@ def create_dmg(settings):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
logging.info('[%s] copying the background image...', script_name)
|
logging.info('[%s] copying the background image...', script_name)
|
||||||
# os.mkdir(volume_basedir + '/.background')
|
os.mkdir(volume_basedir + '/.background')
|
||||||
result = os.system('CpMac %s %s'
|
result = os.system('CpMac %s %s'
|
||||||
% (settings['installer_backgroundimage_file'],
|
% (settings['installer_backgroundimage_file'],
|
||||||
volume_basedir + '/.installer-background.png'))
|
volume_basedir + '/.background/installer-background.png'))
|
||||||
if (result != 0):
|
if (result != 0):
|
||||||
logging.error('[%s] could not copy the background image, dmg creation\
|
logging.error('[%s] could not copy the background image, dmg creation\
|
||||||
failed!', script_name)
|
failed!', script_name)
|
||||||
|
0
resources/osx/openlp-logo-with-text.icns
Executable file → Normal file
0
resources/osx/openlp-logo-with-text.icns
Executable file → Normal file
@ -1,8 +1,8 @@
|
|||||||
[openlp]
|
[openlp]
|
||||||
openlp_appname = OpenLP
|
openlp_appname = OpenLP
|
||||||
openlp_dmgname = OpenLP-1.9.4-bzrXXXX
|
openlp_dmgname = OpenLP-1.9.6-bzrXXXX
|
||||||
openlp_version = XXXX
|
openlp_version = XXXX
|
||||||
openlp_basedir = /Users/openlp/trunk
|
openlp_basedir = /Users/openlp/repo/trunk
|
||||||
openlp_icon_file = openlp-logo-with-text.icns
|
openlp_icon_file = openlp-logo-with-text.icns
|
||||||
openlp_dmg_icon_file = openlp-logo-420x420.png
|
openlp_dmg_icon_file = openlp-logo-420x420.png
|
||||||
installer_backgroundimage_file = installation-background.png
|
installer_backgroundimage_file = installation-background.png
|
@ -1,5 +1,5 @@
|
|||||||
# -*- mode: python -*-
|
# -*- mode: python -*-
|
||||||
a = Analysis([os.path.join(HOMEPATH,'support/_mountzlib.py'), os.path.join(HOMEPATH,'support/useUnicode.py'), '%(openlp_basedir)s/openlp.pyw'],
|
a = Analysis([os.path.join(HOMEPATH,'support/_mountzlib.py'), os.path.join(CONFIGDIR,'support/useUnicode.py'), '%(openlp_basedir)s/openlp.pyw'],
|
||||||
pathex=['%(pyinstaller_basedir)s'], hookspath=['%(openlp_basedir)s/resources/pyinstaller'])
|
pathex=['%(pyinstaller_basedir)s'], hookspath=['%(openlp_basedir)s/resources/pyinstaller'])
|
||||||
pyz = PYZ(a.pure)
|
pyz = PYZ(a.pure)
|
||||||
exe = EXE(pyz,
|
exe = EXE(pyz,
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
# -*- mode: python -*-
|
|
||||||
a = Analysis([
|
|
||||||
os.path.join(HOMEPATH, 'support\\_mountzlib.py'),
|
|
||||||
os.path.join(HOMEPATH, 'support\\useUnicode.py'),
|
|
||||||
os.path.abspath('openlp.pyw')],
|
|
||||||
pathex=[os.path.abspath('.')])
|
|
||||||
pyz = PYZ(a.pure)
|
|
||||||
exe = EXE(pyz, a.scripts, exclude_binaries=1,
|
|
||||||
name=os.path.abspath(os.path.join('build', 'pyi.win32', 'OpenLP',
|
|
||||||
'OpenLP.exe')),
|
|
||||||
debug=False, strip=False, upx=True, console=False,
|
|
||||||
icon=os.path.abspath(os.path.join('resources', 'images', 'OpenLP.ico')))
|
|
||||||
coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True,
|
|
||||||
name=os.path.abspath(os.path.join('dist', 'OpenLP')))
|
|
185
scripts/check_dependencies.py
Executable file
185
scripts/check_dependencies.py
Executable file
@ -0,0 +1,185 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# OpenLP - Open Source Lyrics Projection #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# Copyright (c) 2008-2011 Raoul Snyman #
|
||||||
|
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
|
||||||
|
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
|
||||||
|
# Armin Köhler, Joshua Millar, Stevan Pettit, Andreas Preikschat, Mattias #
|
||||||
|
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||||
|
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# This program is free software; you can redistribute it and/or modify it #
|
||||||
|
# under the terms of the GNU General Public License as published by the Free #
|
||||||
|
# Software Foundation; version 2 of the License. #
|
||||||
|
# #
|
||||||
|
# This program is distributed in the hope that it will be useful, but WITHOUT #
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
|
||||||
|
# more details. #
|
||||||
|
# #
|
||||||
|
# You should have received a copy of the GNU General Public License along #
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
"""
|
||||||
|
This script is used to check dependencies of OpenLP. It checks availability
|
||||||
|
of required python modules and their version. To verify availability of Python
|
||||||
|
modules, simply run this script::
|
||||||
|
|
||||||
|
@:~$ ./check_dependencies.py
|
||||||
|
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
is_win = sys.platform.startswith('win')
|
||||||
|
|
||||||
|
VERS = {
|
||||||
|
'Python': '2.6',
|
||||||
|
'PyQt4': '4.6',
|
||||||
|
'Qt4': '4.6',
|
||||||
|
'sqlalchemy': '0.5',
|
||||||
|
# pyenchant 1.6 required on Windows
|
||||||
|
'enchant': '1.6' if is_win else '1.3'
|
||||||
|
}
|
||||||
|
|
||||||
|
# pywin32
|
||||||
|
WIN32_MODULES = [
|
||||||
|
'win32com',
|
||||||
|
'win32ui',
|
||||||
|
'pywintypes',
|
||||||
|
]
|
||||||
|
|
||||||
|
MODULES = [
|
||||||
|
'PyQt4',
|
||||||
|
'PyQt4.QtCore',
|
||||||
|
'PyQt4.QtGui',
|
||||||
|
'PyQt4.QtNetwork',
|
||||||
|
'PyQt4.QtOpenGL',
|
||||||
|
'PyQt4.QtSvg',
|
||||||
|
'PyQt4.QtTest',
|
||||||
|
'PyQt4.QtWebKit',
|
||||||
|
'PyQt4.phonon',
|
||||||
|
'sqlalchemy',
|
||||||
|
'sqlite3',
|
||||||
|
'lxml',
|
||||||
|
'chardet',
|
||||||
|
'enchant',
|
||||||
|
'BeautifulSoup',
|
||||||
|
'mako',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
OPTIONAL_MODULES = [
|
||||||
|
('sqlite', ' (SQLite 2 support)'),
|
||||||
|
('MySQLdb', ' (MySQL support)'),
|
||||||
|
('psycopg2', ' (PostgreSQL support)'),
|
||||||
|
]
|
||||||
|
|
||||||
|
w = sys.stdout.write
|
||||||
|
|
||||||
|
def check_vers(version, required, text):
|
||||||
|
if type(version) is str:
|
||||||
|
version = version.split('.')
|
||||||
|
version = map(int, version)
|
||||||
|
if type(required) is str:
|
||||||
|
required = required.split('.')
|
||||||
|
required = map(int, required)
|
||||||
|
w(' %s >= %s ... ' % (text, '.'.join(map(str, required))))
|
||||||
|
if version >= required:
|
||||||
|
w('.'.join(map(str, version)) + os.linesep)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
w('FAIL' + os.linesep)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def print_vers_fail(required, text):
|
||||||
|
print(' %s >= %s ... FAIL' % (text, required))
|
||||||
|
|
||||||
|
def verify_python():
|
||||||
|
if not check_vers(list(sys.version_info), VERS['Python'], text='Python'):
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
def verify_versions():
|
||||||
|
print('Verifying version of modules...')
|
||||||
|
try:
|
||||||
|
from PyQt4 import QtCore
|
||||||
|
check_vers(QtCore.PYQT_VERSION_STR, VERS['PyQt4'], 'PyQt4')
|
||||||
|
check_vers(QtCore.qVersion(), VERS['Qt4'], 'Qt4')
|
||||||
|
except ImportError:
|
||||||
|
print_vers_fail(VERS['PyQt4'], 'PyQt4')
|
||||||
|
print_vers_fail(VERS['Qt4'], 'Qt4')
|
||||||
|
try:
|
||||||
|
import sqlalchemy
|
||||||
|
check_vers(sqlalchemy.__version__, VERS['sqlalchemy'], 'sqlalchemy')
|
||||||
|
except ImportError:
|
||||||
|
print_vers_fail(VERS['sqlalchemy'], 'sqlalchemy')
|
||||||
|
try:
|
||||||
|
import enchant
|
||||||
|
check_vers(enchant.__version__, VERS['enchant'], 'enchant')
|
||||||
|
except ImportError:
|
||||||
|
print_vers_fail(VERS['enchant'], 'enchant')
|
||||||
|
|
||||||
|
def check_module(mod, text='', indent=' '):
|
||||||
|
space = (30 - len(mod) - len(text)) * ' '
|
||||||
|
w(indent + '%s%s... ' % (mod, text) + space)
|
||||||
|
try:
|
||||||
|
__import__(mod)
|
||||||
|
w('OK')
|
||||||
|
except ImportError:
|
||||||
|
w('FAIL')
|
||||||
|
w(os.linesep)
|
||||||
|
|
||||||
|
def verify_pyenchant():
|
||||||
|
w('Enchant (spell checker)... ')
|
||||||
|
try:
|
||||||
|
import enchant
|
||||||
|
w(os.linesep)
|
||||||
|
backends = ', '.join([x.name for x in enchant.Broker().describe()])
|
||||||
|
print(' available backends: %s' % backends)
|
||||||
|
langs = ', '.join(enchant.list_languages())
|
||||||
|
print(' available languages: %s' % langs)
|
||||||
|
except ImportError:
|
||||||
|
w('FAIL' + os.linesep)
|
||||||
|
|
||||||
|
def verify_pyqt():
|
||||||
|
w('Qt4 image formats... ')
|
||||||
|
try:
|
||||||
|
from PyQt4 import QtGui
|
||||||
|
read_f = ', '.join([unicode(format).lower()
|
||||||
|
for format in QtGui.QImageReader.supportedImageFormats()])
|
||||||
|
write_f = ', '.join([unicode(format).lower()
|
||||||
|
for format in QtGui.QImageWriter.supportedImageFormats()])
|
||||||
|
w(os.linesep)
|
||||||
|
print(' read: %s' % read_f)
|
||||||
|
print(' write: %s' % write_f)
|
||||||
|
except ImportError:
|
||||||
|
w('FAIL' + os.linesep)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
verify_python()
|
||||||
|
|
||||||
|
print('Checking for modules...')
|
||||||
|
for m in MODULES:
|
||||||
|
check_module(m)
|
||||||
|
|
||||||
|
print('Checking for optional modules...')
|
||||||
|
for m in OPTIONAL_MODULES:
|
||||||
|
check_module(m[0], text=m[1])
|
||||||
|
|
||||||
|
if is_win:
|
||||||
|
print('Checking for Windows specific modules...')
|
||||||
|
for m in WIN32_MODULES:
|
||||||
|
check_module(m)
|
||||||
|
|
||||||
|
verify_versions()
|
||||||
|
verify_pyqt()
|
||||||
|
verify_pyenchant()
|
||||||
|
|
||||||
|
if __name__ == u'__main__':
|
||||||
|
main()
|
@ -32,8 +32,7 @@ Windows Build Script
|
|||||||
This script is used to build the Windows binary and the accompanying installer.
|
This script is used to build the Windows binary and the accompanying installer.
|
||||||
For this script to work out of the box, it depends on a number of things:
|
For this script to work out of the box, it depends on a number of things:
|
||||||
|
|
||||||
Python 2.6
|
Python 2.6/2.7
|
||||||
This build script only works with Python 2.6.
|
|
||||||
|
|
||||||
PyQt4
|
PyQt4
|
||||||
You should already have this installed, OpenLP doesn't work without it. The
|
You should already have this installed, OpenLP doesn't work without it. The
|
||||||
@ -47,12 +46,6 @@ PyEnchant
|
|||||||
Inno Setup 5
|
Inno Setup 5
|
||||||
Inno Setup should be installed into "C:\%PROGRAMFILES%\Inno Setup 5"
|
Inno Setup should be installed into "C:\%PROGRAMFILES%\Inno Setup 5"
|
||||||
|
|
||||||
UPX
|
|
||||||
This is used to compress DLLs and EXEs so that they take up less space, but
|
|
||||||
still function exactly the same. To install UPS, download it from
|
|
||||||
http://upx.sourceforge.net/, extract it into C:\%PROGRAMFILES%\UPX, and then
|
|
||||||
add that directory to your PATH environment variable.
|
|
||||||
|
|
||||||
Sphinx
|
Sphinx
|
||||||
This is used to build the documentation. The documentation trunk must be at
|
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"
|
||||||
@ -61,7 +54,7 @@ HTML Help Workshop
|
|||||||
This is used to create the help file
|
This is used to create the help file
|
||||||
|
|
||||||
PyInstaller
|
PyInstaller
|
||||||
PyInstaller should be a checkout of revision 844 of trunk, and in a
|
PyInstaller should be a checkout of revision 1470 of trunk, and in a
|
||||||
directory called, "pyinstaller" on the same level as OpenLP's Bazaar shared
|
directory called, "pyinstaller" on the same level as OpenLP's Bazaar shared
|
||||||
repository directory. The revision is very important as there is currently
|
repository directory. The revision is very important as there is currently
|
||||||
a major regression in HEAD.
|
a major regression in HEAD.
|
||||||
@ -73,13 +66,8 @@ PyInstaller
|
|||||||
http://svn.pyinstaller.org/trunk
|
http://svn.pyinstaller.org/trunk
|
||||||
|
|
||||||
Then you need to copy the two hook-*.py files from the "pyinstaller"
|
Then you need to copy the two hook-*.py files from the "pyinstaller"
|
||||||
subdirectory in OpenLP's "resources" directory into PyInstaller's "hooks"
|
subdirectory in OpenLP's "resources" directory into PyInstaller's
|
||||||
directory.
|
"PyInstaller/hooks" directory.
|
||||||
|
|
||||||
Once you've done that, open a command prompt (DOS shell), navigate to the
|
|
||||||
PyInstaller directory and run::
|
|
||||||
|
|
||||||
C:\Projects\pyinstaller>python Configure.py
|
|
||||||
|
|
||||||
Bazaar
|
Bazaar
|
||||||
You need the command line "bzr" client installed.
|
You need the command line "bzr" client installed.
|
||||||
@ -102,7 +90,7 @@ psvince.dll
|
|||||||
the install will fail. The dll can be obtained from here:
|
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)
|
||||||
|
|
||||||
Mako
|
Mako
|
||||||
Mako Templates for Python. This package is required for building the
|
Mako Templates for Python. This package is required for building the
|
||||||
remote plugin. It can be installed by going to your
|
remote plugin. It can be installed by going to your
|
||||||
python_directory\scripts\.. and running "easy_install Mako". If you do not
|
python_directory\scripts\.. and running "easy_install Mako". If you do not
|
||||||
@ -137,9 +125,18 @@ site_packages = os.path.join(os.path.split(python_exe)[0], u'Lib',
|
|||||||
|
|
||||||
# Files and executables
|
# Files and executables
|
||||||
pyi_build = os.path.abspath(os.path.join(branch_path, u'..', u'..',
|
pyi_build = os.path.abspath(os.path.join(branch_path, u'..', u'..',
|
||||||
u'pyinstaller', u'Build.py'))
|
u'pyinstaller', u'pyinstaller.py'))
|
||||||
lrelease_exe = os.path.join(site_packages, u'PyQt4', u'bin', u'lrelease.exe')
|
openlp_main_script = os.path.abspath(os.path.join(branch_path, 'openlp.pyw'))
|
||||||
|
if os.path.exists(os.path.join(site_packages, u'PyQt4', u'bin')):
|
||||||
|
# Older versions of the PyQt4 Windows installer put their binaries in the
|
||||||
|
# "bin" directory
|
||||||
|
lrelease_exe = os.path.join(site_packages, u'PyQt4', u'bin', u'lrelease.exe')
|
||||||
|
else:
|
||||||
|
# Newer versions of the PyQt4 Windows installer put their binaries in the
|
||||||
|
# base directory of the installation
|
||||||
|
lrelease_exe = os.path.join(site_packages, u'PyQt4', u'lrelease.exe')
|
||||||
i18n_utils = os.path.join(script_path, u'translation_utils.py')
|
i18n_utils = os.path.join(script_path, u'translation_utils.py')
|
||||||
|
win32_icon = os.path.join(branch_path, u'resources', u'images', 'OpenLP.ico')
|
||||||
|
|
||||||
# Paths
|
# Paths
|
||||||
source_path = os.path.join(branch_path, u'openlp')
|
source_path = os.path.join(branch_path, u'openlp')
|
||||||
@ -148,9 +145,8 @@ manual_build_path = os.path.join(manual_path, u'build')
|
|||||||
helpfile_path = os.path.join(manual_build_path, u'htmlhelp')
|
helpfile_path = os.path.join(manual_build_path, u'htmlhelp')
|
||||||
i18n_path = os.path.join(branch_path, u'resources', u'i18n')
|
i18n_path = os.path.join(branch_path, u'resources', u'i18n')
|
||||||
winres_path = os.path.join(branch_path, u'resources', u'windows')
|
winres_path = os.path.join(branch_path, u'resources', u'windows')
|
||||||
build_path = os.path.join(branch_path, u'build', u'pyi.win32', u'OpenLP')
|
build_path = os.path.join(branch_path, u'build')
|
||||||
dist_path = os.path.join(branch_path, u'dist', u'OpenLP')
|
dist_path = os.path.join(branch_path, u'dist', u'OpenLP')
|
||||||
enchant_path = os.path.join(site_packages, u'enchant')
|
|
||||||
pptviewlib_path = os.path.join(source_path, u'plugins', u'presentations',
|
pptviewlib_path = os.path.join(source_path, u'plugins', u'presentations',
|
||||||
u'lib', u'pptviewlib')
|
u'lib', u'pptviewlib')
|
||||||
|
|
||||||
@ -174,8 +170,16 @@ def update_code():
|
|||||||
def run_pyinstaller():
|
def run_pyinstaller():
|
||||||
print u'Running PyInstaller...'
|
print u'Running PyInstaller...'
|
||||||
os.chdir(branch_path)
|
os.chdir(branch_path)
|
||||||
pyinstaller = Popen((python_exe, pyi_build, u'-y', u'-o', build_path,
|
pyinstaller = Popen((python_exe, pyi_build,
|
||||||
os.path.join(winres_path, u'OpenLP.spec')), stdout=PIPE)
|
u'--noconfirm',
|
||||||
|
u'--windowed',
|
||||||
|
u'--noupx',
|
||||||
|
u'-o', branch_path,
|
||||||
|
u'-i', win32_icon,
|
||||||
|
u'-p', branch_path,
|
||||||
|
u'-n', 'OpenLP',
|
||||||
|
openlp_main_script),
|
||||||
|
stdout=PIPE)
|
||||||
output, error = pyinstaller.communicate()
|
output, error = pyinstaller.communicate()
|
||||||
code = pyinstaller.wait()
|
code = pyinstaller.wait()
|
||||||
if code != 0:
|
if code != 0:
|
||||||
@ -208,19 +212,6 @@ def write_version_file():
|
|||||||
f.write(versionstring)
|
f.write(versionstring)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
def copy_enchant():
|
|
||||||
print u'Copying enchant/pyenchant...'
|
|
||||||
source = enchant_path
|
|
||||||
dest = os.path.join(dist_path, u'enchant')
|
|
||||||
for root, dirs, files in os.walk(source):
|
|
||||||
for filename in files:
|
|
||||||
if not filename.endswith(u'.pyc') and not filename.endswith(u'.pyo'):
|
|
||||||
dest_path = os.path.join(dest, root[len(source) + 1:])
|
|
||||||
if not os.path.exists(dest_path):
|
|
||||||
os.makedirs(dest_path)
|
|
||||||
copy(os.path.join(root, filename),
|
|
||||||
os.path.join(dest_path, filename))
|
|
||||||
|
|
||||||
def copy_plugins():
|
def copy_plugins():
|
||||||
print u'Copying plugins...'
|
print u'Copying plugins...'
|
||||||
source = os.path.join(source_path, u'plugins')
|
source = os.path.join(source_path, u'plugins')
|
||||||
@ -242,10 +233,10 @@ def copy_windows_files():
|
|||||||
os.path.join(dist_path, u'LICENSE.txt'))
|
os.path.join(dist_path, u'LICENSE.txt'))
|
||||||
copy(os.path.join(winres_path, u'psvince.dll'),
|
copy(os.path.join(winres_path, u'psvince.dll'),
|
||||||
os.path.join(dist_path, u'psvince.dll'))
|
os.path.join(dist_path, u'psvince.dll'))
|
||||||
if os.path.isfile(os.path.join(helpfile_path, u'Openlp.chm')):
|
if os.path.isfile(os.path.join(helpfile_path, u'OpenLP.chm')):
|
||||||
print u' Windows help file found'
|
print u' Windows help file found'
|
||||||
copy(os.path.join(helpfile_path, u'Openlp.chm'),
|
copy(os.path.join(helpfile_path, u'OpenLP.chm'),
|
||||||
os.path.join(dist_path, u'Openlp.chm'))
|
os.path.join(dist_path, u'OpenLP.chm'))
|
||||||
else:
|
else:
|
||||||
print u' WARNING ---- Windows help file not found ---- WARNING'
|
print u' WARNING ---- Windows help file not found ---- WARNING'
|
||||||
|
|
||||||
@ -330,17 +321,19 @@ def main():
|
|||||||
import sys
|
import sys
|
||||||
for arg in sys.argv:
|
for arg in sys.argv:
|
||||||
if arg == u'-v' or arg == u'--verbose':
|
if arg == u'-v' or arg == u'--verbose':
|
||||||
print "Script path:", script_path
|
print "OpenLP main script: ......", openlp_main_script
|
||||||
print "Branch path:", branch_path
|
print "Script path: .............", script_path
|
||||||
print "Source path:", source_path
|
print "Branch path: .............", branch_path
|
||||||
print "\"dist\" path:", dist_path
|
print "Source path: .............", source_path
|
||||||
print "PyInstaller:", pyi_build
|
print "\"dist\" path: .............", dist_path
|
||||||
|
print "PyInstaller: .............", pyi_build
|
||||||
print "Documentation branch path:", doc_branch_path
|
print "Documentation branch path:", doc_branch_path
|
||||||
print "Help file build path;", helpfile_path
|
print "Help file build path: ....", helpfile_path
|
||||||
print "Inno Setup path:", innosetup_exe
|
print "Inno Setup path: .........", innosetup_exe
|
||||||
print "Windows resources:", winres_path
|
print "Windows resources: .......", winres_path
|
||||||
print "VCBuild path:", vcbuild_exe
|
print "VCBuild path: ............", vcbuild_exe
|
||||||
print "PPTVIEWLIB path:", pptviewlib_path
|
print "PPTVIEWLIB path: .........", pptviewlib_path
|
||||||
|
print ""
|
||||||
elif arg == u'--skip-update':
|
elif arg == u'--skip-update':
|
||||||
skip_update = True
|
skip_update = True
|
||||||
elif arg == u'/?' or arg == u'-h' or arg == u'--help':
|
elif arg == u'/?' or arg == u'-h' or arg == u'--help':
|
||||||
@ -353,7 +346,6 @@ def main():
|
|||||||
build_pptviewlib()
|
build_pptviewlib()
|
||||||
run_pyinstaller()
|
run_pyinstaller()
|
||||||
write_version_file()
|
write_version_file()
|
||||||
copy_enchant()
|
|
||||||
copy_plugins()
|
copy_plugins()
|
||||||
if os.path.exists(manual_path):
|
if os.path.exists(manual_path):
|
||||||
run_sphinx()
|
run_sphinx()
|
||||||
|
Loading…
Reference in New Issue
Block a user