openlp/openlp/plugins/presentations/lib/mediaitem.py

356 lines
16 KiB
Python

# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2013 Raoul Snyman #
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
# Frode Woldsund, Martin Zibricky #
# --------------------------------------------------------------------------- #
# 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 #
###############################################################################
import logging
import os
from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, build_icon, SettingsManager, \
translate, check_item_selected, Receiver, ItemCapabilities, create_thumb, \
validate_thumb
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
create_horizontal_adjusting_combo_box
from openlp.core.lib.settings import Settings
from openlp.core.utils import locale_compare
from openlp.plugins.presentations.lib import MessageListener
log = logging.getLogger(__name__)
ERROR = QtGui.QImage(u':/general/general_delete.png')
class PresentationMediaItem(MediaManagerItem):
"""
This is the Presentation media manager item for Presentation Items.
It can present files using Openoffice and Powerpoint
"""
log.info(u'Presentations Media Item loaded')
def __init__(self, parent, plugin, icon, controllers):
"""
Constructor. Setup defaults
"""
self.controllers = controllers
self.IconPath = u'presentations/presentation'
self.Automatic = u''
MediaManagerItem.__init__(self, parent, plugin, icon)
self.message_listener = MessageListener(self)
self.hasSearch = True
self.singleServiceItem = False
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'mediaitem_presentation_rebuild'), self.rebuild)
# Allow DnD from the desktop
self.listView.activateDnD()
def retranslateUi(self):
"""
The name of the plugin media displayed in UI
"""
self.onNewPrompt = translate('PresentationPlugin.MediaItem',
'Select Presentation(s)')
self.Automatic = translate('PresentationPlugin.MediaItem',
'Automatic')
self.displayTypeLabel.setText(
translate('PresentationPlugin.MediaItem', 'Present using:'))
def buildFileMaskString(self):
"""
Build the list of file extensions to be used in the Open file dialog
"""
fileType = u''
for controller in self.controllers:
if self.controllers[controller].enabled():
types = self.controllers[controller].supports + \
self.controllers[controller].alsosupports
for type_ in types:
if fileType.find(type_) == -1:
fileType += u'*.%s ' % type_
self.plugin.serviceManager.supportedSuffixes(type_)
self.onNewFileMasks = unicode(translate('PresentationPlugin.MediaItem',
'Presentations (%s)')) % fileType
def requiredIcons(self):
"""
Set which icons the media manager tab should show
"""
MediaManagerItem.requiredIcons(self)
self.hasFileIcon = True
self.hasNewIcon = False
self.hasEditIcon = False
def addEndHeaderBar(self):
"""
Display custom media manager items for presentations
"""
self.presentationWidget = QtGui.QWidget(self)
self.presentationWidget.setObjectName(u'presentationWidget')
self.displayLayout = QtGui.QFormLayout(self.presentationWidget)
self.displayLayout.setMargin(self.displayLayout.spacing())
self.displayLayout.setObjectName(u'displayLayout')
self.displayTypeLabel = QtGui.QLabel(self.presentationWidget)
self.displayTypeLabel.setObjectName(u'displayTypeLabel')
self.displayTypeComboBox = create_horizontal_adjusting_combo_box(
self.presentationWidget, u'displayTypeComboBox')
self.displayTypeLabel.setBuddy(self.displayTypeComboBox)
self.displayLayout.addRow(self.displayTypeLabel,
self.displayTypeComboBox)
# Add the Presentation widget to the page layout
self.pageLayout.addWidget(self.presentationWidget)
def initialise(self):
"""
Populate the media manager tab
"""
self.listView.setIconSize(QtCore.QSize(88, 50))
files = SettingsManager.load_list(
self.settingsSection, u'presentations')
self.loadList(files, True)
self.populateDisplayTypes()
def rebuild(self):
"""
Rebuild the tab in the media manager when changes are made in
the settings
"""
self.populateDisplayTypes()
self.buildFileMaskString()
def populateDisplayTypes(self):
"""
Load the combobox with the enabled presentation controllers,
allowing user to select a specific app if settings allow
"""
self.displayTypeComboBox.clear()
for item in self.controllers:
# load the drop down selection
if self.controllers[item].enabled():
self.displayTypeComboBox.addItem(item)
if self.displayTypeComboBox.count() > 1:
self.displayTypeComboBox.insertItem(0, self.Automatic)
self.displayTypeComboBox.setCurrentIndex(0)
if Settings().value(self.settingsSection + u'/override app',
QtCore.QVariant(QtCore.Qt.Unchecked)) == QtCore.Qt.Checked:
self.presentationWidget.show()
else:
self.presentationWidget.hide()
def loadList(self, files, initialLoad=False):
"""
Add presentations into the media manager
This is called both on initial load of the plugin to populate with
existing files, and when the user adds new files via the media manager
"""
currlist = self.getFileList()
titles = [os.path.split(file)[1] for file in currlist]
Receiver.send_message(u'cursor_busy')
if not initialLoad:
Receiver.send_message(u'cursor_busy')
self.plugin.formParent.displayProgressBar(len(files))
# Sort the presentations by its filename considering language specific
# characters.
files.sort(cmp=locale_compare,
key=lambda filename: os.path.split(unicode(filename))[1])
for file in files:
if not initialLoad:
self.plugin.formParent.incrementProgressBar()
if currlist.count(file) > 0:
continue
filename = os.path.split(unicode(file))[1]
if not os.path.exists(file):
item_name = QtGui.QListWidgetItem(filename)
item_name.setIcon(build_icon(ERROR))
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
item_name.setToolTip(file)
self.listView.addItem(item_name)
else:
if titles.count(filename) > 0:
if not initialLoad:
critical_error_message_box(
translate('PresentationPlugin.MediaItem',
'File Exists'),
translate('PresentationPlugin.MediaItem',
'A presentation with that filename already exists.')
)
continue
controller_name = self.findControllerByType(filename)
if controller_name:
controller = self.controllers[controller_name]
doc = controller.add_document(unicode(file))
thumb = os.path.join(doc.get_thumbnail_folder(),
u'icon.png')
preview = doc.get_thumbnail_path(1, True)
if not preview and not initialLoad:
doc.load_presentation()
preview = doc.get_thumbnail_path(1, True)
doc.close_presentation()
if not (preview and os.path.exists(preview)):
icon = build_icon(u':/general/general_delete.png')
else:
if validate_thumb(preview, thumb):
icon = build_icon(thumb)
else:
icon = create_thumb(preview, thumb)
else:
if initialLoad:
icon = build_icon(u':/general/general_delete.png')
else:
critical_error_message_box(UiStrings().UnsupportedFile,
translate('PresentationPlugin.MediaItem',
'This type of presentation is not supported.'))
continue
item_name = QtGui.QListWidgetItem(filename)
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
item_name.setIcon(icon)
item_name.setToolTip(file)
self.listView.addItem(item_name)
Receiver.send_message(u'cursor_normal')
if not initialLoad:
self.plugin.formParent.finishedProgressBar()
Receiver.send_message(u'cursor_normal')
def onDeleteClick(self):
"""
Remove a presentation item from the list
"""
if check_item_selected(self.listView, UiStrings().SelectDelete):
items = self.listView.selectedIndexes()
row_list = [item.row() for item in items]
row_list.sort(reverse=True)
Receiver.send_message(u'cursor_busy')
self.plugin.formParent.displayProgressBar(len(row_list))
for item in items:
filepath = unicode(item.data(
QtCore.Qt.UserRole).toString())
for cidx in self.controllers:
doc = self.controllers[cidx].add_document(filepath)
doc.presentation_deleted()
doc.close_presentation()
self.plugin.formParent.incrementProgressBar()
self.plugin.formParent.finishedProgressBar()
Receiver.send_message(u'cursor_normal')
for row in row_list:
self.listView.takeItem(row)
SettingsManager.set_list(self.settingsSection,
u'presentations', self.getFileList())
def generateSlideData(self, service_item, item=None, xmlVersion=False,
remote=False):
"""
Load the relevant information for displaying the presentation
in the slidecontroller. In the case of powerpoints, an image
for each slide
"""
if item:
items = [item]
else:
items = self.listView.selectedItems()
if len(items) > 1:
return False
service_item.title = unicode(self.displayTypeComboBox.currentText())
service_item.shortname = unicode(self.displayTypeComboBox.currentText())
service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
service_item.add_capability(ItemCapabilities.HasDetailedTitleDisplay)
shortname = service_item.shortname
if not shortname:
return False
for bitem in items:
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
if os.path.exists(filename):
if shortname == self.Automatic:
service_item.shortname = self.findControllerByType(filename)
if not service_item.shortname:
return False
controller = self.controllers[service_item.shortname]
(path, name) = os.path.split(filename)
doc = controller.add_document(filename)
if doc.get_thumbnail_path(1, True) is None:
doc.load_presentation()
i = 1
img = doc.get_thumbnail_path(i, True)
if img:
while img:
service_item.add_from_command(path, name, img)
i = i + 1
img = doc.get_thumbnail_path(i, True)
doc.close_presentation()
return True
else:
# File is no longer present
if not remote:
critical_error_message_box(
translate('PresentationPlugin.MediaItem',
'Missing Presentation'),
unicode(translate(
'PresentationPlugin.MediaItem',
'The presentation %s is incomplete,'
' please reload.')) % filename)
return False
else:
# File is no longer present
if not remote:
critical_error_message_box(
translate('PresentationPlugin.MediaItem',
'Missing Presentation'),
unicode(translate('PresentationPlugin.MediaItem',
'The presentation %s no longer exists.')) % filename)
return False
def findControllerByType(self, filename):
"""
Determine the default application controller to use for the selected
file type. This is used if "Automatic" is set as the preferred
controller. Find the first (alphabetic) enabled controller which
"supports" the extension. If none found, then look for a controller
which "also supports" it instead.
"""
filetype = os.path.splitext(filename)[1][1:]
if not filetype:
return None
for controller in self.controllers:
if self.controllers[controller].enabled():
if filetype in self.controllers[controller].supports:
return controller
for controller in self.controllers:
if self.controllers[controller].enabled():
if filetype in self.controllers[controller].alsosupports:
return controller
return None
def search(self, string, showError):
files = SettingsManager.load_list(
self.settingsSection, u'presentations')
results = []
string = string.lower()
for file in files:
filename = os.path.split(unicode(file))[1]
if filename.lower().find(string) > -1:
results.append([file, filename])
return results