forked from openlp/openlp
songusage and presentation code standards
This commit is contained in:
parent
0ceaef7a51
commit
dad243dd74
@ -27,6 +27,6 @@
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`presentations` module provides the Presentations plugin which allows
|
||||
OpenLP to show presentations from most popular presentation packages.
|
||||
The :mod:`presentations` module provides the Presentations plugin which allows OpenLP to show presentations from most
|
||||
popular presentation packages.
|
||||
"""
|
||||
|
@ -62,13 +62,14 @@ from openlp.core.lib import ScreenList
|
||||
from openlp.core.utils import delete_file, get_uno_command, get_uno_instance
|
||||
from presentationcontroller import PresentationController, PresentationDocument
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ImpressController(PresentationController):
|
||||
"""
|
||||
Class to control interactions with Impress presentations.
|
||||
It creates the runtime environment, loads and closes the presentation as
|
||||
well as triggering the correct activities based on the users input
|
||||
Class to control interactions with Impress presentations. It creates the runtime environment, loads and closes the
|
||||
presentation as well as triggering the correct activities based on the users input.
|
||||
"""
|
||||
log.info(u'ImpressController loaded')
|
||||
|
||||
@ -79,14 +80,14 @@ class ImpressController(PresentationController):
|
||||
log.debug(u'Initialising')
|
||||
PresentationController.__init__(self, plugin, u'Impress', ImpressDocument)
|
||||
self.supports = [u'odp']
|
||||
self.alsosupports = [u'ppt', u'pps', u'pptx', u'ppsx']
|
||||
self.also_supports = [u'ppt', u'pps', u'pptx', u'ppsx']
|
||||
self.process = None
|
||||
self.desktop = None
|
||||
self.manager = None
|
||||
|
||||
def check_available(self):
|
||||
"""
|
||||
Impress is able to run on this machine
|
||||
Impress is able to run on this machine.
|
||||
"""
|
||||
log.debug(u'check_available')
|
||||
if os.name == u'nt':
|
||||
@ -96,9 +97,8 @@ class ImpressController(PresentationController):
|
||||
|
||||
def start_process(self):
|
||||
"""
|
||||
Loads a running version of OpenOffice in the background.
|
||||
It is not displayed to the user but is available to the UNO interface
|
||||
when required.
|
||||
Loads a running version of OpenOffice in the background. It is not displayed to the user but is available to the
|
||||
UNO interface when required.
|
||||
"""
|
||||
log.debug(u'start process Openoffice')
|
||||
if os.name == u'nt':
|
||||
@ -113,8 +113,7 @@ class ImpressController(PresentationController):
|
||||
|
||||
def get_uno_desktop(self):
|
||||
"""
|
||||
On non-Windows platforms, use Uno. Get the OpenOffice desktop
|
||||
which will be used to manage impress
|
||||
On non-Windows platforms, use Uno. Get the OpenOffice desktop which will be used to manage impress.
|
||||
"""
|
||||
log.debug(u'get UNO Desktop Openoffice')
|
||||
uno_instance = None
|
||||
@ -132,8 +131,7 @@ class ImpressController(PresentationController):
|
||||
loop += 1
|
||||
try:
|
||||
self.manager = uno_instance.ServiceManager
|
||||
log.debug(u'get UNO Desktop Openoffice - createInstanceWithContext'
|
||||
u' - Desktop')
|
||||
log.debug(u'get UNO Desktop Openoffice - createInstanceWithContext - Desktop')
|
||||
desktop = self.manager.createInstanceWithContext("com.sun.star.frame.Desktop", uno_instance)
|
||||
return desktop
|
||||
except:
|
||||
@ -142,8 +140,7 @@ class ImpressController(PresentationController):
|
||||
|
||||
def get_com_desktop(self):
|
||||
"""
|
||||
On Windows platforms, use COM. Return the desktop object which
|
||||
will be used to manage Impress
|
||||
On Windows platforms, use COM. Return the desktop object which will be used to manage Impress.
|
||||
"""
|
||||
log.debug(u'get COM Desktop OpenOffice')
|
||||
if not self.manager:
|
||||
@ -157,7 +154,7 @@ class ImpressController(PresentationController):
|
||||
|
||||
def get_com_servicemanager(self):
|
||||
"""
|
||||
Return the OOo service manager for windows
|
||||
Return the OOo service manager for windows.
|
||||
"""
|
||||
log.debug(u'get_com_servicemanager openoffice')
|
||||
try:
|
||||
@ -168,7 +165,7 @@ class ImpressController(PresentationController):
|
||||
|
||||
def kill(self):
|
||||
"""
|
||||
Called at system exit to clean up any running presentations
|
||||
Called at system exit to clean up any running presentations.
|
||||
"""
|
||||
log.debug(u'Kill OpenOffice')
|
||||
while self.docs:
|
||||
@ -203,12 +200,12 @@ class ImpressController(PresentationController):
|
||||
|
||||
class ImpressDocument(PresentationDocument):
|
||||
"""
|
||||
Class which holds information and controls a single presentation
|
||||
Class which holds information and controls a single presentation.
|
||||
"""
|
||||
|
||||
def __init__(self, controller, presentation):
|
||||
"""
|
||||
Constructor, store information about the file and initialise
|
||||
Constructor, store information about the file and initialise.
|
||||
"""
|
||||
log.debug(u'Init Presentation OpenOffice')
|
||||
PresentationDocument.__init__(self, controller, presentation)
|
||||
@ -218,11 +215,9 @@ class ImpressDocument(PresentationDocument):
|
||||
|
||||
def load_presentation(self):
|
||||
"""
|
||||
Called when a presentation is added to the SlideController.
|
||||
It builds the environment, starts communcations with the background
|
||||
OpenOffice task started earlier. If OpenOffice is not present is is
|
||||
started. Once the environment is available the presentation is loaded
|
||||
and started.
|
||||
Called when a presentation is added to the SlideController. It builds the environment, starts communcations with
|
||||
the background OpenOffice task started earlier. If OpenOffice is not present is is started. Once the environment
|
||||
is available the presentation is loaded and started.
|
||||
"""
|
||||
log.debug(u'Load Presentation OpenOffice')
|
||||
if os.name == u'nt':
|
||||
@ -239,13 +234,12 @@ class ImpressDocument(PresentationDocument):
|
||||
self.desktop = desktop
|
||||
properties = []
|
||||
if os.name != u'nt':
|
||||
# Recent versions of Impress on Windows won't start the presentation
|
||||
# if it starts as minimized. It seems OK on Linux though.
|
||||
# Recent versions of Impress on Windows won't start the presentation if it starts as minimized. It seems OK
|
||||
# on Linux though.
|
||||
properties.append(self.create_property(u'Minimized', True))
|
||||
properties = tuple(properties)
|
||||
try:
|
||||
self.document = desktop.loadComponentFromURL(url, u'_blank',
|
||||
0, properties)
|
||||
self.document = desktop.loadComponentFromURL(url, u'_blank', 0, properties)
|
||||
except:
|
||||
log.warn(u'Failed to load presentation %s' % url)
|
||||
return False
|
||||
@ -262,33 +256,33 @@ class ImpressDocument(PresentationDocument):
|
||||
|
||||
def create_thumbnails(self):
|
||||
"""
|
||||
Create thumbnail images for presentation
|
||||
Create thumbnail images for presentation.
|
||||
"""
|
||||
log.debug(u'create thumbnails OpenOffice')
|
||||
if self.check_thumbnails():
|
||||
return
|
||||
if os.name == u'nt':
|
||||
thumbdirurl = u'file:///' + self.get_temp_folder().replace(u'\\', u'/') \
|
||||
thumb_dir_url = u'file:///' + self.get_temp_folder().replace(u'\\', u'/') \
|
||||
.replace(u':', u'|').replace(u' ', u'%20')
|
||||
else:
|
||||
thumbdirurl = uno.systemPathToFileUrl(self.get_temp_folder())
|
||||
props = []
|
||||
props.append(self.create_property(u'FilterName', u'impress_png_Export'))
|
||||
props = tuple(props)
|
||||
thumb_dir_url = uno.systemPathToFileUrl(self.get_temp_folder())
|
||||
properties = []
|
||||
properties.append(self.create_property(u'FilterName', u'impress_png_Export'))
|
||||
properties = tuple(properties)
|
||||
doc = self.document
|
||||
pages = doc.getDrawPages()
|
||||
if not pages:
|
||||
return
|
||||
if not os.path.isdir(self.get_temp_folder()):
|
||||
os.makedirs(self.get_temp_folder())
|
||||
for idx in range(pages.getCount()):
|
||||
page = pages.getByIndex(idx)
|
||||
for index in range(pages.getCount()):
|
||||
page = pages.getByIndex(index)
|
||||
doc.getCurrentController().setCurrentPage(page)
|
||||
urlpath = u'%s/%s.png' % (thumbdirurl, unicode(idx + 1))
|
||||
path = os.path.join(self.get_temp_folder(), unicode(idx + 1) + u'.png')
|
||||
url_path = u'%s/%s.png' % (thumb_dir_url, unicode(index + 1))
|
||||
path = os.path.join(self.get_temp_folder(), unicode(index + 1) + u'.png')
|
||||
try:
|
||||
doc.storeToURL(urlpath, props)
|
||||
self.convert_thumbnail(path, idx + 1)
|
||||
doc.storeToURL(url_path, properties)
|
||||
self.convert_thumbnail(path, index + 1)
|
||||
delete_file(path)
|
||||
except ErrorCodeIOException, exception:
|
||||
log.exception(u'ERROR! ErrorCodeIOException %d' % exception.ErrCode)
|
||||
@ -297,23 +291,21 @@ class ImpressDocument(PresentationDocument):
|
||||
|
||||
def create_property(self, name, value):
|
||||
"""
|
||||
Create an OOo style property object which are passed into some
|
||||
Uno methods
|
||||
Create an OOo style property object which are passed into some Uno methods.
|
||||
"""
|
||||
log.debug(u'create property OpenOffice')
|
||||
if os.name == u'nt':
|
||||
prop = self.controller.manager.Bridge_GetStruct(u'com.sun.star.beans.PropertyValue')
|
||||
property = self.controller.manager.Bridge_GetStruct(u'com.sun.star.beans.PropertyValue')
|
||||
else:
|
||||
prop = PropertyValue()
|
||||
prop.Name = name
|
||||
prop.Value = value
|
||||
return prop
|
||||
property = PropertyValue()
|
||||
property.Name = name
|
||||
property.Value = value
|
||||
return property
|
||||
|
||||
def close_presentation(self):
|
||||
"""
|
||||
Close presentation and clean up objects
|
||||
Triggered by new object being added to SlideController or OpenLP
|
||||
being shutdown
|
||||
Close presentation and clean up objects. Triggered by new object being added to SlideController or OpenLP being
|
||||
shutdown.
|
||||
"""
|
||||
log.debug(u'close Presentation OpenOffice')
|
||||
if self.document:
|
||||
@ -329,7 +321,7 @@ class ImpressDocument(PresentationDocument):
|
||||
|
||||
def is_loaded(self):
|
||||
"""
|
||||
Returns true if a presentation is loaded
|
||||
Returns true if a presentation is loaded.
|
||||
"""
|
||||
log.debug(u'is loaded OpenOffice')
|
||||
if self.presentation is None or self.document is None:
|
||||
@ -346,7 +338,7 @@ class ImpressDocument(PresentationDocument):
|
||||
|
||||
def is_active(self):
|
||||
"""
|
||||
Returns true if a presentation is active and running
|
||||
Returns true if a presentation is active and running.
|
||||
"""
|
||||
log.debug(u'is active OpenOffice')
|
||||
if not self.is_loaded():
|
||||
@ -355,21 +347,21 @@ class ImpressDocument(PresentationDocument):
|
||||
|
||||
def unblank_screen(self):
|
||||
"""
|
||||
Unblanks the screen
|
||||
Unblanks the screen.
|
||||
"""
|
||||
log.debug(u'unblank screen OpenOffice')
|
||||
return self.control.resume()
|
||||
|
||||
def blank_screen(self):
|
||||
"""
|
||||
Blanks the screen
|
||||
Blanks the screen.
|
||||
"""
|
||||
log.debug(u'blank screen OpenOffice')
|
||||
self.control.blankScreen(0)
|
||||
|
||||
def is_blank(self):
|
||||
"""
|
||||
Returns true if screen is blank
|
||||
Returns true if screen is blank.
|
||||
"""
|
||||
log.debug(u'is blank OpenOffice')
|
||||
if self.control and self.control.isRunning():
|
||||
@ -379,7 +371,7 @@ class ImpressDocument(PresentationDocument):
|
||||
|
||||
def stop_presentation(self):
|
||||
"""
|
||||
Stop the presentation, remove from screen
|
||||
Stop the presentation, remove from screen.
|
||||
"""
|
||||
log.debug(u'stop presentation OpenOffice')
|
||||
# deactivate should hide the screen according to docs, but doesn't
|
||||
@ -389,18 +381,17 @@ class ImpressDocument(PresentationDocument):
|
||||
|
||||
def start_presentation(self):
|
||||
"""
|
||||
Start the presentation from the beginning
|
||||
Start the presentation from the beginning.
|
||||
"""
|
||||
log.debug(u'start presentation OpenOffice')
|
||||
if self.control is None or not self.control.isRunning():
|
||||
self.presentation.start()
|
||||
self.control = self.presentation.getController()
|
||||
# start() returns before the Component is ready.
|
||||
# Try for 15 seconds
|
||||
i = 1
|
||||
while not self.control and i < 150:
|
||||
# start() returns before the Component is ready. Try for 15 seconds.
|
||||
sleep_count = 1
|
||||
while not self.control and sleep_count < 150:
|
||||
time.sleep(0.1)
|
||||
i += 1
|
||||
sleep_count += 1
|
||||
self.control = self.presentation.getController()
|
||||
else:
|
||||
self.control.activate()
|
||||
@ -408,25 +399,25 @@ class ImpressDocument(PresentationDocument):
|
||||
|
||||
def get_slide_number(self):
|
||||
"""
|
||||
Return the current slide number on the screen, from 1
|
||||
Return the current slide number on the screen, from 1.
|
||||
"""
|
||||
return self.control.getCurrentSlideIndex() + 1
|
||||
|
||||
def get_slide_count(self):
|
||||
"""
|
||||
Return the total number of slides
|
||||
Return the total number of slides.
|
||||
"""
|
||||
return self.document.getDrawPages().getCount()
|
||||
|
||||
def goto_slide(self, slideno):
|
||||
"""
|
||||
Go to a specific slide (from 1)
|
||||
Go to a specific slide (from 1).
|
||||
"""
|
||||
self.control.gotoSlideIndex(slideno-1)
|
||||
|
||||
def next_step(self):
|
||||
"""
|
||||
Triggers the next effect of slide on the running presentation
|
||||
Triggers the next effect of slide on the running presentation.
|
||||
"""
|
||||
is_paused = self.control.isPaused()
|
||||
self.control.gotoNextEffect()
|
||||
@ -436,7 +427,7 @@ class ImpressDocument(PresentationDocument):
|
||||
|
||||
def previous_step(self):
|
||||
"""
|
||||
Triggers the previous slide on the running presentation
|
||||
Triggers the previous slide on the running presentation.
|
||||
"""
|
||||
self.control.gotoPreviousSlide()
|
||||
|
||||
@ -470,8 +461,8 @@ class ImpressDocument(PresentationDocument):
|
||||
page = pages.getByIndex(slide_no - 1)
|
||||
if notes:
|
||||
page = page.getNotesPage()
|
||||
for idx in range(page.getCount()):
|
||||
shape = page.getByIndex(idx)
|
||||
for index in range(page.getCount()):
|
||||
shape = page.getByIndex(index)
|
||||
if shape.supportsService("com.sun.star.drawing.Text"):
|
||||
text += shape.getString() + '\n'
|
||||
return text
|
||||
|
@ -38,14 +38,17 @@ from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adj
|
||||
from openlp.core.utils import get_locale_key
|
||||
from openlp.plugins.presentations.lib import MessageListener
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
ERROR = QtGui.QImage(u':/general/general_delete.png')
|
||||
|
||||
ERROR_IMAGE = 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
|
||||
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')
|
||||
|
||||
@ -71,25 +74,25 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
"""
|
||||
self.on_new_prompt = translate('PresentationPlugin.MediaItem', 'Select Presentation(s)')
|
||||
self.Automatic = translate('PresentationPlugin.MediaItem', 'Automatic')
|
||||
self.displayTypeLabel.setText(translate('PresentationPlugin.MediaItem', 'Present using:'))
|
||||
self.display_type_label.setText(translate('PresentationPlugin.MediaItem', 'Present using:'))
|
||||
|
||||
def build_file_mask_string(self):
|
||||
"""
|
||||
Build the list of file extensions to be used in the Open file dialog
|
||||
Build the list of file extensions to be used in the Open file dialog.
|
||||
"""
|
||||
fileType = u''
|
||||
file_type = 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.service_manager.supported_suffixes(type)
|
||||
self.on_new_file_masks = translate('PresentationPlugin.MediaItem', 'Presentations (%s)') % fileType
|
||||
file_types = self.controllers[controller].supports + self.controllers[controller].also_supports
|
||||
for file_type in file_types:
|
||||
if file_type.find(file_type) == -1:
|
||||
file_type += u'*.%s ' % file_type
|
||||
self.service_manager.supported_suffixes(file_type)
|
||||
self.on_new_file_masks = translate('PresentationPlugin.MediaItem', 'Presentations (%s)') % file_type
|
||||
|
||||
def required_icons(self):
|
||||
"""
|
||||
Set which icons the media manager tab should show
|
||||
Set which icons the media manager tab should show.
|
||||
"""
|
||||
MediaManagerItem.required_icons(self)
|
||||
self.has_file_icon = True
|
||||
@ -98,21 +101,21 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
|
||||
def add_end_header_bar(self):
|
||||
"""
|
||||
Display custom media manager items for presentations
|
||||
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,
|
||||
self.presentation_widget = QtGui.QWidget(self)
|
||||
self.presentation_widget.setObjectName(u'presentation_widget')
|
||||
self.display_layout = QtGui.QFormLayout(self.presentation_widget)
|
||||
self.display_layout.setMargin(self.display_layout.spacing())
|
||||
self.display_layout.setObjectName(u'display_layout')
|
||||
self.display_type_label = QtGui.QLabel(self.presentation_widget)
|
||||
self.display_type_label.setObjectName(u'display_type_label')
|
||||
self.displayTypeComboBox = create_horizontal_adjusting_combo_box(self.presentation_widget,
|
||||
u'displayTypeComboBox')
|
||||
self.displayTypeLabel.setBuddy(self.displayTypeComboBox)
|
||||
self.displayLayout.addRow(self.displayTypeLabel, self.displayTypeComboBox)
|
||||
self.display_type_label.setBuddy(self.displayTypeComboBox)
|
||||
self.display_layout.addRow(self.display_type_label, self.displayTypeComboBox)
|
||||
# Add the Presentation widget to the page layout
|
||||
self.page_layout.addWidget(self.presentationWidget)
|
||||
self.page_layout.addWidget(self.presentation_widget)
|
||||
|
||||
def initialise(self):
|
||||
"""
|
||||
@ -120,13 +123,13 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
"""
|
||||
self.list_view.setIconSize(QtCore.QSize(88, 50))
|
||||
files = Settings().value(self.settings_section + u'/presentations files')
|
||||
self.load_list(files, initialLoad=True)
|
||||
self.load_list(files, initial_load=True)
|
||||
self.populate_display_types()
|
||||
|
||||
def populate_display_types(self):
|
||||
"""
|
||||
Load the combobox with the enabled presentation controllers,
|
||||
allowing user to select a specific app if settings allow
|
||||
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:
|
||||
@ -137,38 +140,37 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
self.displayTypeComboBox.insertItem(0, self.Automatic)
|
||||
self.displayTypeComboBox.setCurrentIndex(0)
|
||||
if Settings().value(self.settings_section + u'/override app') == QtCore.Qt.Checked:
|
||||
self.presentationWidget.show()
|
||||
self.presentation_widget.show()
|
||||
else:
|
||||
self.presentationWidget.hide()
|
||||
self.presentation_widget.hide()
|
||||
|
||||
def load_list(self, files, target_group=None, initialLoad=False):
|
||||
def load_list(self, files, target_group=None, initial_load=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
|
||||
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.get_file_list()
|
||||
titles = [os.path.split(file)[1] for file in currlist]
|
||||
current_list = self.get_file_list()
|
||||
titles = [os.path.split(file)[1] for file in current_list]
|
||||
self.application.set_busy_cursor()
|
||||
if not initialLoad:
|
||||
if not initial_load:
|
||||
self.main_window.display_progress_bar(len(files))
|
||||
# Sort the presentations by its filename considering language specific characters.
|
||||
files.sort(key=lambda filename: get_locale_key(os.path.split(unicode(filename))[1]))
|
||||
for file in files:
|
||||
if not initialLoad:
|
||||
if not initial_load:
|
||||
self.main_window.increment_progress_bar()
|
||||
if currlist.count(file) > 0:
|
||||
if current_list.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.setIcon(build_icon(ERROR_IMAGE))
|
||||
item_name.setData(QtCore.Qt.UserRole, file)
|
||||
item_name.setToolTip(file)
|
||||
self.list_view.addItem(item_name)
|
||||
else:
|
||||
if titles.count(filename) > 0:
|
||||
if not initialLoad:
|
||||
if not initial_load:
|
||||
critical_error_message_box(translate('PresentationPlugin.MediaItem', 'File Exists'),
|
||||
translate('PresentationPlugin.MediaItem',
|
||||
'A presentation with that filename already exists.')
|
||||
@ -180,7 +182,7 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
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:
|
||||
if not preview and not initial_load:
|
||||
doc.load_presentation()
|
||||
preview = doc.get_thumbnail_path(1, True)
|
||||
doc.close_presentation()
|
||||
@ -192,7 +194,7 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
else:
|
||||
icon = create_thumb(preview, thumb)
|
||||
else:
|
||||
if initialLoad:
|
||||
if initial_load:
|
||||
icon = build_icon(u':/general/general_delete.png')
|
||||
else:
|
||||
critical_error_message_box(UiStrings().UnsupportedFile,
|
||||
@ -203,13 +205,13 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
item_name.setIcon(icon)
|
||||
item_name.setToolTip(file)
|
||||
self.list_view.addItem(item_name)
|
||||
if not initialLoad:
|
||||
if not initial_load:
|
||||
self.main_window.finished_progress_bar()
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def on_delete_click(self):
|
||||
"""
|
||||
Remove a presentation item from the list
|
||||
Remove a presentation item from the list.
|
||||
"""
|
||||
if check_item_selected(self.list_view, UiStrings().SelectDelete):
|
||||
items = self.list_view.selectedIndexes()
|
||||
@ -230,12 +232,11 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
self.list_view.takeItem(row)
|
||||
Settings().setValue(self.settings_section + u'/presentations files', self.get_file_list())
|
||||
|
||||
def generate_slide_data(self, service_item, item=None, xmlVersion=False,
|
||||
def generate_slide_data(self, service_item, item=None, xml_version=False,
|
||||
remote=False, context=ServiceItemContext.Service):
|
||||
"""
|
||||
Load the relevant information for displaying the presentation
|
||||
in the slidecontroller. In the case of powerpoints, an image
|
||||
for each slide
|
||||
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]
|
||||
@ -287,26 +288,24 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
|
||||
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.
|
||||
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:
|
||||
file_type = os.path.splitext(filename)[1][1:]
|
||||
if not file_type:
|
||||
return None
|
||||
for controller in self.controllers:
|
||||
if self.controllers[controller].enabled():
|
||||
if filetype in self.controllers[controller].supports:
|
||||
if file_type in self.controllers[controller].supports:
|
||||
return controller
|
||||
for controller in self.controllers:
|
||||
if self.controllers[controller].enabled():
|
||||
if filetype in self.controllers[controller].alsosupports:
|
||||
if file_type in self.controllers[controller].also_supports:
|
||||
return controller
|
||||
return None
|
||||
|
||||
def search(self, string, showError):
|
||||
def search(self, string, show_error):
|
||||
files = Settings().value(self.settings_section + u'/presentations files')
|
||||
results = []
|
||||
string = string.lower()
|
||||
|
@ -38,8 +38,8 @@ log = logging.getLogger(__name__)
|
||||
|
||||
class Controller(object):
|
||||
"""
|
||||
This is the Presentation listener who acts on events from the slide
|
||||
controller and passes the messages on the the correct presentation handlers
|
||||
This is the Presentation listener who acts on events from the slide controller and passes the messages on the the
|
||||
correct presentation handlers.
|
||||
"""
|
||||
log.info(u'Controller loaded')
|
||||
|
||||
@ -54,9 +54,8 @@ class Controller(object):
|
||||
|
||||
def add_handler(self, controller, file, hide_mode, slide_no):
|
||||
"""
|
||||
Add a handler, which is an instance of a presentation and
|
||||
slidecontroller combination. If the slidecontroller has a display
|
||||
then load the presentation.
|
||||
Add a handler, which is an instance of a presentation and slidecontroller combination. If the slidecontroller
|
||||
has a display then load the presentation.
|
||||
"""
|
||||
log.debug(u'Live = %s, add_handler %s' % (self.is_live, file))
|
||||
self.controller = controller
|
||||
@ -86,8 +85,7 @@ class Controller(object):
|
||||
|
||||
def activate(self):
|
||||
"""
|
||||
Active the presentation, and show it on the screen.
|
||||
Use the last slide number.
|
||||
Active the presentation, and show it on the screen. Use the last slide number.
|
||||
"""
|
||||
log.debug(u'Live = %s, activate' % self.is_live)
|
||||
if not self.doc:
|
||||
@ -130,7 +128,7 @@ class Controller(object):
|
||||
|
||||
def first(self):
|
||||
"""
|
||||
Based on the handler passed at startup triggers the first slide
|
||||
Based on the handler passed at startup triggers the first slide.
|
||||
"""
|
||||
log.debug(u'Live = %s, first' % self.is_live)
|
||||
if not self.doc:
|
||||
@ -148,7 +146,7 @@ class Controller(object):
|
||||
|
||||
def last(self):
|
||||
"""
|
||||
Based on the handler passed at startup triggers the last slide
|
||||
Based on the handler passed at startup triggers the last slide.
|
||||
"""
|
||||
log.debug(u'Live = %s, last' % self.is_live)
|
||||
if not self.doc:
|
||||
@ -166,7 +164,7 @@ class Controller(object):
|
||||
|
||||
def next(self):
|
||||
"""
|
||||
Based on the handler passed at startup triggers the next slide event
|
||||
Based on the handler passed at startup triggers the next slide event.
|
||||
"""
|
||||
log.debug(u'Live = %s, next' % self.is_live)
|
||||
if not self.doc:
|
||||
@ -182,9 +180,8 @@ class Controller(object):
|
||||
return
|
||||
if not self.activate():
|
||||
return
|
||||
# The "End of slideshow" screen is after the last slide
|
||||
# Note, we can't just stop on the last slide, since it may
|
||||
# contain animations that need to be stepped through.
|
||||
# The "End of slideshow" screen is after the last slide. Note, we can't just stop on the last slide, since it
|
||||
# may contain animations that need to be stepped through.
|
||||
if self.doc.slidenumber > self.doc.get_slide_count():
|
||||
return
|
||||
self.doc.next_step()
|
||||
@ -192,7 +189,7 @@ class Controller(object):
|
||||
|
||||
def previous(self):
|
||||
"""
|
||||
Based on the handler passed at startup triggers the previous slide event
|
||||
Based on the handler passed at startup triggers the previous slide event.
|
||||
"""
|
||||
log.debug(u'Live = %s, previous' % self.is_live)
|
||||
if not self.doc:
|
||||
@ -213,7 +210,7 @@ class Controller(object):
|
||||
|
||||
def shutdown(self):
|
||||
"""
|
||||
Based on the handler passed at startup triggers slide show to shut down
|
||||
Based on the handler passed at startup triggers slide show to shut down.
|
||||
"""
|
||||
log.debug(u'Live = %s, shutdown' % self.is_live)
|
||||
if not self.doc:
|
||||
@ -223,7 +220,7 @@ class Controller(object):
|
||||
|
||||
def blank(self, hide_mode):
|
||||
"""
|
||||
Instruct the controller to blank the presentation
|
||||
Instruct the controller to blank the presentation.
|
||||
"""
|
||||
log.debug(u'Live = %s, blank' % self.is_live)
|
||||
self.hide_mode = hide_mode
|
||||
@ -244,7 +241,7 @@ class Controller(object):
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Instruct the controller to stop and hide the presentation
|
||||
Instruct the controller to stop and hide the presentation.
|
||||
"""
|
||||
log.debug(u'Live = %s, stop' % self.is_live)
|
||||
self.hide_mode = HideMode.Screen
|
||||
@ -260,7 +257,7 @@ class Controller(object):
|
||||
|
||||
def unblank(self):
|
||||
"""
|
||||
Instruct the controller to unblank the presentation
|
||||
Instruct the controller to unblank the presentation.
|
||||
"""
|
||||
log.debug(u'Live = %s, unblank' % self.is_live)
|
||||
self.hide_mode = None
|
||||
@ -283,8 +280,8 @@ class Controller(object):
|
||||
|
||||
class MessageListener(object):
|
||||
"""
|
||||
This is the Presentation listener who acts on events from the slide
|
||||
controller and passes the messages on the the correct presentation handlers
|
||||
This is the Presentation listener who acts on events from the slide controller and passes the messages on the the
|
||||
correct presentation handlers
|
||||
"""
|
||||
log.info(u'Message Listener loaded')
|
||||
|
||||
@ -310,12 +307,11 @@ class MessageListener(object):
|
||||
|
||||
def startup(self, message):
|
||||
"""
|
||||
Start of new presentation
|
||||
Save the handler as any new presentations start here
|
||||
Start of new presentation. Save the handler as any new presentations start here
|
||||
"""
|
||||
log.debug(u'Startup called with message %s' % message)
|
||||
is_live = message[1]
|
||||
item = message[0]
|
||||
log.debug(u'Startup called with message %s' % message)
|
||||
hide_mode = message[2]
|
||||
file = item.get_frame_path()
|
||||
self.handler = item.title
|
||||
@ -331,7 +327,7 @@ class MessageListener(object):
|
||||
|
||||
def slide(self, message):
|
||||
"""
|
||||
React to the message to move to a specific slide
|
||||
React to the message to move to a specific slide.
|
||||
"""
|
||||
is_live = message[1]
|
||||
slide = message[2]
|
||||
@ -342,7 +338,7 @@ class MessageListener(object):
|
||||
|
||||
def first(self, message):
|
||||
"""
|
||||
React to the message to move to the first slide
|
||||
React to the message to move to the first slide.
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
@ -352,7 +348,7 @@ class MessageListener(object):
|
||||
|
||||
def last(self, message):
|
||||
"""
|
||||
React to the message to move to the last slide
|
||||
React to the message to move to the last slide.
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
@ -362,7 +358,7 @@ class MessageListener(object):
|
||||
|
||||
def next(self, message):
|
||||
"""
|
||||
React to the message to move to the next animation/slide
|
||||
React to the message to move to the next animation/slide.
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
@ -372,7 +368,7 @@ class MessageListener(object):
|
||||
|
||||
def previous(self, message):
|
||||
"""
|
||||
React to the message to move to the previous animation/slide
|
||||
React to the message to move to the previous animation/slide.
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
@ -382,8 +378,7 @@ class MessageListener(object):
|
||||
|
||||
def shutdown(self, message):
|
||||
"""
|
||||
React to message to shutdown the presentation. I.e. end the show
|
||||
and close the file
|
||||
React to message to shutdown the presentation. I.e. end the show and close the file.
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
@ -393,7 +388,7 @@ class MessageListener(object):
|
||||
|
||||
def hide(self, message):
|
||||
"""
|
||||
React to the message to show the desktop
|
||||
React to the message to show the desktop.
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
@ -401,7 +396,7 @@ class MessageListener(object):
|
||||
|
||||
def blank(self, message):
|
||||
"""
|
||||
React to the message to blank the display
|
||||
React to the message to blank the display.
|
||||
"""
|
||||
is_live = message[1]
|
||||
hide_mode = message[2]
|
||||
@ -410,7 +405,7 @@ class MessageListener(object):
|
||||
|
||||
def unblank(self, message):
|
||||
"""
|
||||
React to the message to unblank the display
|
||||
React to the message to unblank the display.
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
@ -418,9 +413,7 @@ class MessageListener(object):
|
||||
|
||||
def timeout(self):
|
||||
"""
|
||||
The presentation may be timed or might be controlled by the
|
||||
application directly, rather than through OpenLP. Poll occasionally
|
||||
to check which slide is currently displayed so the slidecontroller
|
||||
view can be updated
|
||||
The presentation may be timed or might be controlled by the application directly, rather than through OpenLP.
|
||||
Poll occasionally to check which slide is currently displayed so the slidecontroller view can be updated.
|
||||
"""
|
||||
self.live_handler.poll()
|
||||
|
@ -26,7 +26,10 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
This modul is for controlling powerpiont. PPT API documentation:
|
||||
`http://msdn.microsoft.com/en-us/library/aa269321(office.10).aspx`_
|
||||
"""
|
||||
import os
|
||||
import logging
|
||||
|
||||
@ -39,16 +42,14 @@ if os.name == u'nt':
|
||||
from openlp.core.lib import ScreenList
|
||||
from presentationcontroller import PresentationController, PresentationDocument
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# PPT API documentation:
|
||||
# http://msdn.microsoft.com/en-us/library/aa269321(office.10).aspx
|
||||
|
||||
class PowerpointController(PresentationController):
|
||||
"""
|
||||
Class to control interactions with PowerPoint Presentations
|
||||
It creates the runtime Environment , Loads the and Closes the Presentation
|
||||
As well as triggering the correct activities based on the users input
|
||||
Class to control interactions with PowerPoint Presentations. It creates the runtime Environment , Loads the and
|
||||
Closes the Presentation. As well as triggering the correct activities based on the users input.
|
||||
"""
|
||||
log.info(u'PowerpointController loaded')
|
||||
|
||||
@ -63,7 +64,7 @@ class PowerpointController(PresentationController):
|
||||
|
||||
def check_available(self):
|
||||
"""
|
||||
PowerPoint is able to run on this machine
|
||||
PowerPoint is able to run on this machine.
|
||||
"""
|
||||
log.debug(u'check_available')
|
||||
if os.name == u'nt':
|
||||
@ -77,7 +78,7 @@ class PowerpointController(PresentationController):
|
||||
if os.name == u'nt':
|
||||
def start_process(self):
|
||||
"""
|
||||
Loads PowerPoint process
|
||||
Loads PowerPoint process.
|
||||
"""
|
||||
log.debug(u'start_process')
|
||||
if not self.process:
|
||||
@ -87,7 +88,7 @@ class PowerpointController(PresentationController):
|
||||
|
||||
def kill(self):
|
||||
"""
|
||||
Called at system exit to clean up any running presentations
|
||||
Called at system exit to clean up any running presentations.
|
||||
"""
|
||||
log.debug(u'Kill powerpoint')
|
||||
while self.docs:
|
||||
@ -105,12 +106,12 @@ class PowerpointController(PresentationController):
|
||||
|
||||
class PowerpointDocument(PresentationDocument):
|
||||
"""
|
||||
Class which holds information and controls a single presentation
|
||||
Class which holds information and controls a single presentation.
|
||||
"""
|
||||
|
||||
def __init__(self, controller, presentation):
|
||||
"""
|
||||
Constructor, store information about the file and initialise
|
||||
Constructor, store information about the file and initialise.
|
||||
"""
|
||||
log.debug(u'Init Presentation Powerpoint')
|
||||
PresentationDocument.__init__(self, controller, presentation)
|
||||
@ -118,8 +119,8 @@ class PowerpointDocument(PresentationDocument):
|
||||
|
||||
def load_presentation(self):
|
||||
"""
|
||||
Called when a presentation is added to the SlideController.
|
||||
Opens the PowerPoint file using the process created earlier.
|
||||
Called when a presentation is added to the SlideController. Opens the PowerPoint file using the process created
|
||||
earlier.
|
||||
"""
|
||||
log.debug(u'load_presentation')
|
||||
if not self.controller.process or not self.controller.process.Visible:
|
||||
@ -142,20 +143,19 @@ class PowerpointDocument(PresentationDocument):
|
||||
self.presentation.Slides[n].Copy()
|
||||
thumbnail = QApplication.clipboard.image()
|
||||
|
||||
However, for the moment, we want a physical file since it makes life
|
||||
easier elsewhere.
|
||||
However, for the moment, we want a physical file since it makes life easier elsewhere.
|
||||
"""
|
||||
log.debug(u'create_thumbnails')
|
||||
if self.check_thumbnails():
|
||||
return
|
||||
for num in range(self.presentation.Slides.Count):
|
||||
self.presentation.Slides(num + 1).Export(os.path.join(
|
||||
self.get_thumbnail_folder(), 'slide%d.png' % (num + 1)), 'png', 320, 240)
|
||||
self.presentation.Slides(num + 1).Export(
|
||||
os.path.join(self.get_thumbnail_folder(), 'slide%d.png' % (num + 1)), 'png', 320, 240)
|
||||
|
||||
def close_presentation(self):
|
||||
"""
|
||||
Close presentation and clean up objects. This is triggered by a new
|
||||
object being added to SlideController or OpenLP being shut down.
|
||||
Close presentation and clean up objects. This is triggered by a new object being added to SlideController or
|
||||
OpenLP being shut down.
|
||||
"""
|
||||
log.debug(u'ClosePresentation')
|
||||
if self.presentation:
|
||||
@ -182,7 +182,6 @@ class PowerpointDocument(PresentationDocument):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def is_active(self):
|
||||
"""
|
||||
Returns ``True`` if a presentation is currently active.
|
||||
@ -253,15 +252,14 @@ class PowerpointDocument(PresentationDocument):
|
||||
dpi = win32ui.GetForegroundWindow().GetDC().GetDeviceCaps(88)
|
||||
except win32ui.error:
|
||||
dpi = 96
|
||||
rect = ScreenList().current[u'size']
|
||||
size = ScreenList().current[u'size']
|
||||
ppt_window = self.presentation.SlideShowSettings.Run()
|
||||
if not ppt_window:
|
||||
return
|
||||
ppt_window.Top = rect.y() * 72 / dpi
|
||||
ppt_window.Height = rect.height() * 72 / dpi
|
||||
ppt_window.Left = rect.x() * 72 / dpi
|
||||
ppt_window.Width = rect.width() * 72 / dpi
|
||||
|
||||
ppt_window.Top = size.y() * 72 / dpi
|
||||
ppt_window.Height = size.height() * 72 / dpi
|
||||
ppt_window.Left = size.x() * 72 / dpi
|
||||
ppt_window.Width = size.width() * 72 / dpi
|
||||
|
||||
def get_slide_number(self):
|
||||
"""
|
||||
@ -318,6 +316,7 @@ class PowerpointDocument(PresentationDocument):
|
||||
"""
|
||||
return _get_text_from_shapes(self.presentation.Slides(slide_no).NotesPage.Shapes)
|
||||
|
||||
|
||||
def _get_text_from_shapes(shapes):
|
||||
"""
|
||||
Returns any text extracted from the shapes on a presentation slide.
|
||||
@ -326,8 +325,8 @@ def _get_text_from_shapes(shapes):
|
||||
A set of shapes to search for text.
|
||||
"""
|
||||
text = ''
|
||||
for idx in range(shapes.Count):
|
||||
shape = shapes(idx + 1)
|
||||
for index in range(shapes.Count):
|
||||
shape = shapes(index + 1)
|
||||
if shape.HasTextFrame:
|
||||
text += shape.TextFrame.TextRange.Text + '\n'
|
||||
return text
|
||||
|
@ -37,13 +37,14 @@ if os.name == u'nt':
|
||||
from openlp.core.lib import ScreenList
|
||||
from presentationcontroller import PresentationController, PresentationDocument
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PptviewController(PresentationController):
|
||||
"""
|
||||
Class to control interactions with PowerPoint Viewer Presentations
|
||||
It creates the runtime Environment , Loads the and Closes the Presentation
|
||||
As well as triggering the correct activities based on the users input
|
||||
Class to control interactions with PowerPoint Viewer Presentations. It creates the runtime Environment , Loads the
|
||||
and Closes the Presentation. As well as triggering the correct activities based on the users input
|
||||
"""
|
||||
log.info(u'PPTViewController loaded')
|
||||
|
||||
@ -58,7 +59,7 @@ class PptviewController(PresentationController):
|
||||
|
||||
def check_available(self):
|
||||
"""
|
||||
PPT Viewer is able to run on this machine
|
||||
PPT Viewer is able to run on this machine.
|
||||
"""
|
||||
log.debug(u'check_available')
|
||||
if os.name != u'nt':
|
||||
@ -68,7 +69,7 @@ class PptviewController(PresentationController):
|
||||
if os.name == u'nt':
|
||||
def check_installed(self):
|
||||
"""
|
||||
Check the viewer is installed
|
||||
Check the viewer is installed.
|
||||
"""
|
||||
log.debug(u'Check installed')
|
||||
try:
|
||||
@ -79,14 +80,14 @@ class PptviewController(PresentationController):
|
||||
|
||||
def start_process(self):
|
||||
"""
|
||||
Loads the PPTVIEWLIB library
|
||||
Loads the PPTVIEWLIB library.
|
||||
"""
|
||||
if self.process:
|
||||
return
|
||||
log.debug(u'start PPTView')
|
||||
dllpath = os.path.join(self.plugin_manager.base_path, u'presentations', u'lib', u'pptviewlib',
|
||||
u'pptviewlib.dll')
|
||||
self.process = cdll.LoadLibrary(dllpath)
|
||||
dll_path = os.path.join(
|
||||
self.plugin_manager.base_path, u'presentations', u'lib', u'pptviewlib', u'pptviewlib.dll')
|
||||
self.process = cdll.LoadLibrary(dll_path)
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
self.process.SetDebug(1)
|
||||
|
||||
@ -101,33 +102,32 @@ class PptviewController(PresentationController):
|
||||
|
||||
class PptviewDocument(PresentationDocument):
|
||||
"""
|
||||
Class which holds information and controls a single presentation
|
||||
Class which holds information and controls a single presentation.
|
||||
"""
|
||||
def __init__(self, controller, presentation):
|
||||
"""
|
||||
Constructor, store information about the file and initialise
|
||||
Constructor, store information about the file and initialise.
|
||||
"""
|
||||
log.debug(u'Init Presentation PowerPoint')
|
||||
PresentationDocument.__init__(self, controller, presentation)
|
||||
self.presentation = None
|
||||
self.pptid = None
|
||||
self.ppt_id = None
|
||||
self.blanked = False
|
||||
self.hidden = False
|
||||
|
||||
def load_presentation(self):
|
||||
"""
|
||||
Called when a presentation is added to the SlideController.
|
||||
It builds the environment, starts communication with the background
|
||||
PptView task started earlier.
|
||||
Called when a presentation is added to the SlideController. It builds the environment, starts communication with
|
||||
the background PptView task started earlier.
|
||||
"""
|
||||
log.debug(u'LoadPresentation')
|
||||
rect = ScreenList().current[u'size']
|
||||
rect = RECT(rect.x(), rect.y(), rect.right(), rect.bottom())
|
||||
size = ScreenList().current[u'size']
|
||||
rect = RECT(size.x(), size.y(), size.right(), size.bottom())
|
||||
filepath = str(self.filepath.replace(u'/', u'\\'))
|
||||
if not os.path.isdir(self.get_temp_folder()):
|
||||
os.makedirs(self.get_temp_folder())
|
||||
self.pptid = self.controller.process.OpenPPT(filepath, None, rect, str(self.get_temp_folder()) + '\\slide')
|
||||
if self.pptid >= 0:
|
||||
self.ppt_id = self.controller.process.OpenPPT(filepath, None, rect, str(self.get_temp_folder()) + '\\slide')
|
||||
if self.ppt_id >= 0:
|
||||
self.create_thumbnails()
|
||||
self.stop_presentation()
|
||||
return True
|
||||
@ -136,8 +136,7 @@ class PptviewDocument(PresentationDocument):
|
||||
|
||||
def create_thumbnails(self):
|
||||
"""
|
||||
PPTviewLib creates large BMP's, but we want small PNG's for consistency.
|
||||
Convert them here.
|
||||
PPTviewLib creates large BMP's, but we want small PNG's for consistency. Convert them here.
|
||||
"""
|
||||
log.debug(u'create_thumbnails')
|
||||
if self.check_thumbnails():
|
||||
@ -149,21 +148,20 @@ class PptviewDocument(PresentationDocument):
|
||||
|
||||
def close_presentation(self):
|
||||
"""
|
||||
Close presentation and clean up objects
|
||||
Triggered by new object being added to SlideController orOpenLP
|
||||
being shut down
|
||||
Close presentation and clean up objects. Triggered by new object being added to SlideController or OpenLP being
|
||||
shut down.
|
||||
"""
|
||||
log.debug(u'ClosePresentation')
|
||||
if self.controller.process:
|
||||
self.controller.process.ClosePPT(self.pptid)
|
||||
self.pptid = -1
|
||||
self.controller.process.ClosePPT(self.ppt_id)
|
||||
self.ppt_id = -1
|
||||
self.controller.remove_doc(self)
|
||||
|
||||
def is_loaded(self):
|
||||
"""
|
||||
Returns true if a presentation is loaded
|
||||
Returns true if a presentation is loaded.
|
||||
"""
|
||||
if self.pptid < 0:
|
||||
if self.ppt_id < 0:
|
||||
return False
|
||||
if self.get_slide_count() < 0:
|
||||
return False
|
||||
@ -171,74 +169,74 @@ class PptviewDocument(PresentationDocument):
|
||||
|
||||
def is_active(self):
|
||||
"""
|
||||
Returns true if a presentation is currently active
|
||||
Returns true if a presentation is currently active.
|
||||
"""
|
||||
return self.is_loaded() and not self.hidden
|
||||
|
||||
def blank_screen(self):
|
||||
"""
|
||||
Blanks the screen
|
||||
Blanks the screen.
|
||||
"""
|
||||
self.controller.process.Blank(self.pptid)
|
||||
self.controller.process.Blank(self.ppt_id)
|
||||
self.blanked = True
|
||||
|
||||
def unblank_screen(self):
|
||||
"""
|
||||
Unblanks (restores) the presentation
|
||||
Unblanks (restores) the presentation.
|
||||
"""
|
||||
self.controller.process.Unblank(self.pptid)
|
||||
self.controller.process.Unblank(self.ppt_id)
|
||||
self.blanked = False
|
||||
|
||||
def is_blank(self):
|
||||
"""
|
||||
Returns true if screen is blank
|
||||
Returns true if screen is blank.
|
||||
"""
|
||||
log.debug(u'is blank OpenOffice')
|
||||
return self.blanked
|
||||
|
||||
def stop_presentation(self):
|
||||
"""
|
||||
Stops the current presentation and hides the output
|
||||
Stops the current presentation and hides the output.
|
||||
"""
|
||||
self.hidden = True
|
||||
self.controller.process.Stop(self.pptid)
|
||||
self.controller.process.Stop(self.ppt_id)
|
||||
|
||||
def start_presentation(self):
|
||||
"""
|
||||
Starts a presentation from the beginning
|
||||
Starts a presentation from the beginning.
|
||||
"""
|
||||
if self.hidden:
|
||||
self.hidden = False
|
||||
self.controller.process.Resume(self.pptid)
|
||||
self.controller.process.Resume(self.ppt_id)
|
||||
else:
|
||||
self.controller.process.RestartShow(self.pptid)
|
||||
self.controller.process.RestartShow(self.ppt_id)
|
||||
|
||||
def get_slide_number(self):
|
||||
"""
|
||||
Returns the current slide number
|
||||
Returns the current slide number.
|
||||
"""
|
||||
return self.controller.process.GetCurrentSlide(self.pptid)
|
||||
return self.controller.process.GetCurrentSlide(self.ppt_id)
|
||||
|
||||
def get_slide_count(self):
|
||||
"""
|
||||
Returns total number of slides
|
||||
Returns total number of slides.
|
||||
"""
|
||||
return self.controller.process.GetSlideCount(self.pptid)
|
||||
return self.controller.process.GetSlideCount(self.ppt_id)
|
||||
|
||||
def goto_slide(self, slideno):
|
||||
"""
|
||||
Moves to a specific slide in the presentation
|
||||
Moves to a specific slide in the presentation.
|
||||
"""
|
||||
self.controller.process.GotoSlide(self.pptid, slideno)
|
||||
self.controller.process.GotoSlide(self.ppt_id, slideno)
|
||||
|
||||
def next_step(self):
|
||||
"""
|
||||
Triggers the next effect of slide on the running presentation
|
||||
Triggers the next effect of slide on the running presentation.
|
||||
"""
|
||||
self.controller.process.NextStep(self.pptid)
|
||||
self.controller.process.NextStep(self.ppt_id)
|
||||
|
||||
def previous_step(self):
|
||||
"""
|
||||
Triggers the previous slide on the running presentation
|
||||
Triggers the previous slide on the running presentation.
|
||||
"""
|
||||
self.controller.process.PrevStep(self.pptid)
|
||||
self.controller.process.PrevStep(self.ppt_id)
|
||||
|
@ -40,9 +40,8 @@ log = logging.getLogger(__name__)
|
||||
|
||||
class PresentationDocument(object):
|
||||
"""
|
||||
Base class for presentation documents to inherit from.
|
||||
Loads and closes the presentation as well as triggering the correct
|
||||
activities based on the users input
|
||||
Base class for presentation documents to inherit from. Loads and closes the presentation as well as triggering the
|
||||
correct activities based on the users input
|
||||
|
||||
**Hook Functions**
|
||||
|
||||
@ -131,20 +130,17 @@ class PresentationDocument(object):
|
||||
"""
|
||||
The location where thumbnail images will be stored
|
||||
"""
|
||||
return os.path.join(
|
||||
self.controller.thumbnail_folder, self.get_file_name())
|
||||
return os.path.join(self.controller.thumbnail_folder, self.get_file_name())
|
||||
|
||||
def get_temp_folder(self):
|
||||
"""
|
||||
The location where thumbnail images will be stored
|
||||
"""
|
||||
return os.path.join(
|
||||
self.controller.temp_folder, self.get_file_name())
|
||||
return os.path.join(self.controller.temp_folder, self.get_file_name())
|
||||
|
||||
def check_thumbnails(self):
|
||||
"""
|
||||
Returns ``True`` if the thumbnail images exist and are more recent than
|
||||
the powerpoint file.
|
||||
Returns ``True`` if the thumbnail images exist and are more recent than the powerpoint file.
|
||||
"""
|
||||
lastimage = self.get_thumbnail_path(self.get_slide_count(), True)
|
||||
if not (lastimage and os.path.isfile(lastimage)):
|
||||
@ -153,8 +149,7 @@ class PresentationDocument(object):
|
||||
|
||||
def close_presentation(self):
|
||||
"""
|
||||
Close presentation and clean up objects
|
||||
Triggered by new object being added to SlideController
|
||||
Close presentation and clean up objects. Triggered by new object being added to SlideController
|
||||
"""
|
||||
self.controller.close_presentation()
|
||||
|
||||
@ -223,8 +218,8 @@ class PresentationDocument(object):
|
||||
|
||||
def next_step(self):
|
||||
"""
|
||||
Triggers the next effect of slide on the running presentation
|
||||
This might be the next animation on the current slide, or the next slide
|
||||
Triggers the next effect of slide on the running presentation. This might be the next animation on the current
|
||||
slide, or the next slide
|
||||
"""
|
||||
pass
|
||||
|
||||
@ -236,8 +231,7 @@ class PresentationDocument(object):
|
||||
|
||||
def convert_thumbnail(self, file, idx):
|
||||
"""
|
||||
Convert the slide image the application made to a standard 320x240
|
||||
.png image.
|
||||
Convert the slide image the application made to a standard 320x240 .png image.
|
||||
"""
|
||||
if self.check_thumbnails():
|
||||
return
|
||||
@ -281,7 +275,7 @@ class PresentationDocument(object):
|
||||
Returns the text on the slide
|
||||
|
||||
``slide_no``
|
||||
The slide the text is required for, starting at 1
|
||||
The slide the text is required for, starting at 1
|
||||
"""
|
||||
return ''
|
||||
|
||||
@ -290,24 +284,21 @@ class PresentationDocument(object):
|
||||
Returns the text on the slide
|
||||
|
||||
``slide_no``
|
||||
The slide the notes are required for, starting at 1
|
||||
The slide the notes are required for, starting at 1
|
||||
"""
|
||||
return ''
|
||||
|
||||
|
||||
class PresentationController(object):
|
||||
"""
|
||||
This class is used to control interactions with presentation applications
|
||||
by creating a runtime environment. This is a base class for presentation
|
||||
controllers to inherit from.
|
||||
This class is used to control interactions with presentation applications by creating a runtime environment. This is
|
||||
a base class for presentation controllers to inherit from.
|
||||
|
||||
To create a new controller, take a copy of this file and name it so it ends
|
||||
with ``controller.py``, i.e. ``foobarcontroller.py``. Make sure it inherits
|
||||
:class:`~openlp.plugins.presentations.lib.presentationcontroller.PresentationController`,
|
||||
and then fill in the blanks. If possible try to make sure it loads on all
|
||||
platforms, usually by using :mod:``os.name`` checks, although
|
||||
``__init__``, ``check_available`` and ``presentation_deleted`` should
|
||||
always be implemented.
|
||||
To create a new controller, take a copy of this file and name it so it ends with ``controller.py``, i.e.
|
||||
``foobarcontroller.py``. Make sure it inherits
|
||||
:class:`~openlp.plugins.presentations.lib.presentationcontroller.PresentationController`, and then fill in the
|
||||
blanks. If possible try to make sure it loads on all platforms, usually by using :mod:``os.name`` checks, although
|
||||
``__init__``, ``check_available`` and ``presentation_deleted`` should always be implemented.
|
||||
|
||||
See :class:`~openlp.plugins.presentations.lib.impresscontroller.ImpressController`,
|
||||
:class:`~openlp.plugins.presentations.lib.powerpointcontroller.PowerpointController` or
|
||||
@ -317,36 +308,34 @@ class PresentationController(object):
|
||||
**Basic Attributes**
|
||||
|
||||
``name``
|
||||
The name that appears in the options and the media manager
|
||||
The name that appears in the options and the media manager.
|
||||
|
||||
``enabled``
|
||||
The controller is enabled
|
||||
The controller is enabled.
|
||||
|
||||
``available``
|
||||
The controller is available on this machine. Set by init via
|
||||
call to check_available
|
||||
The controller is available on this machine. Set by init via call to check_available.
|
||||
|
||||
``plugin``
|
||||
The presentationplugin object
|
||||
The presentationplugin object.
|
||||
|
||||
``supports``
|
||||
The primary native file types this application supports
|
||||
The primary native file types this application supports.
|
||||
|
||||
``alsosupports``
|
||||
Other file types the application can import, although not necessarily
|
||||
the first choice due to potential incompatibilities
|
||||
Other file types the application can import, although not necessarily the first choice due to potential
|
||||
incompatibilities.
|
||||
|
||||
**Hook Functions**
|
||||
|
||||
``kill()``
|
||||
Called at system exit to clean up any running presentations
|
||||
Called at system exit to clean up any running presentations.
|
||||
|
||||
``check_available()``
|
||||
Returns True if presentation application is installed/can run on this
|
||||
machine
|
||||
Returns True if presentation application is installed/can run on this machine.
|
||||
|
||||
``presentation_deleted()``
|
||||
Deletes presentation specific files, e.g. thumbnails
|
||||
Deletes presentation specific files, e.g. thumbnails.
|
||||
|
||||
"""
|
||||
log.info(u'PresentationController loaded')
|
||||
@ -354,9 +343,8 @@ class PresentationController(object):
|
||||
def __init__(self, plugin=None, name=u'PresentationController',
|
||||
document_class=PresentationDocument):
|
||||
"""
|
||||
This is the constructor for the presentationcontroller object. This
|
||||
provides an easy way for descendent plugins to populate common data.
|
||||
This method *must* be overridden, like so::
|
||||
This is the constructor for the presentationcontroller object. This provides an easy way for descendent plugins
|
||||
to populate common data. This method *must* be overridden, like so::
|
||||
|
||||
class MyPresentationController(PresentationController):
|
||||
def __init__(self, plugin):
|
||||
@ -399,28 +387,26 @@ class PresentationController(object):
|
||||
|
||||
def check_available(self):
|
||||
"""
|
||||
Presentation app is able to run on this machine
|
||||
Presentation app is able to run on this machine.
|
||||
"""
|
||||
return False
|
||||
|
||||
def start_process(self):
|
||||
"""
|
||||
Loads a running version of the presentation application in the
|
||||
background.
|
||||
Loads a running version of the presentation application in the background.
|
||||
"""
|
||||
pass
|
||||
|
||||
def kill(self):
|
||||
"""
|
||||
Called at system exit to clean up any running presentations and
|
||||
close the application
|
||||
Called at system exit to clean up any running presentations and close the application.
|
||||
"""
|
||||
log.debug(u'Kill')
|
||||
self.close_presentation()
|
||||
|
||||
def add_document(self, name):
|
||||
"""
|
||||
Called when a new presentation document is opened
|
||||
Called when a new presentation document is opened.
|
||||
"""
|
||||
document = self.document_class(self, name)
|
||||
self.docs.append(document)
|
||||
@ -428,7 +414,7 @@ class PresentationController(object):
|
||||
|
||||
def remove_doc(self, doc=None):
|
||||
"""
|
||||
Called to remove an open document from the collection
|
||||
Called to remove an open document from the collection.
|
||||
"""
|
||||
log.debug(u'remove_doc Presentation')
|
||||
if doc is None:
|
||||
|
@ -91,8 +91,7 @@ class PresentationTab(SettingsTab):
|
||||
if checkbox.isEnabled():
|
||||
checkbox.setText(controller.name)
|
||||
else:
|
||||
checkbox.setText(
|
||||
translate('PresentationPlugin.PresentationTab', '%s (unavailable)') % controller.name)
|
||||
checkbox.setText(translate('PresentationPlugin.PresentationTab', '%s (unavailable)') % controller.name)
|
||||
|
||||
def load(self):
|
||||
"""
|
||||
@ -106,8 +105,8 @@ class PresentationTab(SettingsTab):
|
||||
|
||||
def save(self):
|
||||
"""
|
||||
Save the settings. If the tab hasn't been made visible to the user then there is nothing to do,
|
||||
so exit. This removes the need to start presentation applications unnecessarily.
|
||||
Save the settings. If the tab hasn't been made visible to the user then there is nothing to do, so exit. This
|
||||
removes the need to start presentation applications unnecessarily.
|
||||
"""
|
||||
if not self.activated:
|
||||
return
|
||||
|
@ -27,8 +27,8 @@
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`presentationplugin` module provides the ability for OpenLP to display
|
||||
presentations from a variety of document formats.
|
||||
The :mod:`presentationplugin` module provides the ability for OpenLP to display presentations from a variety of document
|
||||
formats.
|
||||
"""
|
||||
import os
|
||||
import logging
|
||||
@ -39,22 +39,23 @@ from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
from openlp.core.utils import AppLocation
|
||||
from openlp.plugins.presentations.lib import PresentationController, PresentationMediaItem, PresentationTab
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
__default_settings__ = {
|
||||
u'presentations/override app': QtCore.Qt.Unchecked,
|
||||
u'presentations/Impress': QtCore.Qt.Checked,
|
||||
u'presentations/Powerpoint': QtCore.Qt.Checked,
|
||||
u'presentations/Powerpoint Viewer': QtCore.Qt.Checked,
|
||||
u'presentations/presentations files': []
|
||||
}
|
||||
u'presentations/override app': QtCore.Qt.Unchecked,
|
||||
u'presentations/Impress': QtCore.Qt.Checked,
|
||||
u'presentations/Powerpoint': QtCore.Qt.Checked,
|
||||
u'presentations/Powerpoint Viewer': QtCore.Qt.Checked,
|
||||
u'presentations/presentations files': []
|
||||
}
|
||||
|
||||
|
||||
class PresentationPlugin(Plugin):
|
||||
"""
|
||||
This plugin allowed a Presentation to be opened, controlled and displayed
|
||||
on the output display. The plugin controls third party applications such
|
||||
as OpenOffice.org Impress, Microsoft PowerPoint and the PowerPoint viewer
|
||||
This plugin allowed a Presentation to be opened, controlled and displayed on the output display. The plugin controls
|
||||
third party applications such as OpenOffice.org Impress, Microsoft PowerPoint and the PowerPoint viewer.
|
||||
"""
|
||||
log = logging.getLogger(u'PresentationPlugin')
|
||||
|
||||
@ -71,16 +72,14 @@ class PresentationPlugin(Plugin):
|
||||
|
||||
def create_settings_tab(self, parent):
|
||||
"""
|
||||
Create the settings Tab
|
||||
Create the settings Tab.
|
||||
"""
|
||||
visible_name = self.get_string(StringContent.VisibleName)
|
||||
self.settings_tab = PresentationTab(parent, self.name, visible_name[u'title'], self.controllers,
|
||||
self.icon_path)
|
||||
self.settings_tab = PresentationTab(parent, self.name, visible_name[u'title'], self.controllers, self.icon_path)
|
||||
|
||||
def initialise(self):
|
||||
"""
|
||||
Initialise the plugin. Determine which controllers are enabled
|
||||
are start their processes.
|
||||
Initialise the plugin. Determine which controllers are enabled are start their processes.
|
||||
"""
|
||||
log.info(u'Presentations Initialising')
|
||||
Plugin.initialise(self)
|
||||
@ -95,8 +94,8 @@ class PresentationPlugin(Plugin):
|
||||
|
||||
def finalise(self):
|
||||
"""
|
||||
Finalise the plugin. Ask all the enabled presentation applications
|
||||
to close down their applications and release resources.
|
||||
Finalise the plugin. Ask all the enabled presentation applications to close down their applications and release
|
||||
resources.
|
||||
"""
|
||||
log.info(u'Plugin Finalise')
|
||||
# Ask each controller to tidy up.
|
||||
@ -108,26 +107,23 @@ class PresentationPlugin(Plugin):
|
||||
|
||||
def create_media_manager_item(self):
|
||||
"""
|
||||
Create the Media Manager List
|
||||
Create the Media Manager List.
|
||||
"""
|
||||
self.media_item = PresentationMediaItem(
|
||||
self.main_window.media_dock_manager.media_dock, self, self.icon, self.controllers)
|
||||
|
||||
def register_controllers(self, controller):
|
||||
"""
|
||||
Register each presentation controller (Impress, PPT etc) and store for later use
|
||||
Register each presentation controller (Impress, PPT etc) and store for later use.
|
||||
"""
|
||||
self.controllers[controller.name] = controller
|
||||
|
||||
def check_pre_conditions(self):
|
||||
"""
|
||||
Check to see if we have any presentation software available
|
||||
If Not do not install the plugin.
|
||||
Check to see if we have any presentation software available. If not do not install the plugin.
|
||||
"""
|
||||
log.debug(u'check_pre_conditions')
|
||||
controller_dir = os.path.join(
|
||||
AppLocation.get_directory(AppLocation.PluginsDir),
|
||||
u'presentations', u'lib')
|
||||
controller_dir = os.path.join(AppLocation.get_directory(AppLocation.PluginsDir), u'presentations', u'lib')
|
||||
for filename in os.listdir(controller_dir):
|
||||
if filename.endswith(u'controller.py') and not filename == 'presentationcontroller.py':
|
||||
path = os.path.join(controller_dir, filename)
|
||||
@ -146,7 +142,7 @@ class PresentationPlugin(Plugin):
|
||||
|
||||
def about(self):
|
||||
"""
|
||||
Return information about this plugin
|
||||
Return information about this plugin.
|
||||
"""
|
||||
about_text = translate('PresentationPlugin', '<strong>Presentation '
|
||||
'Plugin</strong><br />The presentation plugin provides the '
|
||||
@ -157,7 +153,7 @@ class PresentationPlugin(Plugin):
|
||||
|
||||
def set_plugin_text_strings(self):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
Called to define all translatable texts of the plugin.
|
||||
"""
|
||||
## Name PluginList ##
|
||||
self.text_strings[StringContent.Name] = {
|
||||
|
@ -27,7 +27,6 @@
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`songusage` module contains the Song Usage plugin. The Song Usage
|
||||
plugin provides auditing capabilities for reporting the songs you are using to
|
||||
copyright license organisations.
|
||||
The :mod:`songusage` module contains the Song Usage plugin. The Song Usage plugin provides auditing capabilities for
|
||||
reporting the songs you are using to copyright license organisations.
|
||||
"""
|
||||
|
@ -55,7 +55,8 @@ class Ui_SongUsageDeleteDialog(object):
|
||||
self.retranslateUi(song_usage_delete_dialog)
|
||||
|
||||
def retranslateUi(self, song_usage_delete_dialog):
|
||||
song_usage_delete_dialog.setWindowTitle(translate('SongUsagePlugin.SongUsageDeleteForm', 'Delete Song Usage Data'))
|
||||
song_usage_delete_dialog.setWindowTitle(
|
||||
translate('SongUsagePlugin.SongUsageDeleteForm', 'Delete Song Usage Data'))
|
||||
self.delete_label.setText(
|
||||
translate('SongUsagePlugin.SongUsageDeleteForm', 'Select the date up to which the song usage data '
|
||||
'should be deleted. All data recorded before this date will be permanently deleted.'))
|
||||
|
@ -81,7 +81,8 @@ class Ui_SongUsageDetailDialog(object):
|
||||
self.save_file_push_button.clicked.connect(song_usage_detail_dialog.define_output_location)
|
||||
|
||||
def retranslateUi(self, song_usage_detail_dialog):
|
||||
song_usage_detail_dialog.setWindowTitle(translate('SongUsagePlugin.SongUsageDetailForm', 'Song Usage Extraction'))
|
||||
song_usage_detail_dialog.setWindowTitle(
|
||||
translate('SongUsagePlugin.SongUsageDetailForm', 'Song Usage Extraction'))
|
||||
self.date_range_group_box.setTitle(translate('SongUsagePlugin.SongUsageDetailForm', 'Select Date Range'))
|
||||
self.to_label.setText(translate('SongUsagePlugin.SongUsageDetailForm', 'to'))
|
||||
self.file_group_box.setTitle(translate('SongUsagePlugin.SongUsageDetailForm', 'Report Location'))
|
||||
|
@ -36,12 +36,14 @@ from sqlalchemy.orm import mapper
|
||||
|
||||
from openlp.core.lib.db import BaseModel, init_db
|
||||
|
||||
|
||||
class SongUsageItem(BaseModel):
|
||||
"""
|
||||
SongUsageItem model
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def init_schema(url):
|
||||
"""
|
||||
Setup the songusage database connection and initialise the database schema
|
||||
|
@ -48,11 +48,11 @@ if QtCore.QDate().currentDate().month() < 9:
|
||||
|
||||
|
||||
__default_settings__ = {
|
||||
u'songusage/db type': u'sqlite',
|
||||
u'songusage/active': False,
|
||||
u'songusage/to date': QtCore.QDate(YEAR, 8, 31),
|
||||
u'songusage/from date': QtCore.QDate(YEAR - 1, 9, 1),
|
||||
u'songusage/last directory export': u''
|
||||
u'songusage/db type': u'sqlite',
|
||||
u'songusage/active': False,
|
||||
u'songusage/to date': QtCore.QDate(YEAR, 8, 31),
|
||||
u'songusage/from date': QtCore.QDate(YEAR - 1, 9, 1),
|
||||
u'songusage/last directory export': u''
|
||||
}
|
||||
|
||||
|
||||
@ -76,12 +76,10 @@ class SongUsagePlugin(Plugin):
|
||||
|
||||
def add_tools_menu_item(self, tools_menu):
|
||||
"""
|
||||
Give the SongUsage plugin the opportunity to add items to the
|
||||
**Tools** menu.
|
||||
Give the SongUsage plugin the opportunity to add items to the **Tools** menu.
|
||||
|
||||
``tools_menu``
|
||||
The actual **Tools** menu item, so that your actions can
|
||||
use it as their parent.
|
||||
The actual **Tools** menu item, so that your actions can use it as their parent.
|
||||
"""
|
||||
log.info(u'add tools menu')
|
||||
self.toolsMenu = tools_menu
|
||||
@ -218,8 +216,8 @@ class SongUsagePlugin(Plugin):
|
||||
self.song_usage_detail_form.exec_()
|
||||
|
||||
def about(self):
|
||||
about_text = translate('SongUsagePlugin', '<strong>SongUsage Plugin'
|
||||
'</strong><br />This plugin tracks the usage of songs in services.')
|
||||
about_text = translate('SongUsagePlugin',
|
||||
'<strong>SongUsage Plugin</strong><br />This plugin tracks the usage of songs in services.')
|
||||
return about_text
|
||||
|
||||
def set_plugin_text_strings(self):
|
||||
|
Loading…
Reference in New Issue
Block a user