mirror of https://gitlab.com/openlp/openlp.git
Merge branch 'feature/add-countdown-timer' into 'master'
WIP: Feature/add countdown timer See merge request openlp/openlp!29
This commit is contained in:
commit
3c15ed94c1
|
@ -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);
|
Loading…
Reference in New Issue