openlp/openlp/core/ui/servicemanager.py

1630 lines
76 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
2012-12-10 06:15:42 +00:00
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
2012-12-29 20:56:56 +00:00
# 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, #
2012-11-11 21:16:14 +00:00
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
2012-10-21 13:16:22 +00:00
# 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, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# 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 #
###############################################################################
2013-02-01 21:34:23 +00:00
"""
The service manager sets up, loads, saves and manages services.
"""
import cgi
import cPickle
2011-02-04 12:57:48 +00:00
import logging
import os
import shutil
import zipfile
from tempfile import mkstemp
from datetime import datetime, timedelta
2010-02-27 15:31:23 +00:00
log = logging.getLogger(__name__)
from PyQt4 import QtCore, QtGui
2010-03-03 17:48:37 +00:00
2012-12-10 06:15:42 +00:00
from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, ItemCapabilities, SettingsManager, \
2013-01-23 20:29:43 +00:00
translate, str_to_bool, check_directory_exists, Settings, PluginStatus, Registry, UiStrings
2011-02-18 03:15:09 +00:00
from openlp.core.lib.theme import ThemeLevel
from openlp.core.lib.ui import critical_error_message_box, create_widget_action, find_and_set_in_combo_box
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
2011-02-19 17:33:24 +00:00
from openlp.core.ui.printserviceform import PrintServiceForm
2012-12-10 06:15:42 +00:00
from openlp.core.utils import AppLocation, delete_file, split_filename, format_time
2011-04-09 16:11:02 +00:00
from openlp.core.utils.actions import ActionList, CategoryOrder
2013-02-01 21:34:23 +00:00
2009-06-29 17:37:46 +00:00
class ServiceManagerList(QtGui.QTreeWidget):
2010-06-10 01:57:59 +00:00
"""
Set up key bindings and mouse behaviour for the service list
"""
2012-05-05 12:24:25 +00:00
def __init__(self, serviceManager, parent=None):
2013-02-01 21:34:23 +00:00
"""
Constructor
"""
2010-04-28 14:17:42 +00:00
QtGui.QTreeWidget.__init__(self, parent)
self.serviceManager = serviceManager
2009-10-29 09:18:26 +00:00
def keyPressEvent(self, event):
2013-01-27 07:36:04 +00:00
"""
Capture Key press and respond accordingly.
"""
if isinstance(event, QtGui.QKeyEvent):
# here accept the event and do something
if event.key() == QtCore.Qt.Key_Up:
2013-01-27 07:36:04 +00:00
self.serviceManager.on_move_selection_up()
event.accept()
elif event.key() == QtCore.Qt.Key_Down:
2013-01-27 07:36:04 +00:00
self.serviceManager.on_move_selection_down()
event.accept()
elif event.key() == QtCore.Qt.Key_Delete:
self.serviceManager.onDeleteFromService()
event.accept()
event.ignore()
else:
event.ignore()
2009-10-11 09:31:27 +00:00
def mouseMoveEvent(self, event):
"""
Drag and drop event does not care what data is selected
as the recipient will use events to request the data move
just tell it what plugin to call
"""
if event.buttons() != QtCore.Qt.LeftButton:
2010-03-02 19:44:55 +00:00
event.ignore()
2009-10-11 09:31:27 +00:00
return
if not self.itemAt(self.mapFromGlobal(QtGui.QCursor.pos())):
2011-05-12 15:50:20 +00:00
event.ignore()
return
2009-10-11 09:31:27 +00:00
drag = QtGui.QDrag(self)
2013-01-27 07:36:04 +00:00
mime_data = QtCore.QMimeData()
drag.setMimeData(mime_data)
mime_data.setText(u'ServiceManager')
2010-04-30 21:00:17 +00:00
drag.start(QtCore.Qt.CopyAction)
2009-10-11 09:31:27 +00:00
2013-02-01 21:34:23 +00:00
2013-01-27 07:36:04 +00:00
class ServiceManagerDialog(object):
"""
2013-02-02 19:49:56 +00:00
UI part of the Service Manager
"""
2013-02-01 21:34:23 +00:00
def setup_ui(self, widget):
"""
2013-02-02 19:49:56 +00:00
Define the UI
2013-02-01 21:34:23 +00:00
"""
# Create the top toolbar
2010-07-28 13:15:39 +00:00
self.toolbar = OpenLPToolbar(self)
2012-12-10 06:15:42 +00:00
self.toolbar.addToolbarAction(u'newService', text=UiStrings().NewService, icon=u':/general/general_new.png',
2013-01-27 07:36:04 +00:00
tooltip=UiStrings().CreateService, triggers=self.on_new_service_clicked)
2012-12-10 06:15:42 +00:00
self.toolbar.addToolbarAction(u'openService', text=UiStrings().OpenService, icon=u':/general/general_open.png',
2013-02-01 21:34:23 +00:00
tooltip=translate('OpenLP.ServiceManager', 'Load an existing service.'),
triggers=self.on_load_service_clicked)
2012-12-10 06:15:42 +00:00
self.toolbar.addToolbarAction(u'saveService', text=UiStrings().SaveService, icon=u':/general/general_save.png',
2013-01-27 07:36:04 +00:00
tooltip=translate('OpenLP.ServiceManager', 'Save this service.'), triggers=self.decide_save_method)
2010-07-28 13:15:39 +00:00
self.toolbar.addSeparator()
2013-01-27 07:36:04 +00:00
self.theme_label = QtGui.QLabel(u'%s:' % UiStrings().Theme, self)
self.theme_label.setMargin(3)
self.theme_label.setObjectName(u'theme_label')
self.toolbar.addToolbarWidget(self.theme_label)
self.theme_combo_box = QtGui.QComboBox(self.toolbar)
self.theme_combo_box.setToolTip(translate('OpenLP.ServiceManager', 'Select a theme for the service.'))
self.theme_combo_box.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToMinimumContentsLength)
self.theme_combo_box.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
self.theme_combo_box.setObjectName(u'theme_combo_box')
self.toolbar.addToolbarWidget(self.theme_combo_box)
self.toolbar.setObjectName(u'toolbar')
2010-07-28 13:15:39 +00:00
self.layout.addWidget(self.toolbar)
# Create the service manager list
2013-01-27 07:36:04 +00:00
self.service_manager_list = ServiceManagerList(self)
self.service_manager_list.setEditTriggers(
2009-09-10 20:18:15 +00:00
QtGui.QAbstractItemView.CurrentChanged |
QtGui.QAbstractItemView.DoubleClicked |
QtGui.QAbstractItemView.EditKeyPressed)
2013-01-27 07:36:04 +00:00
self.service_manager_list.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
self.service_manager_list.setAlternatingRowColors(True)
self.service_manager_list.setHeaderHidden(True)
self.service_manager_list.setExpandsOnDoubleClick(False)
self.service_manager_list.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
QtCore.QObject.connect(self.service_manager_list, QtCore.SIGNAL('customContextMenuRequested(QPoint)'),
self.context_menu)
self.service_manager_list.setObjectName(u'service_manager_list')
# enable drop
2013-01-27 07:36:04 +00:00
self.service_manager_list.__class__.dragEnterEvent = self.drag_enter_event
self.service_manager_list.__class__.dragMoveEvent = self.drag_enter_event
self.service_manager_list.__class__.dropEvent = self.drop_event
self.layout.addWidget(self.service_manager_list)
# Add the bottom toolbar
2013-01-27 07:36:04 +00:00
self.order_toolbar = OpenLPToolbar(self)
2011-04-09 16:11:02 +00:00
action_list = ActionList.get_instance()
2013-01-21 07:29:43 +00:00
action_list.add_category(UiStrings().Service, CategoryOrder.standardToolbar)
2013-01-27 07:36:04 +00:00
self.service_manager_list.moveTop = self.order_toolbar.addToolbarAction(u'moveTop',
2012-12-10 18:04:58 +00:00
text=translate('OpenLP.ServiceManager', 'Move to &top'), icon=u':/services/service_top.png',
tooltip=translate('OpenLP.ServiceManager', 'Move item to the top of the service.'),
shortcuts=[QtCore.Qt.Key_Home], category=UiStrings().Service, triggers=self.onServiceTop)
2013-01-27 07:36:04 +00:00
self.service_manager_list.moveUp = self.order_toolbar.addToolbarAction(u'moveUp',
2012-12-10 18:04:58 +00:00
text=translate('OpenLP.ServiceManager', 'Move &up'), icon=u':/services/service_up.png',
tooltip=translate('OpenLP.ServiceManager', 'Move item up one position in the service.'),
shortcuts=[QtCore.Qt.Key_PageUp], category=UiStrings().Service, triggers=self.onServiceUp)
2013-01-27 07:36:04 +00:00
self.service_manager_list.moveDown = self.order_toolbar.addToolbarAction(u'moveDown',
2012-12-10 18:04:58 +00:00
text=translate('OpenLP.ServiceManager', 'Move &down'), icon=u':/services/service_down.png',
tooltip=translate('OpenLP.ServiceManager', 'Move item down one position in the service.'),
shortcuts=[QtCore.Qt.Key_PageDown], category=UiStrings().Service, triggers=self.onServiceDown)
2013-01-27 07:36:04 +00:00
self.service_manager_list.moveBottom = self.order_toolbar.addToolbarAction(u'moveBottom',
2012-12-10 18:04:58 +00:00
text=translate('OpenLP.ServiceManager', 'Move to &bottom'), icon=u':/services/service_bottom.png',
tooltip=translate('OpenLP.ServiceManager', 'Move item to the end of the service.'),
shortcuts=[QtCore.Qt.Key_End], category=UiStrings().Service, triggers=self.onServiceEnd)
2013-01-27 07:36:04 +00:00
self.service_manager_list.down = self.order_toolbar.addToolbarAction(u'down',
2012-12-20 12:09:12 +00:00
text=translate('OpenLP.ServiceManager', 'Move &down'),
tooltip=translate('OpenLP.ServiceManager', 'Moves the selection down the window.'), visible=False,
2013-01-27 07:36:04 +00:00
shortcuts=[QtCore.Qt.Key_Down], triggers=self.on_move_selection_down)
action_list.add_action(self.service_manager_list.down)
self.service_manager_list.up = self.order_toolbar.addToolbarAction(u'up',
2012-12-10 18:04:58 +00:00
text=translate('OpenLP.ServiceManager', 'Move up'), tooltip=translate('OpenLP.ServiceManager',
2013-01-27 07:36:04 +00:00
'Moves the selection up the window.'), visible=False, shortcuts=[QtCore.Qt.Key_Up],
triggers=self.on_move_selection_up)
action_list.add_action(self.service_manager_list.up)
self.order_toolbar.addSeparator()
self.service_manager_list.delete = self.order_toolbar.addToolbarAction(u'delete',
2012-12-10 18:04:58 +00:00
text=translate('OpenLP.ServiceManager', '&Delete From Service'), icon=u':/general/general_delete.png',
tooltip=translate('OpenLP.ServiceManager', 'Delete the selected item from the service.'),
shortcuts=[QtCore.Qt.Key_Delete], triggers=self.onDeleteFromService)
2013-01-27 07:36:04 +00:00
self.order_toolbar.addSeparator()
self.service_manager_list.expand = self.order_toolbar.addToolbarAction(u'expand',
2012-12-20 12:09:12 +00:00
text=translate('OpenLP.ServiceManager', '&Expand all'), icon=u':/services/service_expand_all.png',
tooltip=translate('OpenLP.ServiceManager', 'Expand all the service items.'),
shortcuts=[QtCore.Qt.Key_Plus], category=UiStrings().Service, triggers=self.onExpandAll)
2013-01-27 07:36:04 +00:00
self.service_manager_list.collapse = self.order_toolbar.addToolbarAction(u'collapse',
2012-12-10 18:04:58 +00:00
text=translate('OpenLP.ServiceManager', '&Collapse all'), icon=u':/services/service_collapse_all.png',
tooltip=translate('OpenLP.ServiceManager', 'Collapse all the service items.'),
shortcuts=[QtCore.Qt.Key_Minus], category=UiStrings().Service, triggers=self.onCollapseAll)
2013-01-27 07:36:04 +00:00
self.order_toolbar.addSeparator()
self.service_manager_list.make_live = self.order_toolbar.addToolbarAction(u'make_live',
2012-12-10 18:04:58 +00:00
text=translate('OpenLP.ServiceManager', 'Go Live'), icon=u':/general/general_live.png',
tooltip=translate('OpenLP.ServiceManager', 'Send the selected item to Live.'),
2013-02-01 21:34:23 +00:00
shortcuts=[QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return], category=UiStrings().Service,
triggers=self.make_live)
2013-01-27 07:36:04 +00:00
self.layout.addWidget(self.order_toolbar)
# Connect up our signals and slots
2013-01-27 07:36:04 +00:00
QtCore.QObject.connect(self.theme_combo_box, QtCore.SIGNAL(u'activated(int)'),
self.on_theme_combo_box_selected)
QtCore.QObject.connect(self.service_manager_list, QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
self.on_make_live)
QtCore.QObject.connect(self.service_manager_list, QtCore.SIGNAL(u'itemCollapsed(QTreeWidgetItem*)'),
2012-12-10 06:15:42 +00:00
self.collapsed)
2013-01-27 20:36:18 +00:00
QtCore.QObject.connect(self.service_manager_list, QtCore.SIGNAL(u'itemExpanded(QTreeWidgetItem*)'),
self.expanded)
2013-01-27 07:36:04 +00:00
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_list'), self.update_theme_list)
2013-01-27 20:36:18 +00:00
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'servicemanager_preview_live'),
self.preview_live)
2013-01-27 07:36:04 +00:00
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'servicemanager_next_item'), self.next_item)
2012-12-10 06:15:42 +00:00
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'servicemanager_previous_item'),
2013-01-27 07:36:04 +00:00
self.previous_item)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'servicemanager_set_item'), self.on_set_item)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.config_updated)
2012-12-10 06:15:42 +00:00
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_screen_changed'),
2013-01-27 07:36:04 +00:00
self.regenerate_service_Items)
2013-02-02 19:49:56 +00:00
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_global'), self.theme_change)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'service_item_update'),
self.service_item_update)
# Last little bits of setting up
self.service_theme = Settings().value(self.main_window.serviceManagerSettingsSection + u'/service theme')
2010-04-27 16:27:57 +00:00
self.servicePath = AppLocation.get_section_data_path(u'servicemanager')
2010-12-27 10:18:09 +00:00
# build the drag and drop context menu
2010-05-01 13:05:17 +00:00
self.dndMenu = QtGui.QMenu()
2012-12-28 22:06:43 +00:00
self.newAction = self.dndMenu.addAction(translate('OpenLP.ServiceManager', '&Add New Item'))
2010-05-01 13:05:17 +00:00
self.newAction.setIcon(build_icon(u':/general/general_edit.png'))
2012-12-28 22:06:43 +00:00
self.addToAction = self.dndMenu.addAction(translate('OpenLP.ServiceManager', '&Add to Selected Item'))
2010-05-01 13:05:17 +00:00
self.addToAction.setIcon(build_icon(u':/general/general_edit.png'))
# build the context menu
2010-03-05 09:24:42 +00:00
self.menu = QtGui.QMenu()
2013-01-27 10:18:06 +00:00
self.edit_action = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', '&Edit Item'),
2013-01-27 07:36:04 +00:00
icon=u':/general/general_edit.png', triggers=self.remote_edit)
2013-01-27 10:18:06 +00:00
self.maintain_action = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', '&Reorder Item'),
2013-01-27 07:36:04 +00:00
icon=u':/general/general_edit.png', triggers=self.on_service_item_edit_form)
2013-01-27 10:18:06 +00:00
self.notes_action = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', '&Notes'),
2013-01-27 07:36:04 +00:00
icon=u':/services/service_notes.png', triggers=self.on_service_item_note_form)
2013-01-27 10:18:06 +00:00
self.time_action = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', '&Start Time'),
2013-01-27 07:36:04 +00:00
icon=u':/media/media_time.png', triggers=self.on_start_time_form)
2013-01-27 10:18:06 +00:00
self.auto_start_action = create_widget_action(self.menu, text=u'',
2013-01-27 07:36:04 +00:00
icon=u':/media/auto-start_active.png', triggers=self.on_auto_start)
2012-05-07 15:49:22 +00:00
# Add already existing delete action to the menu.
2013-01-27 07:36:04 +00:00
self.menu.addAction(self.service_manager_list.delete)
self.create_custom_action = create_widget_action(self.menu,
text=translate('OpenLP.ServiceManager', 'Create New &Custom Slide'),
icon=u':/general/general_edit.png', triggers=self.create_custom)
self.menu.addSeparator()
2012-11-09 18:44:25 +00:00
# Add AutoPlay menu actions
2013-01-27 07:36:04 +00:00
self.auto_play_slides_group = QtGui.QMenu(translate('OpenLP.ServiceManager', '&Auto play slides'))
self.menu.addMenu(self.auto_play_slides_group)
self.auto_play_slides_loop = create_widget_action(self.auto_play_slides_group,
2012-11-13 08:11:49 +00:00
text=translate('OpenLP.ServiceManager', 'Auto play slides &Loop'),
2013-01-27 07:36:04 +00:00
checked=False, triggers=self.toggle_auto_play_slides_loop)
self.auto_play_slides_once = create_widget_action(self.auto_play_slides_group,
2012-11-13 08:11:49 +00:00
text=translate('OpenLP.ServiceManager', 'Auto play slides &Once'),
2013-01-27 07:36:04 +00:00
checked=False, triggers=self.toggle_auto_play_slides_once)
self.auto_play_slides_group.addSeparator()
self.timed_slide_interval = create_widget_action(self.auto_play_slides_group,
2012-11-09 18:44:25 +00:00
text=translate('OpenLP.ServiceManager', '&Delay between slides'),
2013-01-27 07:36:04 +00:00
checked=False, triggers=self.on_timed_slide_interval)
self.menu.addSeparator()
2013-01-27 07:36:04 +00:00
self.preview_action = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', 'Show &Preview'),
2013-01-27 20:36:18 +00:00
icon=u':/general/general_preview.png', triggers=self.make_preview)
2012-05-07 15:49:22 +00:00
# Add already existing make live action to the menu.
2013-01-27 07:36:04 +00:00
self.menu.addAction(self.service_manager_list.make_live)
self.menu.addSeparator()
2013-01-27 07:36:04 +00:00
self.theme_menu = QtGui.QMenu(translate('OpenLP.ServiceManager', '&Change Item Theme'))
self.menu.addMenu(self.theme_menu)
self.service_manager_list.addActions(
[self.service_manager_list.moveDown,
self.service_manager_list.moveUp,
self.service_manager_list.make_live,
self.service_manager_list.moveTop,
self.service_manager_list.moveBottom,
self.service_manager_list.up,
self.service_manager_list.down,
self.service_manager_list.expand,
self.service_manager_list.collapse
2011-01-19 21:17:32 +00:00
])
2013-01-27 07:36:04 +00:00
def drag_enter_event(self, event):
"""
Accept Drag events
``event``
Handle of the event pint passed
"""
event.accept()
class ServiceManager(QtGui.QWidget, ServiceManagerDialog):
"""
Manages the services. This involves taking text strings from plugins and
adding them to the service. This service can then be zipped up with all
the resources used into one OSZ or oszl file for use on any OpenLP v2
installation. Also handles the UI tasks of moving things up and down etc.
"""
def __init__(self, parent=None):
"""
Sets up the service manager, toolbars, list view, et al.
"""
QtGui.QWidget.__init__(self, parent)
self.active = build_icon(QtGui.QImage(u':/media/auto-start_active.png'))
self.inactive = build_icon(QtGui.QImage(u':/media/auto-start_inactive.png'))
Registry().register(u'service_manager', self)
self.service_items = []
self.suffixes = []
self.drop_position = 0
self.expand_tabs = False
self.service_id = 0
# is a new service and has not been saved
self._modified = False
self._file_name = u''
self.service_has_all_original_files = True
self.serviceNoteForm = ServiceNoteForm()
self.serviceItemEditForm = ServiceItemEditForm()
self.startTimeForm = StartTimeForm()
# start with the layout
self.layout = QtGui.QVBoxLayout(self)
self.layout.setSpacing(0)
self.layout.setMargin(0)
self.setup_ui(self)
self.config_updated()
def set_modified(self, modified=True):
"""
Setter for property "modified". Sets whether or not the current service
has been modified.
"""
2012-04-10 19:38:25 +00:00
if modified:
2013-01-21 07:29:43 +00:00
self.service_id += 1
self._modified = modified
2013-01-27 07:36:04 +00:00
service_file = self.short_file_name() or translate('OpenLP.ServiceManager', 'Untitled Service')
self.main_window.setServiceModified(modified, service_file)
2013-01-27 07:36:04 +00:00
def is_modified(self):
"""
Getter for boolean property "modified".
"""
return self._modified
2013-01-27 07:36:04 +00:00
def set_file_name(self, file_name):
"""
Setter for service file.
"""
2013-01-27 07:36:04 +00:00
self._file_name = unicode(file_name)
self.main_window.setServiceModified(self.is_modified(), self.short_file_name())
Settings().setValue(u'servicemanager/last file', file_name)
self._saveLite = self._file_name.endswith(u'.oszl')
2013-01-27 07:36:04 +00:00
def file_name(self):
"""
Return the current file name including path.
"""
2013-01-27 07:36:04 +00:00
return self._file_name
2013-01-27 07:36:04 +00:00
def short_file_name(self):
"""
Return the current file name, excluding the path.
"""
2013-01-27 07:36:04 +00:00
return split_filename(self._file_name)[1]
2013-01-27 07:36:04 +00:00
def config_updated(self):
"""
Triggered when Config dialog is updated.
"""
2013-01-27 07:36:04 +00:00
self.expand_tabs = Settings().value(u'advanced/expand service item')
2010-03-05 09:24:42 +00:00
2013-01-27 07:36:04 +00:00
def reset_supported_suffixes(self):
"""
2012-11-26 17:57:36 +00:00
Resets the Suffixes list.
"""
self.suffixes = []
2013-01-27 07:36:04 +00:00
def supported_suffixes(self, suffix):
2012-08-24 20:06:56 +00:00
"""
Adds Suffixes supported to the master list. Called from Plugins.
``suffix``
New Suffix to be supported
"""
if not suffix in self.suffixes:
self.suffixes.append(suffix)
2010-05-05 19:14:48 +00:00
2013-01-27 07:36:04 +00:00
def on_new_service_clicked(self):
"""
Create a new service.
"""
2013-01-27 07:36:04 +00:00
if self.is_modified():
result = self.save_modified_service()
if result == QtGui.QMessageBox.Cancel:
return False
elif result == QtGui.QMessageBox.Save:
2013-01-27 07:36:04 +00:00
if not self.decide_save_method():
return False
2013-01-27 07:36:04 +00:00
self.new_file()
2013-01-27 07:36:04 +00:00
def on_load_service_clicked(self, load_file=None):
2011-08-02 18:17:07 +00:00
"""
Loads the service file and saves the existing one it there is one
unchanged
2013-01-29 17:19:19 +00:00
``load_file``
2011-08-02 18:17:07 +00:00
The service file to the loaded. Will be None is from menu so
selection will be required.
"""
2013-01-27 07:36:04 +00:00
if self.is_modified():
result = self.save_modified_service()
if result == QtGui.QMessageBox.Cancel:
return False
elif result == QtGui.QMessageBox.Save:
2013-01-27 07:36:04 +00:00
self.decide_save_method()
if not load_file:
file_name = QtGui.QFileDialog.getOpenfile_name(self.main_window,
2011-08-02 18:17:07 +00:00
translate('OpenLP.ServiceManager', 'Open File'),
SettingsManager.get_last_dir(self.main_window.serviceManagerSettingsSection),
2013-01-22 21:09:43 +00:00
translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz *.oszl)'))
2013-01-27 07:36:04 +00:00
if not file_name:
2011-08-02 18:17:07 +00:00
return False
else:
2013-01-27 07:36:04 +00:00
file_name = load_file
Settings().setValue(self.main_window.serviceManagerSettingsSection + u'/last directory',
2013-01-27 07:36:04 +00:00
split_filename(file_name)[0])
self.load_file(file_name)
2013-01-27 07:36:04 +00:00
def save_modified_service(self):
2013-01-21 11:11:47 +00:00
"""
Check to see if a service needs to be saved.
"""
return QtGui.QMessageBox.question(self.main_window,
2011-01-26 16:05:55 +00:00
translate('OpenLP.ServiceManager', 'Modified Service'),
2012-12-10 18:04:58 +00:00
translate('OpenLP.ServiceManager',
'The current service has been modified. Would you like to save this service?'),
QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save)
2013-01-27 07:36:04 +00:00
def on_recent_service_clicked(self):
2013-01-21 11:11:47 +00:00
"""
Load a recent file as the service triggered by mainwindow recent service list.
"""
sender = self.sender()
2013-01-27 07:36:04 +00:00
self.load_file(sender.data())
2013-01-27 07:36:04 +00:00
def new_file(self):
"""
Create a blank new service file.
"""
2013-01-27 07:36:04 +00:00
self.service_manager_list.clear()
self.service_items = []
self.set_file_name(u'')
2013-01-21 07:29:43 +00:00
self.service_id += 1
2013-01-27 07:36:04 +00:00
self.set_modified(False)
2012-05-17 15:13:09 +00:00
Settings().setValue(u'servicemanager/last file', u'')
2011-12-10 14:34:28 +00:00
Receiver.send_message(u'servicemanager_new_service')
2013-01-27 07:36:04 +00:00
def save_file(self):
"""
Save the current service file.
A temporary file is created so that we don't overwrite the existing one
and leave a mangled service file should there be an error when saving.
Audio files are also copied into the service manager directory, and
then packaged into the zip file.
"""
2013-01-27 07:36:04 +00:00
if not self.file_name():
return self.save_file_as()
temp_file, temp_file_name = mkstemp(u'.osz', u'openlp_')
# We don't need the file handle.
os.close(temp_file)
log.debug(temp_file_name)
2013-01-27 07:36:04 +00:00
path_file_name = unicode(self.file_name())
2011-08-28 17:45:13 +00:00
path, file_name = os.path.split(path_file_name)
base_name = os.path.splitext(file_name)[0]
service_file_name = '%s.osd' % base_name
2013-01-27 07:36:04 +00:00
log.debug(u'ServiceManager.save_file - %s', path_file_name)
Settings().setValue(self.main_window.serviceManagerSettingsSection + u'/last directory', path)
service = []
write_list = []
missing_list = []
2011-08-28 17:45:13 +00:00
audio_files = []
total_size = 0
2011-04-29 06:21:31 +00:00
Receiver.send_message(u'cursor_busy')
2011-04-29 07:40:19 +00:00
# Number of items + 1 to zip it
2013-01-27 07:36:04 +00:00
self.main_window.displayProgressBar(len(self.service_items) + 1)
# Get list of missing files, and list of files to write
2013-01-27 07:36:04 +00:00
for item in self.service_items:
if not item[u'service_item'].uses_file():
continue
for frame in item[u'service_item'].get_frames():
path_from = item[u'service_item'].get_frame_path(frame=frame)
if path_from in write_list or path_from in missing_list:
continue
2011-08-04 13:43:05 +00:00
if not os.path.exists(path_from):
missing_list.append(path_from)
else:
write_list.append(path_from)
if missing_list:
Receiver.send_message(u'cursor_normal')
2012-12-20 12:09:12 +00:00
title = translate('OpenLP.ServiceManager', 'Service File(s) Missing')
2012-12-05 20:33:39 +00:00
message = translate('OpenLP.ServiceManager',
'The following file(s) in the service are missing:\n\t%s\n\n'
2012-12-20 12:09:12 +00:00
'These files will be removed if you continue to save.') % "\n\t".join(missing_list)
2012-12-10 18:04:58 +00:00
answer = QtGui.QMessageBox.critical(self, title, message,
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel))
if answer == QtGui.QMessageBox.Cancel:
self.main_window.finishedProgressBar()
return False
Receiver.send_message(u'cursor_busy')
# Check if item contains a missing file.
2013-01-27 07:36:04 +00:00
for item in list(self.service_items):
self.main_window.incrementProgressBar()
2012-11-02 18:54:42 +00:00
item[u'service_item'].remove_invalid_frames(missing_list)
if item[u'service_item'].missing_frames():
2013-01-27 07:36:04 +00:00
self.service_items.remove(item)
else:
2012-12-05 22:42:48 +00:00
service_item = item[u'service_item'].get_service_repr(self._saveLite)
if service_item[u'header'][u'background_audio']:
2013-01-27 07:36:04 +00:00
for i, file_name in enumerate(service_item[u'header'][u'background_audio']):
new_file = os.path.join(u'audio', item[u'service_item'].unique_identifier, file_name)
audio_files.append((file_name, new_file))
2012-12-10 18:04:58 +00:00
service_item[u'header'][u'background_audio'][i] = new_file
# Add the service item to the service.
service.append({u'serviceitem': service_item})
2013-01-27 20:36:18 +00:00
self.repaint_service_list(-1, -1)
2013-01-21 07:29:43 +00:00
for file_item in write_list:
file_size = os.path.getsize(file_item)
total_size += file_size
2013-01-27 07:36:04 +00:00
log.debug(u'ServiceManager.save_file - ZIP contents size is %i bytes' % total_size)
service_content = cPickle.dumps(service)
# Usual Zip file cannot exceed 2GiB, file with Zip64 cannot be
# extracted using unzip in UNIX.
allow_zip_64 = (total_size > 2147483648 + len(service_content))
2013-01-27 07:36:04 +00:00
log.debug(u'ServiceManager.save_file - allowZip64 is %s' % allow_zip_64)
2013-01-21 07:29:43 +00:00
zip_file = None
success = True
self.main_window.incrementProgressBar()
try:
2013-01-21 07:29:43 +00:00
zip_file = zipfile.ZipFile(temp_file_name, 'w', zipfile.ZIP_STORED, allow_zip_64)
# First we add service contents.
2013-01-27 07:36:04 +00:00
# We save ALL file_names into ZIP using UTF-8.
2013-01-21 07:29:43 +00:00
zip_file.writestr(service_file_name.encode(u'utf-8'), service_content)
# Finally add all the listed media files.
for write_from in write_list:
2013-01-21 07:29:43 +00:00
zip_file.write(write_from, write_from.encode(u'utf-8'))
for audio_from, audio_to in audio_files:
if audio_from.startswith(u'audio'):
2013-01-21 11:11:47 +00:00
# When items are saved, they get new unique_identifier. Let's copy the
# file to the new location. Unused files can be ignored,
# OpenLP automatically cleans up the service manager dir on
# exit.
audio_from = os.path.join(self.servicePath, audio_from)
save_file = os.path.join(self.servicePath, audio_to)
save_path = os.path.split(save_file)[0]
2012-07-07 14:54:14 +00:00
check_directory_exists(save_path)
if not os.path.exists(save_file):
shutil.copy(audio_from, save_file)
2013-01-21 07:29:43 +00:00
zip_file.write(audio_from, audio_to.encode(u'utf-8'))
except IOError:
log.exception(u'Failed to save service to disk: %s', temp_file_name)
2012-05-17 12:59:57 +00:00
Receiver.send_message(u'openlp_error_message', {
2012-12-10 18:04:58 +00:00
u'title': translate(u'OpenLP.ServiceManager', u'Error Saving File'),
u'message': translate(u'OpenLP.ServiceManager', u'There was an error saving your file.')
2012-05-17 12:59:57 +00:00
})
success = False
finally:
2013-01-21 07:29:43 +00:00
if zip_file:
zip_file.close()
self.main_window.finishedProgressBar()
2011-04-29 06:21:31 +00:00
Receiver.send_message(u'cursor_normal')
if success:
try:
shutil.copy(temp_file_name, path_file_name)
2013-02-01 20:40:23 +00:00
except shutil.Error:
2013-01-27 07:36:04 +00:00
return self.save_file_as()
self.main_window.addRecentFile(path_file_name)
2013-01-27 07:36:04 +00:00
self.set_modified(False)
2012-06-09 15:46:01 +00:00
delete_file(temp_file_name)
return success
2013-01-27 07:36:04 +00:00
def save_local_file(self):
2012-09-14 16:35:07 +00:00
"""
2013-01-21 11:11:47 +00:00
Save the current service file but leave all the file references alone to point to the current machine.
This format is not transportable as it will not contain any files.
2012-09-14 16:35:07 +00:00
"""
2013-01-27 07:36:04 +00:00
if not self.file_name():
return self.save_file_as()
2012-09-14 16:35:07 +00:00
temp_file, temp_file_name = mkstemp(u'.oszl', u'openlp_')
# We don't need the file handle.
os.close(temp_file)
log.debug(temp_file_name)
2013-01-27 07:36:04 +00:00
path_file_name = unicode(self.file_name())
2012-09-14 16:35:07 +00:00
path, file_name = os.path.split(path_file_name)
2013-01-21 11:11:47 +00:00
base_name = os.path.splitext(file_name)[0]
service_file_name = '%s.osd' % base_name
2013-01-27 07:36:04 +00:00
log.debug(u'ServiceManager.save_file - %s', path_file_name)
Settings().setValue(self.main_window.serviceManagerSettingsSection + u'/last directory', path)
2012-09-14 16:35:07 +00:00
service = []
Receiver.send_message(u'cursor_busy')
# Number of items + 1 to zip it
2013-01-27 07:36:04 +00:00
self.main_window.displayProgressBar(len(self.service_items) + 1)
for item in self.service_items:
self.main_window.incrementProgressBar()
2012-12-10 18:04:58 +00:00
service_item = item[u'service_item'].get_service_repr(self._saveLite)
2012-11-01 16:36:45 +00:00
#@todo check for file item on save.
2012-09-14 16:35:07 +00:00
service.append({u'serviceitem': service_item})
self.main_window.incrementProgressBar()
2012-09-14 16:35:07 +00:00
service_content = cPickle.dumps(service)
2013-01-21 07:29:43 +00:00
zip_file = None
2012-09-14 16:35:07 +00:00
success = True
self.main_window.incrementProgressBar()
2012-09-14 16:35:07 +00:00
try:
2013-01-21 07:29:43 +00:00
zip_file = zipfile.ZipFile(temp_file_name, 'w', zipfile.ZIP_STORED,
2012-11-01 16:36:45 +00:00
True)
2012-09-14 16:35:07 +00:00
# First we add service contents.
2013-01-21 07:29:43 +00:00
zip_file.writestr(service_file_name.encode(u'utf-8'), service_content)
2012-09-14 16:35:07 +00:00
except IOError:
log.exception(u'Failed to save service to disk: %s', temp_file_name)
Receiver.send_message(u'openlp_error_message', {
2012-12-10 18:04:58 +00:00
u'title': translate(u'OpenLP.ServiceManager', u'Error Saving File'),
u'message': translate(u'OpenLP.ServiceManager', u'There was an error saving your file.')
2012-09-14 16:35:07 +00:00
})
success = False
finally:
2013-01-21 07:29:43 +00:00
if zip_file:
zip_file.close()
self.main_window.finishedProgressBar()
2012-09-14 16:35:07 +00:00
Receiver.send_message(u'cursor_normal')
if success:
try:
shutil.copy(temp_file_name, path_file_name)
2013-02-01 20:40:23 +00:00
except shutil.Error:
2013-01-27 07:36:04 +00:00
return self.save_file_as()
self.main_window.addRecentFile(path_file_name)
2013-01-27 07:36:04 +00:00
self.set_modified(False)
2012-09-14 16:35:07 +00:00
delete_file(temp_file_name)
return success
2013-01-27 07:36:04 +00:00
def save_file_as(self):
"""
2013-01-27 07:36:04 +00:00
Get a file name and then call :func:`ServiceManager.save_file` to
save the file.
"""
default_service_enabled = Settings().value(u'advanced/default service enabled')
if default_service_enabled:
service_day = Settings().value(u'advanced/default service day')
if service_day == 7:
2012-09-16 15:33:05 +00:00
local_time = datetime.now()
else:
service_hour = Settings().value(u'advanced/default service hour')
service_minute = Settings().value(u'advanced/default service minute')
now = datetime.now()
day_delta = service_day - now.weekday()
if day_delta < 0:
day_delta += 7
time = now + timedelta(days=day_delta)
2012-09-16 15:33:05 +00:00
local_time = time.replace(hour=service_hour, minute=service_minute)
default_pattern = Settings().value(u'advanced/default service name')
2013-01-27 07:36:04 +00:00
default_file_name = format_time(default_pattern, local_time)
else:
2013-01-27 07:36:04 +00:00
default_file_name = u''
directory = Settings().value(self.main_window.serviceManagerSettingsSection + u'/last directory')
2013-01-27 07:36:04 +00:00
path = os.path.join(directory, default_file_name)
2012-11-01 16:54:37 +00:00
# SaveAs from osz to oszl is not valid as the files will be deleted
# on exit which is not sensible or usable in the long term.
2013-01-27 07:36:04 +00:00
if self._file_name.endswith(u'oszl') or self.service_has_all_original_files:
file_name = QtGui.QFileDialog.getSavefile_name(self.main_window, UiStrings().SaveService, path,
2012-11-01 16:36:45 +00:00
translate('OpenLP.ServiceManager',
2012-12-20 12:09:12 +00:00
'OpenLP Service Files (*.osz);; OpenLP Service Files - lite (*.oszl)'))
2012-11-01 16:36:45 +00:00
else:
2013-01-27 07:36:04 +00:00
file_name = QtGui.QFileDialog.getSavefile_name(self.main_window, UiStrings().SaveService, path,
2012-12-20 12:09:12 +00:00
translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz);;'))
2013-01-27 07:36:04 +00:00
if not file_name:
return False
2013-01-27 07:36:04 +00:00
if os.path.splitext(file_name)[1] == u'':
file_name += u'.osz'
else:
2013-01-27 07:36:04 +00:00
ext = os.path.splitext(file_name)[1]
file_name.replace(ext, u'.osz')
self.set_file_name(file_name)
self.decide_save_method()
2013-01-27 07:36:04 +00:00
def decide_save_method(self):
"""
Determine which type of save method to use.
"""
2013-01-27 07:36:04 +00:00
if not self.file_name():
return self.save_file_as()
2012-10-14 16:21:47 +00:00
if self._saveLite:
2013-01-27 07:36:04 +00:00
return self.save_local_file()
2012-09-14 16:35:07 +00:00
else:
2013-01-27 07:36:04 +00:00
return self.save_file()
2013-01-27 07:36:04 +00:00
def load_file(self, file_name):
"""
Load an existing service file
"""
2013-01-27 07:36:04 +00:00
if not file_name:
return False
2013-01-27 07:36:04 +00:00
file_name = unicode(file_name)
if not os.path.exists(file_name):
return False
zip_file = None
2013-01-27 07:36:04 +00:00
file_to = None
try:
2013-01-27 07:36:04 +00:00
zip_file = zipfile.ZipFile(file_name)
for zip_info in zip_file.infolist():
try:
2013-01-27 07:36:04 +00:00
ucsfile = zip_info.filename.decode(u'utf-8')
except UnicodeDecodeError:
2013-02-01 20:09:47 +00:00
log.exception(u'file_name "%s" is not valid UTF-8' %
zip_info.file_name.decode(u'utf-8', u'replace'))
2012-12-10 18:04:58 +00:00
critical_error_message_box(message=translate('OpenLP.ServiceManager',
'File is not a valid service.\n The content encoding is not UTF-8.'))
continue
2012-02-26 21:09:22 +00:00
osfile = ucsfile.replace(u'/', os.path.sep)
if not osfile.startswith(u'audio'):
osfile = os.path.split(osfile)[1]
log.debug(u'Extract file: %s', osfile)
2013-01-27 07:36:04 +00:00
zip_info.filename = osfile
zip_file.extract(zip_info, self.servicePath)
2011-08-30 19:42:12 +00:00
if osfile.endswith(u'osd'):
p_file = os.path.join(self.servicePath, osfile)
if 'p_file' in locals():
2011-02-03 03:50:04 +00:00
Receiver.send_message(u'cursor_busy')
2013-01-27 07:36:04 +00:00
file_to = open(p_file, u'r')
items = cPickle.load(file_to)
file_to.close()
self.new_file()
self.set_file_name(file_name)
self.main_window.displayProgressBar(len(items))
for item in items:
self.main_window.incrementProgressBar()
2013-01-27 07:36:04 +00:00
service_item = ServiceItem()
2012-10-14 16:21:47 +00:00
if self._saveLite:
2013-01-27 07:36:04 +00:00
service_item.set_from_service(item)
else:
2013-01-27 07:36:04 +00:00
service_item.set_from_service(item, self.servicePath)
service_item.validate_item(self.suffixes)
2013-01-21 07:34:50 +00:00
self.load_item_unique_identifier = 0
2013-01-27 07:36:04 +00:00
if service_item.is_capable(ItemCapabilities.OnLoadUpdate):
Receiver.send_message(u'%s_service_load' % service_item.name.lower(), service_item)
# if the item has been processed
2013-01-27 07:36:04 +00:00
if service_item.unique_identifier == self.load_item_unique_identifier:
service_item.edit_id = int(self.load_item_edit_id)
service_item.temporary_edit = self.load_item_temporary
2013-01-27 20:36:18 +00:00
self.add_service_item(service_item, repaint=False)
2011-01-14 18:58:47 +00:00
delete_file(p_file)
2013-01-27 07:36:04 +00:00
self.main_window.addRecentFile(file_name)
self.set_modified(False)
Settings().setValue('servicemanager/last file', file_name)
else:
2012-12-10 18:04:58 +00:00
critical_error_message_box(message=translate('OpenLP.ServiceManager', 'File is not a valid service.'))
log.exception(u'File contains no service data')
2011-03-24 20:37:02 +00:00
except (IOError, NameError, zipfile.BadZipfile):
2013-01-27 07:36:04 +00:00
log.exception(u'Problem loading service file %s' % file_name)
2012-12-10 18:04:58 +00:00
critical_error_message_box(message=translate('OpenLP.ServiceManager',
2011-03-24 20:37:02 +00:00
'File could not be opened because it is corrupt.'))
2011-03-15 14:38:16 +00:00
except zipfile.BadZipfile:
2013-01-27 07:36:04 +00:00
if os.path.getsize(file_name) == 0:
log.exception(u'Service file is zero sized: %s' % file_name)
2012-12-10 18:04:58 +00:00
QtGui.QMessageBox.information(self, translate('OpenLP.ServiceManager', 'Empty File'),
translate('OpenLP.ServiceManager', 'This service file does not contain any data.'))
else:
log.exception(u'Service file is cannot be extracted as zip: '
2013-01-27 07:36:04 +00:00
u'%s' % file_name)
2012-12-10 18:04:58 +00:00
QtGui.QMessageBox.information(self, translate('OpenLP.ServiceManager', 'Corrupt File'),
translate('OpenLP.ServiceManager',
'This file is either corrupt or it is not an OpenLP 2 service file.'))
2011-03-15 14:38:16 +00:00
return
finally:
2013-01-27 07:36:04 +00:00
if file_to:
file_to.close()
if zip_file:
zip_file.close()
self.main_window.finishedProgressBar()
2011-04-29 08:45:36 +00:00
Receiver.send_message(u'cursor_normal')
2013-01-27 20:36:18 +00:00
self.repaint_service_list(-1, -1)
2013-01-27 07:36:04 +00:00
def load_Last_file(self):
"""
Load the last service item from the service manager when the
service was last closed. Can be blank if there was no service
present.
"""
2013-01-27 07:36:04 +00:00
file_name = Settings().value(u'servicemanager/last file')
if file_name:
self.load_file(file_name)
2013-01-27 07:36:04 +00:00
def context_menu(self, point):
2013-01-21 11:11:47 +00:00
"""
The Right click context menu from the Serviceitem list
"""
2013-01-27 07:36:04 +00:00
item = self.service_manager_list.itemAt(point)
2010-03-12 19:39:15 +00:00
if item is None:
return
2012-05-17 20:06:23 +00:00
if item.parent():
2012-05-19 09:13:32 +00:00
pos = item.parent().data(0, QtCore.Qt.UserRole)
2010-03-05 09:24:42 +00:00
else:
2012-05-19 09:13:32 +00:00
pos = item.data(0, QtCore.Qt.UserRole)
2013-01-27 07:36:04 +00:00
service_item = self.service_items[pos - 1]
2013-01-27 10:18:06 +00:00
self.edit_action.setVisible(False)
self.create_custom_action.setVisible(False)
2013-01-27 10:18:06 +00:00
self.maintain_action.setVisible(False)
self.notes_action.setVisible(False)
self.time_action.setVisible(False)
self.auto_start_action.setVisible(False)
2013-01-27 07:36:04 +00:00
if service_item[u'service_item'].is_capable(ItemCapabilities.CanEdit) and service_item[u'service_item'].edit_id:
2013-01-27 10:18:06 +00:00
self.edit_action.setVisible(True)
2013-01-27 07:36:04 +00:00
if service_item[u'service_item'].is_capable(ItemCapabilities.CanMaintain):
2013-01-27 10:18:06 +00:00
self.maintain_action.setVisible(True)
2010-03-05 09:24:42 +00:00
if item.parent() is None:
2013-01-27 10:18:06 +00:00
self.notes_action.setVisible(True)
2013-01-27 07:36:04 +00:00
if service_item[u'service_item'].is_capable(ItemCapabilities.CanLoop) and \
len(service_item[u'service_item'].get_frames()) > 1:
self.auto_play_slides_group.menuAction().setVisible(True)
self.auto_play_slides_once.setChecked(service_item[u'service_item'].auto_play_slides_once)
self.auto_play_slides_loop.setChecked(service_item[u'service_item'].auto_play_slides_loop)
self.timed_slide_interval.setChecked(service_item[u'service_item'].timed_slide_interval > 0)
if service_item[u'service_item'].timed_slide_interval > 0:
delay_suffix = u' %s s' % unicode(service_item[u'service_item'].timed_slide_interval)
2012-11-09 18:44:25 +00:00
else:
2012-11-16 18:48:49 +00:00
delay_suffix = u' ...'
2013-02-01 21:34:23 +00:00
self.timed_slide_interval.setText(
translate('OpenLP.ServiceManager', '&Delay between slides') + delay_suffix)
2012-12-25 20:22:41 +00:00
# TODO for future: make group explains itself more visually
2012-11-09 18:44:25 +00:00
else:
2013-01-27 07:36:04 +00:00
self.auto_play_slides_group.menuAction().setVisible(False)
if service_item[u'service_item'].is_capable(ItemCapabilities.HasVariableStartTime):
2013-01-27 10:18:06 +00:00
self.time_action.setVisible(True)
2013-01-27 07:36:04 +00:00
if service_item[u'service_item'].is_capable(ItemCapabilities.CanAutoStartForLive):
2013-01-27 10:18:06 +00:00
self.auto_start_action.setVisible(True)
self.auto_start_action.setIcon(self.inactive)
2013-02-01 21:34:23 +00:00
self.auto_start_action.setText(translate('OpenLP.ServiceManager', '&Auto Start - inactive'))
2013-01-27 07:36:04 +00:00
if service_item[u'service_item'].will_auto_start:
2013-01-27 10:18:06 +00:00
self.auto_start_action.setText(translate('OpenLP.ServiceManager', '&Auto Start - active'))
self.auto_start_action.setIcon(self.active)
2013-01-27 07:36:04 +00:00
if service_item[u'service_item'].is_text():
2013-01-22 21:25:16 +00:00
for plugin in self.plugin_manager.plugins:
if plugin.name == u'custom' and plugin.status == PluginStatus.Active:
self.create_custom_action.setVisible(True)
break
2013-01-27 07:36:04 +00:00
self.theme_menu.menuAction().setVisible(False)
2011-05-27 06:29:14 +00:00
# Set up the theme menu.
2013-01-27 07:36:04 +00:00
if service_item[u'service_item'].is_text() and self.renderer.theme_level == ThemeLevel.Song:
self.theme_menu.menuAction().setVisible(True)
2011-05-27 06:29:14 +00:00
# The service item does not have a theme, check the "Default".
2013-01-27 07:36:04 +00:00
if service_item[u'service_item'].theme is None:
2013-01-27 10:18:06 +00:00
theme_action = self.theme_menu.defaultAction()
2011-05-26 08:15:56 +00:00
else:
2013-01-27 10:18:06 +00:00
theme_action = self.theme_menu.findChild(QtGui.QAction, service_item[u'service_item'].theme)
if theme_action is not None:
theme_action.setChecked(True)
2013-01-27 07:36:04 +00:00
self.menu.exec_(self.service_manager_list.mapToGlobal(point))
2013-01-27 07:36:04 +00:00
def on_service_item_note_form(self):
"""
Allow the service note to be edited
"""
2013-01-27 07:36:04 +00:00
item = self.find_service_item()[0]
2013-01-27 20:36:18 +00:00
self.serviceNoteForm.text_edit.setPlainText(self.service_items[item][u'service_item'].notes)
2010-03-17 21:08:18 +00:00
if self.serviceNoteForm.exec_():
2013-01-27 20:36:18 +00:00
self.service_items[item][u'service_item'].notes = self.serviceNoteForm.text_edit.toPlainText()
self.repaint_service_list(item, -1)
2013-01-27 07:36:04 +00:00
self.set_modified()
2010-03-03 17:48:37 +00:00
2013-01-27 07:36:04 +00:00
def on_start_time_form(self):
"""
Opens a dialog to type in service item notes.
"""
2013-01-27 07:36:04 +00:00
item = self.find_service_item()[0]
self.startTimeForm.item = self.service_items[item]
if self.startTimeForm.exec_():
2013-01-27 20:36:18 +00:00
self.repaint_service_list(item, -1)
2013-01-27 07:36:04 +00:00
def toggle_auto_play_slides_once(self):
2012-11-09 18:44:25 +00:00
"""
Toggle Auto play slide once.
2012-11-13 08:32:09 +00:00
Inverts auto play once option for the item
2012-11-09 18:44:25 +00:00
"""
2013-01-27 07:36:04 +00:00
item = self.find_service_item()[0]
service_item = self.service_items[item][u'service_item']
2012-11-14 11:47:15 +00:00
service_item.auto_play_slides_once = not service_item.auto_play_slides_once
if service_item.auto_play_slides_once:
service_item.auto_play_slides_loop = False
2013-01-27 07:36:04 +00:00
self.auto_play_slides_loop.setChecked(False)
2012-11-14 11:47:15 +00:00
if service_item.auto_play_slides_once and service_item.timed_slide_interval == 0:
2013-01-24 09:18:38 +00:00
service_item.timed_slide_interval = Settings().value(
2013-01-30 22:01:52 +00:00
self.main_window.generalSettingsSection + u'/loop delay')
2013-01-27 07:36:04 +00:00
self.set_modified()
2012-11-09 18:44:25 +00:00
2013-01-27 07:36:04 +00:00
def toggle_auto_play_slides_loop(self):
2012-11-09 18:44:25 +00:00
"""
Toggle Auto play slide loop.
"""
2013-01-27 07:36:04 +00:00
item = self.find_service_item()[0]
service_item = self.service_items[item][u'service_item']
2012-11-14 11:47:15 +00:00
service_item.auto_play_slides_loop = not service_item.auto_play_slides_loop
if service_item.auto_play_slides_loop:
service_item.auto_play_slides_once = False
2013-01-27 07:36:04 +00:00
self.auto_play_slides_once.setChecked(False)
2012-11-14 11:47:15 +00:00
if service_item.auto_play_slides_loop and service_item.timed_slide_interval == 0:
2013-01-24 09:18:38 +00:00
service_item.timed_slide_interval = Settings().value(
2013-01-30 22:01:52 +00:00
self.main_window.generalSettingsSection + u'/loop delay')
2013-01-27 07:36:04 +00:00
self.set_modified()
2012-11-09 18:44:25 +00:00
2013-01-27 07:36:04 +00:00
def on_timed_slide_interval(self):
2012-11-09 18:44:25 +00:00
"""
2012-12-29 22:52:19 +00:00
Shows input dialog for enter interval in seconds for delay
2012-11-09 18:44:25 +00:00
"""
2013-01-27 07:36:04 +00:00
item = self.find_service_item()[0]
service_item = self.service_items[item][u'service_item']
2012-11-14 11:47:15 +00:00
if service_item.timed_slide_interval == 0:
2013-01-24 09:18:38 +00:00
timed_slide_interval = Settings().value(self.mainwindow.generalSettingsSection + u'/loop delay')
2012-11-09 18:44:25 +00:00
else:
2012-11-14 11:47:15 +00:00
timed_slide_interval = service_item.timed_slide_interval
2012-12-29 22:52:19 +00:00
timed_slide_interval, ok = QtGui.QInputDialog.getInteger(self, translate('OpenLP.ServiceManager',
'Input delay'), translate('OpenLP.ServiceManager', 'Delay between slides in seconds.'),
2012-12-18 20:25:07 +00:00
timed_slide_interval, 0, 180, 1)
2012-11-09 18:44:25 +00:00
if ok:
2012-11-14 11:47:15 +00:00
service_item.timed_slide_interval = timed_slide_interval
2013-01-21 11:11:47 +00:00
if service_item.timed_slide_interval != 0 and not service_item.auto_play_slides_loop \
and not service_item.auto_play_slides_once:
2012-11-14 11:47:15 +00:00
service_item.auto_play_slides_loop = True
elif service_item.timed_slide_interval == 0:
service_item.auto_play_slides_loop = False
service_item.auto_play_slides_once = False
2013-01-27 07:36:04 +00:00
self.set_modified()
2012-11-09 18:44:25 +00:00
2013-01-27 07:36:04 +00:00
def on_auto_start(self):
"""
Toggles to Auto Start Setting.
"""
2013-01-27 07:36:04 +00:00
item = self.find_service_item()[0]
self.service_items[item][u'service_item'].will_auto_start = \
not self.service_items[item][u'service_item'].will_auto_start
2013-01-27 07:36:04 +00:00
def on_service_item_edit_form(self):
2012-08-24 20:06:56 +00:00
"""
Opens a dialog to edit the service item and update the service
display if changes are saved.
"""
2013-01-27 07:36:04 +00:00
item = self.find_service_item()[0]
2013-01-27 20:36:18 +00:00
self.serviceItemEditForm.set_service_item(self.service_items[item][u'service_item'])
if self.serviceItemEditForm.exec_():
2013-01-27 20:36:18 +00:00
self.add_service_item(self.serviceItemEditForm.get_service_item(),
2013-01-27 07:36:04 +00:00
replace=True, expand=self.service_items[item][u'expanded'])
2013-01-27 07:36:04 +00:00
def preview_live(self, message):
"""
Called by the SlideController to request a preview item be made live
2012-08-24 20:06:56 +00:00
and allows the next preview to be updated if relevant.
"""
2013-01-21 07:34:50 +00:00
unique_identifier, row = message.split(u':')
2013-01-27 07:36:04 +00:00
for sitem in self.service_items:
2013-01-21 07:34:50 +00:00
if sitem[u'service_item'].unique_identifier == unique_identifier:
2013-01-27 07:36:04 +00:00
item = self.service_manager_list.topLevelItem(sitem[u'order'] - 1)
self.service_manager_list.setCurrentItem(item)
self.make_live(int(row))
return
2013-01-27 07:36:04 +00:00
def next_item(self):
"""
Called by the SlideController to select the next service item.
"""
2013-01-27 07:36:04 +00:00
if not self.service_manager_list.selectedItems():
2010-02-04 19:25:32 +00:00
return
2013-01-27 07:36:04 +00:00
selected = self.service_manager_list.selectedItems()[0]
lookFor = 0
2013-01-27 07:36:04 +00:00
serviceIterator = QtGui.QTreeWidgetItemIterator(self.service_manager_list)
while serviceIterator.value():
if lookFor == 1 and serviceIterator.value().parent() is None:
2013-01-27 07:36:04 +00:00
self.service_manager_list.setCurrentItem(serviceIterator.value())
self.make_live()
return
if serviceIterator.value() == selected:
lookFor = 1
serviceIterator += 1
2013-01-27 07:36:04 +00:00
def previous_item(self, message):
2010-04-26 21:29:40 +00:00
"""
Called by the SlideController to select the previous service item.
2010-04-26 21:29:40 +00:00
"""
2013-01-27 07:36:04 +00:00
if not self.service_manager_list.selectedItems():
2010-04-26 21:29:40 +00:00
return
2013-01-27 07:36:04 +00:00
selected = self.service_manager_list.selectedItems()[0]
2010-04-26 21:29:40 +00:00
prevItem = None
prevItemLastSlide = None
2013-01-27 07:36:04 +00:00
serviceIterator = QtGui.QTreeWidgetItemIterator(self.service_manager_list)
2010-04-26 21:29:40 +00:00
while serviceIterator.value():
if serviceIterator.value() == selected:
2012-01-23 09:33:12 +00:00
if message == u'last slide' and prevItemLastSlide:
2012-05-19 09:13:32 +00:00
pos = prevItem.data(0, QtCore.Qt.UserRole)
2013-01-27 07:36:04 +00:00
check_expanded = self.service_items[pos - 1][u'expanded']
self.service_manager_list.setCurrentItem(prevItemLastSlide)
if not check_expanded:
2013-01-27 07:36:04 +00:00
self.service_manager_list.collapseItem(prevItem)
self.make_live()
self.service_manager_list.setCurrentItem(prevItem)
elif prevItem:
2013-01-27 07:36:04 +00:00
self.service_manager_list.setCurrentItem(prevItem)
self.make_live()
2010-04-26 21:29:40 +00:00
return
if serviceIterator.value().parent() is None:
prevItem = serviceIterator.value()
if serviceIterator.value().parent() is prevItem:
prevItemLastSlide = serviceIterator.value()
2010-04-26 21:29:40 +00:00
serviceIterator += 1
2013-01-27 07:36:04 +00:00
def on_set_item(self, message):
"""
Called by a signal to select a specific item.
"""
2013-01-27 07:36:04 +00:00
self.set_item(int(message))
2010-05-04 20:01:45 +00:00
2013-01-27 07:36:04 +00:00
def set_item(self, index):
"""
Makes a specific item in the service live.
"""
2013-01-27 07:36:04 +00:00
if index >= 0 and index < self.service_manager_list.topLevelItemCount:
item = self.service_manager_list.topLevelItem(index)
self.service_manager_list.setCurrentItem(item)
self.make_live()
2013-01-27 07:36:04 +00:00
def on_move_selection_up(self):
"""
Moves the cursor selection up the window.
Called by the up arrow.
"""
2013-01-27 07:36:04 +00:00
item = self.service_manager_list.currentItem()
itemBefore = self.service_manager_list.itemAbove(item)
if itemBefore is None:
return
2013-01-27 07:36:04 +00:00
self.service_manager_list.setCurrentItem(itemBefore)
2013-01-27 07:36:04 +00:00
def on_move_selection_down(self):
"""
Moves the cursor selection down the window.
Called by the down arrow.
"""
2013-01-27 07:36:04 +00:00
item = self.service_manager_list.currentItem()
itemAfter = self.service_manager_list.itemBelow(item)
if itemAfter is None:
return
2013-01-27 07:36:04 +00:00
self.service_manager_list.setCurrentItem(itemAfter)
def onCollapseAll(self):
"""
Collapse all the service items.
"""
2013-01-27 07:36:04 +00:00
for item in self.service_items:
item[u'expanded'] = False
2013-01-27 07:36:04 +00:00
self.service_manager_list.collapseAll()
def collapsed(self, item):
"""
Record if an item is collapsed. Used when repainting the list to get the
correct state.
"""
2012-05-19 09:13:32 +00:00
pos = item.data(0, QtCore.Qt.UserRole)
2013-01-27 07:36:04 +00:00
self.service_items[pos - 1][u'expanded'] = False
def onExpandAll(self):
"""
Collapse all the service items.
"""
2013-01-27 07:36:04 +00:00
for item in self.service_items:
item[u'expanded'] = True
2013-01-27 07:36:04 +00:00
self.service_manager_list.expandAll()
def expanded(self, item):
"""
Record if an item is collapsed. Used when repainting the list to get the
correct state.
"""
2012-05-19 09:13:32 +00:00
pos = item.data(0, QtCore.Qt.UserRole)
2013-01-27 07:36:04 +00:00
self.service_items[pos - 1][u'expanded'] = True
def onServiceTop(self):
"""
Move the current ServiceItem to the top of the list.
"""
2013-01-27 07:36:04 +00:00
item, child = self.find_service_item()
if item < len(self.service_items) and item != -1:
temp = self.service_items[item]
self.service_items.remove(self.service_items[item])
self.service_items.insert(0, temp)
2013-01-27 20:36:18 +00:00
self.repaint_service_list(0, child)
2013-01-27 07:36:04 +00:00
self.set_modified()
def onServiceUp(self):
"""
Move the current ServiceItem one position up in the list.
"""
2013-01-27 07:36:04 +00:00
item, child = self.find_service_item()
if item > 0:
2013-01-27 07:36:04 +00:00
temp = self.service_items[item]
self.service_items.remove(self.service_items[item])
self.service_items.insert(item - 1, temp)
2013-01-27 20:36:18 +00:00
self.repaint_service_list(item - 1, child)
2013-01-27 07:36:04 +00:00
self.set_modified()
def onServiceDown(self):
"""
Move the current ServiceItem one position down in the list.
"""
2013-01-27 07:36:04 +00:00
item, child = self.find_service_item()
if item < len(self.service_items) and item != -1:
temp = self.service_items[item]
self.service_items.remove(self.service_items[item])
self.service_items.insert(item + 1, temp)
2013-01-27 20:36:18 +00:00
self.repaint_service_list(item + 1, child)
2013-01-27 07:36:04 +00:00
self.set_modified()
def onServiceEnd(self):
"""
Move the current ServiceItem to the bottom of the list.
"""
2013-01-27 07:36:04 +00:00
item, child = self.find_service_item()
if item < len(self.service_items) and item != -1:
temp = self.service_items[item]
self.service_items.remove(self.service_items[item])
self.service_items.insert(len(self.service_items), temp)
2013-01-27 20:36:18 +00:00
self.repaint_service_list(len(self.service_items) - 1, child)
2013-01-27 07:36:04 +00:00
self.set_modified()
def onDeleteFromService(self):
"""
Remove the current ServiceItem from the list.
"""
2013-01-27 07:36:04 +00:00
item = self.find_service_item()[0]
if item != -1:
2013-01-27 07:36:04 +00:00
self.service_items.remove(self.service_items[item])
2013-01-27 20:36:18 +00:00
self.repaint_service_list(item - 1, -1)
2013-01-27 07:36:04 +00:00
self.set_modified()
2013-01-27 20:36:18 +00:00
def repaint_service_list(self, serviceItem, serviceItemChild):
"""
Clear the existing service list and prepaint all the items. This is
used when moving items as the move takes place in a supporting list,
and when regenerating all the items due to theme changes.
``serviceItem``
2011-01-20 16:12:07 +00:00
The item which changed. (int)
2011-01-22 07:31:32 +00:00
``serviceItemChild``
2011-01-20 16:12:07 +00:00
The child of the ``serviceItem``, which will be selected. (int)
"""
# Correct order of items in array
count = 1
2012-12-08 16:20:52 +00:00
self.service_has_all_original_files = True
2013-01-27 07:36:04 +00:00
for item in self.service_items:
item[u'order'] = count
count += 1
2012-12-08 16:20:52 +00:00
if not item[u'service_item'].has_original_files:
self.service_has_all_original_files = False
# Repaint the screen
2013-01-27 07:36:04 +00:00
self.service_manager_list.clear()
for item_count, item in enumerate(self.service_items):
2009-11-14 08:40:14 +00:00
serviceitem = item[u'service_item']
2013-01-27 07:36:04 +00:00
treewidgetitem = QtGui.QTreeWidgetItem(self.service_manager_list)
2010-05-07 18:29:17 +00:00
if serviceitem.is_valid:
2010-05-04 20:01:45 +00:00
if serviceitem.notes:
icon = QtGui.QImage(serviceitem.icon)
2012-12-10 18:04:58 +00:00
icon = icon.scaled(80, 80, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
2010-05-04 20:01:45 +00:00
overlay = QtGui.QImage(':/services/service_item_notes.png')
2012-12-10 18:04:58 +00:00
overlay = overlay.scaled(80, 80, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
2010-05-04 20:01:45 +00:00
painter = QtGui.QPainter(icon)
painter.drawImage(0, 0, overlay)
painter.end()
treewidgetitem.setIcon(0, build_icon(icon))
2011-12-10 08:45:17 +00:00
elif serviceitem.temporary_edit:
icon = QtGui.QImage(serviceitem.icon)
2012-12-10 18:04:58 +00:00
icon = icon.scaled(80, 80, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
2011-12-10 08:45:17 +00:00
overlay = QtGui.QImage(':/general/general_export.png')
2012-12-10 18:04:58 +00:00
overlay = overlay.scaled(40, 40, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
2011-12-10 08:45:17 +00:00
painter = QtGui.QPainter(icon)
painter.drawImage(40, 0, overlay)
painter.end()
treewidgetitem.setIcon(0, build_icon(icon))
2010-05-04 20:01:45 +00:00
else:
treewidgetitem.setIcon(0, serviceitem.iconic_representation)
2010-03-06 08:00:36 +00:00
else:
2012-12-10 18:04:58 +00:00
treewidgetitem.setIcon(0, build_icon(u':/general/general_delete.png'))
2011-01-29 07:53:21 +00:00
treewidgetitem.setText(0, serviceitem.get_display_title())
tips = []
2011-12-10 08:45:17 +00:00
if serviceitem.temporary_edit:
tips.append(u'<strong>%s:</strong> <em>%s</em>' %
2012-05-17 18:57:01 +00:00
(translate('OpenLP.ServiceManager', 'Edit'),
2012-12-20 12:09:12 +00:00
(translate('OpenLP.ServiceManager', 'Service copy only'))))
if serviceitem.theme and serviceitem.theme != -1:
2011-07-10 11:59:23 +00:00
tips.append(u'<strong>%s:</strong> <em>%s</em>' %
2012-12-20 12:09:12 +00:00
(translate('OpenLP.ServiceManager', 'Slide theme'), serviceitem.theme))
if serviceitem.notes:
2011-07-10 12:02:58 +00:00
tips.append(u'<strong>%s: </strong> %s' %
2012-12-20 12:09:12 +00:00
(translate('OpenLP.ServiceManager', 'Notes'), cgi.escape(serviceitem.notes)))
2012-12-10 18:04:58 +00:00
if item[u'service_item'].is_capable(ItemCapabilities.HasVariableStartTime):
2011-07-10 11:59:23 +00:00
tips.append(item[u'service_item'].get_media_time())
treewidgetitem.setToolTip(0, u'<br>'.join(tips))
2012-05-17 15:13:09 +00:00
treewidgetitem.setData(0, QtCore.Qt.UserRole, item[u'order'])
2011-06-04 18:08:48 +00:00
treewidgetitem.setSelected(item[u'selected'])
2011-01-20 16:12:07 +00:00
# Add the children to their parent treewidgetitem.
for count, frame in enumerate(serviceitem.get_frames()):
2011-01-22 07:31:32 +00:00
child = QtGui.QTreeWidgetItem(treewidgetitem)
text = frame[u'title'].replace(u'\n', u' ')
2011-01-22 07:31:32 +00:00
child.setText(0, text[:40])
2012-05-17 15:13:09 +00:00
child.setData(0, QtCore.Qt.UserRole, count)
2013-01-21 07:29:43 +00:00
if serviceItem == item_count:
2011-01-22 07:31:32 +00:00
if item[u'expanded'] and serviceItemChild == count:
2013-01-27 07:36:04 +00:00
self.service_manager_list.setCurrentItem(child)
2011-01-22 07:31:32 +00:00
elif serviceItemChild == -1:
2013-01-27 07:36:04 +00:00
self.service_manager_list.setCurrentItem(treewidgetitem)
2010-03-08 19:50:35 +00:00
treewidgetitem.setExpanded(item[u'expanded'])
2013-02-01 20:40:23 +00:00
def clean_up(self):
2009-09-19 21:45:50 +00:00
"""
2012-08-24 20:06:56 +00:00
Empties the servicePath of temporary files on system exit.
2009-09-19 21:45:50 +00:00
"""
log.debug(u'Cleaning up servicePath')
2013-02-01 20:40:23 +00:00
for file_name in os.listdir(self.servicePath):
file_path = os.path.join(self.servicePath, file_name)
2011-01-14 18:58:47 +00:00
delete_file(file_path)
if os.path.exists(os.path.join(self.servicePath, u'audio')):
shutil.rmtree(os.path.join(self.servicePath, u'audio'), True)
2013-01-27 07:36:04 +00:00
def on_theme_combo_box_selected(self, currentIndex):
"""
Set the theme for the current service.
"""
2013-01-27 07:36:04 +00:00
log.debug(u'ontheme_combo_box_selected')
self.service_theme = self.theme_combo_box.currentText()
2013-01-22 21:09:43 +00:00
self.renderer.set_service_theme(self.service_theme)
Settings().setValue(self.main_window.serviceManagerSettingsSection + u'/service theme', self.service_theme)
2013-01-27 07:36:04 +00:00
self.regenerate_service_Items(True)
2009-06-26 16:39:16 +00:00
2013-02-01 20:40:23 +00:00
def theme_change(self):
"""
The theme may have changed in the settings dialog so make
sure the theme combo box is in the correct state.
"""
2013-02-01 20:40:23 +00:00
log.debug(u'theme_change')
2013-01-22 21:09:43 +00:00
visible = self.renderer.theme_level == ThemeLevel.Global
2013-01-27 07:36:04 +00:00
self.theme_label.setVisible(visible)
self.theme_combo_box.setVisible(visible)
2013-01-27 07:36:04 +00:00
def regenerate_service_Items(self, changed=False):
"""
Rebuild the service list as things have changed and a
repaint is the easiest way to do this.
"""
2011-01-01 12:20:42 +00:00
Receiver.send_message(u'cursor_busy')
2013-01-27 07:36:04 +00:00
log.debug(u'regenerate_service_Items')
2010-08-26 05:01:29 +00:00
# force reset of renderer as theme data has changed
2012-12-08 16:20:52 +00:00
self.service_has_all_original_files = True
2013-01-27 07:36:04 +00:00
if self.service_items:
for item in self.service_items:
2011-06-04 18:08:48 +00:00
item[u'selected'] = False
2013-01-27 07:36:04 +00:00
serviceIterator = QtGui.QTreeWidgetItemIterator(self.service_manager_list)
selectedItem = None
2011-06-04 18:08:48 +00:00
while serviceIterator.value():
if serviceIterator.value().isSelected():
selectedItem = serviceIterator.value()
serviceIterator += 1
if selectedItem is not None:
if selectedItem.parent() is None:
2012-05-19 09:13:32 +00:00
pos = selectedItem.data(0, QtCore.Qt.UserRole)
2011-06-04 18:08:48 +00:00
else:
2012-05-19 09:13:32 +00:00
pos = selectedItem.parent().data(0, QtCore.Qt.UserRole)
2013-01-27 07:36:04 +00:00
self.service_items[pos - 1][u'selected'] = True
tempServiceItems = self.service_items
self.service_manager_list.clear()
self.service_items = []
2010-03-05 12:06:19 +00:00
self.isNew = True
2009-06-10 15:54:46 +00:00
for item in tempServiceItems:
2013-01-27 20:36:18 +00:00
self.add_service_item(item[u'service_item'], False, expand=item[u'expanded'], repaint=False,
2012-12-10 18:04:58 +00:00
selected=item[u'selected'])
2010-08-26 05:01:29 +00:00
# Set to False as items may have changed rendering
# does not impact the saved song so True may also be valid
if changed:
2013-01-27 07:36:04 +00:00
self.set_modified()
2011-06-04 18:08:48 +00:00
# Repaint it once only at the end
2013-01-27 20:36:18 +00:00
self.repaint_service_list(-1, -1)
2011-01-01 12:20:42 +00:00
Receiver.send_message(u'cursor_normal')
2013-02-01 20:40:23 +00:00
def service_item_update(self, message):
2010-09-30 05:12:06 +00:00
"""
Triggered from plugins to update service items.
2011-09-25 07:27:09 +00:00
Save the values as they will be used as part of the service load
2010-09-30 05:12:06 +00:00
"""
2013-01-21 07:34:50 +00:00
edit_id, self.load_item_unique_identifier, temporary = message.split(u':')
2011-12-12 18:00:12 +00:00
self.load_item_edit_id = int(edit_id)
2011-12-12 17:22:40 +00:00
self.load_item_temporary = str_to_bool(temporary)
2010-09-30 05:12:06 +00:00
2013-01-27 20:36:18 +00:00
def replace_service_item(self, newItem):
"""
Using the service item passed replace the one with the same edit id
if found.
"""
2013-01-27 07:36:04 +00:00
for item_count, item in enumerate(self.service_items):
2012-12-10 18:04:58 +00:00
if item[u'service_item'].edit_id == newItem.edit_id and item[u'service_item'].name == newItem.name:
newItem.render()
newItem.merge(item[u'service_item'])
item[u'service_item'] = newItem
2013-01-27 20:36:18 +00:00
self.repaint_service_list(item_count + 1, 0)
2013-01-22 21:25:16 +00:00
self.live_controller.replaceServiceManagerItem(newItem)
2013-01-27 07:36:04 +00:00
self.set_modified()
2013-01-27 20:36:18 +00:00
def add_service_item(self, item, rebuild=False, expand=None, replace=False, repaint=True, selected=False):
"""
Add a Service item to the list
``item``
Service Item to be added
``expand``
Override the default expand settings. (Tristate)
"""
2010-11-19 18:05:49 +00:00
# if not passed set to config value
if expand is None:
2013-01-27 07:36:04 +00:00
expand = self.expand_tabs
item.from_service = True
2010-04-20 22:00:55 +00:00
if replace:
2013-01-27 07:36:04 +00:00
sitem, child = self.find_service_item()
item.merge(self.service_items[sitem][u'service_item'])
self.service_items[sitem][u'service_item'] = item
2013-01-27 20:36:18 +00:00
self.repaint_service_list(sitem, child)
2013-01-22 21:25:16 +00:00
self.live_controller.replaceServiceManagerItem(item)
2009-10-29 09:18:26 +00:00
else:
2011-10-02 19:57:42 +00:00
item.render()
2010-09-30 05:12:06 +00:00
# nothing selected for dnd
2013-01-27 07:36:04 +00:00
if self.drop_position == 0:
if isinstance(item, list):
for inditem in item:
2013-01-27 07:36:04 +00:00
self.service_items.append({u'service_item': inditem,
u'order': len(self.service_items) + 1,
2011-06-04 18:08:48 +00:00
u'expanded': expand, u'selected': selected})
else:
2013-01-27 07:36:04 +00:00
self.service_items.append({u'service_item': item,
u'order': len(self.service_items) + 1,
2011-06-04 18:08:48 +00:00
u'expanded': expand, u'selected': selected})
2011-04-29 08:45:36 +00:00
if repaint:
2013-01-27 20:36:18 +00:00
self.repaint_service_list(len(self.service_items) - 1, -1)
2009-10-29 09:18:26 +00:00
else:
2013-01-27 07:36:04 +00:00
self.service_items.insert(self.drop_position,
{u'service_item': item, u'order': self.drop_position,
2011-06-04 18:08:48 +00:00
u'expanded': expand, u'selected': selected})
2013-01-27 20:36:18 +00:00
self.repaint_service_list(self.drop_position, -1)
2010-09-30 05:12:06 +00:00
# if rebuilding list make sure live is fixed.
if rebuild:
2013-01-22 21:25:16 +00:00
self.live_controller.replaceServiceManagerItem(item)
2013-01-27 07:36:04 +00:00
self.drop_position = 0
self.set_modified()
2013-01-27 20:36:18 +00:00
def make_preview(self):
"""
Send the current item to the Preview slide controller
"""
2011-05-26 04:48:13 +00:00
Receiver.send_message(u'cursor_busy')
2013-01-27 07:36:04 +00:00
item, child = self.find_service_item()
if self.service_items[item][u'service_item'].is_valid:
self.preview_controller.addServiceManagerItem(self.service_items[item][u'service_item'], child)
2010-05-06 16:49:12 +00:00
else:
2012-12-10 18:04:58 +00:00
critical_error_message_box(translate('OpenLP.ServiceManager', 'Missing Display Handler'),
translate('OpenLP.ServiceManager',
'Your item cannot be displayed as there is no handler to display it'))
2011-05-26 04:48:13 +00:00
Receiver.send_message(u'cursor_normal')
2013-01-27 20:36:18 +00:00
def get_service_item(self):
2010-03-16 20:22:28 +00:00
"""
Send the current item to the Preview slide controller
"""
2013-01-27 07:36:04 +00:00
item = self.find_service_item()[0]
2010-03-16 20:22:28 +00:00
if item == -1:
return False
else:
2013-01-27 07:36:04 +00:00
return self.service_items[item][u'service_item']
2013-01-27 07:36:04 +00:00
def on_make_live(self):
2011-03-25 06:13:42 +00:00
"""
Send the current item to the Live slide controller but triggered
by a tablewidget click event.
"""
2013-01-27 07:36:04 +00:00
self.make_live()
2011-03-25 06:13:42 +00:00
2013-01-27 07:36:04 +00:00
def make_live(self, row=-1):
"""
Send the current item to the Live slide controller
``row``
2011-03-25 06:13:42 +00:00
Row number to be displayed if from preview.
-1 is passed if the value is not set
"""
2013-01-27 07:36:04 +00:00
item, child = self.find_service_item()
# No items in service
if item == -1:
return
if row != -1:
child = row
2011-05-26 04:48:13 +00:00
Receiver.send_message(u'cursor_busy')
2013-01-27 07:36:04 +00:00
if self.service_items[item][u'service_item'].is_valid:
self.live_controller.addServiceManagerItem(self.service_items[item][u'service_item'], child)
if Settings().value(self.main_window.generalSettingsSection + u'/auto preview'):
2010-05-04 20:01:45 +00:00
item += 1
2013-01-27 07:36:04 +00:00
if self.service_items and item < len(self.service_items) and \
self.service_items[item][u'service_item'].is_capable(ItemCapabilities.CanPreview):
self.preview_controller.addServiceManagerItem(self.service_items[item][u'service_item'], 0)
next_item = self.service_manager_list.topLevelItem(item)
self.service_manager_list.setCurrentItem(next_item)
2013-01-22 21:25:16 +00:00
self.live_controller.previewListWidget.setFocus()
2010-05-04 20:01:45 +00:00
else:
2012-12-10 18:04:58 +00:00
critical_error_message_box(translate('OpenLP.ServiceManager', 'Missing Display Handler'),
translate('OpenLP.ServiceManager',
'Your item cannot be displayed as the plugin required to display it is missing or inactive'))
2011-05-26 04:48:13 +00:00
Receiver.send_message(u'cursor_normal')
2013-01-27 07:36:04 +00:00
def remote_edit(self):
2009-10-29 09:18:26 +00:00
"""
2013-01-27 09:57:03 +00:00
Triggers a remote edit to a plugin to allow item to be edited.
2009-10-29 09:18:26 +00:00
"""
2013-02-01 20:40:23 +00:00
item = self.find_service_item()[0]
2013-01-27 07:36:04 +00:00
if self.service_items[item][u'service_item'].is_capable(ItemCapabilities.CanEdit):
2013-01-27 09:57:03 +00:00
new_item = Registry().get(self.service_items[item][u'service_item'].name). \
onRemoteEdit(self.service_items[item][u'service_item'].edit_id)
if new_item:
2013-01-27 20:36:18 +00:00
self.add_service_item(new_item, replace=True)
2009-10-29 09:18:26 +00:00
def create_custom(self):
"""
Saves the current text item as a custom slide
"""
2013-01-27 07:36:04 +00:00
item = self.find_service_item()[0]
Receiver.send_message(u'custom_create_from_service', self.service_items[item][u'service_item'])
2013-01-27 07:36:04 +00:00
def find_service_item(self):
"""
2012-05-07 08:21:21 +00:00
Finds the first selected ServiceItem in the list and returns the
position of the serviceitem and its selected child item. For example,
if the third child item (in the Slidecontroller known as slide) in the
second service item is selected this will return::
2011-01-20 16:12:07 +00:00
(1, 2)
"""
2013-01-27 07:36:04 +00:00
items = self.service_manager_list.selectedItems()
2012-05-07 16:01:53 +00:00
serviceItem = -1
serviceItemChild = -1
for item in items:
2013-01-21 07:29:43 +00:00
parent_item = item.parent()
if parent_item is None:
2012-05-19 09:13:32 +00:00
serviceItem = item.data(0, QtCore.Qt.UserRole)
else:
2013-01-21 07:29:43 +00:00
serviceItem = parent_item.data(0, QtCore.Qt.UserRole)
2012-05-19 09:13:32 +00:00
serviceItemChild = item.data(0, QtCore.Qt.UserRole)
2012-05-07 08:21:21 +00:00
# Adjust for zero based arrays.
serviceItem -= 1
# Only process the first item on the list for this method.
break
return serviceItem, serviceItemChild
2013-01-27 07:36:04 +00:00
def drop_event(self, event):
"""
Receive drop event and trigger an internal event to get the
plugins to build and push the correct service item
The drag event payload carries the plugin name
``event``
Handle of the event pint passed
"""
link = event.mimeData()
2012-03-12 22:12:16 +00:00
if link.hasUrls():
2011-07-27 18:28:35 +00:00
event.setDropAction(QtCore.Qt.CopyAction)
event.accept()
2012-03-12 22:12:16 +00:00
for url in link.urls():
2013-01-27 07:36:04 +00:00
file_name = url.toLocalFile()
if file_name.endswith(u'.osz'):
self.on_load_service_clicked(file_name)
elif file_name.endswith(u'.oszl'):
2012-09-14 16:35:07 +00:00
# todo correct
2013-01-27 07:36:04 +00:00
self.on_load_service_clicked(file_name)
2012-03-12 22:12:16 +00:00
elif link.hasText():
2012-05-17 18:57:01 +00:00
plugin = link.text()
2013-01-27 07:36:04 +00:00
item = self.service_manager_list.itemAt(event.pos())
2010-09-30 05:12:06 +00:00
# ServiceManager started the drag and drop
2009-10-11 09:31:27 +00:00
if plugin == u'ServiceManager':
2013-01-27 07:36:04 +00:00
startpos, child = self.find_service_item()
2010-11-28 13:41:52 +00:00
# If no items selected
if startpos == -1:
return
2010-02-27 00:11:26 +00:00
if item is None:
2013-01-27 07:36:04 +00:00
endpos = len(self.service_items)
2009-10-11 09:31:27 +00:00
else:
2013-01-21 11:11:47 +00:00
endpos = self._get_parent_item_data(item) - 1
2013-01-27 07:36:04 +00:00
serviceItem = self.service_items[startpos]
self.service_items.remove(serviceItem)
self.service_items.insert(endpos, serviceItem)
2013-01-27 20:36:18 +00:00
self.repaint_service_list(endpos, child)
2013-01-27 07:36:04 +00:00
self.set_modified()
2009-10-11 09:31:27 +00:00
else:
2010-09-30 05:12:06 +00:00
# we are not over anything so drop
2010-05-01 13:05:17 +00:00
replace = False
2010-06-09 17:09:32 +00:00
if item is None:
2013-01-27 07:36:04 +00:00
self.drop_position = len(self.service_items)
2010-03-14 07:56:39 +00:00
else:
# we are over something so lets investigate
2013-01-21 11:11:47 +00:00
pos = self._get_parent_item_data(item) - 1
2013-01-27 07:36:04 +00:00
serviceItem = self.service_items[pos]
2010-05-24 22:37:20 +00:00
if (plugin == serviceItem[u'service_item'].name and
2012-12-10 18:04:58 +00:00
serviceItem[u'service_item'].is_capable(ItemCapabilities.CanAppend)):
2010-05-24 22:37:20 +00:00
action = self.dndMenu.exec_(QtGui.QCursor.pos())
2010-09-30 05:12:06 +00:00
# New action required
2010-05-24 22:37:20 +00:00
if action == self.newAction:
2013-01-27 07:36:04 +00:00
self.drop_position = self._get_parent_item_data(item)
2010-09-30 05:12:06 +00:00
# Append to existing action
2010-05-24 22:37:20 +00:00
if action == self.addToAction:
2013-01-27 07:36:04 +00:00
self.drop_position = self._get_parent_item_data(item)
2010-05-24 22:37:20 +00:00
item.setSelected(True)
replace = True
2010-05-01 13:05:17 +00:00
else:
2013-01-27 07:36:04 +00:00
self.drop_position = self._get_parent_item_data(item)
2010-05-01 13:05:17 +00:00
Receiver.send_message(u'%s_add_service_item' % plugin, replace)
2013-01-27 07:36:04 +00:00
def update_theme_list(self, theme_list):
"""
Called from ThemeManager when the Themes have changed
``theme_list``
A list of current themes to be displayed
"""
2013-01-27 07:36:04 +00:00
self.theme_combo_box.clear()
self.theme_menu.clear()
self.theme_combo_box.addItem(u'')
theme_group = QtGui.QActionGroup(self.theme_menu)
theme_group.setExclusive(True)
theme_group.setObjectName(u'theme_group')
2011-05-27 06:29:14 +00:00
# Create a "Default" theme, which allows the user to reset the item's
# theme to the service theme or global theme.
2013-01-27 07:36:04 +00:00
defaultTheme = create_widget_action(self.theme_menu, text=UiStrings().Default, checked=False,
triggers=self.on_theme_change_action)
self.theme_menu.setDefaultAction(defaultTheme)
theme_group.addAction(defaultTheme)
self.theme_menu.addSeparator()
for theme in theme_list:
2013-01-27 07:36:04 +00:00
self.theme_combo_box.addItem(theme)
theme_group.addAction(create_widget_action(self.theme_menu, theme, text=theme, checked=False,
triggers=self.on_theme_change_action))
find_and_set_in_combo_box(self.theme_combo_box, self.service_theme)
2013-01-22 21:09:43 +00:00
self.renderer.set_service_theme(self.service_theme)
2013-01-27 07:36:04 +00:00
self.regenerate_service_Items()
2013-01-27 07:36:04 +00:00
def on_theme_change_action(self):
2013-01-21 17:22:10 +00:00
"""
Handles theme change events
"""
2012-05-17 18:57:01 +00:00
theme = self.sender().objectName()
2011-05-27 06:29:14 +00:00
# No object name means that the "Default" theme is supposed to be used.
if not theme:
theme = None
2013-01-27 07:36:04 +00:00
item = self.find_service_item()[0]
self.service_items[item][u'service_item'].update_theme(theme)
self.regenerate_service_Items(True)
2013-01-21 11:11:47 +00:00
def _get_parent_item_data(self, item):
2013-01-21 17:22:10 +00:00
"""
Finds and returns the parent item for any item
"""
2013-01-21 07:29:43 +00:00
parent_item = item.parent()
if parent_item is None:
2012-05-19 09:13:32 +00:00
return item.data(0, QtCore.Qt.UserRole)
else:
2013-01-21 07:29:43 +00:00
return parent_item.data(0, QtCore.Qt.UserRole)
2010-05-04 20:01:45 +00:00
2013-01-27 07:36:04 +00:00
def print_service_order(self):
"""
Print a Service Order Sheet.
"""
2013-01-26 07:39:07 +00:00
settingDialog = PrintServiceForm()
2011-04-15 21:55:11 +00:00
settingDialog.exec_()
2013-01-22 21:09:43 +00:00
def _get_renderer(self):
"""
Adds the Renderer to the class dynamically
"""
if not hasattr(self, u'_renderer'):
self._renderer = Registry().get(u'renderer')
return self._renderer
2013-01-22 21:25:16 +00:00
renderer = property(_get_renderer)
def _get_live_controller(self):
"""
Adds the live controller to the class dynamically
"""
if not hasattr(self, u'_live_controller'):
self._live_controller = Registry().get(u'live_controller')
return self._live_controller
live_controller = property(_get_live_controller)
def _get_preview_controller(self):
"""
Adds the preview controller to the class dynamically
"""
if not hasattr(self, u'_preview_controller'):
self._preview_controller = Registry().get(u'preview_controller')
return self._preview_controller
preview_controller = property(_get_preview_controller)
def _get_plugin_manager(self):
"""
Adds the plugin manager to the class dynamically
"""
if not hasattr(self, u'_plugin_manager'):
self._plugin_manager = Registry().get(u'plugin_manager')
return self._plugin_manager
plugin_manager = property(_get_plugin_manager)
def _get_main_window(self):
"""
Adds the main window to the class dynamically
"""
if not hasattr(self, u'_main_window'):
self._main_window = Registry().get(u'main_window')
return self._main_window
main_window = property(_get_main_window)