This commit is contained in:
Andreas Preikschat 2011-05-09 13:49:11 +02:00
commit 21680d0c84
21 changed files with 361 additions and 92 deletions

View File

@ -223,6 +223,28 @@ def resize_image(image, width, height, background=QtCore.Qt.black):
painter.drawImage((width - realw) / 2, (height - realh) / 2, preview) painter.drawImage((width - realw) / 2, (height - realh) / 2, preview)
return new_image return new_image
def check_search_result(treeWidget, search_results):
"""
Checks if the given ``search_results`` is empty and adds a
"No Search Results" item to the given ``treeWidget``.
``treeWidget``
The ``QTreeWidget`` where the "No Search Results" item should be added
to, if the ``search_results`` is empty.
``search_results``
This can either be a list or a dict.
"""
if search_results or treeWidget.count():
return
message = translate('OpenLP.MediaManagerItem', 'No Search Results')
item = QtGui.QListWidgetItem(message)
item.setFlags(QtCore.Qt.NoItemFlags)
font = QtGui.QFont()
font.setItalic(True)
item.setFont(font)
treeWidget.addItem(item)
def check_item_selected(list_widget, message): def check_item_selected(list_widget, message):
""" """
Check if a list item is selected so an action may be performed on it Check if a list item is selected so an action may be performed on it

View File

@ -87,8 +87,8 @@ class BaseModel(object):
Creates an instance of a class and populates it, returning the instance Creates an instance of a class and populates it, returning the instance
""" """
instance = cls() instance = cls()
for key in kwargs: for key, value in kwargs.iteritems():
instance.__setattr__(key, kwargs[key]) instance.__setattr__(key, value)
return instance return instance

View File

@ -111,10 +111,6 @@ class EventReceiver(QtCore.QObject):
``servicemanager_set_item`` ``servicemanager_set_item``
Go live on a specific item, by index Go live on a specific item, by index
``servicemanager_list_request``
Request the service list. Responds with servicemanager_list_response
containing a array of dictionaries
``maindisplay_blank`` ``maindisplay_blank``
Blank the maindisplay window Blank the maindisplay window

View File

@ -74,10 +74,10 @@ class SearchEdit(QtGui.QLineEdit):
if hasattr(self, u'menuButton'): if hasattr(self, u'menuButton'):
leftPadding = self.menuButton.width() leftPadding = self.menuButton.width()
self.setStyleSheet( self.setStyleSheet(
u'QLineEdit { padding-left: %spx; padding-right: %spx; } ' % \ u'QLineEdit { padding-left: %spx; padding-right: %spx; } ' %
(leftPadding, rightPadding)) (leftPadding, rightPadding))
else: else:
self.setStyleSheet(u'QLineEdit { padding-right: %spx; } ' % \ self.setStyleSheet(u'QLineEdit { padding-right: %spx; } ' %
rightPadding) rightPadding)
msz = self.minimumSizeHint() msz = self.minimumSizeHint()
self.setMinimumSize( self.setMinimumSize(

View File

@ -269,11 +269,9 @@ class ServiceItem(object):
} }
service_data = [] service_data = []
if self.service_item_type == ServiceItemType.Text: if self.service_item_type == ServiceItemType.Text:
for slide in self._raw_frames: service_data = [slide for slide in self._raw_frames]
service_data.append(slide)
elif self.service_item_type == ServiceItemType.Image: elif self.service_item_type == ServiceItemType.Image:
for slide in self._raw_frames: service_data = [slide[u'title'] for slide in self._raw_frames]
service_data.append(slide[u'title'])
elif self.service_item_type == ServiceItemType.Command: elif self.service_item_type == ServiceItemType.Command:
for slide in self._raw_frames: for slide in self._raw_frames:
service_data.append( service_data.append(

View File

@ -130,7 +130,7 @@ class UiStrings(object):
self.VersePerLine = translate('OpenLP.Ui', 'Verse Per Line') self.VersePerLine = translate('OpenLP.Ui', 'Verse Per Line')
self.Version = translate('OpenLP.Ui', 'Version') self.Version = translate('OpenLP.Ui', 'Version')
self.View = translate('OpenLP.Ui', 'View') self.View = translate('OpenLP.Ui', 'View')
self.ViewMode = translate('OpenLP.Ui', 'View Model') self.ViewMode = translate('OpenLP.Ui', 'View Mode')
def add_welcome_page(parent, image): def add_welcome_page(parent, image):
""" """

View File

@ -112,11 +112,14 @@ class Ui_DisplayTagDialog(object):
self.endTagLineEdit = QtGui.QLineEdit(self.editGroupBox) self.endTagLineEdit = QtGui.QLineEdit(self.editGroupBox)
self.endTagLineEdit.setObjectName(u'endTagLineEdit') self.endTagLineEdit.setObjectName(u'endTagLineEdit')
self.dataGridLayout.addWidget(self.endTagLineEdit, 4, 1, 1, 1) self.dataGridLayout.addWidget(self.endTagLineEdit, 4, 1, 1, 1)
self.updatePushButton = QtGui.QPushButton(self.editGroupBox) self.savePushButton = QtGui.QPushButton(self.editGroupBox)
self.updatePushButton.setObjectName(u'updatePushButton') self.savePushButton.setObjectName(u'savePushButton')
self.dataGridLayout.addWidget(self.updatePushButton, 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 = create_accept_reject_button_box(displayTagDialog) self.buttonBox = QtGui.QDialogButtonBox(displayTagDialog)
closeButton = QtGui.QDialogButtonBox.Close
self.buttonBox.setObjectName('displayTagDialogButtonBox')
self.buttonBox.setStandardButtons(closeButton)
self.listdataGridLayout.addWidget(self.buttonBox, 3, 0, 1, 1) self.listdataGridLayout.addWidget(self.buttonBox, 3, 0, 1, 1)
self.retranslateUi(displayTagDialog) self.retranslateUi(displayTagDialog)
@ -127,8 +130,8 @@ class Ui_DisplayTagDialog(object):
'Configure Display Tags')) 'Configure Display Tags'))
self.editGroupBox.setTitle( self.editGroupBox.setTitle(
translate('OpenLP.DisplayTagDialog', 'Edit Selection')) translate('OpenLP.DisplayTagDialog', 'Edit Selection'))
self.updatePushButton.setText( self.savePushButton.setText(
translate('OpenLP.DisplayTagDialog', 'Update')) translate('OpenLP.DisplayTagDialog', 'Save'))
self.descriptionLabel.setText( self.descriptionLabel.setText(
translate('OpenLP.DisplayTagDialog', 'Description')) translate('OpenLP.DisplayTagDialog', 'Description'))
self.tagLabel.setText(translate('OpenLP.DisplayTagDialog', 'Tag')) self.tagLabel.setText(translate('OpenLP.DisplayTagDialog', 'Tag'))

View File

@ -54,10 +54,12 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
QtCore.SIGNAL(u'pressed()'), self.onDefaultPushed) QtCore.SIGNAL(u'pressed()'), self.onDefaultPushed)
QtCore.QObject.connect(self.newPushButton, QtCore.QObject.connect(self.newPushButton,
QtCore.SIGNAL(u'pressed()'), self.onNewPushed) QtCore.SIGNAL(u'pressed()'), self.onNewPushed)
QtCore.QObject.connect(self.updatePushButton, QtCore.QObject.connect(self.savePushButton,
QtCore.SIGNAL(u'pressed()'), self.onUpdatePushed) QtCore.SIGNAL(u'pressed()'), self.onSavedPushed)
QtCore.QObject.connect(self.deletePushButton, QtCore.QObject.connect(self.deletePushButton,
QtCore.SIGNAL(u'pressed()'), self.onDeletePushed) QtCore.SIGNAL(u'pressed()'), self.onDeletePushed)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'),
self.close)
def exec_(self): def exec_(self):
""" """
@ -87,30 +89,6 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
for t in user_tags: for t in user_tags:
DisplayTags.add_html_tag(t) DisplayTags.add_html_tag(t)
def accept(self):
"""
Save Custom tags in a pickle .
"""
temp = []
for tag in DisplayTags.get_html_tags():
if not tag[u'protected']:
temp.append(tag)
if temp:
ctemp = cPickle.dumps(temp)
QtCore.QSettings().setValue(u'displayTags/html_tags',
QtCore.QVariant(ctemp))
else:
QtCore.QSettings().setValue(u'displayTags/html_tags',
QtCore.QVariant(u''))
return QtGui.QDialog.accept(self)
def reject(self):
"""
Reset Custom tags from Settings.
"""
self._resetTable()
return QtGui.QDialog.reject(self)
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.
@ -127,14 +105,14 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
self.tagLineEdit.setEnabled(False) self.tagLineEdit.setEnabled(False)
self.startTagLineEdit.setEnabled(False) self.startTagLineEdit.setEnabled(False)
self.endTagLineEdit.setEnabled(False) self.endTagLineEdit.setEnabled(False)
self.updatePushButton.setEnabled(False) self.savePushButton.setEnabled(False)
self.deletePushButton.setEnabled(False) self.deletePushButton.setEnabled(False)
else: else:
self.descriptionLineEdit.setEnabled(True) self.descriptionLineEdit.setEnabled(True)
self.tagLineEdit.setEnabled(True) self.tagLineEdit.setEnabled(True)
self.startTagLineEdit.setEnabled(True) self.startTagLineEdit.setEnabled(True)
self.endTagLineEdit.setEnabled(True) self.endTagLineEdit.setEnabled(True)
self.updatePushButton.setEnabled(True) self.savePushButton.setEnabled(True)
self.deletePushButton.setEnabled(True) self.deletePushButton.setEnabled(True)
def onNewPushed(self): def onNewPushed(self):
@ -174,9 +152,9 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
self.selected = -1 self.selected = -1
self._resetTable() self._resetTable()
def onUpdatePushed(self): def onSavedPushed(self):
""" """
Update Custom Tag details if not duplicate. Update Custom Tag details if not duplicate and save the data.
""" """
html_expands = DisplayTags.get_html_tags() html_expands = DisplayTags.get_html_tags()
if self.selected != -1: if self.selected != -1:
@ -197,6 +175,17 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
html[u'end tag'] = u'{/%s}' % tag html[u'end tag'] = u'{/%s}' % tag
self.selected = -1 self.selected = -1
self._resetTable() self._resetTable()
temp = []
for tag in DisplayTags.get_html_tags():
if not tag[u'protected']:
temp.append(tag)
if temp:
ctemp = cPickle.dumps(temp)
QtCore.QSettings().setValue(u'displayTags/html_tags',
QtCore.QVariant(ctemp))
else:
QtCore.QSettings().setValue(u'displayTags/html_tags',
QtCore.QVariant(u''))
def _resetTable(self): def _resetTable(self):
""" """
@ -205,7 +194,7 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
self.tagTableWidget.clearContents() self.tagTableWidget.clearContents()
self.tagTableWidget.setRowCount(0) self.tagTableWidget.setRowCount(0)
self.newPushButton.setEnabled(True) self.newPushButton.setEnabled(True)
self.updatePushButton.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(DisplayTags.get_html_tags()):
self.tagTableWidget.setRowCount( self.tagTableWidget.setRowCount(

View File

@ -130,9 +130,12 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
file.close() file.close()
file = open(filename, u'wb') file = open(filename, u'wb')
file.write(report.encode(u'utf-8')) file.write(report.encode(u'utf-8'))
finally:
file.close() file.close()
except IOError: except IOError:
log.exception(u'Failed to write crash report') log.exception(u'Failed to write crash report')
finally:
file.close()
def onSendReportButtonPressed(self): def onSendReportButtonPressed(self):
""" """
@ -186,3 +189,4 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
def __buttonState(self, state): def __buttonState(self, state):
self.saveReportButton.setEnabled(state) self.saveReportButton.setEnabled(state)
self.sendReportButton.setEnabled(state) self.sendReportButton.setEnabled(state)

View File

@ -38,7 +38,7 @@ from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \
ThemeManager, SlideController, PluginForm, MediaDockManager, \ ThemeManager, SlideController, PluginForm, MediaDockManager, \
ShortcutListForm, DisplayTagForm ShortcutListForm, DisplayTagForm
from openlp.core.utils import AppLocation, add_actions, LanguageManager, \ from openlp.core.utils import AppLocation, add_actions, LanguageManager, \
get_application_version get_application_version, delete_file
from openlp.core.utils.actions import ActionList, CategoryOrder from openlp.core.utils.actions import ActionList, CategoryOrder
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -657,8 +657,10 @@ 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):
return
for filename in os.listdir(temp_dir): for filename in os.listdir(temp_dir):
os.remove(os.path.join(temp_dir, filename)) delete_file(os.path.join(temp_dir, filename))
os.removedirs(temp_dir) os.removedirs(temp_dir)
def blankCheck(self): def blankCheck(self):

View File

@ -274,8 +274,6 @@ class ServiceManager(QtGui.QWidget):
QtCore.SIGNAL(u'servicemanager_previous_item'), self.previousItem) QtCore.SIGNAL(u'servicemanager_previous_item'), self.previousItem)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'servicemanager_set_item'), self.onSetItem) QtCore.SIGNAL(u'servicemanager_set_item'), self.onSetItem)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'servicemanager_list_request'), self.listRequest)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'config_updated'), self.configUpdated) QtCore.SIGNAL(u'config_updated'), self.configUpdated)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
@ -1307,23 +1305,6 @@ class ServiceManager(QtGui.QWidget):
else: else:
return parentitem.data(0, QtCore.Qt.UserRole).toInt()[0] return parentitem.data(0, QtCore.Qt.UserRole).toInt()[0]
def listRequest(self, message=None):
data = []
item = self.findServiceItem()[0]
if item >= 0 and item < len(self.serviceItems):
curitem = self.serviceItems[item]
else:
curitem = None
for item in self.serviceItems:
service_item = item[u'service_item']
data_item = {}
data_item[u'title'] = unicode(service_item.get_display_title())
data_item[u'plugin'] = unicode(service_item.name)
data_item[u'notes'] = unicode(service_item.notes)
data_item[u'selected'] = (item == curitem)
data.append(data_item)
Receiver.send_message(u'servicemanager_list_response', data)
def printServiceOrder(self): def printServiceOrder(self):
""" """
Print a Service Order Sheet. Print a Service Order Sheet.

View File

@ -29,7 +29,7 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
translate translate, check_search_result
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
@ -61,6 +61,7 @@ class BibleMediaItem(MediaManagerItem):
self.quickPreviewAllowed = True self.quickPreviewAllowed = True
self.search_results = {} self.search_results = {}
self.second_search_results = {} self.second_search_results = {}
check_search_result(self.listView, self.search_results)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'bibles_load_list'), self.reloadBibles) QtCore.SIGNAL(u'bibles_load_list'), self.reloadBibles)
@ -522,8 +523,9 @@ class BibleMediaItem(MediaManagerItem):
self.__checkSecondBible(bible, second_bible) self.__checkSecondBible(bible, second_bible)
elif self.search_results: elif self.search_results:
self.displayResults(bible, second_bible) self.displayResults(bible, second_bible)
Receiver.send_message(u'cursor_normal')
self.advancedSearchButton.setEnabled(True) self.advancedSearchButton.setEnabled(True)
check_search_result(self.listView, self.search_results)
Receiver.send_message(u'cursor_normal')
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
def onQuickSearchButton(self): def onQuickSearchButton(self):
@ -563,6 +565,7 @@ class BibleMediaItem(MediaManagerItem):
elif self.search_results: elif self.search_results:
self.displayResults(bible, second_bible) self.displayResults(bible, second_bible)
self.quickSearchButton.setEnabled(True) self.quickSearchButton.setEnabled(True)
check_search_result(self.listView, self.search_results)
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')

View File

@ -48,6 +48,7 @@ window.OpenLP = {
$.each(data.results.items, function (idx, value) { $.each(data.results.items, function (idx, value) {
var li = $("<li data-icon=\"false\">").append( var li = $("<li data-icon=\"false\">").append(
$("<a href=\"#\">").attr("value", parseInt(idx, 10)).text(value["title"])); $("<a href=\"#\">").attr("value", parseInt(idx, 10)).text(value["title"]));
li.attr("uuid", value["id"])
li.children("a").click(OpenLP.setItem); li.children("a").click(OpenLP.setItem);
ul.append(li); ul.append(li);
}); });
@ -119,10 +120,10 @@ window.OpenLP = {
$("#service-manager div[data-role=content] ul[data-role=listview] li").attr("data-theme", "c").removeClass("ui-btn-up-e").addClass("ui-btn-up-c"); $("#service-manager div[data-role=content] ul[data-role=listview] li").attr("data-theme", "c").removeClass("ui-btn-up-e").addClass("ui-btn-up-c");
$("#service-manager div[data-role=content] ul[data-role=listview] li a").each(function () { $("#service-manager div[data-role=content] ul[data-role=listview] li a").each(function () {
var item = $(this); var item = $(this);
if (item.text() == OpenLP.currentItem) {
while (item[0].tagName != "LI") { while (item[0].tagName != "LI") {
item = item.parent(); item = item.parent();
} }
if (item.attr("uuid") == OpenLP.currentItem) {
item.attr("data-theme", "e").removeClass("ui-btn-up-c").addClass("ui-btn-up-e"); item.attr("data-theme", "e").removeClass("ui-btn-up-c").addClass("ui-btn-up-e");
return false; return false;
} }

View File

@ -0,0 +1,66 @@
/*****************************************************************************
* OpenLP - Open Source Lyrics Projection *
* ------------------------------------------------------------------------- *
* Copyright (c) 2008-2010 Raoul Snyman *
* Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael *
* Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, *
* Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, *
* 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 *
*****************************************************************************/
body {
background-color: black;
font-family: sans-serif;
overflow: hidden;
}
#currentslide {
font-size: 40pt;
color: white;
}
#nextslide {
font-size: 30pt;
color: grey;
padding-top: 25px;
}
#right {
float: right;
}
#clock {
font-size: 40pt;
color: yellow;
text-align: right;
}
#notes {
font-size: 36pt;
color: salmon;
text-align: right;
}
#verseorder {
font-size: 30pt;
color: green;
text-align: left;
}
.currenttag {
color: lightgreen;
font-weight: bold;
}

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<!--
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# 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 #
###############################################################################
-->
<head>
<meta charset="utf-8" />
<title>OpenLP 2.0 Remote</title>
<link rel="stylesheet" href="/files/stage.css" />
<script type="text/javascript" src="/files/jquery.js"></script>
<script type="text/javascript" src="/files/stage.js"></script>
</head>
<body>
<div id="right">
<div id="clock"></div>
<div id="notes"></div>
</div>
<div id="verseorder"></div>
<div id="currentslide"></div>
<div id="nextslide"></div>
</body>
</html>

View File

@ -0,0 +1,104 @@
/*****************************************************************************
* OpenLP - Open Source Lyrics Projection *
* ------------------------------------------------------------------------- *
* Copyright (c) 2008-2010 Raoul Snyman *
* Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael *
* Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, *
* Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, *
* 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 *
*****************************************************************************/
window.OpenLP = {
loadService: function (event) {
$.getJSON(
"/api/service/list",
function (data, status) {
OpenLP.nextSong = "";
$("#notes").html("");
for (idx in data.results.items) {
idx = parseInt(idx, 10);
if ((data.results.items[idx]["selected"]) &&
(data.results.items.length > idx + 1)) {
$("#notes").html(data.results.items[idx]["notes"]);
OpenLP.nextSong = data.results.items[idx + 1]["title"];
break;
}
}
OpenLP.updateSlide();
}
);
},
loadSlides: function (event) {
$.getJSON(
"/api/controller/live/text",
function (data, status) {
OpenLP.currentSlides = data.results.slides;
OpenLP.currentSlide = 0;
var div = $("#verseorder");
div.html("");
for (idx in data.results.slides) {
idx = parseInt(idx, 10);
div.append("&nbsp;<span>");
var tag = data.results.slides[idx]["tag"];
if (tag == 'None')
tag = idx;
$("#verseorder span").last().attr("id", "tag" + idx).text(tag);
if (data.results.slides[idx]["selected"])
OpenLP.currentSlide = idx;
}
OpenLP.loadService();
}
);
},
updateSlide: function() {
$("#verseorder span").removeClass("currenttag");
$("#tag" + OpenLP.currentSlide).addClass("currenttag");
$("#currentslide").html(OpenLP.currentSlides[OpenLP.currentSlide]["text"]);
if (OpenLP.currentSlide < OpenLP.currentSlides.length - 1)
$("#nextslide").html(OpenLP.currentSlides[OpenLP.currentSlide + 1]["text"]);
else
$("#nextslide").html("Next: " + OpenLP.nextSong);
},
updateClock: function() {
var div = $("#clock");
var t = new Date();
var h = t.getHours();
if (h > 12)
h = h - 12;
var m = t.getMinutes();
if (m < 10)
m = '0' + m + '';
div.html(h + ":" + m);
},
pollServer: function () {
$.getJSON(
"/api/poll",
function (data, status) {
OpenLP.updateClock();
if (OpenLP.currentItem != data.results.item) {
OpenLP.currentItem = data.results.item;
OpenLP.loadSlides();
}
else if (OpenLP.currentSlide != data.results.slide) {
OpenLP.currentSlide = parseInt(data.results.slide, 10);
OpenLP.updateSlide();
}
}
);
}
}
$.ajaxSetup({ cache: false });
setInterval("OpenLP.pollServer();", 500);
OpenLP.pollServer();

View File

@ -34,6 +34,9 @@ the remotes.
``/`` ``/``
Go to the web interface. Go to the web interface.
``/stage``
Show the stage view.
``/files/{filename}`` ``/files/{filename}``
Serve a static file. Serve a static file.
@ -241,6 +244,7 @@ class HttpConnection(object):
self.parent = parent self.parent = parent
self.routes = [ self.routes = [
(u'^/$', self.serve_file), (u'^/$', self.serve_file),
(u'^/(stage)$', self.serve_file),
(r'^/files/(.*)$', self.serve_file), (r'^/files/(.*)$', self.serve_file),
(r'^/api/poll$', self.poll), (r'^/api/poll$', self.poll),
(r'^/api/controller/(live|preview)/(.*)$', self.controller), (r'^/api/controller/(live|preview)/(.*)$', self.controller),
@ -256,18 +260,18 @@ class HttpConnection(object):
def _get_service_items(self): def _get_service_items(self):
service_items = [] service_items = []
service_manager = self.parent.parent.serviceManager service_manager = self.parent.parent.serviceManager
item = service_manager.findServiceItem()[0] if self.parent.current_item:
if item >= 0 and item < len(service_manager.serviceItems): cur_uuid = self.parent.current_item._uuid
curitem = service_manager.serviceItems[item]
else: else:
curitem = None cur_uuid = None
for item in service_manager.serviceItems: for item in service_manager.serviceItems:
service_item = item[u'service_item'] service_item = item[u'service_item']
service_items.append({ service_items.append({
u'id': unicode(service_item._uuid),
u'title': unicode(service_item.get_display_title()), u'title': unicode(service_item.get_display_title()),
u'plugin': unicode(service_item.name), u'plugin': unicode(service_item.name),
u'notes': unicode(service_item.notes), u'notes': unicode(service_item.notes),
u'selected': (item == curitem) u'selected': (service_item._uuid == cur_uuid)
}) })
return service_items return service_items
@ -312,6 +316,8 @@ class HttpConnection(object):
log.debug(u'serve file request %s' % filename) log.debug(u'serve file request %s' % filename)
if not filename: if not filename:
filename = u'index.html' filename = u'index.html'
elif filename == u'stage':
filename = u'stage.html'
path = os.path.normpath(os.path.join(self.parent.html_dir, filename)) path = os.path.normpath(os.path.join(self.parent.html_dir, filename))
if not path.startswith(self.parent.html_dir): if not path.startswith(self.parent.html_dir):
return HttpResponse(code=u'404 Not Found') return HttpResponse(code=u'404 Not Found')
@ -349,7 +355,7 @@ class HttpConnection(object):
""" """
result = { result = {
u'slide': self.parent.current_slide or 0, u'slide': self.parent.current_slide or 0,
u'item': self.parent.current_item.title \ u'item': self.parent.current_item._uuid \
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}),

View File

@ -24,10 +24,12 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui, QtNetwork
from openlp.core.lib import SettingsTab, translate from openlp.core.lib import SettingsTab, translate
ZERO_URL = u'0.0.0.0'
class RemoteTab(SettingsTab): class RemoteTab(SettingsTab):
""" """
RemoteTab is the Remotes settings tab in the settings dialog. RemoteTab is the Remotes settings tab in the settings dialog.
@ -51,13 +53,29 @@ class RemoteTab(SettingsTab):
self.addressEdit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp( self.addressEdit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(
u'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'), self)) u'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'), self))
self.addressEdit.setObjectName(u'addressEdit') self.addressEdit.setObjectName(u'addressEdit')
QtCore.QObject.connect(self.addressEdit,
QtCore.SIGNAL(u'textChanged(const QString&)'), self.setUrls)
self.serverSettingsLayout.addRow(self.addressLabel, self.addressEdit) self.serverSettingsLayout.addRow(self.addressLabel, self.addressEdit)
self.portLabel = QtGui.QLabel(self.serverSettingsGroupBox) self.portLabel = QtGui.QLabel(self.serverSettingsGroupBox)
self.portLabel.setObjectName(u'portLabel') self.portLabel.setObjectName(u'portLabel')
self.portSpinBox = QtGui.QSpinBox(self.serverSettingsGroupBox) self.portSpinBox = QtGui.QSpinBox(self.serverSettingsGroupBox)
self.portSpinBox.setMaximum(32767) self.portSpinBox.setMaximum(32767)
self.portSpinBox.setObjectName(u'portSpinBox') self.portSpinBox.setObjectName(u'portSpinBox')
QtCore.QObject.connect(self.portSpinBox,
QtCore.SIGNAL(u'valueChanged(int)'), self.setUrls)
self.serverSettingsLayout.addRow(self.portLabel, self.portSpinBox) self.serverSettingsLayout.addRow(self.portLabel, self.portSpinBox)
self.remoteUrlLabel = QtGui.QLabel(self.serverSettingsGroupBox)
self.remoteUrlLabel.setObjectName(u'remoteUrlLabel')
self.remoteUrl = QtGui.QLabel(self.serverSettingsGroupBox)
self.remoteUrl.setObjectName(u'remoteUrl')
self.remoteUrl.setOpenExternalLinks(True)
self.serverSettingsLayout.addRow(self.remoteUrlLabel, self.remoteUrl)
self.stageUrlLabel = QtGui.QLabel(self.serverSettingsGroupBox)
self.stageUrlLabel.setObjectName(u'stageUrlLabel')
self.stageUrl = QtGui.QLabel(self.serverSettingsGroupBox)
self.stageUrl.setObjectName(u'stageUrl')
self.stageUrl.setOpenExternalLinks(True)
self.serverSettingsLayout.addRow(self.stageUrlLabel, self.stageUrl)
self.leftLayout.addWidget(self.serverSettingsGroupBox) self.leftLayout.addWidget(self.serverSettingsGroupBox)
self.leftLayout.addStretch() self.leftLayout.addStretch()
self.rightLayout.addStretch() self.rightLayout.addStretch()
@ -69,6 +87,34 @@ class RemoteTab(SettingsTab):
'Serve on IP address:')) 'Serve on IP address:'))
self.portLabel.setText(translate('RemotePlugin.RemoteTab', self.portLabel.setText(translate('RemotePlugin.RemoteTab',
'Port number:')) 'Port number:'))
self.remoteUrlLabel.setText(translate('RemotePlugin.RemoteTab',
'Remote URL:'))
self.stageUrlLabel.setText(translate('RemotePlugin.RemoteTab',
'Stage view URL:'))
def setUrls(self):
ipAddress = None
if self.addressEdit.text() == ZERO_URL:
for ip in QtNetwork.QNetworkInterface.allAddresses():
if ip.protocol() == 0 and ip != QtNetwork.QHostAddress.LocalHost:
ipAddress = ip.toString()
break
else:
ipAddress = self.addressEdit.text()
if not ipAddress:
self.remoteUrlLabel.setVisible(False)
self.remoteUrl.setVisible(False)
self.stageUrlLabel.setVisible(False)
self.stageUrl.setVisible(False)
return
self.remoteUrlLabel.setVisible(True)
self.remoteUrl.setVisible(True)
self.stageUrlLabel.setVisible(True)
self.stageUrl.setVisible(True)
url = u'http://%s:%s/' % (ipAddress, self.portSpinBox.value())
self.remoteUrl.setText(u'<a href="%s">%s</a>' % (url, url))
url = url + u'stage'
self.stageUrl.setText(u'<a href="%s">%s</a>' % (url, url))
def load(self): def load(self):
self.portSpinBox.setValue( self.portSpinBox.setValue(
@ -76,7 +122,8 @@ class RemoteTab(SettingsTab):
QtCore.QVariant(4316)).toInt()[0]) QtCore.QVariant(4316)).toInt()[0])
self.addressEdit.setText( self.addressEdit.setText(
QtCore.QSettings().value(self.settingsSection + u'/ip address', QtCore.QSettings().value(self.settingsSection + u'/ip address',
QtCore.QVariant(u'0.0.0.0')).toString()) QtCore.QVariant(ZERO_URL)).toString())
self.setUrls()
def save(self): def save(self):
QtCore.QSettings().setValue(self.settingsSection + u'/port', QtCore.QSettings().setValue(self.settingsSection + u'/port',

View File

@ -329,7 +329,7 @@ class SongExportForm(OpenLPWizard):
self.availableListWidget, unicode(text)) self.availableListWidget, unicode(text))
] ]
for item in self._findListWidgetItems(self.availableListWidget): for item in self._findListWidgetItems(self.availableListWidget):
item.setHidden(False if item in search_result else True) item.setHidden(item not in search_result)
def onUncheckButtonClicked(self): def onUncheckButtonClicked(self):
""" """
@ -361,3 +361,4 @@ class SongExportForm(OpenLPWizard):
options=QtGui.QFileDialog.ShowDirsOnly)) options=QtGui.QFileDialog.ShowDirsOnly))
SettingsManager.set_last_dir(self.plugin.settingsSection, path, 1) SettingsManager.set_last_dir(self.plugin.settingsSection, path, 1)
self.directoryLineEdit.setText(path) self.directoryLineEdit.setText(path)

View File

@ -32,7 +32,7 @@ from PyQt4 import QtCore, QtGui
from sqlalchemy.sql import or_ 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, check_search_result
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
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
@ -199,6 +199,7 @@ class SongMediaItem(MediaManagerItem):
search_results = self.parent.manager.get_all_objects(Song, search_results = self.parent.manager.get_all_objects(Song,
Song.theme_name == search_keywords) Song.theme_name == search_keywords)
self.displayResultsSong(search_results) self.displayResultsSong(search_results)
check_search_result(self.listView, search_results)
def onSongListLoad(self): def onSongListLoad(self):
""" """

View File

@ -229,12 +229,14 @@ class SongsPlugin(Plugin):
If the first time wizard has run, this function is run to import all the If the first time wizard has run, this function is run to import all the
new songs into the database. new songs into the database.
""" """
self.onToolsReindexItemTriggered()
db_dir = unicode(os.path.join(gettempdir(), u'openlp')) db_dir = unicode(os.path.join(gettempdir(), u'openlp'))
if not os.path.exists(db_dir):
return
song_dbs = [] song_dbs = []
for sfile in os.listdir(db_dir): for sfile in os.listdir(db_dir):
if sfile.startswith(u'songs_') and sfile.endswith(u'.sqlite'): if sfile.startswith(u'songs_') and sfile.endswith(u'.sqlite'):
song_dbs.append(os.path.join(db_dir, sfile)) song_dbs.append(os.path.join(db_dir, sfile))
self.onToolsReindexItemTriggered()
if len(song_dbs) == 0: if len(song_dbs) == 0:
return return
progress = QtGui.QProgressDialog(self.formparent) progress = QtGui.QProgressDialog(self.formparent)