This commit is contained in:
Andreas Preikschat 2011-05-23 14:20:03 +02:00
commit 004d23def7
20 changed files with 178 additions and 36 deletions

View File

@ -85,10 +85,13 @@ class OpenLP(QtGui.QApplication):
QtGui.QApplication.exec_()
self.sharedMemory.detach()
def run(self):
def run(self, args):
"""
Run the OpenLP application.
"""
# On Windows, the args passed into the constructor are
# ignored. Not very handy, so set the ones we want to use.
self.args = args
# provide a listener for widgets to reqest a screen update.
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
@ -115,7 +118,7 @@ class OpenLP(QtGui.QApplication):
# make sure Qt really display the splash screen
self.processEvents()
# start the main app window
self.mainWindow = MainWindow(self.clipboard(), self.arguments())
self.mainWindow = MainWindow(self.clipboard(), self.args)
self.mainWindow.show()
if show_splash:
# now kill the splashscreen
@ -250,7 +253,7 @@ def main():
log.debug(u'Could not find default_translator.')
if not options.no_error_form:
sys.excepthook = app.hookException
sys.exit(app.run())
sys.exit(app.run(qt_args))
if __name__ == u'__main__':
"""

View File

@ -111,10 +111,14 @@ class MediaManagerItem(QtGui.QWidget):
self.requiredIcons()
self.setupUi()
self.retranslateUi()
self.autoSelectItem = None
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'%s_service_load' % self.parent.name.lower()),
self.serviceLoad)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'%s_set_autoselect_item' % self.parent.name.lower()),
self.setAutoSelectItem)
def requiredIcons(self):
"""
This method is called to define the icons for the plugin.
@ -467,6 +471,9 @@ class MediaManagerItem(QtGui.QWidget):
if keepFocus:
self.listView.setFocus()
def setAutoSelectItem(self, itemToSelect=None):
self.autoSelectItem = itemToSelect
def onLiveClick(self):
"""
Send an item live by building a service item then adding that service
@ -502,24 +509,24 @@ class MediaManagerItem(QtGui.QWidget):
if not self.listView.selectedIndexes() and not self.remoteTriggered:
QtGui.QMessageBox.information(self, UiStrings().NISp,
translate('OpenLP.MediaManagerItem',
'You must select one or more items.'))
'You must select one or more items to add.'))
else:
# Is it posssible to process multiple list items to generate
# multiple service items?
if self.singleServiceItem or self.remoteTriggered:
log.debug(u'%s Add requested', self.plugin.name)
serviceItem = self.buildServiceItem(None, True)
if serviceItem:
serviceItem.from_plugin = False
self.parent.serviceManager.addServiceItem(serviceItem,
replace=self.remoteTriggered)
self.addToService(replace=self.remoteTriggered)
else:
items = self.listView.selectedIndexes()
for item in items:
serviceItem = self.buildServiceItem(item, True)
if serviceItem:
serviceItem.from_plugin = False
self.parent.serviceManager.addServiceItem(serviceItem)
self.addToService(item)
def addToService(self, item=None, replace=None):
serviceItem = self.buildServiceItem(item, True)
if serviceItem:
serviceItem.from_plugin = False
self.parent.serviceManager.addServiceItem(serviceItem,
replace=replace)
def onAddEditClick(self):
"""

View File

@ -229,6 +229,8 @@ class Ui_MainWindow(object):
self.ToolsOpenDataFolder = icon_action(mainWindow,
u'ToolsOpenDataFolder', u':/general/general_open.png',
category=UiStrings().Tools)
self.updateThemeImages = base_action(mainWindow,
u'updateThemeImages', category=UiStrings().Tools)
action_list.add_category(UiStrings().Settings, CategoryOrder.standardMenu)
self.settingsPluginListItem = shortcut_action(mainWindow,
u'settingsPluginListItem', [QtGui.QKeySequence(u'Alt+F7')],
@ -292,6 +294,7 @@ class Ui_MainWindow(object):
self.SettingsConfigureItem))
add_actions(self.ToolsMenu, (self.ToolsAddToolItem, None))
add_actions(self.ToolsMenu, (self.ToolsOpenDataFolder, None))
add_actions(self.ToolsMenu, [self.updateThemeImages])
add_actions(self.HelpMenu, (self.HelpDocumentationItem,
self.HelpOnlineHelpItem, None, self.helpWebSiteItem,
self.HelpAboutItem))
@ -433,6 +436,11 @@ class Ui_MainWindow(object):
translate('OpenLP.MainWindow', 'Open &Data Folder...'))
self.ToolsOpenDataFolder.setStatusTip(translate('OpenLP.MainWindow',
'Open the folder where songs, bibles and other data resides.'))
self.updateThemeImages.setText(
translate('OpenLP.MainWindow', 'Update Theme Images'))
self.updateThemeImages.setStatusTip(
translate('OpenLP.MainWindow', 'Update the preview images for all '
'themes.'))
self.ModeDefaultItem.setText(
translate('OpenLP.MainWindow', '&Default'))
self.ModeDefaultItem.setStatusTip(translate('OpenLP.MainWindow',
@ -505,6 +513,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtCore.SIGNAL(u'triggered()'), self.onHelpOnLineHelpClicked)
QtCore.QObject.connect(self.ToolsOpenDataFolder,
QtCore.SIGNAL(u'triggered()'), self.onToolsOpenDataFolderClicked)
QtCore.QObject.connect(self.updateThemeImages,
QtCore.SIGNAL(u'triggered()'), self.onUpdateThemeImages)
QtCore.QObject.connect(self.DisplayTagItem,
QtCore.SIGNAL(u'triggered()'), self.onDisplayTagItemClicked)
QtCore.QObject.connect(self.SettingsConfigureItem,
@ -615,11 +625,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
if self.liveController.display.isVisible():
self.liveController.display.setFocus()
self.activateWindow()
# On Windows, arguments contains the entire commandline
# So args[0]=='python' args[1]=='openlp.pyw'
# Therefore this approach is not going to work
# Bypass for now.
if len(self.arguments) and os.name != u'nt':
if len(self.arguments):
args = []
for a in self.arguments:
args.extend([a])
@ -717,6 +723,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
path = AppLocation.get_data_path()
QtGui.QDesktopServices.openUrl(QtCore.QUrl("file:///" + path))
def onUpdateThemeImages(self):
"""
Updates the new theme preview images.
"""
self.themeManagerContents.updatePreviewImages()
def onDisplayTagItemClicked(self):
"""
Show the Settings dialog
@ -778,16 +790,18 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def screenChanged(self):
"""
The screen has changed to so tell the displays to update_display
their locations
The screen has changed so we have to update components such as the
renderer.
"""
log.debug(u'screenChanged')
Receiver.send_message(u'cursor_busy')
self.image_manager.update_display()
self.renderer.update_display()
self.liveController.screenSizeChanged()
self.previewController.screenSizeChanged()
self.liveController.screenSizeChanged()
self.setFocus()
self.activateWindow()
Receiver.send_message(u'cursor_normal')
def closeEvent(self, event):
"""

View File

@ -757,7 +757,7 @@ class ServiceManager(QtGui.QWidget):
"""
Called by a signal to select a specific item.
"""
self.setItem(int(message[0]))
self.setItem(int(message))
def setItem(self, index):
"""

View File

@ -210,6 +210,11 @@ class SlideController(QtGui.QWidget):
u'Go Live', u':/general/general_live.png',
translate('OpenLP.SlideController', 'Move to live'),
self.onGoLive)
self.toolbar.addToolbarButton(
# Does not need translating - control string.
u'Add to Service', u':/general/general_add.png',
translate('OpenLP.SlideController', 'Add to Service'),
self.onPreviewAddToService)
self.toolbar.addToolbarSeparator(u'Close Separator')
self.toolbar.addToolbarButton(
# Does not need translating - control string.
@ -1044,12 +1049,26 @@ class SlideController(QtGui.QWidget):
Receiver.send_message(u'%s_edit' % self.serviceItem.name.lower(),
u'P:%s' % self.serviceItem.edit_id)
def onPreviewAddToService(self):
"""
From the preview display request the Item to be added to service
"""
self.parent.ServiceManagerContents.addServiceItem(self.serviceItem)
def onGoLiveClick(self):
"""
triggered by clicking the Preview slide items
"""
if QtCore.QSettings().value(u'advanced/double click live',
QtCore.QVariant(False)).toBool():
# Live and Preview have issues if we have video or presentations
# playing in both at the same time.
if self.serviceItem.is_command():
Receiver.send_message(u'%s_stop' %
self.serviceItem.name.lower(),
[self.serviceItem, self.isLive])
if self.serviceItem.is_media():
self.onMediaClose()
self.onGoLive()
def onGoLive(self):

View File

@ -660,6 +660,18 @@ class ThemeManager(QtGui.QWidget):
pixmap.save(thumb, u'png')
log.debug(u'Theme image written to %s', samplepathname)
def updatePreviewImages(self):
"""
Called to update the themes' preview images.
"""
self.mainwindow.displayProgressBar(len(self.themelist))
for theme in self.themelist:
self.mainwindow.incrementProgressBar()
self.generateAndSaveImage(
self.path, theme, self.getThemeData(theme))
self.mainwindow.finishedProgressBar()
self.loadThemes()
def generateImage(self, themeData, forcePage=False):
"""
Call the renderer to build a Sample Image

View File

@ -342,7 +342,7 @@ def add_actions(target, actions):
The menu or toolbar to add actions to.
``actions``
The actions to be added. An action consisting of the keyword 'None'
The actions to be added. An action consisting of the keyword ``None``
will result in a separator being inserted into the target.
"""
for action in actions:

View File

@ -114,6 +114,8 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
def accept(self):
log.debug(u'accept')
if self.saveCustom():
Receiver.send_message(u'custom_set_autoselect_item',
self.customSlide.title)
Receiver.send_message(u'custom_load_list')
QtGui.QDialog.accept(self)

View File

@ -26,7 +26,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, SpellTextEdit
from openlp.core.lib import translate, SpellTextEdit, build_icon
from openlp.core.lib.ui import create_accept_reject_button_box
class Ui_CustomSlideEditDialog(object):
@ -39,9 +39,15 @@ class Ui_CustomSlideEditDialog(object):
self.dialogLayout.addWidget(self.slideTextEdit)
self.buttonBox = create_accept_reject_button_box(customSlideEditDialog)
self.splitButton = QtGui.QPushButton(customSlideEditDialog)
self.splitButton.setIcon(build_icon(u':/general/general_add.png'))
self.splitButton.setObjectName(u'splitButton')
self.buttonBox.addButton(self.splitButton,
QtGui.QDialogButtonBox.ActionRole)
self.insertButton = QtGui.QPushButton(customSlideEditDialog)
self.insertButton.setIcon(build_icon(u':/general/general_add.png'))
self.insertButton.setObjectName(u'insertButton')
self.buttonBox.addButton(self.insertButton,
QtGui.QDialogButtonBox.ActionRole)
self.dialogLayout.addWidget(self.buttonBox)
self.retranslateUi(customSlideEditDialog)
QtCore.QMetaObject.connectSlotsByName(customSlideEditDialog)
@ -50,5 +56,10 @@ class Ui_CustomSlideEditDialog(object):
self.splitButton.setText(
translate('CustomPlugin.EditCustomForm', 'Split Slide'))
self.splitButton.setToolTip(
translate('CustomPlugin.EditCustomForm', 'Split a slide into two '
'only if it does not fit on the screen as one slide.'))
self.insertButton.setText(
translate('CustomPlugin.EditCustomForm', 'Insert Slide'))
self.insertButton.setToolTip(
translate('CustomPlugin.EditCustomForm', 'Split a slide into two '
'by inserting a slide splitter.'))

View File

@ -44,6 +44,8 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
# Connecting signals and slots
QtCore.QObject.connect(self.insertButton,
QtCore.SIGNAL(u'clicked()'), self.onInsertButtonPressed)
QtCore.QObject.connect(self.splitButton,
QtCore.SIGNAL(u'clicked()'), self.onSplitButtonPressed)
@ -65,7 +67,7 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog):
"""
return self.slideTextEdit.toPlainText().split(u'\n[===]\n')
def onSplitButtonPressed(self):
def onInsertButtonPressed(self):
"""
Adds a slide split at the cursor.
"""
@ -73,3 +75,12 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog):
self.slideTextEdit.insertPlainText(u'\n')
self.slideTextEdit.insertPlainText(u'[===]\n')
self.slideTextEdit.setFocus()
def onSplitButtonPressed(self):
"""
Adds a virtual split at cursor.
"""
if self.slideTextEdit.textCursor().columnNumber() != 0:
self.slideTextEdit.insertPlainText(u'\n')
self.slideTextEdit.insertPlainText(u'[---]')
self.slideTextEdit.setFocus()

View File

@ -140,6 +140,9 @@ class CustomMediaItem(MediaManagerItem):
custom_name.setData(
QtCore.Qt.UserRole, QtCore.QVariant(customSlide.id))
self.listView.addItem(custom_name)
# Auto-select the item if name has been set
if customSlide.title == self.autoSelectItem :
self.listView.setCurrentItem(custom_name)
def onNewClick(self):
self.parent.edit_custom_form.loadCustom(0)

View File

@ -45,6 +45,7 @@ else:
try:
import uno
from com.sun.star.beans import PropertyValue
from com.sun.star.task import ErrorCodeIOException
uno_available = True
except ImportError:
uno_available = False
@ -286,6 +287,9 @@ class ImpressDocument(PresentationDocument):
doc.storeToURL(urlpath, props)
self.convert_thumbnail(path, idx + 1)
delete_file(path)
except ErrorCodeIOException, exception:
log.exception(u'ERROR! ErrorCodeIOException %d' %
exception.ErrCode)
except:
log.exception(u'%s - Unable to store openoffice preview' % path)

View File

@ -219,10 +219,11 @@ window.OpenLP = {
}
else {
$.each(data.results.items, function (idx, value) {
var li = $("<li data-icon=\"false\">").append(
$("<a href=\"#\">").attr("value", value[0]).text(value[1]));
li.children("a").click(OpenLP.goLive);
ul.append(li);
var item = $("<li>").text(value[1]);
var golive = $("<a href=\"#\">Go Live</a>").attr("value", value[0]).click(OpenLP.goLive);
var additem = $("<a href=\"#\">Add To Service</a>").attr("value", value[0]).click(OpenLP.addToService);
item.append($("<ul>").append($("<li>").append(golive)).append($("<li>").append(additem)));
ul.append(item);
});
}
ul.listview("refresh");
@ -231,16 +232,28 @@ window.OpenLP = {
return false;
},
goLive: function (event) {
var slide = OpenLP.getElement(event);
var id = slide.attr("value");
var item = OpenLP.getElement(event);
var id = item.attr("value");
var text = JSON.stringify({"request": {"id": id}});
$.getJSON(
"/api/" + $("#search-plugin").val() + "/live",
{"data": text})
$.mobile.changePage("slide-controller");
return false;
},
addToService: function (event) {
var item = OpenLP.getElement(event);
var id = item.attr("value");
var text = JSON.stringify({"request": {"id": id}});
$.getJSON(
"/api/" + $("#search-plugin").val() + "/add",
{"data": text},
function () {
history.back();
}
);
return false;
}
}
// Service Manager
$("#service-manager").live("pagebeforeshow", OpenLP.loadService);

View File

@ -253,7 +253,8 @@ class HttpConnection(object):
(r'^/api/alert$', self.alert),
(r'^/api/plugin/(search)$', self.pluginInfo),
(r'^/api/(.*)/search$', self.search),
(r'^/api/(.*)/live$', self.go_live)
(r'^/api/(.*)/live$', self.go_live),
(r'^/api/(.*)/add$', self.add_to_service)
]
QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'readyRead()'),
self.ready_read)
@ -490,6 +491,16 @@ class HttpConnection(object):
if plugin.status == PluginStatus.Active and plugin.mediaItem:
plugin.mediaItem.goLive(id)
def add_to_service(self, type):
"""
Add item of type ``type`` to the end of the service
"""
id = json.loads(self.url_params[u'data'][0])[u'request'][u'id']
plugin = self.parent.parent.pluginManager.get_plugin_by_name(type)
if plugin.status == PluginStatus.Active and plugin.mediaItem:
item_id = plugin.mediaItem.createItemFromId(id)
plugin.mediaItem.addToService(item_id)
def send_response(self, response):
http = u'HTTP/1.1 %s\r\n' % response.code
for header, value in response.headers.iteritems():

View File

@ -695,6 +695,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.clearCaches()
if self._validate_song():
self.saveSong()
Receiver.send_message(u'songs_set_autoselect_item',
unicode(self.titleEdit.text()))
Receiver.send_message(u'songs_load_list')
QtGui.QDialog.accept(self)

View File

@ -42,6 +42,10 @@ class Ui_EditVerseDialog(object):
self.dialogLayout.addWidget(self.verseTextEdit)
self.verseTypeLayout = QtGui.QHBoxLayout()
self.verseTypeLayout.setObjectName(u'verseTypeLayout')
self.splitButton = QtGui.QPushButton(editVerseDialog)
self.splitButton.setIcon(build_icon(u':/general/general_add.png'))
self.splitButton.setObjectName(u'splitButton')
self.verseTypeLayout.addWidget(self.splitButton)
self.verseTypeLabel = QtGui.QLabel(editVerseDialog)
self.verseTypeLabel.setObjectName(u'verseTypeLabel')
self.verseTypeLayout.addWidget(self.verseTypeLabel)
@ -84,5 +88,13 @@ class Ui_EditVerseDialog(object):
VerseType.TranslatedNames[VerseType.Ending])
self.verseTypeComboBox.setItemText(VerseType.Other,
VerseType.TranslatedNames[VerseType.Other])
self.splitButton.setText(
translate('SongsPlugin.EditVerseForm', '&Split'))
self.splitButton.setToolTip(
translate('SongsPlugin.EditVerseForm', 'Split a slide into two '
'only if it does not fit on the screen as one slide.'))
self.insertButton.setText(
translate('SongsPlugin.EditVerseForm', '&Insert'))
self.insertButton.setToolTip(
translate('SongsPlugin.EditVerseForm', 'Split a slide into two '
'by inserting a verse splitter.'))

View File

@ -51,6 +51,8 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
self.contextMenu)
QtCore.QObject.connect(self.insertButton, QtCore.SIGNAL(u'clicked()'),
self.onInsertButtonClicked)
QtCore.QObject.connect(self.splitButton, QtCore.SIGNAL(u'clicked()'),
self.onSplitButtonClicked)
QtCore.QObject.connect(self.verseTextEdit,
QtCore.SIGNAL(u'cursorPositionChanged()'),
self.onCursorPositionChanged)
@ -70,6 +72,13 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
(verse_tag, verse_num))
self.verseTextEdit.setFocus()
def onSplitButtonClicked(self):
verse_type_index = self.verseTypeComboBox.currentIndex()
if self.verseTextEdit.textCursor().columnNumber() != 0:
self.verseTextEdit.insertPlainText(u'\n')
self.verseTextEdit.insertPlainText(u'[---]')
self.verseTextEdit.setFocus()
def onInsertButtonClicked(self):
verse_type_index = self.verseTypeComboBox.currentIndex()
self.insertVerse(VerseType.Tags[verse_type_index],

View File

@ -237,6 +237,9 @@ class SongMediaItem(MediaManagerItem):
song_name = QtGui.QListWidgetItem(song_detail)
song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id))
self.listView.addItem(song_name)
# Auto-select the item if name has been set
if song.title == self.autoSelectItem :
self.listView.setCurrentItem(song_name)
def displayResultsAuthor(self, searchresults):
log.debug(u'display results Author')

View File

@ -110,6 +110,7 @@ class WowImport(SongImport):
self.title = file_name.rpartition(u'.')[0]
songData = open(file, 'rb')
if songData.read(19) != u'WoW File\nSong Words':
self.log_error(file)
continue
# Seek to byte which stores number of blocks in the song
songData.seek(56)

View File

@ -16,7 +16,7 @@
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{AA7699FA-B2D2-43F4-8A70-D497D03C9485}
AppID={{AA7699FA-B2D2-43F4-8A70-D497D03C9485}
AppName={#AppName}
AppVerName={#AppVerName}
AppPublisher={#AppPublisher}
@ -29,11 +29,12 @@ AllowNoIcons=true
LicenseFile=LICENSE.txt
OutputDir=..\..\dist
OutputBaseFilename=OpenLP-{#RealVersion}-setup
Compression=lzma
Compression=lzma/Max
SolidCompression=true
SetupIconFile=OpenLP.ico
WizardImageFile=WizImageBig.bmp
WizardSmallImageFile=WizImageSmall.bmp
ChangesAssociations=true
[Languages]
Name: english; MessagesFile: compiler:Default.isl
@ -79,6 +80,10 @@ Name: {userappdata}\Microsoft\Internet Explorer\Quick Launch\{#AppName}; Filenam
Filename: {app}\{#AppExeName}; Description: {cm:LaunchProgram,{#AppName}}; Flags: nowait postinstall skipifsilent
[Registry]
Root: HKCR; Subkey: ".osz"; ValueType: string; ValueName: ""; ValueData: "OpenLP"; Flags: uninsdeletevalue
Root: HKCR; Subkey: "OpenLP"; ValueType: string; ValueName: ""; ValueData: "OpenLP Service"; Flags: uninsdeletekey
Root: HKCR; Subkey: "OpenLP\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\OpenLP.exe,0"
Root: HKCR; Subkey: "OpenLP\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\OpenLP.exe"" ""%1"""
[Code]
function GetUninstallString(): String;