forked from openlp/openlp
r1723
This commit is contained in:
commit
dd00f95f64
@ -137,7 +137,7 @@ def image_to_byte(image):
|
||||
# convert to base64 encoding so does not get missed!
|
||||
return byte_array.toBase64()
|
||||
|
||||
def resize_image(image_path, width, height, background=QtCore.Qt.black):
|
||||
def resize_image(image_path, width, height, background):
|
||||
"""
|
||||
Resize an image to fit on the current screen.
|
||||
|
||||
|
@ -31,11 +31,13 @@ import logging
|
||||
import os
|
||||
|
||||
from PyQt4 import QtCore
|
||||
from sqlalchemy import create_engine, MetaData
|
||||
from sqlalchemy.exc import InvalidRequestError
|
||||
from sqlalchemy.orm import scoped_session, sessionmaker
|
||||
from sqlalchemy import Table, MetaData, Column, types, create_engine
|
||||
from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError
|
||||
from sqlalchemy.orm import scoped_session, sessionmaker, mapper
|
||||
from sqlalchemy.pool import NullPool
|
||||
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
from openlp.core.utils import AppLocation, delete_file
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -59,6 +61,48 @@ def init_db(url, auto_flush=True, auto_commit=False):
|
||||
autocommit=auto_commit, bind=engine))
|
||||
return session, metadata
|
||||
|
||||
|
||||
def upgrade_db(url, upgrade):
|
||||
"""
|
||||
Upgrade a database.
|
||||
|
||||
``url``
|
||||
The url of the database to upgrade.
|
||||
|
||||
``upgrade``
|
||||
The python module that contains the upgrade instructions.
|
||||
"""
|
||||
session, metadata = init_db(url)
|
||||
tables = upgrade.upgrade_setup(metadata)
|
||||
metadata_table = Table(u'metadata', metadata,
|
||||
Column(u'key', types.Unicode(64), primary_key=True),
|
||||
Column(u'value', types.UnicodeText(), default=None)
|
||||
)
|
||||
metadata_table.create(checkfirst=True)
|
||||
mapper(Metadata, metadata_table)
|
||||
version_meta = session.query(Metadata).get(u'version')
|
||||
if version_meta is None:
|
||||
version_meta = Metadata.populate(key=u'version', value=u'0')
|
||||
version = 0
|
||||
else:
|
||||
version = int(version_meta.value)
|
||||
if version > upgrade.__version__:
|
||||
return version, upgrade.__version__
|
||||
version += 1
|
||||
while hasattr(upgrade, u'upgrade_%d' % version):
|
||||
log.debug(u'Running upgrade_%d', version)
|
||||
try:
|
||||
getattr(upgrade, u'upgrade_%d' % version)(session, metadata, tables)
|
||||
version_meta.value = unicode(version)
|
||||
except SQLAlchemyError, DBAPIError:
|
||||
log.exception(u'Could not run database upgrade script "upgrade_%s"'\
|
||||
', upgrade process has been halted.', version)
|
||||
break
|
||||
version += 1
|
||||
session.add(version_meta)
|
||||
session.commit()
|
||||
return int(version_meta.value), upgrade.__version__
|
||||
|
||||
def delete_database(plugin_name, db_file_name=None):
|
||||
"""
|
||||
Remove a database file from the system.
|
||||
@ -79,6 +123,7 @@ def delete_database(plugin_name, db_file_name=None):
|
||||
AppLocation.get_section_data_path(plugin_name), plugin_name)
|
||||
return delete_file(db_file_path)
|
||||
|
||||
|
||||
class BaseModel(object):
|
||||
"""
|
||||
BaseModel provides a base object with a set of generic functions
|
||||
@ -94,11 +139,19 @@ class BaseModel(object):
|
||||
return instance
|
||||
|
||||
|
||||
class Metadata(BaseModel):
|
||||
"""
|
||||
Provides a class for the metadata table.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class Manager(object):
|
||||
"""
|
||||
Provide generic object persistence management
|
||||
"""
|
||||
def __init__(self, plugin_name, init_schema, db_file_name=None):
|
||||
def __init__(self, plugin_name, init_schema, db_file_name=None,
|
||||
upgrade_mod=None):
|
||||
"""
|
||||
Runs the initialisation process that includes creating the connection
|
||||
to the database and the tables if they don't exist.
|
||||
@ -109,6 +162,9 @@ class Manager(object):
|
||||
``init_schema``
|
||||
The init_schema function for this database
|
||||
|
||||
``upgrade_schema``
|
||||
The upgrade_schema function for this database
|
||||
|
||||
``db_file_name``
|
||||
The file name to use for this database. Defaults to None resulting
|
||||
in the plugin_name being used.
|
||||
@ -134,7 +190,27 @@ class Manager(object):
|
||||
unicode(settings.value(u'db hostname').toString()),
|
||||
unicode(settings.value(u'db database').toString()))
|
||||
settings.endGroup()
|
||||
self.session = init_schema(self.db_url)
|
||||
if upgrade_mod:
|
||||
db_ver, up_ver = upgrade_db(self.db_url, upgrade_mod)
|
||||
if db_ver > up_ver:
|
||||
critical_error_message_box(
|
||||
translate('OpenLP.Manager', 'Database Error'),
|
||||
unicode(translate('OpenLP.Manager', 'The database being '
|
||||
'loaded was created in a more recent version of '
|
||||
'OpenLP. The database is version %d, while OpenLP '
|
||||
'expects version %d. The database will not be loaded.'
|
||||
'\n\nDatabase: %s')) % \
|
||||
(db_ver, up_ver, self.db_url)
|
||||
)
|
||||
return
|
||||
try:
|
||||
self.session = init_schema(self.db_url)
|
||||
except:
|
||||
critical_error_message_box(
|
||||
translate('OpenLP.Manager', 'Database Error'),
|
||||
unicode(translate('OpenLP.Manager', 'OpenLP cannot load your '
|
||||
'database.\n\nDatabase: %s')) % self.db_url
|
||||
)
|
||||
|
||||
def save_object(self, object_instance, commit=True):
|
||||
"""
|
||||
@ -223,7 +299,9 @@ class Manager(object):
|
||||
query = self.session.query(object_class)
|
||||
if filter_clause is not None:
|
||||
query = query.filter(filter_clause)
|
||||
if order_by_ref is not None:
|
||||
if isinstance(order_by_ref, list):
|
||||
return query.order_by(*order_by_ref).all()
|
||||
elif order_by_ref is not None:
|
||||
return query.order_by(order_by_ref).all()
|
||||
return query.all()
|
||||
|
||||
|
@ -36,7 +36,7 @@ import Queue
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib import resize_image, image_to_byte
|
||||
from openlp.core.lib import resize_image, image_to_byte, Receiver
|
||||
from openlp.core.ui import ScreenList
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -100,12 +100,14 @@ class Image(object):
|
||||
variables ``image`` and ``image_bytes`` to ``None`` and add the image object
|
||||
to the queue of images to process.
|
||||
"""
|
||||
def __init__(self, name='', path=''):
|
||||
def __init__(self, name, path, source, background):
|
||||
self.name = name
|
||||
self.path = path
|
||||
self.image = None
|
||||
self.image_bytes = None
|
||||
self.priority = Priority.Normal
|
||||
self.source = source
|
||||
self.background = background
|
||||
|
||||
|
||||
class PriorityQueue(Queue.PriorityQueue):
|
||||
@ -151,6 +153,8 @@ class ImageManager(QtCore.QObject):
|
||||
self._cache = {}
|
||||
self._imageThread = ImageThread(self)
|
||||
self._conversion_queue = PriorityQueue()
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'config_updated'), self.process_updates)
|
||||
|
||||
def update_display(self):
|
||||
"""
|
||||
@ -162,12 +166,42 @@ class ImageManager(QtCore.QObject):
|
||||
self.height = current_screen[u'size'].height()
|
||||
# Mark the images as dirty for a rebuild by setting the image and byte
|
||||
# stream to None.
|
||||
self._conversion_queue = PriorityQueue()
|
||||
for key, image in self._cache.iteritems():
|
||||
image.priority = Priority.Normal
|
||||
image.image = None
|
||||
image.image_bytes = None
|
||||
self._conversion_queue.put((image.priority, image))
|
||||
self._reset_image(image)
|
||||
|
||||
def update_images(self, image_type, background):
|
||||
"""
|
||||
Border has changed so update all the images affected.
|
||||
"""
|
||||
log.debug(u'update_images')
|
||||
# Mark the images as dirty for a rebuild by setting the image and byte
|
||||
# stream to None.
|
||||
for key, image in self._cache.iteritems():
|
||||
if image.source == image_type:
|
||||
image.background = background
|
||||
self._reset_image(image)
|
||||
|
||||
def update_image(self, name, image_type, background):
|
||||
"""
|
||||
Border has changed so update the image affected.
|
||||
"""
|
||||
log.debug(u'update_images')
|
||||
# Mark the images as dirty for a rebuild by setting the image and byte
|
||||
# stream to None.
|
||||
for key, image in self._cache.iteritems():
|
||||
if image.source == image_type and image.name == name:
|
||||
image.background = background
|
||||
self._reset_image(image)
|
||||
|
||||
def _reset_image(self, image):
|
||||
image.image = None
|
||||
image.image_bytes = None
|
||||
self._conversion_queue.modify_priority(image, Priority.Normal)
|
||||
|
||||
def process_updates(self):
|
||||
"""
|
||||
Flush the queue to updated any data to update
|
||||
"""
|
||||
# We want only one thread.
|
||||
if not self._imageThread.isRunning():
|
||||
self._imageThread.start()
|
||||
@ -215,13 +249,13 @@ class ImageManager(QtCore.QObject):
|
||||
self._conversion_queue.remove(self._cache[name])
|
||||
del self._cache[name]
|
||||
|
||||
def add_image(self, name, path):
|
||||
def add_image(self, name, path, source, background):
|
||||
"""
|
||||
Add image to cache if it is not already there.
|
||||
"""
|
||||
log.debug(u'add_image %s:%s' % (name, path))
|
||||
if not name in self._cache:
|
||||
image = Image(name, path)
|
||||
image = Image(name, path, source, background)
|
||||
self._cache[name] = image
|
||||
self._conversion_queue.put((image.priority, image))
|
||||
else:
|
||||
@ -247,7 +281,8 @@ class ImageManager(QtCore.QObject):
|
||||
image = self._conversion_queue.get()[1]
|
||||
# Generate the QImage for the image.
|
||||
if image.image is None:
|
||||
image.image = resize_image(image.path, self.width, self.height)
|
||||
image.image = resize_image(image.path, self.width, self.height,
|
||||
image.background)
|
||||
# Set the priority to Lowest and stop here as we need to process
|
||||
# more important images first.
|
||||
if image.priority == Priority.Normal:
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt4 import QtCore, QtWebKit
|
||||
from PyQt4 import QtGui, QtCore, QtWebKit
|
||||
|
||||
from openlp.core.lib import ServiceItem, expand_tags, \
|
||||
build_lyrics_format_css, build_lyrics_outline_css, Receiver, \
|
||||
@ -166,7 +166,8 @@ class Renderer(object):
|
||||
# if No file do not update cache
|
||||
if self.theme_data.background_filename:
|
||||
self.imageManager.add_image(self.theme_data.theme_name,
|
||||
self.theme_data.background_filename)
|
||||
self.theme_data.background_filename, u'theme',
|
||||
QtGui.QColor(self.theme_data.background_border_color))
|
||||
return self._rect, self._rect_footer
|
||||
|
||||
def generate_preview(self, theme_data, force_page=False):
|
||||
|
@ -115,6 +115,7 @@ class ServiceItem(object):
|
||||
self.end_time = 0
|
||||
self.media_length = 0
|
||||
self.from_service = False
|
||||
self.image_border = u'#000000'
|
||||
self._new_item()
|
||||
|
||||
def _new_item(self):
|
||||
@ -195,7 +196,7 @@ class ServiceItem(object):
|
||||
self.foot_text = \
|
||||
u'<br>'.join([footer for footer in self.raw_footer if footer])
|
||||
|
||||
def add_from_image(self, path, title):
|
||||
def add_from_image(self, path, title, background=None):
|
||||
"""
|
||||
Add an image slide to the service item.
|
||||
|
||||
@ -205,9 +206,12 @@ class ServiceItem(object):
|
||||
``title``
|
||||
A title for the slide in the service item.
|
||||
"""
|
||||
if background:
|
||||
self.image_border = background
|
||||
self.service_item_type = ServiceItemType.Image
|
||||
self._raw_frames.append({u'title': title, u'path': path})
|
||||
self.renderer.imageManager.add_image(title, path)
|
||||
self.renderer.imageManager.add_image(title, path, u'image',
|
||||
self.image_border)
|
||||
self._new_item()
|
||||
|
||||
def add_from_text(self, title, raw_slide, verse_tag=None):
|
||||
|
@ -44,6 +44,7 @@ BLANK_THEME_XML = \
|
||||
<name> </name>
|
||||
<background type="image">
|
||||
<filename></filename>
|
||||
<borderColor>#000000</borderColor>
|
||||
</background>
|
||||
<background type="gradient">
|
||||
<startColor>#000000</startColor>
|
||||
@ -282,7 +283,7 @@ class ThemeXML(object):
|
||||
# Create direction element
|
||||
self.child_element(background, u'direction', unicode(direction))
|
||||
|
||||
def add_background_image(self, filename):
|
||||
def add_background_image(self, filename, borderColor):
|
||||
"""
|
||||
Add a image background.
|
||||
|
||||
@ -294,6 +295,8 @@ class ThemeXML(object):
|
||||
self.theme.appendChild(background)
|
||||
# Create Filename element
|
||||
self.child_element(background, u'filename', filename)
|
||||
# Create endColor element
|
||||
self.child_element(background, u'borderColor', unicode(borderColor))
|
||||
|
||||
def add_font(self, name, color, size, override, fonttype=u'main',
|
||||
bold=u'False', italics=u'False', line_adjustment=0,
|
||||
@ -597,7 +600,7 @@ class ThemeXML(object):
|
||||
self.background_direction)
|
||||
else:
|
||||
filename = os.path.split(self.background_filename)[1]
|
||||
self.add_background_image(filename)
|
||||
self.add_background_image(filename, self.background_border_color)
|
||||
self.add_font(self.font_main_name,
|
||||
self.font_main_color,
|
||||
self.font_main_size,
|
||||
|
@ -228,11 +228,11 @@ class MainDisplay(QtGui.QGraphicsView):
|
||||
shrinkItem.setVisible(False)
|
||||
self.setGeometry(self.screen[u'size'])
|
||||
|
||||
def directImage(self, name, path):
|
||||
def directImage(self, name, path, background):
|
||||
"""
|
||||
API for replacement backgrounds so Images are added directly to cache
|
||||
"""
|
||||
self.imageManager.add_image(name, path)
|
||||
self.imageManager.add_image(name, path, u'image', background)
|
||||
if hasattr(self, u'serviceItem'):
|
||||
self.override[u'image'] = name
|
||||
self.override[u'theme'] = self.serviceItem.themedata.theme_name
|
||||
|
@ -417,7 +417,7 @@ class Ui_MainWindow(object):
|
||||
self.settingsShortcutsItem.setText(
|
||||
translate('OpenLP.MainWindow', 'Configure &Shortcuts...'))
|
||||
self.formattingTagItem.setText(
|
||||
translate('OpenLP.MainWindow', '&Configure Formatting Tags...'))
|
||||
translate('OpenLP.MainWindow', 'Configure &Formatting Tags...'))
|
||||
self.settingsConfigureItem.setText(
|
||||
translate('OpenLP.MainWindow', '&Configure OpenLP...'))
|
||||
self.viewMediaManagerItem.setText(
|
||||
|
@ -31,7 +31,7 @@ import os
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from lxml import html
|
||||
|
||||
from openlp.core.lib import translate, get_text_file_string
|
||||
from openlp.core.lib import translate, get_text_file_string, Receiver
|
||||
from openlp.core.lib.ui import UiStrings
|
||||
from openlp.core.ui.printservicedialog import Ui_PrintServiceDialog, ZoomSize
|
||||
from openlp.core.utils import AppLocation
|
||||
@ -327,12 +327,14 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
"""
|
||||
Copies the display text to the clipboard as plain text
|
||||
"""
|
||||
self.update_song_usage()
|
||||
self.mainWindow.clipboard.setText(self.document.toPlainText())
|
||||
|
||||
def copyHtmlText(self):
|
||||
"""
|
||||
Copies the display text to the clipboard as Html
|
||||
"""
|
||||
self.update_song_usage()
|
||||
self.mainWindow.clipboard.setText(self.document.toHtml())
|
||||
|
||||
def printServiceOrder(self):
|
||||
@ -341,6 +343,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
"""
|
||||
if not self.printDialog.exec_():
|
||||
return
|
||||
self.update_song_usage()
|
||||
# Print the document.
|
||||
self.document.print_(self.printer)
|
||||
|
||||
@ -397,3 +400,9 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
settings.setValue(u'print notes',
|
||||
QtCore.QVariant(self.notesCheckBox.isChecked()))
|
||||
settings.endGroup()
|
||||
|
||||
def update_song_usage(self):
|
||||
for index, item in enumerate(self.serviceManager.serviceItems):
|
||||
# Trigger Audit requests
|
||||
Receiver.send_message(u'print_service_started',
|
||||
[item[u'service_item']])
|
||||
|
@ -66,6 +66,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
self.onGradientComboBoxCurrentIndexChanged)
|
||||
QtCore.QObject.connect(self.colorButton,
|
||||
QtCore.SIGNAL(u'clicked()'), self.onColorButtonClicked)
|
||||
QtCore.QObject.connect(self.imageColorButton,
|
||||
QtCore.SIGNAL(u'clicked()'), self.onImageColorButtonClicked)
|
||||
QtCore.QObject.connect(self.gradientStartButton,
|
||||
QtCore.SIGNAL(u'clicked()'), self.onGradientStartButtonClicked)
|
||||
QtCore.QObject.connect(self.gradientEndButton,
|
||||
@ -330,6 +332,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
self.theme.background_end_color)
|
||||
self.setField(u'background_type', QtCore.QVariant(1))
|
||||
else:
|
||||
self.imageColorButton.setStyleSheet(u'background-color: %s' %
|
||||
self.theme.background_border_color)
|
||||
self.imageFileEdit.setText(self.theme.background_filename)
|
||||
self.setField(u'background_type', QtCore.QVariant(2))
|
||||
if self.theme.background_direction == \
|
||||
@ -464,6 +468,14 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
self._colorButton(self.theme.background_color)
|
||||
self.setBackgroundPageValues()
|
||||
|
||||
def onImageColorButtonClicked(self):
|
||||
"""
|
||||
Background / Gradient 1 Color button pushed.
|
||||
"""
|
||||
self.theme.background_border_color = \
|
||||
self._colorButton(self.theme.background_border_color)
|
||||
self.setBackgroundPageValues()
|
||||
|
||||
def onGradientStartButtonClicked(self):
|
||||
"""
|
||||
Gradient 2 Color button pushed.
|
||||
@ -564,7 +576,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
|
||||
def accept(self):
|
||||
"""
|
||||
Lets save the them as Finish has been pressed
|
||||
Lets save the theme as Finish has been pressed
|
||||
"""
|
||||
# Save the theme name
|
||||
self.theme.theme_name = unicode(self.field(u'name').toString())
|
||||
|
@ -610,6 +610,11 @@ class ThemeManager(QtGui.QWidget):
|
||||
and to trigger the reload of the theme list
|
||||
"""
|
||||
self._writeTheme(theme, imageFrom, imageTo)
|
||||
if theme.background_type == \
|
||||
BackgroundType.to_string(BackgroundType.Image):
|
||||
self.mainwindow.imageManager.update_image(theme.theme_name,
|
||||
u'theme', QtGui.QColor(theme.background_border_color))
|
||||
self.mainwindow.imageManager.process_updates()
|
||||
self.loadThemes()
|
||||
|
||||
def _writeTheme(self, theme, imageFrom, imageTo):
|
||||
|
@ -105,6 +105,11 @@ class Ui_ThemeWizard(object):
|
||||
self.imageLayout = QtGui.QFormLayout(self.imageWidget)
|
||||
self.imageLayout.setMargin(0)
|
||||
self.imageLayout.setObjectName(u'ImageLayout')
|
||||
self.imageColorLabel = QtGui.QLabel(self.colorWidget)
|
||||
self.imageColorLabel.setObjectName(u'ImageColorLabel')
|
||||
self.imageColorButton = QtGui.QPushButton(self.colorWidget)
|
||||
self.imageColorButton.setObjectName(u'ImageColorButton')
|
||||
self.imageLayout.addRow(self.imageColorLabel, self.imageColorButton)
|
||||
self.imageLabel = QtGui.QLabel(self.imageWidget)
|
||||
self.imageLabel.setObjectName(u'ImageLabel')
|
||||
self.imageFileLayout = QtGui.QHBoxLayout()
|
||||
@ -118,7 +123,7 @@ class Ui_ThemeWizard(object):
|
||||
build_icon(u':/general/general_open.png'))
|
||||
self.imageFileLayout.addWidget(self.imageBrowseButton)
|
||||
self.imageLayout.addRow(self.imageLabel, self.imageFileLayout)
|
||||
self.imageLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
|
||||
self.imageLayout.setItem(2, QtGui.QFormLayout.LabelRole, self.spacer)
|
||||
self.backgroundStack.addWidget(self.imageWidget)
|
||||
self.backgroundLayout.addLayout(self.backgroundStack)
|
||||
themeWizard.addPage(self.backgroundPage)
|
||||
@ -443,6 +448,8 @@ class Ui_ThemeWizard(object):
|
||||
translate('OpenLP.ThemeWizard', 'Top Left - Bottom Right'))
|
||||
self.gradientComboBox.setItemText(BackgroundGradientType.LeftBottom,
|
||||
translate('OpenLP.ThemeWizard', 'Bottom Left - Top Right'))
|
||||
self.imageColorLabel.setText(
|
||||
translate(u'OpenLP.ThemeWizard', 'Background color:'))
|
||||
self.imageLabel.setText(u'%s:' % UiStrings().Image)
|
||||
self.mainAreaPage.setTitle(
|
||||
translate('OpenLP.ThemeWizard', 'Main Area Font Details'))
|
||||
|
@ -217,8 +217,7 @@ class CustomMediaItem(MediaManagerItem):
|
||||
for item in self.listView.selectedIndexes()]
|
||||
for id in id_list:
|
||||
self.plugin.manager.delete_object(CustomSlide, id)
|
||||
for row in row_list:
|
||||
self.listView.takeItem(row)
|
||||
self.onSearchTextButtonClick()
|
||||
|
||||
def onFocus(self):
|
||||
self.searchTextEdit.setFocus()
|
||||
|
@ -25,10 +25,13 @@
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
import logging
|
||||
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
from openlp.plugins.images.lib import ImageMediaItem
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate, \
|
||||
Receiver
|
||||
from openlp.plugins.images.lib import ImageMediaItem, ImageTab
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -36,10 +39,13 @@ class ImagePlugin(Plugin):
|
||||
log.info(u'Image Plugin loaded')
|
||||
|
||||
def __init__(self, plugin_helpers):
|
||||
Plugin.__init__(self, u'images', plugin_helpers, ImageMediaItem)
|
||||
Plugin.__init__(self, u'images', plugin_helpers, ImageMediaItem,
|
||||
ImageTab)
|
||||
self.weight = -7
|
||||
self.icon_path = u':/plugins/plugin_images.png'
|
||||
self.icon = build_icon(self.icon_path)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'image_updated'), self.image_updated)
|
||||
|
||||
def about(self):
|
||||
about_text = translate('ImagePlugin', '<strong>Image Plugin</strong>'
|
||||
@ -81,3 +87,13 @@ class ImagePlugin(Plugin):
|
||||
'Add the selected image to the service.')
|
||||
}
|
||||
self.setPluginUiTextStrings(tooltips)
|
||||
|
||||
def image_updated(self):
|
||||
"""
|
||||
Triggered by saving and changing the image border. Sets the images in
|
||||
image manager to require updates. Actual update is triggered by the
|
||||
last part of saving the config.
|
||||
"""
|
||||
background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection
|
||||
+ u'/background color', QtCore.QVariant(u'#000000')))
|
||||
self.liveController.imageManager.update_images(u'image', background)
|
||||
|
@ -26,3 +26,4 @@
|
||||
###############################################################################
|
||||
|
||||
from mediaitem import ImageMediaItem
|
||||
from imagetab import ImageTab
|
||||
|
101
openlp/plugins/images/lib/imagetab.py
Normal file
101
openlp/plugins/images/lib/imagetab.py
Normal file
@ -0,0 +1,101 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2011 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
|
||||
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
|
||||
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SettingsTab, translate, Receiver
|
||||
from openlp.core.lib.ui import UiStrings, create_valign_combo
|
||||
|
||||
class ImageTab(SettingsTab):
|
||||
"""
|
||||
ImageTab is the images settings tab in the settings dialog.
|
||||
"""
|
||||
def __init__(self, parent, name, visible_title, icon_path):
|
||||
SettingsTab.__init__(self, parent, name, visible_title, icon_path)
|
||||
|
||||
def setupUi(self):
|
||||
self.setObjectName(u'ImagesTab')
|
||||
SettingsTab.setupUi(self)
|
||||
self.bgColorGroupBox = QtGui.QGroupBox(self.leftColumn)
|
||||
self.bgColorGroupBox.setObjectName(u'FontGroupBox')
|
||||
self.formLayout = QtGui.QFormLayout(self.bgColorGroupBox)
|
||||
self.formLayout.setObjectName(u'FormLayout')
|
||||
self.colorLayout = QtGui.QHBoxLayout()
|
||||
self.backgroundColorLabel = QtGui.QLabel(self.bgColorGroupBox)
|
||||
self.backgroundColorLabel.setObjectName(u'BackgroundColorLabel')
|
||||
self.colorLayout.addWidget(self.backgroundColorLabel)
|
||||
self.backgroundColorButton = QtGui.QPushButton(self.bgColorGroupBox)
|
||||
self.backgroundColorButton.setObjectName(u'BackgroundColorButton')
|
||||
self.colorLayout.addWidget(self.backgroundColorButton)
|
||||
self.formLayout.addRow(self.colorLayout)
|
||||
self.informationLabel = QtGui.QLabel(self.bgColorGroupBox)
|
||||
self.informationLabel.setObjectName(u'InformationLabel')
|
||||
self.formLayout.addRow(self.informationLabel)
|
||||
self.leftLayout.addWidget(self.bgColorGroupBox)
|
||||
self.leftLayout.addStretch()
|
||||
self.rightColumn.setSizePolicy(
|
||||
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
|
||||
self.rightLayout.addStretch()
|
||||
# Signals and slots
|
||||
QtCore.QObject.connect(self.backgroundColorButton,
|
||||
QtCore.SIGNAL(u'pressed()'), self.onbackgroundColorButtonClicked)
|
||||
|
||||
def retranslateUi(self):
|
||||
self.bgColorGroupBox.setTitle(
|
||||
translate('ImagesPlugin.ImageTab', 'Background Color'))
|
||||
self.backgroundColorLabel.setText(
|
||||
translate('ImagesPlugin.ImageTab', 'Default Color:'))
|
||||
self.informationLabel.setText(
|
||||
translate('ImagesPlugin.ImageTab', 'Provides border where image '
|
||||
'is not the correct dimensions for the screen when resized.'))
|
||||
|
||||
def onbackgroundColorButtonClicked(self):
|
||||
new_color = QtGui.QColorDialog.getColor(
|
||||
QtGui.QColor(self.bg_color), self)
|
||||
if new_color.isValid():
|
||||
self.bg_color = new_color.name()
|
||||
self.backgroundColorButton.setStyleSheet(
|
||||
u'background-color: %s' % self.bg_color)
|
||||
|
||||
def load(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
self.bg_color = unicode(settings.value(
|
||||
u'background color', QtCore.QVariant(u'#000000')).toString())
|
||||
self.initial_color = self.bg_color
|
||||
settings.endGroup()
|
||||
self.backgroundColorButton.setStyleSheet(
|
||||
u'background-color: %s' % self.bg_color)
|
||||
|
||||
def save(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
settings.setValue(u'background color', QtCore.QVariant(self.bg_color))
|
||||
settings.endGroup()
|
||||
if self.initial_color != self.bg_color:
|
||||
Receiver.send_message(u'image_updated')
|
||||
|
@ -140,6 +140,8 @@ class ImageMediaItem(MediaManagerItem):
|
||||
self.plugin.formparent.finishedProgressBar()
|
||||
|
||||
def generateSlideData(self, service_item, item=None, xmlVersion=False):
|
||||
background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection
|
||||
+ u'/background color', QtCore.QVariant(u'#000000')))
|
||||
if item:
|
||||
items = [item]
|
||||
else:
|
||||
@ -183,7 +185,7 @@ class ImageMediaItem(MediaManagerItem):
|
||||
for bitem in items:
|
||||
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
|
||||
(path, name) = os.path.split(filename)
|
||||
service_item.add_from_image(filename, name)
|
||||
service_item.add_from_image(filename, name, background)
|
||||
return True
|
||||
|
||||
def onResetClick(self):
|
||||
@ -206,13 +208,16 @@ class ImageMediaItem(MediaManagerItem):
|
||||
if check_item_selected(self.listView,
|
||||
translate('ImagePlugin.MediaItem',
|
||||
'You must select an image to replace the background with.')):
|
||||
background = QtGui.QColor(QtCore.QSettings().value(
|
||||
self.settingsSection + u'/background color',
|
||||
QtCore.QVariant(u'#000000')))
|
||||
item = self.listView.selectedIndexes()[0]
|
||||
bitem = self.listView.item(item.row())
|
||||
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
|
||||
if os.path.exists(filename):
|
||||
(path, name) = os.path.split(filename)
|
||||
if self.plugin.liveController.display.directImage(name,
|
||||
filename):
|
||||
filename, background):
|
||||
self.resetAction.setVisible(True)
|
||||
else:
|
||||
critical_error_message_box(UiStrings().LiveBGError,
|
||||
|
@ -70,7 +70,6 @@ class Topic(BaseModel):
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def init_schema(url):
|
||||
"""
|
||||
Setup the songs database connection and initialise the database schema.
|
||||
@ -111,10 +110,6 @@ def init_schema(url):
|
||||
* file_name
|
||||
* type
|
||||
|
||||
**media_files_songs Table**
|
||||
* media_file_id
|
||||
* song_id
|
||||
|
||||
**song_books Table**
|
||||
The *song_books* table holds a list of books that a congregation gets
|
||||
their songs from, or old hymnals now no longer used. This table has the
|
||||
@ -162,7 +157,7 @@ def init_schema(url):
|
||||
|
||||
# Definition of the "authors" table
|
||||
authors_table = Table(u'authors', metadata,
|
||||
Column(u'id', types.Integer, primary_key=True),
|
||||
Column(u'id', types.Integer(), primary_key=True),
|
||||
Column(u'first_name', types.Unicode(128)),
|
||||
Column(u'last_name', types.Unicode(128)),
|
||||
Column(u'display_name', types.Unicode(255), index=True, nullable=False)
|
||||
@ -170,22 +165,25 @@ def init_schema(url):
|
||||
|
||||
# Definition of the "media_files" table
|
||||
media_files_table = Table(u'media_files', metadata,
|
||||
Column(u'id', types.Integer, primary_key=True),
|
||||
Column(u'id', types.Integer(), primary_key=True),
|
||||
Column(u'song_id', types.Integer(), ForeignKey(u'songs.id'),
|
||||
default=None),
|
||||
Column(u'file_name', types.Unicode(255), nullable=False),
|
||||
Column(u'type', types.Unicode(64), nullable=False, default=u'audio')
|
||||
Column(u'type', types.Unicode(64), nullable=False, default=u'audio'),
|
||||
Column(u'weight', types.Integer(), default=0)
|
||||
)
|
||||
|
||||
# Definition of the "song_books" table
|
||||
song_books_table = Table(u'song_books', metadata,
|
||||
Column(u'id', types.Integer, primary_key=True),
|
||||
Column(u'id', types.Integer(), primary_key=True),
|
||||
Column(u'name', types.Unicode(128), nullable=False),
|
||||
Column(u'publisher', types.Unicode(128))
|
||||
)
|
||||
|
||||
# Definition of the "songs" table
|
||||
songs_table = Table(u'songs', metadata,
|
||||
Column(u'id', types.Integer, primary_key=True),
|
||||
Column(u'song_book_id', types.Integer,
|
||||
Column(u'id', types.Integer(), primary_key=True),
|
||||
Column(u'song_book_id', types.Integer(),
|
||||
ForeignKey(u'song_books.id'), default=None),
|
||||
Column(u'title', types.Unicode(255), nullable=False),
|
||||
Column(u'alternate_title', types.Unicode(255)),
|
||||
@ -202,31 +200,23 @@ def init_schema(url):
|
||||
|
||||
# Definition of the "topics" table
|
||||
topics_table = Table(u'topics', metadata,
|
||||
Column(u'id', types.Integer, primary_key=True),
|
||||
Column(u'id', types.Integer(), primary_key=True),
|
||||
Column(u'name', types.Unicode(128), index=True, nullable=False)
|
||||
)
|
||||
|
||||
# Definition of the "authors_songs" table
|
||||
authors_songs_table = Table(u'authors_songs', metadata,
|
||||
Column(u'author_id', types.Integer,
|
||||
Column(u'author_id', types.Integer(),
|
||||
ForeignKey(u'authors.id'), primary_key=True),
|
||||
Column(u'song_id', types.Integer,
|
||||
ForeignKey(u'songs.id'), primary_key=True)
|
||||
)
|
||||
|
||||
# Definition of the "media_files_songs" table
|
||||
media_files_songs_table = Table(u'media_files_songs', metadata,
|
||||
Column(u'media_file_id', types.Integer,
|
||||
ForeignKey(u'media_files.id'), primary_key=True),
|
||||
Column(u'song_id', types.Integer,
|
||||
Column(u'song_id', types.Integer(),
|
||||
ForeignKey(u'songs.id'), primary_key=True)
|
||||
)
|
||||
|
||||
# Definition of the "songs_topics" table
|
||||
songs_topics_table = Table(u'songs_topics', metadata,
|
||||
Column(u'song_id', types.Integer,
|
||||
Column(u'song_id', types.Integer(),
|
||||
ForeignKey(u'songs.id'), primary_key=True),
|
||||
Column(u'topic_id', types.Integer,
|
||||
Column(u'topic_id', types.Integer(),
|
||||
ForeignKey(u'topics.id'), primary_key=True)
|
||||
)
|
||||
|
||||
@ -238,8 +228,7 @@ def init_schema(url):
|
||||
'authors': relation(Author, backref='songs',
|
||||
secondary=authors_songs_table, lazy=False),
|
||||
'book': relation(Book, backref='songs'),
|
||||
'media_files': relation(MediaFile, backref='songs',
|
||||
secondary=media_files_songs_table),
|
||||
'media_files': relation(MediaFile, backref='songs'),
|
||||
'topics': relation(Topic, backref='songs',
|
||||
secondary=songs_topics_table)
|
||||
})
|
||||
|
77
openlp/plugins/songs/lib/upgrade.py
Normal file
77
openlp/plugins/songs/lib/upgrade.py
Normal file
@ -0,0 +1,77 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2011 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
|
||||
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
|
||||
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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:`upgrade` module provides a way for the database and schema that is the backend for
|
||||
the Songs plugin
|
||||
"""
|
||||
|
||||
from sqlalchemy import Column, ForeignKey, Table, types
|
||||
from migrate import changeset
|
||||
from migrate.changeset.constraint import ForeignKeyConstraint
|
||||
|
||||
__version__ = 1
|
||||
|
||||
def upgrade_setup(metadata):
|
||||
"""
|
||||
Set up the latest revision all tables, with reflection, needed for the
|
||||
upgrade process. If you want to drop a table, you need to remove it from
|
||||
here, and add it to your upgrade function.
|
||||
"""
|
||||
tables = {
|
||||
u'authors': Table(u'authors', metadata, autoload=True),
|
||||
u'media_files': Table(u'media_files', metadata, autoload=True),
|
||||
u'song_books': Table(u'song_books', metadata, autoload=True),
|
||||
u'songs': Table(u'songs', metadata, autoload=True),
|
||||
u'topics': Table(u'topics', metadata, autoload=True),
|
||||
u'authors_songs': Table(u'authors_songs', metadata, autoload=True),
|
||||
u'songs_topics': Table(u'songs_topics', metadata, autoload=True)
|
||||
}
|
||||
return tables
|
||||
|
||||
|
||||
def upgrade_1(session, metadata, tables):
|
||||
"""
|
||||
Version 1 upgrade.
|
||||
|
||||
This upgrade removes the many-to-many relationship between songs and
|
||||
media_files and replaces it with a one-to-many, which is far more
|
||||
representative of the real relationship between the two entities.
|
||||
|
||||
In order to facilitate this one-to-many relationship, a song_id column is
|
||||
added to the media_files table, and a weight column so that the media
|
||||
files can be ordered.
|
||||
"""
|
||||
Table(u'media_files_songs', metadata, autoload=True).drop(checkfirst=True)
|
||||
Column(u'song_id', types.Integer(), default=None)\
|
||||
.create(table=tables[u'media_files'], populate_default=True)
|
||||
Column(u'weight', types.Integer(), default=0)\
|
||||
.create(table=tables[u'media_files'], populate_default=True)
|
||||
if metadata.bind.url.get_dialect().name != 'sqlite':
|
||||
# SQLite doesn't support ALTER TABLE ADD CONSTRAINT
|
||||
ForeignKeyConstraint([u'song_id'], [u'songs.id'],
|
||||
table=tables[u'media_files']).create()
|
||||
|
@ -36,7 +36,8 @@ from openlp.core.lib import Plugin, StringContent, build_icon, translate, \
|
||||
from openlp.core.lib.db import Manager
|
||||
from openlp.core.lib.ui import UiStrings, base_action, icon_action
|
||||
from openlp.core.utils.actions import ActionList
|
||||
from openlp.plugins.songs.lib import clean_song, SongMediaItem, SongsTab
|
||||
from openlp.plugins.songs.lib import clean_song, upgrade, SongMediaItem, \
|
||||
SongsTab
|
||||
from openlp.plugins.songs.lib.db import init_schema, Song
|
||||
from openlp.plugins.songs.lib.importer import SongFormat
|
||||
from openlp.plugins.songs.lib.olpimport import OpenLPSongImport
|
||||
@ -58,8 +59,8 @@ class SongsPlugin(Plugin):
|
||||
Create and set up the Songs plugin.
|
||||
"""
|
||||
Plugin.__init__(self, u'songs', plugin_helpers, SongMediaItem, SongsTab)
|
||||
self.manager = Manager(u'songs', init_schema, upgrade_mod=upgrade)
|
||||
self.weight = -10
|
||||
self.manager = Manager(u'songs', init_schema)
|
||||
self.icon_path = u':/plugins/plugin_songs.png'
|
||||
self.icon = build_icon(self.icon_path)
|
||||
|
||||
|
@ -34,26 +34,33 @@ class Ui_SongUsageDeleteDialog(object):
|
||||
def setupUi(self, songUsageDeleteDialog):
|
||||
songUsageDeleteDialog.setObjectName(u'songUsageDeleteDialog')
|
||||
songUsageDeleteDialog.resize(291, 243)
|
||||
self.layoutWidget = QtGui.QWidget(songUsageDeleteDialog)
|
||||
self.layoutWidget.setGeometry(QtCore.QRect(20, 10, 247, 181))
|
||||
self.layoutWidget.setObjectName(u'layoutWidget')
|
||||
self.verticalLayout = QtGui.QVBoxLayout(self.layoutWidget)
|
||||
self.verticalLayout = QtGui.QVBoxLayout(songUsageDeleteDialog)
|
||||
self.verticalLayout.setSpacing(8)
|
||||
self.verticalLayout.setContentsMargins(8, 8, 8, 8)
|
||||
self.verticalLayout.setObjectName(u'verticalLayout')
|
||||
self.deleteCalendar = QtGui.QCalendarWidget(self.layoutWidget)
|
||||
self.deleteLabel = QtGui.QLabel(songUsageDeleteDialog)
|
||||
self.deleteLabel.setObjectName(u'deleteLabel')
|
||||
self.verticalLayout.addWidget(self.deleteLabel)
|
||||
self.deleteCalendar = QtGui.QCalendarWidget(songUsageDeleteDialog)
|
||||
self.deleteCalendar.setFirstDayOfWeek(QtCore.Qt.Sunday)
|
||||
self.deleteCalendar.setGridVisible(True)
|
||||
self.deleteCalendar.setVerticalHeaderFormat(
|
||||
QtGui.QCalendarWidget.NoVerticalHeader)
|
||||
self.deleteCalendar.setObjectName(u'deleteCalendar')
|
||||
self.verticalLayout.addWidget(self.deleteCalendar)
|
||||
self.buttonBox = create_accept_reject_button_box(
|
||||
songUsageDeleteDialog, True)
|
||||
self.buttonBox.setGeometry(QtCore.QRect(30, 210, 245, 25))
|
||||
self.buttonBox = QtGui.QDialogButtonBox(songUsageDeleteDialog)
|
||||
self.buttonBox.setStandardButtons(
|
||||
QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
|
||||
self.buttonBox.setObjectName(u'buttonBox')
|
||||
self.verticalLayout.addWidget(self.buttonBox)
|
||||
self.retranslateUi(songUsageDeleteDialog)
|
||||
QtCore.QMetaObject.connectSlotsByName(songUsageDeleteDialog)
|
||||
|
||||
def retranslateUi(self, songUsageDeleteDialog):
|
||||
songUsageDeleteDialog.setWindowTitle(
|
||||
translate('SongUsagePlugin.SongUsageDeleteForm',
|
||||
'Delete Song Usage Data'))
|
||||
'Delete Song Usage Data'))
|
||||
self.deleteLabel.setText(
|
||||
translate('SongUsagePlugin.SongUsageDeleteForm',
|
||||
'Select the date up to which the song usage data should be '
|
||||
'deleted. All data recorded before this date will be '
|
||||
'permanently deleted.'))
|
||||
|
@ -25,7 +25,7 @@
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
from PyQt4 import QtGui
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import translate, Receiver
|
||||
from openlp.plugins.songusage.lib.db import SongUsageItem
|
||||
@ -42,23 +42,32 @@ class SongUsageDeleteForm(QtGui.QDialog, Ui_SongUsageDeleteDialog):
|
||||
self.manager = manager
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
QtCore.QObject.connect(
|
||||
self.buttonBox, QtCore.SIGNAL(u'clicked(QAbstractButton*)'),
|
||||
self.onButtonBoxClicked)
|
||||
|
||||
def accept(self):
|
||||
ret = QtGui.QMessageBox.question(self,
|
||||
translate('SongUsagePlugin.SongUsageDeleteForm',
|
||||
'Delete Selected Song Usage Events?'),
|
||||
translate('SongUsagePlugin.SongUsageDeleteForm',
|
||||
'Are you sure you want to delete selected Song Usage data?'),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok |
|
||||
QtGui.QMessageBox.Cancel),
|
||||
QtGui.QMessageBox.Cancel)
|
||||
if ret == QtGui.QMessageBox.Ok:
|
||||
deleteDate = self.deleteCalendar.selectedDate().toPyDate()
|
||||
self.manager.delete_all_objects(SongUsageItem,
|
||||
SongUsageItem.usagedate <= deleteDate)
|
||||
Receiver.send_message(u'openlp_information_message', {
|
||||
u'title': translate('SongUsagePlugin.SongUsageDeleteForm',
|
||||
'Deletion Successful'),
|
||||
u'message': translate('SongUsagePlugin.SongUsageDeleteForm',
|
||||
'All requested data has been deleted successfully. ')})
|
||||
self.close()
|
||||
def onButtonBoxClicked(self, button):
|
||||
if self.buttonBox.standardButton(button) == QtGui.QDialogButtonBox.Ok:
|
||||
ret = QtGui.QMessageBox.question(self,
|
||||
translate('SongUsagePlugin.SongUsageDeleteForm',
|
||||
'Delete Selected Song Usage Events?'),
|
||||
translate('SongUsagePlugin.SongUsageDeleteForm',
|
||||
'Are you sure you want to delete selected Song Usage '
|
||||
'data?'),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
|
||||
QtGui.QMessageBox.No),
|
||||
QtGui.QMessageBox.No)
|
||||
if ret == QtGui.QMessageBox.Yes:
|
||||
deleteDate = self.deleteCalendar.selectedDate().toPyDate()
|
||||
self.manager.delete_all_objects(SongUsageItem,
|
||||
SongUsageItem.usagedate <= deleteDate)
|
||||
Receiver.send_message(u'openlp_information_message', {
|
||||
u'title': translate('SongUsagePlugin.SongUsageDeleteForm',
|
||||
'Deletion Successful'),
|
||||
u'message': translate(
|
||||
'SongUsagePlugin.SongUsageDeleteForm',
|
||||
'All requested data has been deleted successfully. ')}
|
||||
)
|
||||
self.accept()
|
||||
else:
|
||||
self.reject()
|
||||
|
@ -35,12 +35,14 @@ class Ui_SongUsageDetailDialog(object):
|
||||
songUsageDetailDialog.setObjectName(u'songUsageDetailDialog')
|
||||
songUsageDetailDialog.resize(609, 413)
|
||||
self.verticalLayout = QtGui.QVBoxLayout(songUsageDetailDialog)
|
||||
self.verticalLayout.setSpacing(8)
|
||||
self.verticalLayout.setContentsMargins(8, 8, 8, 8)
|
||||
self.verticalLayout.setObjectName(u'verticalLayout')
|
||||
self.dateRangeGroupBox = QtGui.QGroupBox(songUsageDetailDialog)
|
||||
self.dateRangeGroupBox.setObjectName(u'dateRangeGroupBox')
|
||||
self.verticalLayout2 = QtGui.QVBoxLayout(self.dateRangeGroupBox)
|
||||
self.verticalLayout2.setObjectName(u'verticalLayout2')
|
||||
self.dateHorizontalLayout = QtGui.QHBoxLayout()
|
||||
self.dateHorizontalLayout = QtGui.QHBoxLayout(self.dateRangeGroupBox)
|
||||
self.dateHorizontalLayout.setSpacing(8)
|
||||
self.dateHorizontalLayout.setContentsMargins(8, 8, 8, 8)
|
||||
self.dateHorizontalLayout.setObjectName(u'dateHorizontalLayout')
|
||||
self.fromDate = QtGui.QCalendarWidget(self.dateRangeGroupBox)
|
||||
self.fromDate.setObjectName(u'fromDate')
|
||||
@ -53,26 +55,25 @@ class Ui_SongUsageDetailDialog(object):
|
||||
self.toDate = QtGui.QCalendarWidget(self.dateRangeGroupBox)
|
||||
self.toDate.setObjectName(u'toDate')
|
||||
self.dateHorizontalLayout.addWidget(self.toDate)
|
||||
self.verticalLayout2.addLayout(self.dateHorizontalLayout)
|
||||
self.verticalLayout.addWidget(self.dateRangeGroupBox)
|
||||
self.fileGroupBox = QtGui.QGroupBox(self.dateRangeGroupBox)
|
||||
self.fileGroupBox.setObjectName(u'fileGroupBox')
|
||||
self.verticalLayout4 = QtGui.QVBoxLayout(self.fileGroupBox)
|
||||
self.verticalLayout4.setObjectName(u'verticalLayout4')
|
||||
self.horizontalLayout = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName(u'horizontalLayout')
|
||||
self.fileHorizontalLayout = QtGui.QHBoxLayout(self.fileGroupBox)
|
||||
self.fileHorizontalLayout.setSpacing(8)
|
||||
self.fileHorizontalLayout.setContentsMargins(8, 8, 8, 8)
|
||||
self.fileHorizontalLayout.setObjectName(u'fileHorizontalLayout')
|
||||
self.fileLineEdit = QtGui.QLineEdit(self.fileGroupBox)
|
||||
self.fileLineEdit.setObjectName(u'fileLineEdit')
|
||||
self.fileLineEdit.setReadOnly(True)
|
||||
self.fileLineEdit.setEnabled(False)
|
||||
self.horizontalLayout.addWidget(self.fileLineEdit)
|
||||
self.fileHorizontalLayout.addWidget(self.fileLineEdit)
|
||||
self.saveFilePushButton = QtGui.QPushButton(self.fileGroupBox)
|
||||
self.saveFilePushButton.setMaximumWidth(
|
||||
self.saveFilePushButton.size().height())
|
||||
self.saveFilePushButton.setIcon(
|
||||
build_icon(u':/general/general_open.png'))
|
||||
self.saveFilePushButton.setObjectName(u'saveFilePushButton')
|
||||
self.horizontalLayout.addWidget(self.saveFilePushButton)
|
||||
self.verticalLayout4.addLayout(self.horizontalLayout)
|
||||
self.verticalLayout2.addWidget(self.fileGroupBox)
|
||||
self.verticalLayout.addWidget(self.dateRangeGroupBox)
|
||||
self.fileHorizontalLayout.addWidget(self.saveFilePushButton)
|
||||
self.verticalLayout.addWidget(self.fileGroupBox)
|
||||
self.buttonBox = create_accept_reject_button_box(
|
||||
songUsageDetailDialog, True)
|
||||
self.verticalLayout.addWidget(self.buttonBox)
|
||||
|
@ -96,6 +96,7 @@ class SongUsagePlugin(Plugin):
|
||||
self.songUsageActiveButton = QtGui.QToolButton(
|
||||
self.formparent.statusBar)
|
||||
self.songUsageActiveButton.setCheckable(True)
|
||||
self.songUsageActiveButton.setAutoRaise(True)
|
||||
self.songUsageActiveButton.setStatusTip(translate('SongUsagePlugin',
|
||||
'Toggle the tracking of song usage.'))
|
||||
self.songUsageActiveButton.setObjectName(u'songUsageActiveButton')
|
||||
@ -121,6 +122,9 @@ class SongUsagePlugin(Plugin):
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'slidecontroller_live_started'),
|
||||
self.onReceiveSongUsage)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'print_service_started'),
|
||||
self.onReceiveSongUsage)
|
||||
self.songUsageActive = QtCore.QSettings().value(
|
||||
self.settingsSection + u'/active',
|
||||
QtCore.QVariant(False)).toBool()
|
||||
|
@ -11,7 +11,7 @@ Package: openlp
|
||||
Architecture: all
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}, python-qt4,
|
||||
python-qt4-phonon, python-sqlalchemy, python-chardet, python-beautifulsoup,
|
||||
python-lxml, python-sqlite, python-enchant
|
||||
python-lxml, python-sqlite, python-enchant, python-mako, python-migrate
|
||||
Conflicts: python-openlp
|
||||
Description: Church lyrics projection application
|
||||
OpenLP is free church presentation software, or lyrics projection software,
|
||||
|
1986
resources/i18n/af.ts
1986
resources/i18n/af.ts
File diff suppressed because it is too large
Load Diff
3126
resources/i18n/cs.ts
3126
resources/i18n/cs.ts
File diff suppressed because it is too large
Load Diff
1765
resources/i18n/de.ts
1765
resources/i18n/de.ts
File diff suppressed because it is too large
Load Diff
1797
resources/i18n/en.ts
1797
resources/i18n/en.ts
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
2138
resources/i18n/es.ts
2138
resources/i18n/es.ts
File diff suppressed because it is too large
Load Diff
2142
resources/i18n/et.ts
2142
resources/i18n/et.ts
File diff suppressed because it is too large
Load Diff
1994
resources/i18n/fr.ts
1994
resources/i18n/fr.ts
File diff suppressed because it is too large
Load Diff
2530
resources/i18n/hu.ts
2530
resources/i18n/hu.ts
File diff suppressed because it is too large
Load Diff
2020
resources/i18n/id.ts
2020
resources/i18n/id.ts
File diff suppressed because it is too large
Load Diff
2421
resources/i18n/ja.ts
2421
resources/i18n/ja.ts
File diff suppressed because it is too large
Load Diff
1814
resources/i18n/ko.ts
1814
resources/i18n/ko.ts
File diff suppressed because it is too large
Load Diff
1797
resources/i18n/nb.ts
1797
resources/i18n/nb.ts
File diff suppressed because it is too large
Load Diff
1988
resources/i18n/nl.ts
1988
resources/i18n/nl.ts
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2294
resources/i18n/ru.ts
2294
resources/i18n/ru.ts
File diff suppressed because it is too large
Load Diff
1809
resources/i18n/sv.ts
1809
resources/i18n/sv.ts
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -46,14 +46,14 @@ VERS = {
|
||||
'sqlalchemy': '0.5',
|
||||
# pyenchant 1.6 required on Windows
|
||||
'enchant': '1.6' if is_win else '1.3'
|
||||
}
|
||||
}
|
||||
|
||||
# pywin32
|
||||
WIN32_MODULES = [
|
||||
'win32com',
|
||||
'win32ui',
|
||||
'pywintypes',
|
||||
]
|
||||
]
|
||||
|
||||
MODULES = [
|
||||
'PyQt4',
|
||||
@ -72,7 +72,8 @@ MODULES = [
|
||||
'enchant',
|
||||
'BeautifulSoup',
|
||||
'mako',
|
||||
]
|
||||
'migrate',
|
||||
]
|
||||
|
||||
|
||||
OPTIONAL_MODULES = [
|
||||
|
@ -186,25 +186,6 @@ def update_export_at_pootle(source_filename):
|
||||
page = urllib.urlopen(REVIEW_URL)
|
||||
page.close()
|
||||
|
||||
|
||||
def download_file(source_filename, dest_filename):
|
||||
"""
|
||||
Download a file and save it to disk.
|
||||
|
||||
``source_filename``
|
||||
The file to download.
|
||||
|
||||
``dest_filename``
|
||||
The new local file name.
|
||||
"""
|
||||
print_verbose(u'Downloading from: %s' % (SERVER_URL + source_filename))
|
||||
page = urllib.urlopen(SERVER_URL + source_filename)
|
||||
content = page.read().decode('utf8')
|
||||
page.close()
|
||||
file = open(dest_filename, u'w')
|
||||
file.write(content.encode('utf8'))
|
||||
file.close()
|
||||
|
||||
def download_translations():
|
||||
"""
|
||||
This method downloads the translation files from the Pootle server.
|
||||
@ -219,7 +200,7 @@ def download_translations():
|
||||
filename = os.path.join(os.path.abspath(u'..'), u'resources', u'i18n',
|
||||
language_file)
|
||||
print_verbose(u'Get Translation File: %s' % filename)
|
||||
download_file(language_file, filename)
|
||||
urllib.urlretrieve(SERVER_URL + language_file, filename)
|
||||
print_quiet(u' Done.')
|
||||
|
||||
def prepare_project():
|
||||
@ -304,7 +285,7 @@ def create_translation(language):
|
||||
if not language.endswith(u'.ts'):
|
||||
language += u'.ts'
|
||||
filename = os.path.join(os.path.abspath(u'..'), u'resources', u'i18n', language)
|
||||
download_file(u'en.ts', filename)
|
||||
urllib.urlretrieve(SERVER_URL + u'en.ts', filename)
|
||||
print_quiet(u' ** Please Note **')
|
||||
print_quiet(u' In order to get this file into OpenLP and onto the '
|
||||
u'Pootle translation server you will need to subscribe to the '
|
||||
|
Loading…
Reference in New Issue
Block a user