mirror of https://gitlab.com/openlp/openlp.git
Compare commits
12 Commits
083f2bbfc2
...
0717e49b46
Author | SHA1 | Date |
---|---|---|
Charles Crossan | 0717e49b46 | |
Raoul Snyman | 6bbfe00ec0 | |
Tim Bentley | cee0a9d573 | |
Charles Crossan | 6d6ba612c0 | |
Charles Crossan | 18aa7c38a6 | |
Charles Crossan | 8fbe858004 | |
Charles Crossan | 10af0507bc | |
Charles Crossan | 733fd0a057 | |
Charles Crossan | 11d3350078 | |
Charles Crossan | ee2e072856 | |
Charles Crossan | 89ff005d57 | |
Charles Crossan | 362962a992 |
|
@ -0,0 +1,33 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, 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 #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`countdown` module provides the Countdown plugin which allows
|
||||
themed countdown, timers to be displayed on the main screen
|
||||
type.
|
||||
"""
|
|
@ -0,0 +1,177 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, 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 #
|
||||
# #
|
||||
###############################################################################
|
||||
# This file contains MIT licensed code #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`~openlp.plugins.countdown.countdownplugin` module contains the Plugin class
|
||||
for the Countdown plugin.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from openlp.core.lib.plugin import Plugin, StringContent
|
||||
from openlp.core.common.i18n import translate
|
||||
from openlp.core.lib.db import Manager
|
||||
from openlp.plugins.countdown.lib.countdowntab import CountdownTab
|
||||
from openlp.plugins.countdown.lib.db import CountdownSlide, init_schema
|
||||
from openlp.plugins.countdown.lib.mediaitem import CountdownMediaItem,CountdownSearch
|
||||
from PyQt5 import QtGui, QtCore
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
__default_settings__ = {
|
||||
'countdown/db type': 'sqlite',
|
||||
'countdown/last search type': CountdownSearch.Titles,
|
||||
'countdown/display event name': True,
|
||||
'countdown/display legend': True,
|
||||
'shortcuts/listViewCountdownDeleteItem': [QtGui.QKeySequence(QtCore.Qt.Key_Delete)],
|
||||
'shortcuts/listViewCountdownPreviewItem': [QtGui.QKeySequence(QtCore.Qt.Key_Enter),
|
||||
QtGui.QKeySequence(QtCore.Qt.Key_Return)],
|
||||
'shortcuts/listViewCountdownLiveItem': [QtGui.QKeySequence(QtCore.Qt.ShiftModifier | QtCore.Qt.Key_Enter),
|
||||
QtGui.QKeySequence(QtCore.Qt.ShiftModifier | QtCore.Qt.Key_Return)],
|
||||
'shortcuts/listViewCountdownServiceItem': [QtGui.QKeySequence(QtCore.Qt.Key_Plus),
|
||||
QtGui.QKeySequence(QtCore.Qt.Key_Equal)],
|
||||
}
|
||||
|
||||
|
||||
class CountdownPlugin(Plugin):
|
||||
"""
|
||||
This plugin enables the user to create, edit and display countdown timers.
|
||||
All Countdown timers have one slide, which is dynamically updated by JavaScript running in webkit.
|
||||
The slide manager will display only one slide for all countdown items
|
||||
with a textual representation of the countdown event
|
||||
Examples include countdowns until: worship time, Christmas, Easter.
|
||||
Examples do not include countdowns until: judgement day.
|
||||
"""
|
||||
log.info('Countdown Plugin loaded')
|
||||
|
||||
def __init__(self):
|
||||
super(CountdownPlugin, self).__init__('countdown', __default_settings__, CountdownMediaItem, CountdownTab)
|
||||
self.weight = -1
|
||||
self.db_manager = Manager('countdown', init_schema)
|
||||
self.icon_path = ':/plugins/plugin_custom.png'
|
||||
self.icon = self.icon_path
|
||||
|
||||
@staticmethod
|
||||
def about(self):
|
||||
about_text = translate('CountdownPlugin', '<strong>Countdown Plugin </strong><br />The countdown plugin '
|
||||
'provides the ability to display a live countdown to an event')
|
||||
return about_text
|
||||
|
||||
def uses_theme(self, theme):
|
||||
"""
|
||||
Called to find out if the countdown plugin is currently using a theme.
|
||||
|
||||
Returns True if the theme is being used, otherwise returns False.
|
||||
"""
|
||||
if self.db_manager.get_all_objects(CountdownSlide, CountdownSlide.theme_name == theme):
|
||||
return True
|
||||
return False
|
||||
|
||||
def rename_theme(self, old_theme, new_theme):
|
||||
"""
|
||||
Renames a theme the countdown plugin is using making the plugin use the new name.
|
||||
|
||||
:param old_theme: The name of the theme the plugin should stop using.
|
||||
:param new_theme: The new name the plugin should now use.
|
||||
"""
|
||||
countdowns_using_theme = self.db_manager.get_all_objects(CountdownSlide, CountdownSlide.theme_name == old_theme)
|
||||
for countdown in countdowns_using_theme:
|
||||
countdown.theme_name = new_theme
|
||||
self.db_manager.save_object(countdown)
|
||||
|
||||
def set_plugin_text_strings(self):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
# Name PluginList
|
||||
self.text_strings[StringContent.Name] = {
|
||||
'singular': translate('CountdownPlugin', 'Countdown Slide', 'name singular'),
|
||||
'plural': translate('CountdownPlugin', 'Countdown Slides', 'name plural')
|
||||
}
|
||||
# Name for MediaDockManager, SettingsManager
|
||||
self.text_strings[StringContent.VisibleName] = {
|
||||
'title': translate('CountdownPlugin', 'Countdown Slides', 'container title')
|
||||
}
|
||||
# Middle Header Bar
|
||||
tooltips = {
|
||||
'load': translate('CountdownPlugin', 'Load a new countdown slide.'),
|
||||
'import': translate('CountdownPlugin', 'Import a countdown slide.'),
|
||||
'new': translate('CountdownPlugin', 'Add a new countdown slide.'),
|
||||
'edit': translate('CountdownPlugin', 'Edit the selected countdown slide.'),
|
||||
'delete': translate('CountdownPlugin', 'Delete the selected countdown slide.'),
|
||||
'preview': translate('CountdownPlugin', 'Preview the selected countdown slide.'),
|
||||
'live': translate('CountdownPlugin', 'Send the selected countdown slide live.'),
|
||||
'service': translate('CountdownPlugin', 'Add the selected countdown slide to the service.')
|
||||
}
|
||||
self.set_plugin_ui_text_strings(tooltips)
|
||||
|
||||
def finalise(self):
|
||||
"""
|
||||
Time to tidy up on exit
|
||||
"""
|
||||
log.info('Countdown Finalising')
|
||||
self.db_manager.finalise()
|
||||
Plugin.finalise(self)
|
||||
|
||||
def get_display_css(self):
|
||||
"""
|
||||
Add css style sheets to htmlbuilder.
|
||||
Currently, countdowns use no custom CSS, but that will probably change, so lets build an empty class
|
||||
"""
|
||||
css = """
|
||||
#countdowntext{
|
||||
|
||||
}
|
||||
"""
|
||||
|
||||
return css
|
||||
|
||||
def get_display_javascript(self):
|
||||
try:
|
||||
countdownjs_file_path = AppLocation.get_directory(AppLocation.AppDir) / '..' / 'Resources' / 'countdown.js'
|
||||
with countdownjs_file_path.open('r') as file_handle:
|
||||
content = file_handle.read()
|
||||
except (OSError):
|
||||
log.exception('Failed to open text file {text}'.format(text=text_file_path))
|
||||
return content
|
||||
|
||||
|
||||
def get_display_html(self):
|
||||
"""
|
||||
Add html code to htmlbuilder.
|
||||
|
||||
"""
|
||||
log.debug('Countdown get_display_html called')
|
||||
HTML = """
|
||||
<div id="countdown" class="lyricstable"><h1 id="countdowntext">test</h1></div>
|
||||
"""
|
||||
HTML = ""
|
||||
return HTML
|
|
@ -0,0 +1,28 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, 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 #
|
||||
###############################################################################
|
|
@ -0,0 +1,228 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, 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 #
|
||||
###############################################################################
|
||||
|
||||
from PyQt5 import QtGui
|
||||
|
||||
from openlp.core.common.i18n import translate
|
||||
from openlp.core.lib import build_icon
|
||||
from openlp.core.lib.ui import create_button_box
|
||||
|
||||
|
||||
class Ui_CountdownEditDialog(object):
|
||||
|
||||
def setupUi(self, countdown_edit_dialog):
|
||||
# Set up the main Window
|
||||
countdown_edit_dialog.setObjectName("countdown_edit_dialog")
|
||||
countdown_edit_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg'))
|
||||
countdown_edit_dialog.resize(450, 350)
|
||||
# Set up the main content layout
|
||||
self.dialog_layout = QtGui.QVBoxLayout(countdown_edit_dialog)
|
||||
self.dialog_layout.setObjectName('dialog_layout')
|
||||
|
||||
# Set up a layout for the title label and edit box
|
||||
self.title_layout = QtGui.QHBoxLayout()
|
||||
self.title_layout.setObjectName('title_layout')
|
||||
self.title_label = QtGui.QLabel(countdown_edit_dialog)
|
||||
self.title_label.setObjectName('title_label')
|
||||
self.title_layout.addWidget(self.title_label)
|
||||
self.title_edit = QtGui.QLineEdit(countdown_edit_dialog)
|
||||
self.title_label.setBuddy(self.title_edit)
|
||||
self.title_edit.setObjectName('title_edit')
|
||||
self.title_layout.addWidget(self.title_edit)
|
||||
self.dialog_layout.addLayout(self.title_layout)
|
||||
|
||||
# set up a layout for the countdown properties
|
||||
self.central_layout = QtGui.QFormLayout()
|
||||
self.central_layout.setObjectName('central_layout')
|
||||
|
||||
# build label for countdown_type
|
||||
self.countdown_type_label = QtGui.QLabel(countdown_edit_dialog)
|
||||
self.countdown_type_label.setObjectName("countdown_type_label")
|
||||
# build countdown_type_combo_box combo box
|
||||
self.countdown_type_combo_box = QtGui.QComboBox(countdown_edit_dialog)
|
||||
self.countdown_type_combo_box.setObjectName("countdown_type_combo_box")
|
||||
self.countdown_type_combo_box.addItem("")
|
||||
self.countdown_type_combo_box.addItem("")
|
||||
self.countdown_type_label.setBuddy(self.countdown_type_combo_box)
|
||||
self.central_layout.addRow(self.countdown_type_label, self.countdown_type_combo_box)
|
||||
|
||||
# build label for countdown time
|
||||
self.countdown_duration_label = QtGui.QLabel(countdown_edit_dialog)
|
||||
self.countdown_duration_label.setObjectName("countdown_duration_label")
|
||||
# build time edit box for countdown time
|
||||
self.countdown_duration_time_edit = QtGui.QTimeEdit(countdown_edit_dialog)
|
||||
self.countdown_duration_time_edit.setObjectName("countdown_duration_time_edit")
|
||||
# add to layout
|
||||
self.countdown_duration_label.setBuddy(self.countdown_duration_time_edit)
|
||||
self.central_layout.addRow(self.countdown_duration_label, self.countdown_duration_time_edit)
|
||||
|
||||
# Build label for use_specific_date
|
||||
self.use_specific_date_label = QtGui.QLabel(countdown_edit_dialog)
|
||||
self.use_specific_date_label.setObjectName("use_specific_date_label")
|
||||
# Build Check box for use_specific_date
|
||||
self.use_specific_date_check_box = QtGui.QCheckBox(countdown_edit_dialog)
|
||||
self.use_specific_date_check_box.setObjectName("use_specific_date_check_box")
|
||||
# add use specific date to layout
|
||||
self.use_specific_date_label.setBuddy(self.use_specific_date_check_box)
|
||||
self.central_layout.addRow(self.use_specific_date_label, self.use_specific_date_check_box)
|
||||
|
||||
# build label for countdown date
|
||||
self.countdown_date_label = QtGui.QLabel(countdown_edit_dialog)
|
||||
self.countdown_date_label.setObjectName("countdown_date_label")
|
||||
# build date edit box for countdown date
|
||||
self.countdown_date_date_edit = QtGui.QDateEdit(countdown_edit_dialog)
|
||||
self.countdown_date_date_edit.setObjectName("countdown_date_date_edit")
|
||||
|
||||
# add countdown date to layout
|
||||
self.countdown_date_label.setBuddy(self.countdown_date_date_edit)
|
||||
self.central_layout.addRow(self.countdown_date_label, self.countdown_date_date_edit)
|
||||
|
||||
# build label for use_specific_time_checkbox
|
||||
self.use_specific_time_label = QtGui.QLabel(countdown_edit_dialog)
|
||||
self.use_specific_time_label.setObjectName("use_specific_time_label")
|
||||
# build use_specific_time_checkbox
|
||||
self.use_specific_time_check_box = QtGui.QCheckBox(countdown_edit_dialog)
|
||||
self.use_specific_time_check_box.setObjectName("use_specific_time_check_box")
|
||||
# add to layout
|
||||
self.use_specific_time_label.setBuddy(self.use_specific_time_check_box)
|
||||
self.central_layout.addRow(self.use_specific_time_label, self.use_specific_time_check_box)
|
||||
|
||||
# build label for countdown time
|
||||
self.countdown_time_label = QtGui.QLabel(countdown_edit_dialog)
|
||||
self.countdown_time_label.setObjectName("countdown_time_label")
|
||||
# build time edit box for countdown time
|
||||
self.countdown_time_time_edit = QtGui.QTimeEdit(countdown_edit_dialog)
|
||||
self.countdown_time_time_edit.setObjectName("countdown_time_time_edit")
|
||||
# add to layout
|
||||
self.countdown_time_label.setBuddy(self.countdown_time_time_edit)
|
||||
self.central_layout.addRow(self.countdown_time_label, self.countdown_time_time_edit)
|
||||
|
||||
# build label for interval_large
|
||||
self.interval_large_label = QtGui.QLabel(countdown_edit_dialog)
|
||||
self.interval_large_label.setObjectName("interval_large_label")
|
||||
# build interval_large combo box
|
||||
self.interval_large_combo_box = QtGui.QComboBox(countdown_edit_dialog)
|
||||
self.interval_large_combo_box.setObjectName("interval_large_combo_box")
|
||||
self.interval_large_combo_box.addItem("")
|
||||
self.interval_large_combo_box.addItem("")
|
||||
self.interval_large_combo_box.addItem("")
|
||||
self.interval_large_combo_box.addItem("")
|
||||
self.interval_large_combo_box.addItem("")
|
||||
self.interval_large_combo_box.addItem("")
|
||||
self.interval_large_combo_box.addItem("")
|
||||
self.interval_large_combo_box.addItem("")
|
||||
# add to layout
|
||||
self.interval_large_label.setBuddy(self.interval_large_combo_box)
|
||||
self.central_layout.addRow(self.interval_large_label, self.interval_large_combo_box)
|
||||
|
||||
# build label for interval small
|
||||
self.interval_small_label = QtGui.QLabel(countdown_edit_dialog)
|
||||
self.interval_small_label.setObjectName("interval_small_label")
|
||||
# build interval_small_combo_box
|
||||
self.interval_small_combo_box = QtGui.QComboBox(countdown_edit_dialog)
|
||||
self.interval_small_combo_box.setObjectName("interval_small_combo_box")
|
||||
self.interval_small_combo_box.addItem("")
|
||||
self.interval_small_combo_box.addItem("")
|
||||
self.interval_small_combo_box.addItem("")
|
||||
self.interval_small_combo_box.addItem("")
|
||||
self.interval_small_combo_box.addItem("")
|
||||
self.interval_small_combo_box.addItem("")
|
||||
self.interval_small_combo_box.addItem("")
|
||||
self.interval_small_combo_box.addItem("")
|
||||
# add to layout
|
||||
self.interval_small_label.setBuddy(self.interval_small_combo_box)
|
||||
self.central_layout.addRow(self.interval_small_label, self.interval_small_combo_box)
|
||||
|
||||
# build label for finish_action
|
||||
self.finish_action_label = QtGui.QLabel(countdown_edit_dialog)
|
||||
self.finish_action_label.setObjectName("finish_action_label")
|
||||
# build finish_action_combo_box
|
||||
self.finish_action_combo_box = QtGui.QComboBox(countdown_edit_dialog)
|
||||
self.finish_action_combo_box.setObjectName("finish_action_combo_box")
|
||||
self.finish_action_combo_box.addItem("")
|
||||
self.finish_action_combo_box.addItem("")
|
||||
self.finish_action_combo_box.addItem("")
|
||||
self.finish_action_label.setBuddy(self.finish_action_combo_box)
|
||||
self.central_layout.addRow(self.finish_action_label, self.finish_action_combo_box)
|
||||
|
||||
# add the central_layout to the dialog_layout
|
||||
self.dialog_layout.addLayout(self.central_layout)
|
||||
# create the bottom layout
|
||||
self.bottom_form_layout = QtGui.QFormLayout()
|
||||
self.bottom_form_layout.setObjectName('bottom_form_layout')
|
||||
self.theme_label = QtGui.QLabel(countdown_edit_dialog)
|
||||
self.theme_label.setObjectName('theme_label')
|
||||
self.theme_combo_box = QtGui.QComboBox(countdown_edit_dialog)
|
||||
self.theme_combo_box.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
|
||||
self.theme_combo_box.setObjectName('theme_combo_box')
|
||||
self.theme_label.setBuddy(self.theme_combo_box)
|
||||
self.bottom_form_layout.addRow(self.theme_label, self.theme_combo_box)
|
||||
|
||||
# add the bottom_layout to the dialog_layout
|
||||
self.dialog_layout.addLayout(self.bottom_form_layout)
|
||||
# Create the cancel, save button box, and add it to the dialog_layout
|
||||
self.button_box = create_button_box(countdown_edit_dialog, 'button_box', ['cancel', 'save'])
|
||||
self.dialog_layout.addWidget(self.button_box)
|
||||
# retranslate the UI
|
||||
self.retranslateUi(countdown_edit_dialog)
|
||||
|
||||
def retranslateUi(self, countdown_edit_dialog):
|
||||
countdown_edit_dialog.setWindowTitle(translate("customEditDialog", "Edit Countdown Slides", None))
|
||||
self.theme_label.setText(translate("customEditDialog", "Theme:", None))
|
||||
self.title_label.setText(translate("customEditDialog", "Title:", None))
|
||||
self.countdown_type_label.setText(translate("customEditDialog", "Countdown Type", None))
|
||||
self.countdown_type_combo_box.setItemText(0, translate("customEditDialog", "Future Date / Time", None))
|
||||
self.countdown_type_combo_box.setItemText(1, translate("customEditDialog", "Specific Duration", None))
|
||||
self.countdown_duration_label.setText(translate("customEditDialog", "Countdown Duration", None))
|
||||
self.use_specific_date_label.setText(translate("customEditDialog", "Use Specific Date", None))
|
||||
self.countdown_date_label.setText(translate("customEditDialog", "Countdown Date", None))
|
||||
self.use_specific_time_label.setText(translate("customEditDialog", "Use Specific Time", None))
|
||||
self.countdown_time_label.setText(translate("customEditDialog", "Countdown Time", None))
|
||||
self.interval_large_label.setText(translate("customEditDialog", "Largest Interval to Display", None))
|
||||
self.interval_large_combo_box.setItemText(0, translate("customEditDialog", "Years", None))
|
||||
self.interval_large_combo_box.setItemText(1, translate("customEditDialog", "Months", None))
|
||||
self.interval_large_combo_box.setItemText(2, translate("customEditDialog", "Weeks", None))
|
||||
self.interval_large_combo_box.setItemText(3, translate("customEditDialog", "Days", None))
|
||||
self.interval_large_combo_box.setItemText(4, translate("customEditDialog", "Hours", None))
|
||||
self.interval_large_combo_box.setItemText(5, translate("customEditDialog", "Minues", None))
|
||||
self.interval_large_combo_box.setItemText(6, translate("customEditDialog", "Seconds", None))
|
||||
self.interval_large_combo_box.setItemText(7, translate("customEditDialog", "Miliseconds", None))
|
||||
self.interval_small_label.setText(translate("customEditDialog", "Smallest Interval to Display", None))
|
||||
self.interval_small_combo_box.setItemText(0, translate("customEditDialog", "Years", None))
|
||||
self.interval_small_combo_box.setItemText(1, translate("customEditDialog", "Months", None))
|
||||
self.interval_small_combo_box.setItemText(2, translate("customEditDialog", "Weeks", None))
|
||||
self.interval_small_combo_box.setItemText(3, translate("customEditDialog", "Days", None))
|
||||
self.interval_small_combo_box.setItemText(4, translate("customEditDialog", "Hours", None))
|
||||
self.interval_small_combo_box.setItemText(5, translate("customEditDialog", "Minues", None))
|
||||
self.interval_small_combo_box.setItemText(6, translate("customEditDialog", "Seconds", None))
|
||||
self.interval_small_combo_box.setItemText(7, translate("customEditDialog", "Miliseconds", None))
|
||||
self.finish_action_label.setText(translate("customEditDialog", "Finish Action", None))
|
||||
self.finish_action_combo_box.setItemText(0, translate("customEditDialog", "Blink", None))
|
||||
self.finish_action_combo_box.setItemText(1, translate("customEditDialog", "Blank", None))
|
||||
self.finish_action_combo_box.setItemText(2, translate("customEditDialog", "Next Slide", None))
|
|
@ -0,0 +1,287 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, 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 #
|
||||
###############################################################################
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt5 import QtGui
|
||||
from PyQt5.QtWidgets import QDialog
|
||||
|
||||
from openlp.core.common.i18n import translate
|
||||
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
from openlp.plugins.countdown.lib.db import CountdownSlide
|
||||
from .editcountdowndialog import Ui_CountdownEditDialog
|
||||
# from .editcountdownslideform import EditCountdownSlideForm
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EditCountdownForm(QDialog, Ui_CountdownEditDialog):
|
||||
"""
|
||||
Class documentation goes here.
|
||||
"""
|
||||
log.info('Countdown Editor loaded')
|
||||
|
||||
def __init__(self, media_item, parent, manager):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
super(EditCountdownForm, self).__init__(parent)
|
||||
self.manager = manager
|
||||
self.media_item = media_item
|
||||
self.setupUi(self)
|
||||
# Create other objects and forms.
|
||||
# self.edit_slide_form = EditCountdownSlideForm(self)
|
||||
# Connecting signals and slots
|
||||
# self.preview_button.clicked.connect(self.on_preview_button_clicked)
|
||||
# self.add_button.clicked.connect(self.on_add_button_clicked)
|
||||
# self.edit_button.clicked.connect(self.on_edit_button_clicked)
|
||||
# self.edit_all_button.clicked.connect(self.on_edit_all_button_clicked)
|
||||
# self.slide_list_view.currentRowChanged.connect(self.on_current_row_changed)
|
||||
# self.slide_list_view.doubleClicked.connect(self.on_edit_button_clicked)
|
||||
Registry().register_function('theme_update_list', self.load_themes)
|
||||
|
||||
def load_themes(self, theme_list):
|
||||
"""
|
||||
Load a list of themes into the themes combo box.
|
||||
:param theme_list: The list of themes to load.
|
||||
"""
|
||||
self.theme_combo_box.clear()
|
||||
self.theme_combo_box.addItem('')
|
||||
self.theme_combo_box.addItems(theme_list)
|
||||
|
||||
def load_countdown(self, id, preview=False):
|
||||
"""
|
||||
Called when editing or creating a new countdown.
|
||||
:param id: The countdown's id. If zero, then a new countdown is created
|
||||
"""
|
||||
if id == 0:
|
||||
self.countdown_slide = CountdownSlide()
|
||||
self.title_edit.setText('')
|
||||
self.theme_combo_box.setCurrentIndex(0)
|
||||
else:
|
||||
self.countdown_slide = self.manager.get_object(CountdownSlide, id)
|
||||
self.title_edit.setText(self.countdown_slide.title)
|
||||
|
||||
self.countdown_type_combo_box.setCurrentIndex(self.countdown_slide.countdown_type)
|
||||
if self.countdown_slide.countdown_type == 1:
|
||||
self.countdown_duration_time_edit.setTime(self.countdown_slide.countdown_duration)
|
||||
else:
|
||||
|
||||
if self.countdown_slide.countdown_use_specific_date:
|
||||
self.use_specific_date_check_box.setChecked(True)
|
||||
self.countdown_date_date_edit.setDate(self.countdown_slide.countdown_specific_date)
|
||||
if self.countdown_slide.countdown_use_specific_time:
|
||||
self.use_specific_time_check_box.setChecked(True)
|
||||
self.countdown_time_time_edit.setTime(self.countdown_slide.countdown_specific_time)
|
||||
|
||||
self.interval_large_combo_box.setCurrentIndex(self.countdown_slide.interval_large)
|
||||
self.interval_small_combo_box.setCurrentIndex(self.countdown_slide.interval_small)
|
||||
self.finish_action_combo_box.setCurrentIndex(self.countdown_slide.finish_action)
|
||||
|
||||
self.countdown_slide.theme_name = self.theme_combo_box.currentText()
|
||||
self.media_item.auto_select_id = self.countdown_slide.id
|
||||
|
||||
# theme = self.countdown_slide.theme_name
|
||||
# find_and_set_in_combo_box(self.theme_combo_box, theme)
|
||||
self.title_edit.setFocus()
|
||||
log.debug('load successful')
|
||||
|
||||
def accept(self):
|
||||
"""
|
||||
Override the QDialog method to check if the countdown slide has been saved before closing the dialog.
|
||||
"""
|
||||
|
||||
log.debug('accept')
|
||||
if self.save_countdown():
|
||||
QtGui.QDialog.accept(self)
|
||||
log.debug('Save successful')
|
||||
|
||||
def save_countdown(self):
|
||||
"""
|
||||
Saves the countdown.
|
||||
"""
|
||||
if not self._validate():
|
||||
return False
|
||||
# sxml = CountdownXMLBuilder()
|
||||
# for count in range(self.slide_list_view.count()):
|
||||
# sxml.add_verse_to_lyrics('countdown', str(count + 1), self.slide_list_view.item(count).text())
|
||||
|
||||
self.countdown_slide.title = self.title_edit.text()
|
||||
self.countdown_slide.countdown_type = self.countdown_type_combo_box.currentIndex()
|
||||
if self.countdown_slide.countdown_type == 1:
|
||||
self.countdown_slide.countdown_duration = self.countdown_duration_time_edit.time().toPyTime()
|
||||
else:
|
||||
self.countdown_slide.countdown_use_specific_date = self.use_specific_date_check_box.isChecked()
|
||||
if self.countdown_slide.countdown_use_specific_date:
|
||||
self.countdown_slide.countdown_specific_date = self.countdown_date_date_edit.date().toPyDate()
|
||||
self.countdown_slide.countdown_use_specific_time = self.use_specific_time_check_box.isChecked()
|
||||
if self.countdown_slide.countdown_use_specific_time:
|
||||
self.countdown_slide.countdown_specific_time = self.countdown_time_time_edit.time().toPyTime()
|
||||
|
||||
self.countdown_slide.interval_large = self.interval_large_combo_box.currentIndex()
|
||||
self.countdown_slide.interval_small = self.interval_small_combo_box.currentIndex()
|
||||
self.countdown_slide.finish_action = self.finish_action_combo_box.currentIndex()
|
||||
|
||||
self.countdown_slide.theme_name = self.theme_combo_box.currentText()
|
||||
self.media_item.auto_select_id = self.countdown_slide.id
|
||||
success = self.manager.save_object(self.countdown_slide)
|
||||
return success
|
||||
|
||||
def on_up_button_clicked(self):
|
||||
"""
|
||||
Move a slide up in the list when the "Up" button is clicked.
|
||||
|
||||
selected_row = self.slide_list_view.currentRow()
|
||||
if selected_row != 0:
|
||||
qw = self.slide_list_view.takeItem(selected_row)
|
||||
self.slide_list_view.insertItem(selected_row - 1, qw)
|
||||
self.slide_list_view.setCurrentRow(selected_row - 1)
|
||||
"""
|
||||
|
||||
def on_down_button_clicked(self):
|
||||
"""
|
||||
Move a slide down in the list when the "Down" button is clicked.
|
||||
|
||||
selected_row = self.slide_list_view.currentRow()
|
||||
# zero base arrays
|
||||
if selected_row != self.slide_list_view.count() - 1:
|
||||
qw = self.slide_list_view.takeItem(selected_row)
|
||||
self.slide_list_view.insertItem(selected_row + 1, qw)
|
||||
self.slide_list_view.setCurrentRow(selected_row + 1)
|
||||
"""
|
||||
|
||||
def on_add_button_clicked(self):
|
||||
"""
|
||||
Add a new blank slide.
|
||||
|
||||
self.edit_slide_form.set_text('')
|
||||
if self.edit_slide_form.exec_():
|
||||
self.slide_list_view.addItems(self.edit_slide_form.get_text())
|
||||
"""
|
||||
|
||||
def on_edit_button_clicked(self):
|
||||
"""
|
||||
Edit the currently selected slide.
|
||||
|
||||
self.edit_slide_form.set_text(self.slide_list_view.currentItem().text())
|
||||
if self.edit_slide_form.exec_():
|
||||
self.update_slide_list(self.edit_slide_form.get_text())
|
||||
"""
|
||||
|
||||
def on_edit_all_button_clicked(self):
|
||||
"""
|
||||
Edits all slides.
|
||||
|
||||
slide_text = ''
|
||||
for row in range(self.slide_list_view.count()):
|
||||
item = self.slide_list_view.item(row)
|
||||
slide_text += item.text()
|
||||
if row != self.slide_list_view.count() - 1:
|
||||
slide_text += '\n[===]\n'
|
||||
self.edit_slide_form.set_text(slide_text)
|
||||
if self.edit_slide_form.exec_():
|
||||
self.update_slide_list(self.edit_slide_form.get_text(), True)
|
||||
"""
|
||||
|
||||
def on_preview_button_clicked(self):
|
||||
"""
|
||||
Save the countdown item and preview it.
|
||||
|
||||
log.debug('onPreview')
|
||||
if self.save_countdown():
|
||||
Registry().execute('countdown_preview')
|
||||
"""
|
||||
def update_slide_list(self, slides, edit_all=False):
|
||||
"""
|
||||
Updates the slide list after editing slides.
|
||||
|
||||
:param slides: A list of all slides which have been edited.
|
||||
:param edit_all: Indicates if all slides or only one slide has been edited.
|
||||
|
||||
if edit_all:
|
||||
self.slide_list_view.clear()
|
||||
self.slide_list_view.addItems(slides)
|
||||
else:
|
||||
old_row = self.slide_list_view.currentRow()
|
||||
# Create a list with all (old/unedited) slides.
|
||||
old_slides = [self.slide_list_view.item(row).text() for row in range(self.slide_list_view.count())]
|
||||
self.slide_list_view.clear()
|
||||
old_slides.pop(old_row)
|
||||
# Insert all slides to make the old_slides list complete.
|
||||
for slide in slides:
|
||||
old_slides.insert(old_row, slide)
|
||||
self.slide_list_view.addItems(old_slides)
|
||||
self.slide_list_view.repaint()
|
||||
"""
|
||||
|
||||
def on_delete_button_clicked(self):
|
||||
"""
|
||||
Removes the current row from the list.
|
||||
|
||||
self.slide_list_view.takeItem(self.slide_list_view.currentRow())
|
||||
self.on_current_row_changed(self.slide_list_view.currentRow())
|
||||
"""
|
||||
|
||||
def on_current_row_changed(self, row):
|
||||
"""
|
||||
Called when the *slide_list_view*'s current row has been changed. This
|
||||
enables or disables buttons which require an slide to act on.
|
||||
|
||||
:param row: The row (int). If there is no current row, the value is -1.
|
||||
|
||||
if row == -1:
|
||||
self.delete_button.setEnabled(False)
|
||||
self.edit_button.setEnabled(False)
|
||||
self.up_button.setEnabled(False)
|
||||
self.down_button.setEnabled(False)
|
||||
else:
|
||||
self.delete_button.setEnabled(True)
|
||||
self.edit_button.setEnabled(True)
|
||||
# Decide if the up/down buttons should be enabled or not.
|
||||
self.down_button.setEnabled(self.slide_list_view.count() - 1 != row)
|
||||
self.up_button.setEnabled(row != 0)
|
||||
"""
|
||||
|
||||
def _validate(self):
|
||||
"""
|
||||
Checks whether a countdown is valid or not.
|
||||
"""
|
||||
# We must have a title.
|
||||
if not self.title_edit.displayText():
|
||||
self.title_edit.setFocus()
|
||||
critical_error_message_box(message=translate('CountdownPlugin.EditCountdownForm', 'You need to type in a title.'))
|
||||
return False
|
||||
# We must have at least one slide.
|
||||
# if self.slide_list_view.count() == 0:
|
||||
# critical_error_message_box(message=translate('CountdownPlugin.EditCountdownForm',
|
||||
# 'You need to add at least one slide.'))
|
||||
# return False
|
||||
return True
|
|
@ -0,0 +1,61 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, 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 #
|
||||
###############################################################################
|
||||
|
||||
from PyQt5 import QtWidgets
|
||||
|
||||
from openlp.core.common.i18n import UiStrings, translate
|
||||
from openlp.core.widgets.edits import SpellTextEdit
|
||||
from openlp.core.lib import build_icon
|
||||
from openlp.core.lib.ui import create_button, create_button_box
|
||||
|
||||
|
||||
class Ui_CountdownSlideEditDialog(object):
|
||||
def setupUi(self, countdown_slide_edit_dialog):
|
||||
countdown_slide_edit_dialog.setObjectName('countdown_slide_edit_dialog')
|
||||
countdown_slide_edit_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo.svg'))
|
||||
countdown_slide_edit_dialog.resize(350, 300)
|
||||
self.dialog_layout = QtWidgets.QVBoxLayout(countdown_slide_edit_dialog)
|
||||
self.slide_text_edit = SpellTextEdit(self)
|
||||
self.slide_text_edit.setObjectName('slide_text_edit')
|
||||
self.dialog_layout.addWidget(self.slide_text_edit)
|
||||
self.split_button = create_button(countdown_slide_edit_dialog, 'splitButton', icon=':/general/general_add.png')
|
||||
self.insert_button = create_button(countdown_slide_edit_dialog, 'insertButton',
|
||||
icon=':/general/general_add.png')
|
||||
self.button_box = create_button_box(countdown_slide_edit_dialog, 'button_box', ['cancel', 'save'],
|
||||
[self.split_button, self.insert_button])
|
||||
self.dialog_layout.addWidget(self.button_box)
|
||||
self.retranslateUi(countdown_slide_edit_dialog)
|
||||
|
||||
def retranslateUi(self, countdown_slide_edit_dialog):
|
||||
countdown_slide_edit_dialog.setWindowTitle(translate('CountdownPlugin.EditVerseForm', 'Edit Slide'))
|
||||
self.split_button.setText(UiStrings().Split)
|
||||
self.split_button.setToolTip(UiStrings().SplitToolTip)
|
||||
self.insert_button.setText(translate('CountdownPlugin.EditCountdownForm', 'Insert Slide'))
|
||||
self.insert_button.setToolTip(translate('CountdownPlugin.EditCountdownForm',
|
||||
'Split a slide into two by inserting a slide splitter.'))
|
|
@ -0,0 +1,97 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, 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 #
|
||||
###############################################################################
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt5.QtWidgets import QDialog
|
||||
from .editcountdownslidedialog import Ui_CountdownSlideEditDialog
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EditCountdownSlideForm(QDialog, Ui_CountdownSlideEditDialog):
|
||||
"""
|
||||
Class documentation goes here.
|
||||
"""
|
||||
log.info('Countdown Verse Editor loaded')
|
||||
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
super(EditCountdownSlideForm, self).__init__(parent)
|
||||
self.setupUi(self)
|
||||
# Connecting signals and slots
|
||||
self.insert_button.clicked.connect(self.on_insert_button_clicked)
|
||||
self.split_button.clicked.connect(self.on_split_button_clicked)
|
||||
|
||||
def set_text(self, text):
|
||||
"""
|
||||
Set the text for slide_text_edit.
|
||||
|
||||
:param text: The text (unicode).
|
||||
"""
|
||||
self.slide_text_edit.clear()
|
||||
if text:
|
||||
self.slide_text_edit.setPlainText(text)
|
||||
self.slide_text_edit.setFocus()
|
||||
|
||||
def get_text(self):
|
||||
"""
|
||||
Returns a list with all slides.
|
||||
"""
|
||||
return self.slide_text_edit.toPlainText().split('\n[===]\n')
|
||||
|
||||
def on_insert_button_clicked(self):
|
||||
"""
|
||||
Adds a slide split at the cursor.
|
||||
"""
|
||||
self.insert_single_line_text_at_cursor('[===]')
|
||||
self.slide_text_edit.setFocus()
|
||||
|
||||
def on_split_button_clicked(self):
|
||||
"""
|
||||
Adds an optional split at cursor.
|
||||
"""
|
||||
self.insert_single_line_text_at_cursor('[---]')
|
||||
self.slide_text_edit.setFocus()
|
||||
|
||||
def insert_single_line_text_at_cursor(self, text):
|
||||
"""
|
||||
Adds a single line at the cursor position.
|
||||
|
||||
:param text: The text to be inserted
|
||||
"""
|
||||
full_text = self.slide_text_edit.toPlainText()
|
||||
position = self.slide_text_edit.textCursor().position()
|
||||
if position and full_text[position - 1] != '\n':
|
||||
text = '\n' + text
|
||||
if position == len(full_text) or full_text[position] != '\n':
|
||||
text += '\n'
|
||||
self.slide_text_edit.insertPlainText(text)
|
|
@ -0,0 +1,28 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, 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 #
|
||||
###############################################################################
|
|
@ -0,0 +1,126 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, 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 #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`~openlp.plugins.countdown.lib.countdowntab` module contains the settings tab
|
||||
for the Countdown Slides plugin, which is inserted into the configuration dialog.
|
||||
"""
|
||||
|
||||
from PyQt5 import QtCore, QtWidgets
|
||||
from openlp.core.common.i18n import translate
|
||||
|
||||
|
||||
from openlp.core.common.settings import Settings
|
||||
from openlp.core.lib.settingstab import SettingsTab
|
||||
|
||||
|
||||
class CountdownTab(SettingsTab):
|
||||
"""
|
||||
CountdownTab is the Countdown settings tab in the settings dialog.
|
||||
"""
|
||||
def __init__(self, parent, title, visible_title, icon_path):
|
||||
super(CountdownTab, self).__init__(parent, title, visible_title, icon_path)
|
||||
|
||||
def setupUi(self):
|
||||
self.setObjectName('CountdownTab')
|
||||
super(CountdownTab, self).setupUi()
|
||||
self.countdown_mode_group_box = QtWidgets.QGroupBox(self.left_column)
|
||||
self.countdown_mode_group_box.setObjectName('countdown_mode_group_box')
|
||||
self.countdown_mode_layout = QtWidgets.QFormLayout(self.countdown_mode_group_box)
|
||||
self.countdown_mode_layout.setObjectName('countdown_mode_layout')
|
||||
self.show_countdown_event_name_checkbox = QtWidgets.QCheckBox(self.countdown_mode_group_box)
|
||||
self.show_countdown_event_name_checkbox.setObjectName('show_countdown_event_name_checkbox')
|
||||
self.show_countdown_legend_checkbox = QtWidgets.QCheckBox(self.countdown_mode_group_box)
|
||||
self.show_countdown_legend_checkbox.setObjectName('show_countdown_legend_checkbox')
|
||||
self.countdown_mode_layout.addRow(self.show_countdown_event_name_checkbox)
|
||||
self.countdown_mode_layout.addRow(self.show_countdown_legend_checkbox)
|
||||
self.left_layout.addWidget(self.countdown_mode_group_box)
|
||||
self.left_layout.addStretch()
|
||||
self.right_layout.addStretch()
|
||||
|
||||
self.show_countdown_event_name_checkbox.stateChanged.connect(self.on_show_countdown_event_name_check_box_changed)
|
||||
self.show_countdown_legend_checkbox.stateChanged.connect(self.on_show_countdown_legend_check_box_changed)
|
||||
|
||||
def retranslateUi(self):
|
||||
self.countdown_mode_group_box.setTitle(translate('CountdownPlugin.CountdownTab', 'Countdown Options'))
|
||||
|
||||
self.show_countdown_event_name_checkbox.setText(translate('CountdownPlugin.CountdownTab',
|
||||
'Show Countdown event name'))
|
||||
|
||||
self.show_countdown_legend_checkbox.setText(translate('CountdownPlugin.CountdownTab',
|
||||
'Show a legend with the countdon (H:M:S)'))
|
||||
|
||||
def on_show_countdown_event_name_check_box_changed(self, check_state):
|
||||
"""
|
||||
Toggle the setting for displaying the countdown event name.
|
||||
|
||||
:param check_state: The current check box state
|
||||
"""
|
||||
self.display_event_name = False
|
||||
# we have a set value convert to True/False
|
||||
if check_state == QtCore.Qt.Checked:
|
||||
self.display_event_name = True
|
||||
|
||||
def on_show_countdown_legend_check_box_changed(self, check_state):
|
||||
"""
|
||||
Toggle the setting for displaying the countdown legend
|
||||
|
||||
:param check_state: The current check box state
|
||||
"""
|
||||
self.display_legend = False
|
||||
# we have a set value convert to True/False
|
||||
if check_state == QtCore.Qt.Checked:
|
||||
self.display_legend = True
|
||||
|
||||
def load(self):
|
||||
"""
|
||||
|
||||
Load the settings into the dialog
|
||||
"""
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settings_section)
|
||||
self.display_event_name = settings.value('display event name')
|
||||
self.display_legend = settings.value('display legend')
|
||||
|
||||
self.show_countdown_event_name_checkbox.setChecked(self.display_event_name)
|
||||
self.show_countdown_legend_checkbox.setChecked(self.display_legend)
|
||||
settings.endGroup()
|
||||
|
||||
def save(self):
|
||||
"""
|
||||
Save the Dialog settings
|
||||
"""
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settings_section)
|
||||
settings.setValue('display event name', self.display_event_name)
|
||||
settings.setValue('display legend', self.display_legend)
|
||||
|
||||
settings.endGroup()
|
||||
if self.tab_visited:
|
||||
self.settings_form.register_post_process('countdown_config_updated')
|
||||
self.tab_visited = False
|
|
@ -0,0 +1,163 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, 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 #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`countdownxmlhandler` module provides the XML functionality for countdown
|
||||
slides
|
||||
|
||||
The basic XML is of the format::
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<song version="1.0">
|
||||
<lyrics language="en">
|
||||
<verse type="chorus" label="1">
|
||||
<![CDATA[ ... ]]>
|
||||
</verse>
|
||||
</lyrics>
|
||||
</song>
|
||||
"""
|
||||
|
||||
import logging
|
||||
import datetime
|
||||
from xml.dom.minidom import Document
|
||||
from xml.etree.ElementTree import dump
|
||||
from lxml import etree, objectify
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# TODO: These classes need to be refactored into a single class.
|
||||
class CountdownXMLBuilder(object):
|
||||
"""
|
||||
This class builds the XML used to describe songs.
|
||||
"""
|
||||
log.info('CountdownXMLBuilder Loaded')
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Set up the countdown builder.
|
||||
"""
|
||||
# Create the minidom document
|
||||
self.countdown_xml = Document()
|
||||
self.new_document()
|
||||
self.add_lyrics_to_song()
|
||||
|
||||
def new_document(self):
|
||||
"""
|
||||
Create a new countdown XML document.
|
||||
"""
|
||||
# Create the <song> base element
|
||||
self.song = self.countdown_xml.createElement('song')
|
||||
self.countdown_xml.appendChild(self.song)
|
||||
self.song.setAttribute('version', '1.0')
|
||||
|
||||
def add_lyrics_to_song(self):
|
||||
"""
|
||||
Set up and add a ``<lyrics>`` tag which contains the lyrics of the
|
||||
countdown item.
|
||||
"""
|
||||
# Create the main <lyrics> element
|
||||
self.lyrics = self.countdown_xml.createElement('lyrics')
|
||||
self.lyrics.setAttribute('language', 'en')
|
||||
self.song.appendChild(self.lyrics)
|
||||
|
||||
def add_verse_to_lyrics(self, verse_type, number, content):
|
||||
"""
|
||||
Add a verse to the ``<lyrics>`` tag.
|
||||
|
||||
:param verse_type: A string denoting the type of verse. Possible values are "Chorus", "Verse", "Bridge",
|
||||
and "Countdown".
|
||||
:param number: An integer denoting the number of the item, for example: verse 1.
|
||||
:param content: The actual text of the verse to be stored.
|
||||
|
||||
"""
|
||||
verse = self.countdown_xml.createElement('verse')
|
||||
verse.setAttribute('type', verse_type)
|
||||
verse.setAttribute('label', number)
|
||||
self.lyrics.appendChild(verse)
|
||||
# add data as a CDATA section to protect the XML from special chars
|
||||
cds = self.countdown_xml.createCDATASection(content)
|
||||
verse.appendChild(cds)
|
||||
|
||||
def _dump_xml(self):
|
||||
"""
|
||||
Debugging aid to dump XML so that we can see what we have.
|
||||
"""
|
||||
return self.countdown_xml.toprettyxml(indent=' ')
|
||||
|
||||
def extract_xml(self):
|
||||
"""
|
||||
Extract our newly created XML countdown.
|
||||
"""
|
||||
return self.countdown_xml.toxml('utf-8')
|
||||
|
||||
|
||||
class CountdownXMLParser(object):
|
||||
"""
|
||||
A class to read in and parse a countdown's XML.
|
||||
"""
|
||||
log.info('CountdownXMLParser Loaded')
|
||||
|
||||
def __init__(self, xml):
|
||||
"""
|
||||
Set up our countdown XML parser.
|
||||
|
||||
:param xml: The XML of the countdown to be parsed.
|
||||
"""
|
||||
self.countdown_xml = None
|
||||
if xml[:5] == '<?xml':
|
||||
xml = xml[38:]
|
||||
try:
|
||||
self.countdown_xml = objectify.fromstring(xml)
|
||||
except etree.XMLSyntaxError:
|
||||
log.exception('Invalid xml %s', xml)
|
||||
|
||||
def get_time_remaining(self):
|
||||
"""
|
||||
Iterates through the verses in the XML and returns a list of verses and their attributes.
|
||||
"""
|
||||
"""xml_iter = self.countdown_xml.getiterator()
|
||||
verse_list = []
|
||||
for element in xml_iter:
|
||||
if element.tag == 'verse':
|
||||
if element.text is None:
|
||||
element.text = ''
|
||||
verse_list.append([element.attrib, str(element.text)])
|
||||
"""
|
||||
time_remaining = datetime.datetime(2011, 5, 5) - datetime.datetime.now()
|
||||
return str(time_remaining)
|
||||
|
||||
def get_countdown_item_settings(self):
|
||||
test = 'test data'
|
||||
return test
|
||||
|
||||
def _dump_xml(self):
|
||||
"""
|
||||
Debugging aid to dump XML so that we can see what we have.
|
||||
"""
|
||||
return dump(self.countdown_xml)
|
|
@ -0,0 +1,85 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, 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 #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`db` module provides the database and schema that is the backend for
|
||||
the Countdown plugin
|
||||
"""
|
||||
|
||||
from sqlalchemy import Column, Table, types
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from openlp.core.lib.db import BaseModel, init_db
|
||||
from openlp.core.common.i18n import get_locale_key
|
||||
|
||||
|
||||
class CountdownSlide(BaseModel):
|
||||
"""
|
||||
CountdownSlide model
|
||||
"""
|
||||
# By default sort the countdowns by its title considering language specific characters.
|
||||
def __lt__(self, other):
|
||||
return get_locale_key(self.title) < get_locale_key(other.title)
|
||||
|
||||
def __eq__(self, other):
|
||||
return get_locale_key(self.title) == get_locale_key(other.title)
|
||||
|
||||
def __hash__(self):
|
||||
"""
|
||||
Return the hash for a countdown slide.
|
||||
"""
|
||||
return self.id
|
||||
|
||||
|
||||
def init_schema(url):
|
||||
"""
|
||||
Setup the countdown database connection and initialise the database schema
|
||||
|
||||
:param url: The database to setup
|
||||
"""
|
||||
session, metadata = init_db(url)
|
||||
|
||||
countdown_slide_table = Table('countdown_slide', metadata,
|
||||
Column('id', types.Integer(), primary_key=True),
|
||||
Column('title', types.Unicode(255), nullable=False),
|
||||
Column('countdown_type', types.Integer),
|
||||
Column('countdown_duration', types.Time),
|
||||
Column('countdown_use_specific_date', types.Unicode(2)),
|
||||
Column('countdown_specific_date', types.Date),
|
||||
Column('countdown_use_specific_time', types.Unicode(2)),
|
||||
Column('countdown_specific_time', types.Time),
|
||||
Column('interval_large', types.Integer),
|
||||
Column('interval_small', types.Integer),
|
||||
Column('finish_action', types.Integer),
|
||||
Column('theme_name', types.Unicode(128))
|
||||
)
|
||||
|
||||
mapper(CountdownSlide, countdown_slide_table)
|
||||
|
||||
metadata.create_all(checkfirst=True)
|
||||
return session
|
|
@ -0,0 +1,317 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# ountdown copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, 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 #
|
||||
###############################################################################
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt5 import QtGui, QtCore, QtWidgets
|
||||
from PyQt5.QtWidgets import QDialog
|
||||
from sqlalchemy.sql import or_, func, and_
|
||||
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.common.settings import Settings
|
||||
from openlp.core.common.i18n import UiStrings, translate
|
||||
from openlp.core.lib.mediamanageritem import MediaManagerItem
|
||||
from openlp.core.lib.serviceitem import ItemCapabilities
|
||||
from openlp.core.lib.plugin import PluginStatus
|
||||
from openlp.core.lib import ServiceItemContext, check_item_selected
|
||||
from openlp.plugins.countdown.forms.editcountdownform import EditCountdownForm
|
||||
from openlp.plugins.countdown.lib.db import CountdownSlide
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CountdownSearch(object):
|
||||
"""
|
||||
An enumeration for countdown search methods.
|
||||
"""
|
||||
Titles = 1
|
||||
Themes = 2
|
||||
|
||||
|
||||
class CountdownMediaItem(MediaManagerItem):
|
||||
"""
|
||||
This is the countdown media manager item for Countdown Slides.
|
||||
"""
|
||||
log.info('Countdown Media Item loaded')
|
||||
|
||||
def __init__(self, parent, plugin):
|
||||
self.icon_path = 'countdown/countdown'
|
||||
super(CountdownMediaItem, self).__init__(parent, plugin)
|
||||
|
||||
def setup_item(self):
|
||||
"""
|
||||
Do some additional setup.
|
||||
"""
|
||||
self.edit_countdown_form = EditCountdownForm(self, self.main_window, self.plugin.db_manager)
|
||||
self.single_service_item = False
|
||||
self.quick_preview_allowed = True
|
||||
self.has_search = True
|
||||
# Holds information about whether the edit is remotely triggered and
|
||||
# which Countdown is required.
|
||||
self.remote_countdown = -1
|
||||
|
||||
def add_end_header_bar(self):
|
||||
"""
|
||||
Add the Countdown End Head bar and register events and functions
|
||||
"""
|
||||
self.toolbar.addSeparator()
|
||||
self.add_search_to_toolbar()
|
||||
# Signals and slots
|
||||
QtCore.QObject.connect(self.search_text_edit, QtCore.SIGNAL('cleared()'), self.on_clear_text_button_click)
|
||||
QtCore.QObject.connect(self.search_text_edit, QtCore.SIGNAL('searchTypeChanged(int)'),
|
||||
self.on_search_text_button_clicked)
|
||||
Registry().register_function('countdown_load_list', self.load_list)
|
||||
Registry().register_function('countdown_preview', self.on_preview_click)
|
||||
# Registry().register_function('countdown_create_from_service', self.create_from_service_item)
|
||||
|
||||
def config_update(self):
|
||||
"""
|
||||
Config has been updated so reload values
|
||||
"""
|
||||
log.debug('Config loaded')
|
||||
|
||||
def retranslateUi(self):
|
||||
"""
|
||||
|
||||
|
||||
"""
|
||||
self.search_text_label.setText('%s:' % UiStrings().Search)
|
||||
self.search_text_button.setText(UiStrings().Search)
|
||||
|
||||
def initialise(self):
|
||||
"""
|
||||
Initialise the UI so it can provide Searches
|
||||
"""
|
||||
self.search_text_edit.set_search_types(
|
||||
[(CountdownSearch.Titles, ':/songs/song_search_title.png', translate('SongsPlugin.MediaItem', 'Titles'),
|
||||
translate('SongsPlugin.MediaItem', 'Search Titles...')),
|
||||
(CountdownSearch.Themes, ':/slides/slide_theme.png', UiStrings().Themes, UiStrings().SearchThemes)])
|
||||
self.search_text_edit.set_current_search_type(Settings().value('%s/last search type' % self.settings_section))
|
||||
self.load_list(self.plugin.db_manager.get_all_objects(CountdownSlide, order_by_ref=CountdownSlide.title))
|
||||
self.config_update()
|
||||
|
||||
def load_list(self, countdown_slides, target_group=None):
|
||||
# Sort out what countdown we want to select after loading the list.
|
||||
"""
|
||||
|
||||
:param countdown_slides:
|
||||
:param target_group:
|
||||
"""
|
||||
self.save_auto_select_id()
|
||||
self.list_view.clear()
|
||||
countdown_slides.sort()
|
||||
for countdown_slide in countdown_slides:
|
||||
countdown_name = QtGui.QListWidgetItem(countdown_slide.title)
|
||||
countdown_name.setData(QtCore.Qt.UserRole, countdown_slide.id)
|
||||
self.list_view.addItem(countdown_name)
|
||||
# Auto-select the countdown.
|
||||
if countdown_slide.id == self.auto_select_id:
|
||||
self.list_view.setCurrentItem(countdown_name)
|
||||
self.auto_select_id = -1
|
||||
# Called to redisplay the countdown list screen edith from a search
|
||||
# or from the exit of the Countdown edit dialog. If remote editing is
|
||||
# active trigger it and clean up so it will not update again.
|
||||
|
||||
def on_new_click(self):
|
||||
"""
|
||||
Handle the New item event
|
||||
"""
|
||||
self.edit_countdown_form.load_countdown(0)
|
||||
self.edit_countdown_form.exec_()
|
||||
self.on_clear_text_button_click()
|
||||
self.on_selection_change()
|
||||
|
||||
def on_remote_edit(self, countdown_id, preview=False):
|
||||
"""
|
||||
Called by ServiceManager or SlideController by event passing the countdown Id in the payload along with an
|
||||
indicator to say which type of display is required.
|
||||
|
||||
:param countdown_id: The id of the item to be edited
|
||||
:param preview: Do we need to update the Preview after the edit. (Default False)
|
||||
"""
|
||||
countdown_id = int(countdown_id)
|
||||
valid = self.plugin.db_manager.get_object(CountdownSlide, countdown_id)
|
||||
if valid:
|
||||
self.edit_countdown_form.load_countdown(countdown_id, preview)
|
||||
if self.edit_countdown_form.exec_() == QDialog.Accepted:
|
||||
self.remote_triggered = True
|
||||
self.remote_countdown = countdown_id
|
||||
self.auto_select_id = -1
|
||||
self.on_search_text_button_clicked()
|
||||
item = self.build_service_item(remote=True)
|
||||
self.remote_triggered = None
|
||||
self.remote_countdown = 1
|
||||
if item:
|
||||
return item
|
||||
return None
|
||||
|
||||
def on_edit_click(self):
|
||||
"""
|
||||
Edit a countdown item
|
||||
"""
|
||||
if check_item_selected(self.list_view, UiStrings().SelectEdit):
|
||||
item = self.list_view.currentItem()
|
||||
item_id = item.data(QtCore.Qt.UserRole)
|
||||
self.edit_countdown_form.load_countdown(item_id, False)
|
||||
self.edit_countdown_form.exec_()
|
||||
self.auto_select_id = -1
|
||||
self.on_search_text_button_clicked()
|
||||
|
||||
def on_delete_click(self):
|
||||
"""
|
||||
Remove a countdown item from the list and database
|
||||
"""
|
||||
if check_item_selected(self.list_view, UiStrings().SelectDelete):
|
||||
items = self.list_view.selectedIndexes()
|
||||
if QtWidgets.QMessageBox.question(self, UiStrings().ConfirmDelete,
|
||||
translate('CountdownPlugin.MediaItem',
|
||||
'Are you sure you want to delete the %n selected countdown slide(s)?',
|
||||
'', QtCore.QCoreApplication.CodecForTr, len(items)),
|
||||
QtWidgets.QMessageBox.StandardButtons(
|
||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No),
|
||||
QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.No:
|
||||
return
|
||||
row_list = [item.row() for item in self.list_view.selectedIndexes()]
|
||||
row_list.sort(reverse=True)
|
||||
id_list = [(item.data(QtCore.Qt.UserRole)) for item in self.list_view.selectedIndexes()]
|
||||
for id in id_list:
|
||||
self.plugin.db_manager.delete_object(CountdownSlide, id)
|
||||
self.on_search_text_button_clicked()
|
||||
|
||||
def on_focus(self):
|
||||
"""
|
||||
Set the focus
|
||||
"""
|
||||
self.search_text_edit.setFocus()
|
||||
|
||||
def generate_slide_data(self, service_item, item=None, xml_version=False,
|
||||
remote=False, context=ServiceItemContext.Service):
|
||||
"""
|
||||
Generate the slide data. Needs to be implemented by the plugin.
|
||||
:param service_item: To be updated
|
||||
:param item: The countdown database item to be used
|
||||
:param xml_version: No used
|
||||
:param remote: Is this triggered by the Preview Controller or Service Manager.
|
||||
:param context: Why is this item required to be build (Default Service).
|
||||
"""
|
||||
item_id = self._get_id_of_item_to_generate(item, self.remote_countdown)
|
||||
service_item.add_capability(ItemCapabilities.CanEdit)
|
||||
service_item.add_capability(ItemCapabilities.CanPreview)
|
||||
service_item.add_capability(ItemCapabilities.CanLoop)
|
||||
service_item.add_capability(ItemCapabilities.CanSoftBreak)
|
||||
service_item.add_capability(ItemCapabilities.OnLoadUpdate)
|
||||
service_item.add_capability(ItemCapabilities.CanAutoStartForLive)
|
||||
service_item.add_capability(ItemCapabilities.CanEditTitle)
|
||||
countdown_slide = self.plugin.db_manager.get_object(CountdownSlide, item_id)
|
||||
title = countdown_slide.title
|
||||
service_item.edit_id = item_id
|
||||
theme = countdown_slide.theme_name
|
||||
if theme:
|
||||
service_item.theme = theme
|
||||
service_item.title = "Countdown until " + title
|
||||
service_item.processor = 'webkit'
|
||||
service_item.add_from_text("Countdown until " + title)
|
||||
return True
|
||||
|
||||
def on_search_text_button_clicked(self):
|
||||
"""
|
||||
Search the plugin database
|
||||
"""
|
||||
# Save the current search type to the configuration.
|
||||
Settings().setValue('%s/last search type' % self.settings_section, self.search_text_edit.current_search_type())
|
||||
# Reload the list considering the new search type.
|
||||
search_type = self.search_text_edit.current_search_type()
|
||||
search_keywords = '%' + self.whitespace.sub(' ', self.search_text_edit.displayText()) + '%'
|
||||
if search_type == CountdownSearch.Titles:
|
||||
log.debug('Titles Search')
|
||||
search_results = self.plugin.db_manager.get_all_objects(CountdownSlide,
|
||||
CountdownSlide.title.like(search_keywords),
|
||||
order_by_ref=CountdownSlide.title)
|
||||
self.load_list(search_results)
|
||||
elif search_type == CountdownSearch.Themes:
|
||||
log.debug('Theme Search')
|
||||
search_results = self.plugin.db_manager.get_all_objects(CountdownSlide,
|
||||
CountdownSlide.theme_name.like(search_keywords),
|
||||
order_by_ref=CountdownSlide.title)
|
||||
self.load_list(search_results)
|
||||
self.check_search_result()
|
||||
|
||||
def on_search_text_edit_changed(self, text):
|
||||
"""
|
||||
If search as type enabled invoke the search on each key press. If the Title is being searched do not start until
|
||||
2 characters have been entered.
|
||||
|
||||
:param text: The search text
|
||||
"""
|
||||
search_length = 2
|
||||
if len(text) > search_length:
|
||||
self.on_search_text_button_clicked()
|
||||
elif not text:
|
||||
self.on_clear_text_button_click()
|
||||
|
||||
def service_load(self, item):
|
||||
"""
|
||||
Triggered by a countdown item being loaded by the service manager.
|
||||
|
||||
:param item: The service Item from the service to load found in the database.
|
||||
"""
|
||||
log.debug('service_load')
|
||||
if self.plugin.status != PluginStatus.Active:
|
||||
return
|
||||
countdown = self.plugin.db_manager.get_object_filtered(CountdownSlide, and_(CountdownSlide.title == item.title,
|
||||
CountdownSlide.theme_name == item.theme,
|
||||
CountdownSlide.credits ==
|
||||
item.raw_footer[0][len(item.title) + 1:]))
|
||||
if countdown:
|
||||
item.edit_id = countdown.id
|
||||
return item
|
||||
else:
|
||||
if self.add_countdown_from_service:
|
||||
self.create_from_service_item(item)
|
||||
|
||||
def on_clear_text_button_click(self):
|
||||
"""
|
||||
Clear the search text.
|
||||
"""
|
||||
self.search_text_edit.clear()
|
||||
self.on_search_text_button_clicked()
|
||||
|
||||
def search(self, string, show_error):
|
||||
"""
|
||||
Search the database for a given item.
|
||||
|
||||
:param string: The search string
|
||||
:param show_error: The error string to be show.
|
||||
"""
|
||||
search = '%' + string.lower() + '%'
|
||||
search_results = self.plugin.db_manager.get_all_objects(CountdownSlide,
|
||||
or_(func.lower(CountdownSlide.title).like(search),
|
||||
func.lower(CountdownSlide.text).like(search)),
|
||||
order_by_ref=CountdownSlide.title)
|
||||
return [[countdown.id, countdown.title] for countdown in search_results]
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
countdown.js v2.3.4 http://countdownjs.org
|
||||
Copyright (c)2006-2012 Stephen M. McKamey.
|
||||
Licensed under The MIT License.
|
||||
*/
|
||||
var module,countdown=function(r){function v(a,b){var c=a.getTime();a.setUTCMonth(a.getUTCMonth()+b);return Math.round((a.getTime()-c)/864E5)}function t(a){var b=a.getTime(),c=new Date(b);c.setUTCMonth(a.getUTCMonth()+1);return Math.round((c.getTime()-b)/864E5)}function f(a,b){return a+" "+(1===a?p[b]:q[b])}function n(){}function l(a,b,c,g,x,d){0<=a[c]&&(b+=a[c],delete a[c]);b/=x;if(1>=b+1)return 0;if(0<=a[g]){a[g]=+(a[g]+b).toFixed(d);switch(g){case "seconds":if(60!==a.seconds||isNaN(a.minutes))break;
|
||||
a.minutes++;a.seconds=0;case "minutes":if(60!==a.minutes||isNaN(a.hours))break;a.hours++;a.minutes=0;case "hours":if(24!==a.hours||isNaN(a.days))break;a.days++;a.hours=0;case "days":if(7!==a.days||isNaN(a.weeks))break;a.weeks++;a.days=0;case "weeks":if(a.weeks!==t(a.refMonth)/7||isNaN(a.months))break;a.months++;a.weeks=0;case "months":if(12!==a.months||isNaN(a.years))break;a.years++;a.months=0;case "years":if(10!==a.years||isNaN(a.decades))break;a.decades++;a.years=0;case "decades":if(10!==a.decades||
|
||||
isNaN(a.centuries))break;a.centuries++;a.decades=0;case "centuries":if(10!==a.centuries||isNaN(a.millennia))break;a.millennia++;a.centuries=0}return 0}return b}function w(a,b,c,g,d,k){a.start=b;a.end=c;a.units=g;a.value=c.getTime()-b.getTime();if(0>a.value){var f=c;c=b;b=f}a.refMonth=new Date(b.getFullYear(),b.getMonth(),15);try{a.millennia=0;a.centuries=0;a.decades=0;a.years=c.getUTCFullYear()-b.getUTCFullYear();a.months=c.getUTCMonth()-b.getUTCMonth();a.weeks=0;a.days=c.getUTCDate()-b.getUTCDate();
|
||||
a.hours=c.getUTCHours()-b.getUTCHours();a.minutes=c.getUTCMinutes()-b.getUTCMinutes();a.seconds=c.getUTCSeconds()-b.getUTCSeconds();a.milliseconds=c.getUTCMilliseconds()-b.getUTCMilliseconds();var h;0>a.milliseconds?(h=s(-a.milliseconds/1E3),a.seconds-=h,a.milliseconds+=1E3*h):1E3<=a.milliseconds&&(a.seconds+=m(a.milliseconds/1E3),a.milliseconds%=1E3);0>a.seconds?(h=s(-a.seconds/60),a.minutes-=h,a.seconds+=60*h):60<=a.seconds&&(a.minutes+=m(a.seconds/60),a.seconds%=60);0>a.minutes?(h=s(-a.minutes/
|
||||
60),a.hours-=h,a.minutes+=60*h):60<=a.minutes&&(a.hours+=m(a.minutes/60),a.minutes%=60);0>a.hours?(h=s(-a.hours/24),a.days-=h,a.hours+=24*h):24<=a.hours&&(a.days+=m(a.hours/24),a.hours%=24);for(;0>a.days;)a.months--,a.days+=v(a.refMonth,1);7<=a.days&&(a.weeks+=m(a.days/7),a.days%=7);0>a.months?(h=s(-a.months/12),a.years-=h,a.months+=12*h):12<=a.months&&(a.years+=m(a.months/12),a.months%=12);10<=a.years&&(a.decades+=m(a.years/10),a.years%=10,10<=a.decades&&(a.centuries+=m(a.decades/10),a.decades%=
|
||||
10,10<=a.centuries&&(a.millennia+=m(a.centuries/10),a.centuries%=10)));b=0;!(g&1024)||b>=d?(a.centuries+=10*a.millennia,delete a.millennia):a.millennia&&b++;!(g&512)||b>=d?(a.decades+=10*a.centuries,delete a.centuries):a.centuries&&b++;!(g&256)||b>=d?(a.years+=10*a.decades,delete a.decades):a.decades&&b++;!(g&128)||b>=d?(a.months+=12*a.years,delete a.years):a.years&&b++;!(g&64)||b>=d?(a.months&&(a.days+=v(a.refMonth,a.months)),delete a.months,7<=a.days&&(a.weeks+=m(a.days/7),a.days%=7)):a.months&&
|
||||
b++;!(g&32)||b>=d?(a.days+=7*a.weeks,delete a.weeks):a.weeks&&b++;!(g&16)||b>=d?(a.hours+=24*a.days,delete a.days):a.days&&b++;!(g&8)||b>=d?(a.minutes+=60*a.hours,delete a.hours):a.hours&&b++;!(g&4)||b>=d?(a.seconds+=60*a.minutes,delete a.minutes):a.minutes&&b++;!(g&2)||b>=d?(a.milliseconds+=1E3*a.seconds,delete a.seconds):a.seconds&&b++;if(!(g&1)||b>=d){var e=l(a,0,"milliseconds","seconds",1E3,k);if(e&&(e=l(a,e,"seconds","minutes",60,k))&&(e=l(a,e,"minutes","hours",60,k))&&(e=l(a,e,"hours","days",
|
||||
24,k))&&(e=l(a,e,"days","weeks",7,k))&&(e=l(a,e,"weeks","months",t(a.refMonth)/7,k))){g=e;var n,p=a.refMonth,q=p.getTime(),r=new Date(q);r.setUTCFullYear(p.getUTCFullYear()+1);n=Math.round((r.getTime()-q)/864E5);if(e=l(a,g,"months","years",n/t(a.refMonth),k))if(e=l(a,e,"years","decades",10,k))if(e=l(a,e,"decades","centuries",10,k))if(e=l(a,e,"centuries","millennia",10,k))throw Error("Fractional unit overflow");}}}finally{delete a.refMonth}return a}function d(a,b,c,d,f){var k;c=+c||222;d=0<d?d:NaN;
|
||||
f=0<f?20>f?Math.round(f):20:0;"function"===typeof a?(k=a,a=null):a instanceof Date||(a=null!==a&&isFinite(a)?new Date(a):null);"function"===typeof b?(k=b,b=null):b instanceof Date||(b=null!==b&&isFinite(b)?new Date(b):null);if(!a&&!b)return new n;if(!k)return w(new n,a||new Date,b||new Date,c,d,f);var l=c&1?1E3/30:c&2?1E3:c&4?6E4:c&8?36E5:c&16?864E5:6048E5,h,e=function(){k(w(new n,a||new Date,b||new Date,c,d,f),h)};e();return h=setInterval(e,l)}var s=Math.ceil,m=Math.floor,p,q,u;n.prototype.toString=
|
||||
function(){var a=u(this),b=a.length;if(!b)return"";1<b&&(a[b-1]="and "+a[b-1]);return a.join(", ")};n.prototype.toHTML=function(a){a=a||"span";var b=u(this),c=b.length;if(!c)return"";for(var d=0;d<c;d++)b[d]="\x3c"+a+"\x3e"+b[d]+"\x3c/"+a+"\x3e";--c&&(b[c]="and "+b[c]);return b.join(", ")};u=function(a){var b=[],c=a.millennia;c&&b.push(f(c,10));(c=a.centuries)&&b.push(f(c,9));(c=a.decades)&&b.push(f(c,8));(c=a.years)&&b.push(f(c,7));(c=a.months)&&b.push(f(c,6));(c=a.weeks)&&b.push(f(c,5));(c=a.days)&&
|
||||
b.push(f(c,4));(c=a.hours)&&b.push(f(c,3));(c=a.minutes)&&b.push(f(c,2));(c=a.seconds)&&b.push(f(c,1));(c=a.milliseconds)&&b.push(f(c,0));return b};d.MILLISECONDS=1;d.SECONDS=2;d.MINUTES=4;d.HOURS=8;d.DAYS=16;d.WEEKS=32;d.MONTHS=64;d.YEARS=128;d.DECADES=256;d.CENTURIES=512;d.MILLENNIA=1024;d.DEFAULTS=222;d.ALL=2047;d.setLabels=function(a,b){a=a||[];a.split&&(a=a.split("|"));b=b||[];b.split&&(b=b.split("|"));for(var c=0;10>=c;c++)p[c]=a[c]||p[c],q[c]=b[c]||q[c]};(d.resetLabels=function(){p="millisecond second minute hour day week month year decade century millennium".split(" ");
|
||||
q="milliseconds seconds minutes hours days weeks months years decades centuries millennia".split(" ")})();r&&r.exports?r.exports=d:"function"===typeof window.define&&window.define.amd&&window.define("countdown",[],function(){return d});return d}(module);
|
||||
function update_countdown_text(){
|
||||
show_text(countdown( new Date(2014, 11, 28) ).toString());
|
||||
timer2 = window.setTimeout(function(){update_countdown_text()}, 100);
|
||||
}
|
||||
var timer2 = window.setTimeout(function(){update_countdown_text()}, 100);
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue