forked from openlp/openlp
Merge branch 'master' of gitlab.com:openlp/openlp into master
This commit is contained in:
commit
7e3bc679b0
16
appveyor.yml
16
appveyor.yml
@ -4,23 +4,23 @@ cache:
|
||||
- '%LOCALAPPDATA%\pip\Cache'
|
||||
- /Users/appveyor/Libraries/Caches/pip
|
||||
|
||||
stack: python 3.7
|
||||
stack: python 3.9
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
PY_DIR: C:\\Python37-x64
|
||||
PY_DIR: C:\\Python39-x64
|
||||
CHOCO_VLC_ARG:
|
||||
FORCE_PACKAGING: 0
|
||||
FORCE_PACKAGING: 1
|
||||
FORCE_PACKAGING_MANUAL: 0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
PY_DIR: C:\\Python37
|
||||
PY_DIR: C:\\Python39
|
||||
CHOCO_VLC_ARG: --forcex86
|
||||
FORCE_PACKAGING: 0
|
||||
FORCE_PACKAGING: 1
|
||||
FORCE_PACKAGING_MANUAL: 0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: macos-mojave
|
||||
QT_QPA_PLATFORM: offscreen
|
||||
FORCE_PACKAGING: 0
|
||||
FORCE_PACKAGING: 1
|
||||
FORCE_PACKAGING_MANUAL: 0
|
||||
|
||||
init:
|
||||
@ -48,8 +48,8 @@ test_script:
|
||||
after_test:
|
||||
# Only package on the master repo
|
||||
- ps: >-
|
||||
If (!(Test-Path env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME) -Or ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME -eq "") -Or ($env:FORCE_PACKAGING -eq 1)) {
|
||||
# Continue on eror
|
||||
If (($env:APPVEYOR_REPO_TAG) -Or ($env:APPVEYOR_SCHEDULED_BUILD) -Or ($env:FORCE_PACKAGING -eq 1)) {
|
||||
# Continue on error
|
||||
$ErrorActionPreference = "Continue"
|
||||
# This is where we create a package using PyInstaller
|
||||
# Install PyInstaller
|
||||
|
@ -73,6 +73,15 @@ class DisplayStyle(IntEnum):
|
||||
Square = 3
|
||||
|
||||
|
||||
@unique
|
||||
class ImageThemeMode(IntEnum):
|
||||
"""
|
||||
An enumeration for image background settings.
|
||||
"""
|
||||
Black = 1
|
||||
CustomTheme = 2
|
||||
|
||||
|
||||
@unique
|
||||
class LayoutStyle(IntEnum):
|
||||
"""
|
||||
|
@ -32,8 +32,8 @@ from tempfile import gettempdir
|
||||
from PyQt5 import QtCore, QtGui
|
||||
|
||||
from openlp.core.common import SlideLimits, ThemeLevel, is_linux, is_win
|
||||
from openlp.core.common.enum import AlertLocation, BibleSearch, CustomSearch, LayoutStyle, DisplayStyle, \
|
||||
LanguageSelection, SongSearch, PluginStatus
|
||||
from openlp.core.common.enum import AlertLocation, BibleSearch, CustomSearch, ImageThemeMode, LayoutStyle, \
|
||||
DisplayStyle, LanguageSelection, SongSearch, PluginStatus
|
||||
from openlp.core.common.json import OpenLPJSONDecoder, OpenLPJSONEncoder, is_serializable
|
||||
from openlp.core.common.path import files_to_paths, str_to_path
|
||||
|
||||
@ -259,7 +259,8 @@ class Settings(QtCore.QSettings):
|
||||
'core/override position': False,
|
||||
'core/monitor': {},
|
||||
'core/application version': '0.0',
|
||||
'images/background color': '#000000',
|
||||
'images/background mode': ImageThemeMode.Black,
|
||||
'images/theme': None,
|
||||
'images/db type': 'sqlite',
|
||||
'images/db username': '',
|
||||
'images/db password': '',
|
||||
@ -414,6 +415,7 @@ class Settings(QtCore.QSettings):
|
||||
('presentations/presentations files', 'presentations/presentations files', [(files_to_paths, None)]),
|
||||
('core/logo file', 'core/logo file', [(str_to_path, None)]),
|
||||
('presentations/last directory', 'presentations/last directory', [(str_to_path, None)]),
|
||||
('images/background color', '', []),
|
||||
('images/last directory', 'images/last directory', [(str_to_path, None)]),
|
||||
('media/last directory', 'media/last directory', [(str_to_path, None)]),
|
||||
('songuasge/db password', 'songusage/db password', []),
|
||||
|
@ -645,13 +645,12 @@ var Display = {
|
||||
* Set image slides
|
||||
* @param {Object[]} slides - A list of images to add as JS objects [{"path": "url/to/file"}]
|
||||
*/
|
||||
setImageSlides: function (slides, background) {
|
||||
setImageSlides: function (slides) {
|
||||
Display._clearSlidesList();
|
||||
var parentSection = document.createElement("section");
|
||||
slides.forEach(function (slide, index) {
|
||||
var section = document.createElement("section");
|
||||
section.setAttribute("id", index);
|
||||
section.setAttribute("data-background", background);
|
||||
section.setAttribute("style", "height: 100%; width: 100%;");
|
||||
var img = document.createElement('img');
|
||||
img.src = slide.path;
|
||||
@ -876,10 +875,9 @@ var Display = {
|
||||
},
|
||||
/**
|
||||
* Set background image, replaced when theme is updated/applied
|
||||
* @param bg_color Colour behind the image
|
||||
* @param image_path Image path
|
||||
*/
|
||||
setBackgroundImage: function (bg_color, image_path) {
|
||||
setBackgroundImage: function (image_path) {
|
||||
var targetElement = $(".slides > section")[0];
|
||||
targetElement.setAttribute("data-background", "url('" + image_path + "')");
|
||||
targetElement.setAttribute("data-background-size", "cover");
|
||||
|
@ -256,7 +256,7 @@ class ScreenList(metaclass=Singleton):
|
||||
for number, screen_dict in screen_settings.items():
|
||||
# Sometimes this loads as a string instead of an int
|
||||
number = int(number)
|
||||
# Compare geometry, primarity of screen from settings with avilable screens
|
||||
# Compare geometry, primary of screen from settings with available screens
|
||||
if self.has_screen(screen_dict):
|
||||
# If match was found, we're all happy, update with custom geometry, display info, if available
|
||||
self[number].update(screen_dict)
|
||||
|
@ -155,10 +155,9 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties, LogMixin):
|
||||
self.setGeometry(screen.display_geometry)
|
||||
self.screen_number = screen.number
|
||||
|
||||
def set_background_image(self, bg_color, image_path):
|
||||
def set_background_image(self, image_path):
|
||||
image_uri = image_path.as_uri()
|
||||
self.run_javascript('Display.setBackgroundImage("{bg_color}", "{image}");'.format(bg_color=bg_color,
|
||||
image=image_uri))
|
||||
self.run_javascript('Display.setBackgroundImage("{image}");'.format(image=image_uri))
|
||||
|
||||
def set_single_image(self, bg_color, image_path):
|
||||
"""
|
||||
@ -280,9 +279,7 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties, LogMixin):
|
||||
else:
|
||||
image['thumbnail'] = image['path']
|
||||
json_images = json.dumps(imagesr)
|
||||
background = self.settings.value('images/background color')
|
||||
self.run_javascript('Display.setImageSlides({images}, "{background}");'.format(images=json_images,
|
||||
background=background))
|
||||
self.run_javascript('Display.setImageSlides({images});'.format(images=json_images))
|
||||
|
||||
def load_video(self, video):
|
||||
"""
|
||||
|
@ -167,6 +167,9 @@ class ItemCapabilities(object):
|
||||
|
||||
``HasBackgroundStream``
|
||||
That a video stream is present with the text
|
||||
|
||||
``ProvidesOwnTheme``
|
||||
The capability to tell the SlideController to force the use of the service item theme.
|
||||
"""
|
||||
CanPreview = 1
|
||||
CanEdit = 2
|
||||
@ -193,6 +196,7 @@ class ItemCapabilities(object):
|
||||
CanStream = 23
|
||||
HasBackgroundVideo = 24
|
||||
HasBackgroundStream = 25
|
||||
ProvidesOwnTheme = 26
|
||||
|
||||
|
||||
def get_text_file_string(text_file_path):
|
||||
|
@ -129,8 +129,8 @@ class ServiceItem(RegistryProperties):
|
||||
# but use song theme if level is song (and it exists)
|
||||
if service_theme and self.from_service:
|
||||
theme = service_theme
|
||||
if theme_level == ThemeLevel.Song and self.theme:
|
||||
theme = self.theme
|
||||
if self.is_capable(ItemCapabilities.ProvidesOwnTheme) or theme_level == ThemeLevel.Song and self.theme:
|
||||
theme = self.theme
|
||||
theme = theme_manager.get_theme_data(theme)
|
||||
# Clean up capabilities and reload from the theme.
|
||||
if self.is_text():
|
||||
|
@ -29,7 +29,6 @@ try:
|
||||
except ImportError:
|
||||
pymediainfo_available = False
|
||||
|
||||
from subprocess import check_output
|
||||
from PyQt5 import QtCore
|
||||
|
||||
from openlp.core.state import State
|
||||
@ -343,13 +342,9 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
|
||||
"""
|
||||
if MediaInfo.can_parse():
|
||||
media_data = MediaInfo.parse(media_path)
|
||||
else:
|
||||
xml = check_output(['mediainfo', '-f', '--Output=XML', '--Inform=OLDXML', media_path])
|
||||
if not xml.startswith(b'<?xml'):
|
||||
xml = check_output(['mediainfo', '-f', '--Output=XML', media_path])
|
||||
media_data = MediaInfo(xml.decode("utf-8"))
|
||||
# duration returns in milli seconds
|
||||
return media_data.tracks[0].duration
|
||||
# duration returns in milli seconds
|
||||
return media_data.tracks[0].duration
|
||||
return 0
|
||||
|
||||
def media_setup_optical(self, filename, title, audio_track, subtitle_track, start, end, display, controller):
|
||||
"""
|
||||
|
@ -872,15 +872,15 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
self.delay_spin_box.setValue(int(item.timed_slide_interval))
|
||||
self.on_play_slides_once()
|
||||
|
||||
def set_background_image(self, bg_color, image_path):
|
||||
def set_background_image(self, image_path):
|
||||
"""
|
||||
Reload the theme on displays.
|
||||
"""
|
||||
# Set theme for preview
|
||||
self.preview_display.set_background_image(bg_color, image_path)
|
||||
self.preview_display.set_background_image(image_path)
|
||||
# Set theme for displays
|
||||
for display in self.displays:
|
||||
display.set_background_image(bg_color, image_path)
|
||||
display.set_background_image(image_path)
|
||||
|
||||
def theme_updated(self, var=None):
|
||||
"""
|
||||
|
@ -21,9 +21,11 @@
|
||||
|
||||
from PyQt5 import QtWidgets
|
||||
|
||||
from openlp.core.common.i18n import UiStrings, translate
|
||||
from openlp.core.common.i18n import translate
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.common.enum import ImageThemeMode
|
||||
from openlp.core.lib.settingstab import SettingsTab
|
||||
from openlp.core.widgets.buttons import ColorButton
|
||||
from openlp.core.lib.ui import find_and_set_in_combo_box
|
||||
|
||||
|
||||
class ImageTab(SettingsTab):
|
||||
@ -33,44 +35,85 @@ class ImageTab(SettingsTab):
|
||||
def setup_ui(self):
|
||||
self.setObjectName('ImagesTab')
|
||||
super(ImageTab, self).setup_ui()
|
||||
self.background_color_group_box = QtWidgets.QGroupBox(self.left_column)
|
||||
self.background_color_group_box.setObjectName('background_color_group_box')
|
||||
self.form_layout = QtWidgets.QFormLayout(self.background_color_group_box)
|
||||
self.form_layout.setObjectName('form_layout')
|
||||
self.color_layout = QtWidgets.QHBoxLayout()
|
||||
self.background_color_label = QtWidgets.QLabel(self.background_color_group_box)
|
||||
self.background_color_label.setObjectName('background_color_label')
|
||||
self.color_layout.addWidget(self.background_color_label)
|
||||
self.background_color_button = ColorButton(self.background_color_group_box)
|
||||
self.background_color_button.setObjectName('background_color_button')
|
||||
self.color_layout.addWidget(self.background_color_button)
|
||||
self.form_layout.addRow(self.color_layout)
|
||||
self.information_label = QtWidgets.QLabel(self.background_color_group_box)
|
||||
self.information_label.setObjectName('information_label')
|
||||
self.information_label.setWordWrap(True)
|
||||
self.form_layout.addRow(self.information_label)
|
||||
self.left_layout.addWidget(self.background_color_group_box)
|
||||
self.image_theme_group_box = QtWidgets.QGroupBox(self.left_column)
|
||||
self.image_theme_group_box.setObjectName('image_theme_group_box')
|
||||
self.image_theme_group_box_layout = QtWidgets.QFormLayout(self.image_theme_group_box)
|
||||
self.image_theme_group_box_layout.setObjectName('image_theme_group_box_layout')
|
||||
# Theme mode radios
|
||||
self.radio_group = QtWidgets.QButtonGroup(self)
|
||||
self.use_black_radio = QtWidgets.QRadioButton('', self)
|
||||
self.radio_group.addButton(self.use_black_radio, ImageThemeMode.Black)
|
||||
self.image_theme_group_box_layout.setWidget(0, QtWidgets.QFormLayout.SpanningRole, self.use_black_radio)
|
||||
self.custom_theme_radio = QtWidgets.QRadioButton('', self)
|
||||
self.radio_group.addButton(self.custom_theme_radio, ImageThemeMode.CustomTheme)
|
||||
self.image_theme_group_box_layout.setWidget(2, QtWidgets.QFormLayout.SpanningRole, self.custom_theme_radio)
|
||||
# Theme selection
|
||||
self.theme_combo_box = QtWidgets.QComboBox(self.image_theme_group_box)
|
||||
self.theme_combo_box.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToMinimumContentsLength)
|
||||
self.theme_combo_box.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
self.theme_combo_box.setObjectName('theme_combo_box')
|
||||
self.image_theme_label = QtWidgets.QLabel(self.theme_combo_box)
|
||||
self.image_theme_label.setObjectName('image_theme_label')
|
||||
self.image_theme_group_box_layout.addRow(self.image_theme_label, self.theme_combo_box)
|
||||
# Add all to layout
|
||||
self.left_layout.addWidget(self.image_theme_group_box)
|
||||
self.left_layout.addStretch()
|
||||
self.right_column.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
self.right_layout.addStretch()
|
||||
# Signals and slots
|
||||
self.background_color_button.colorChanged.connect(self.on_background_color_changed)
|
||||
self.radio_group.buttonToggled.connect(self.on_radio_group_button_toggled)
|
||||
self.theme_combo_box.activated.connect(self.on_image_theme_changed)
|
||||
Registry().register_function('theme_update_list', self.update_theme_list)
|
||||
|
||||
def retranslate_ui(self):
|
||||
self.background_color_group_box.setTitle(UiStrings().BackgroundColor)
|
||||
self.background_color_label.setText(UiStrings().BackgroundColorColon)
|
||||
self.information_label.setText(
|
||||
translate('ImagesPlugin.ImageTab', 'Visible background for images with aspect ratio different to screen.'))
|
||||
self.image_theme_group_box.setTitle(translate('ImagesPlugin.ImageTab', 'Image Background'))
|
||||
self.use_black_radio.setText(translate('ImagesPlugin.ImageTab', 'Use blank theme'))
|
||||
self.custom_theme_radio.setText(translate('ImagesPlugin.ImageTab', 'Custom theme'))
|
||||
self.image_theme_label.setText(translate('ImagesPlugin.ImageTab', 'Theme:'))
|
||||
|
||||
def on_background_color_changed(self, color):
|
||||
self.background_color = color
|
||||
def on_radio_group_button_toggled(self, button, checked):
|
||||
"""
|
||||
Handles the toggled signal on the radio buttons. The signal is emitted twice if a radio butting being toggled on
|
||||
causes another radio button in the group to be toggled off.
|
||||
|
||||
En/Disables the `Custom Theme` line edits depending on the currently selected radio button
|
||||
|
||||
:param QtWidgets.QRadioButton button: The button that has toggled
|
||||
:param bool checked: The buttons new state
|
||||
"""
|
||||
group_id = self.radio_group.id(button) # The work around (see above comment)
|
||||
enable_manual_edits = group_id == ImageThemeMode.CustomTheme and checked
|
||||
if checked:
|
||||
self.background_mode = group_id
|
||||
self.theme_combo_box.setEnabled(enable_manual_edits)
|
||||
|
||||
def on_image_theme_changed(self):
|
||||
self.image_theme = self.theme_combo_box.currentText()
|
||||
|
||||
def update_theme_list(self, theme_list):
|
||||
"""
|
||||
Called from ThemeManager when the Themes have changed.
|
||||
|
||||
:param theme_list: The list of available themes::
|
||||
|
||||
['Bible Theme', 'Song Theme']
|
||||
"""
|
||||
# Reload as may have been triggered by the ThemeManager.
|
||||
self.image_theme = self.settings.value('images/theme')
|
||||
self.theme_combo_box.clear()
|
||||
self.theme_combo_box.addItems(theme_list)
|
||||
find_and_set_in_combo_box(self.theme_combo_box, self.image_theme)
|
||||
|
||||
def load(self):
|
||||
self.background_color = self.settings.value('images/background color')
|
||||
self.initial_color = self.background_color
|
||||
self.background_color_button.color = self.background_color
|
||||
self.background_mode = self.settings.value('images/background mode')
|
||||
self.initial_mode = self.background_mode
|
||||
checked_radio = self.radio_group.button(self.background_mode)
|
||||
checked_radio.setChecked(True)
|
||||
self.image_theme = self.settings.value('images/theme')
|
||||
self.initial_theme = self.image_theme
|
||||
|
||||
def save(self):
|
||||
self.settings.setValue('images/background color', self.background_color)
|
||||
if self.initial_color != self.background_color:
|
||||
self.settings.setValue('images/background mode', self.radio_group.checkedId())
|
||||
self.settings.setValue('images/theme', self.image_theme)
|
||||
if self.initial_theme != self.image_theme or self.initial_mode != self.background_mode:
|
||||
self.settings_form.register_post_process('images_config_updated')
|
||||
|
@ -22,13 +22,14 @@
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
from PyQt5 import QtCore, QtWidgets
|
||||
|
||||
from openlp.core.common import delete_file, get_images_filter, sha256_file_hash
|
||||
from openlp.core.common.applocation import AppLocation
|
||||
from openlp.core.common.i18n import UiStrings, get_natural_key, translate
|
||||
from openlp.core.common.path import create_paths
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.common.enum import ImageThemeMode
|
||||
from openlp.core.lib import ServiceItemContext, build_icon, check_item_selected, create_thumb, validate_thumb
|
||||
from openlp.core.lib.mediamanageritem import MediaManagerItem
|
||||
from openlp.core.lib.plugin import StringContent
|
||||
@ -571,8 +572,12 @@ class ImageMediaItem(MediaManagerItem):
|
||||
service_item.add_capability(ItemCapabilities.CanAppend)
|
||||
service_item.add_capability(ItemCapabilities.CanEditTitle)
|
||||
service_item.add_capability(ItemCapabilities.HasThumbnails)
|
||||
# force a nonexistent theme
|
||||
service_item.theme = -1
|
||||
service_item.add_capability(ItemCapabilities.ProvidesOwnTheme)
|
||||
if self.settings.value('images/background mode') == ImageThemeMode.CustomTheme:
|
||||
service_item.theme = self.settings.value('images/theme')
|
||||
else:
|
||||
# force a nonexistent theme
|
||||
service_item.theme = -1
|
||||
missing_items_file_names = []
|
||||
images = []
|
||||
existing_images = []
|
||||
@ -682,14 +687,13 @@ class ImageMediaItem(MediaManagerItem):
|
||||
if check_item_selected(
|
||||
self.list_view,
|
||||
translate('ImagePlugin.MediaItem', 'You must select an image to replace the background with.')):
|
||||
background = QtGui.QColor(self.settings.value('images/background color'))
|
||||
bitem = self.list_view.selectedItems()[0]
|
||||
if not isinstance(bitem.data(0, QtCore.Qt.UserRole), ImageFilenames):
|
||||
# Only continue when an image is selected.
|
||||
return
|
||||
file_path = bitem.data(0, QtCore.Qt.UserRole).file_path
|
||||
if file_path.exists():
|
||||
self.live_controller.set_background_image(background, file_path)
|
||||
self.live_controller.set_background_image(file_path)
|
||||
self.reset_action.setVisible(True)
|
||||
self.reset_action_context.setVisible(True)
|
||||
else:
|
||||
|
@ -329,6 +329,7 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
service_item.add_capability(ItemCapabilities.CanPreview)
|
||||
service_item.add_capability(ItemCapabilities.CanLoop)
|
||||
service_item.add_capability(ItemCapabilities.CanAppend)
|
||||
service_item.add_capability(ItemCapabilities.ProvidesOwnTheme)
|
||||
service_item.name = 'images'
|
||||
# force a nonexistent theme
|
||||
service_item.theme = -1
|
||||
|
@ -137,7 +137,9 @@ class PresentationPlugin(Plugin):
|
||||
super().app_startup()
|
||||
presentation_paths = self.settings.value('presentations/presentations files')
|
||||
for path in presentation_paths:
|
||||
self.media_item.clean_up_thumbnails(path, clean_for_update=True)
|
||||
# check to see if the file exists before trying to process it.
|
||||
if path.exists():
|
||||
self.media_item.clean_up_thumbnails(path, clean_for_update=True)
|
||||
self.media_item.list_view.clear()
|
||||
# Update the thumbnail scheme if needed
|
||||
if self.settings.value('presentations/thumbnail_scheme') != 'sha256file':
|
||||
|
1191
resources/i18n/af.ts
1191
resources/i18n/af.ts
File diff suppressed because it is too large
Load Diff
1191
resources/i18n/bg.ts
1191
resources/i18n/bg.ts
File diff suppressed because it is too large
Load Diff
1199
resources/i18n/cs.ts
1199
resources/i18n/cs.ts
File diff suppressed because it is too large
Load Diff
1199
resources/i18n/da.ts
1199
resources/i18n/da.ts
File diff suppressed because it is too large
Load Diff
1209
resources/i18n/de.ts
1209
resources/i18n/de.ts
File diff suppressed because it is too large
Load Diff
1191
resources/i18n/el.ts
1191
resources/i18n/el.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
1174
resources/i18n/es.ts
1174
resources/i18n/es.ts
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1089
resources/i18n/et.ts
1089
resources/i18n/et.ts
File diff suppressed because it is too large
Load Diff
1204
resources/i18n/fi.ts
1204
resources/i18n/fi.ts
File diff suppressed because it is too large
Load Diff
1172
resources/i18n/fr.ts
1172
resources/i18n/fr.ts
File diff suppressed because it is too large
Load Diff
1089
resources/i18n/hu.ts
1089
resources/i18n/hu.ts
File diff suppressed because it is too large
Load Diff
1197
resources/i18n/id.ts
1197
resources/i18n/id.ts
File diff suppressed because it is too large
Load Diff
1521
resources/i18n/it.ts
1521
resources/i18n/it.ts
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1167
resources/i18n/ja.ts
1167
resources/i18n/ja.ts
File diff suppressed because it is too large
Load Diff
1193
resources/i18n/ko.ts
1193
resources/i18n/ko.ts
File diff suppressed because it is too large
Load Diff
1162
resources/i18n/lt.ts
1162
resources/i18n/lt.ts
File diff suppressed because it is too large
Load Diff
1089
resources/i18n/nb.ts
1089
resources/i18n/nb.ts
File diff suppressed because it is too large
Load Diff
1199
resources/i18n/nl.ts
1199
resources/i18n/nl.ts
File diff suppressed because it is too large
Load Diff
1202
resources/i18n/pl.ts
1202
resources/i18n/pl.ts
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1197
resources/i18n/ro.ts
1197
resources/i18n/ro.ts
File diff suppressed because it is too large
Load Diff
1197
resources/i18n/ru.ts
1197
resources/i18n/ru.ts
File diff suppressed because it is too large
Load Diff
1207
resources/i18n/sk.ts
1207
resources/i18n/sk.ts
File diff suppressed because it is too large
Load Diff
1199
resources/i18n/sl.ts
1199
resources/i18n/sl.ts
File diff suppressed because it is too large
Load Diff
1256
resources/i18n/sv.ts
1256
resources/i18n/sv.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
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -522,7 +522,7 @@ def test_service_item_get_theme_data_song_level_service_fallback(settings):
|
||||
Test the service item - get theme data when set to song theme level
|
||||
but the song theme doesn't exist
|
||||
"""
|
||||
# GIVEN: A service item with a theme and theme level set to song
|
||||
# GIVEN: A service item with no theme and theme level set to song
|
||||
service_item = ServiceItem(None)
|
||||
service_item.from_service = True
|
||||
mocked_theme_manager = MagicMock()
|
||||
@ -544,7 +544,7 @@ def test_service_item_get_theme_data_song_level_global_fallback(settings):
|
||||
Test the service item - get theme data when set to song theme level
|
||||
but the song and service theme don't exist
|
||||
"""
|
||||
# GIVEN: A service item with a theme and theme level set to song
|
||||
# GIVEN: A service item with no theme and theme level set to song
|
||||
service_item = ServiceItem(None)
|
||||
mocked_theme_manager = MagicMock()
|
||||
mocked_theme_manager.global_theme = 'global_theme'
|
||||
@ -560,6 +560,30 @@ def test_service_item_get_theme_data_song_level_global_fallback(settings):
|
||||
assert theme == mocked_theme_manager.global_theme
|
||||
|
||||
|
||||
def test_service_item_get_theme_data_theme_override(settings):
|
||||
"""
|
||||
Test the service item - get theme data when set to global theme level
|
||||
but the service item has the `ProvidesOwnTheme`
|
||||
capability overriding the global theme
|
||||
"""
|
||||
# GIVEN: A service item with a theme and theme level set to global
|
||||
service_item = ServiceItem(None)
|
||||
service_item.theme = 'item_theme'
|
||||
service_item.add_capability(ItemCapabilities.ProvidesOwnTheme)
|
||||
mocked_theme_manager = MagicMock()
|
||||
mocked_theme_manager.global_theme = 'global_theme'
|
||||
mocked_theme_manager.get_theme_data = Mock(side_effect=lambda value: value)
|
||||
Registry().register('theme_manager', mocked_theme_manager)
|
||||
settings.setValue('servicemanager/service theme', 'service_theme')
|
||||
settings.setValue('themes/theme level', ThemeLevel.Global)
|
||||
|
||||
# WHEN: Get theme data is run
|
||||
theme = service_item.get_theme_data()
|
||||
|
||||
# THEN: theme should be the service item's theme
|
||||
assert theme == service_item.theme
|
||||
|
||||
|
||||
def test_remove_capability(settings):
|
||||
# GIVEN: A service item with a capability
|
||||
service_item = ServiceItem(None)
|
||||
|
@ -794,11 +794,11 @@ def test_set_background_image(registry):
|
||||
slide_controller.displays = [mock_display]
|
||||
|
||||
# WHEN: set_background_image is called
|
||||
slide_controller.set_background_image(sentinel.colour, sentinel.image)
|
||||
slide_controller.set_background_image(sentinel.image)
|
||||
|
||||
# THEN: The preview and main display are called with the new colour and image
|
||||
slide_controller.preview_display.set_background_image.assert_called_once_with(sentinel.colour, sentinel.image)
|
||||
mock_display.set_background_image.assert_called_once_with(sentinel.colour, sentinel.image)
|
||||
slide_controller.preview_display.set_background_image.assert_called_once_with(sentinel.image)
|
||||
mock_display.set_background_image.assert_called_once_with(sentinel.image)
|
||||
|
||||
|
||||
def test_theme_updated(mock_settings):
|
||||
|
@ -25,6 +25,7 @@ import pytest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.common.enum import ImageThemeMode
|
||||
from openlp.plugins.images.lib.imagetab import ImageTab
|
||||
|
||||
|
||||
@ -48,16 +49,33 @@ def test_save_tab_nochange(form):
|
||||
'Image Post processing should not have been requested'
|
||||
|
||||
|
||||
def test_save_tab_change(form):
|
||||
def test_save_tab_theme_change(form):
|
||||
"""
|
||||
Test a color change is applied and triggers post processing.
|
||||
Test a theme change is applied and triggers post processing.
|
||||
"""
|
||||
# GIVEN: Apply a change to the form.
|
||||
form.on_background_color_changed('#999999')
|
||||
form.theme_combo_box.currentText = MagicMock(return_value='my_theme')
|
||||
form.on_image_theme_changed()
|
||||
# WHEN: the save is invoked
|
||||
form.save()
|
||||
# THEN: the post process should be requested
|
||||
assert 1 == form.settings_form.register_post_process.call_count, \
|
||||
'Image Post processing should have been requested'
|
||||
# THEN: The color should be set
|
||||
assert form.background_color == '#999999', 'The updated color should have been saved'
|
||||
# THEN: The theme should be set
|
||||
assert form.image_theme == 'my_theme', 'The updated theme should have been saved'
|
||||
|
||||
|
||||
def test_save_tab_theme_mode_change(form):
|
||||
"""
|
||||
Test a theme change is applied and triggers post processing.
|
||||
"""
|
||||
# GIVEN: Apply a change to the form.
|
||||
form.radio_group.id = MagicMock(return_value=ImageThemeMode.CustomTheme)
|
||||
form.on_radio_group_button_toggled('radio_thing', True)
|
||||
# WHEN: the save is invoked
|
||||
form.save()
|
||||
# THEN: the post process should be requested
|
||||
assert 1 == form.settings_form.register_post_process.call_count, \
|
||||
'Image Post processing should have been requested'
|
||||
# THEN: The theme should be set
|
||||
assert form.background_mode == ImageThemeMode.CustomTheme, 'The updated background mode should have been saved'
|
||||
|
@ -28,6 +28,8 @@ from unittest.mock import ANY, MagicMock, patch
|
||||
from PyQt5 import QtCore, QtWidgets
|
||||
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.common.enum import ImageThemeMode
|
||||
from openlp.core.lib.serviceitem import ItemCapabilities
|
||||
from openlp.plugins.images.lib.db import ImageFilenames, ImageGroups
|
||||
from openlp.plugins.images.lib.mediaitem import ImageMediaItem
|
||||
|
||||
@ -203,11 +205,44 @@ def test_on_display_changed(media_item):
|
||||
media_item.reset_action_context.setVisible.assert_called_with(False)
|
||||
|
||||
|
||||
def test_generate_slide_data_default_theme(media_item):
|
||||
"""
|
||||
Test that the generated service item provides the corect theme
|
||||
"""
|
||||
# GIVEN: A mocked service item and settings
|
||||
mocked_service_item = MagicMock()
|
||||
media_item.list_view = MagicMock()
|
||||
Registry().get('settings').value.side_effect = [ImageThemeMode.Black]
|
||||
|
||||
# WHEN: generate_slide_data is called
|
||||
media_item.generate_slide_data(mocked_service_item)
|
||||
|
||||
# THEN: The service item should force the theme, and use the default theme
|
||||
mocked_service_item.add_capability.assert_any_call(ItemCapabilities.ProvidesOwnTheme)
|
||||
assert mocked_service_item.theme == -1
|
||||
|
||||
|
||||
def test_generate_slide_data_custom_theme(media_item):
|
||||
"""
|
||||
Test that the generated service item provides the corect theme
|
||||
"""
|
||||
# GIVEN: A mocked service item and settings
|
||||
mocked_service_item = MagicMock()
|
||||
media_item.list_view = MagicMock()
|
||||
Registry().get('settings').value.side_effect = [ImageThemeMode.CustomTheme, 'theme_name']
|
||||
|
||||
# WHEN: generate_slide_data is called
|
||||
media_item.generate_slide_data(mocked_service_item)
|
||||
|
||||
# THEN: The service item should force the theme, and use the theme in the settings
|
||||
mocked_service_item.add_capability.assert_any_call(ItemCapabilities.ProvidesOwnTheme)
|
||||
assert mocked_service_item.theme == 'theme_name'
|
||||
|
||||
|
||||
@patch('openlp.plugins.images.lib.mediaitem.check_item_selected')
|
||||
@patch('openlp.plugins.images.lib.mediaitem.isinstance')
|
||||
@patch('openlp.plugins.images.lib.mediaitem.QtGui.QColor')
|
||||
@patch('openlp.plugins.images.lib.mediaitem.Path.exists')
|
||||
def test_on_replace_click(mocked_exists, mocked_qcolor, mocked_isinstance, mocked_check_item_selected, media_item):
|
||||
def test_on_replace_click(mocked_exists, mocked_isinstance, mocked_check_item_selected, media_item):
|
||||
"""
|
||||
Test that on_replace_click() actually sets the background
|
||||
"""
|
||||
@ -218,7 +253,6 @@ def test_on_replace_click(mocked_exists, mocked_qcolor, mocked_isinstance, mocke
|
||||
mocked_check_item_selected.return_value = True
|
||||
mocked_isinstance.return_value = True
|
||||
mocked_exists.return_value = True
|
||||
mocked_qcolor.return_value = 'BackgroundColor'
|
||||
|
||||
# WHEN: on_replace_click is called
|
||||
media_item.on_replace_click()
|
||||
@ -226,7 +260,7 @@ def test_on_replace_click(mocked_exists, mocked_qcolor, mocked_isinstance, mocke
|
||||
# THEN: the reset_action should be set visible, and the image should be set
|
||||
media_item.reset_action.setVisible.assert_called_with(True)
|
||||
media_item.reset_action_context.setVisible.assert_called_with(True)
|
||||
media_item.live_controller.set_background_image.assert_called_with('BackgroundColor', ANY)
|
||||
media_item.live_controller.set_background_image.assert_called_with(ANY)
|
||||
|
||||
|
||||
@patch('openlp.plugins.images.lib.mediaitem.delete_file')
|
||||
|
@ -25,6 +25,8 @@ from pathlib import Path
|
||||
from unittest.mock import MagicMock, PropertyMock, call, patch
|
||||
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.lib import ServiceItemContext
|
||||
from openlp.core.lib.serviceitem import ItemCapabilities
|
||||
from openlp.plugins.presentations.lib.mediaitem import PresentationMediaItem
|
||||
|
||||
|
||||
@ -127,6 +129,23 @@ def test_clean_up_thumbnails_missing_file(media_item):
|
||||
mocked_doc.assert_has_calls([call.get_thumbnail_path(1, True), call.presentation_deleted()], True)
|
||||
|
||||
|
||||
def test_pdf_generate_slide_data(media_item):
|
||||
"""
|
||||
Test that the generate slide data function makes the correct ajustments to a pdf service item.
|
||||
"""
|
||||
# GIVEN: A mocked pdf service item
|
||||
media_item.list_view = MagicMock()
|
||||
media_item.display_type_combo_box = MagicMock()
|
||||
mocked_service_item = MagicMock()
|
||||
|
||||
# WHEN: generate_slide_data is called
|
||||
media_item.generate_slide_data(mocked_service_item, context=ServiceItemContext.Live, file_path=Path('test.pdf'))
|
||||
|
||||
# THEN: Should be categorized as images and overrides the theme
|
||||
assert mocked_service_item.name == 'images'
|
||||
mocked_service_item.add_capability.assert_any_call(ItemCapabilities.ProvidesOwnTheme)
|
||||
|
||||
|
||||
@patch('openlp.plugins.presentations.lib.mediaitem.MediaManagerItem._setup')
|
||||
@patch('openlp.plugins.presentations.lib.mediaitem.PresentationMediaItem.setup_item')
|
||||
def test_search(mock_setup, mock_item, registry):
|
||||
|
@ -792,7 +792,7 @@ describe("Display.setBackgroundImage and Display.resetTheme", function () {
|
||||
spyOn(Reveal, "sync");
|
||||
spyOn(Reveal, "slide");
|
||||
|
||||
Display.setBackgroundImage("#fff", "/file/path");
|
||||
Display.setBackgroundImage("/file/path");
|
||||
|
||||
expect($(".slides > section")[0].getAttribute("data-background")).toEqual("url('/file/path')");
|
||||
expect(Reveal.sync).toHaveBeenCalledTimes(1);
|
||||
|
Loading…
Reference in New Issue
Block a user