forked from openlp/openlp
More stuff working! Now you can see the text items in the slide controller and you can change the current slide
This commit is contained in:
parent
8b826f29c4
commit
1a744383e5
@ -226,15 +226,24 @@ AudioPlayer.prototype.play = function () {
|
|||||||
console.warn("No track currently paused and no track specified, doing nothing.");
|
console.warn("No track currently paused and no track specified, doing nothing.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pause
|
||||||
|
*/
|
||||||
AudioPlayer.prototype.pause = function () {
|
AudioPlayer.prototype.pause = function () {
|
||||||
this._audioElement.pause();
|
this._audioElement.pause();
|
||||||
this._state = AudioState.Paused;
|
this._state = AudioState.Paused;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop playing
|
||||||
|
*/
|
||||||
AudioPlayer.prototype.stop = function () {
|
AudioPlayer.prototype.stop = function () {
|
||||||
this._audioElement.pause();
|
this._audioElement.pause();
|
||||||
this._audioElement.src = "";
|
this._audioElement.src = "";
|
||||||
this._state = AudioState.Stopped;
|
this._state = AudioState.Stopped;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Display object is what we use from OpenLP
|
* The Display object is what we use from OpenLP
|
||||||
*/
|
*/
|
||||||
@ -250,8 +259,8 @@ var Display = {
|
|||||||
overview: false,
|
overview: false,
|
||||||
center: false,
|
center: false,
|
||||||
help: false,
|
help: false,
|
||||||
transition: "slide",
|
transition: "none",
|
||||||
backgroundTransition: "fade",
|
backgroundTransition: "none",
|
||||||
viewDistance: 9999,
|
viewDistance: 9999,
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%"
|
height: "100%"
|
||||||
@ -321,15 +330,15 @@ var Display = {
|
|||||||
slides.forEach(function (slide) {
|
slides.forEach(function (slide) {
|
||||||
Display.addTextSlide(slide.verse, slide.text, false);
|
Display.addTextSlide(slide.verse, slide.text, false);
|
||||||
});
|
});
|
||||||
this.reinit();
|
Display.reinit();
|
||||||
|
Display.goToSlide(0);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Set image slides
|
* Set image slides
|
||||||
* @param {Object[]} slides - A list of images to add as JS objects [{"file": "url/to/file"}]
|
* @param {Object[]} slides - A list of images to add as JS objects [{"file": "url/to/file"}]
|
||||||
*/
|
*/
|
||||||
setImageSlides: function (slides) {
|
setImageSlides: function (slides) {
|
||||||
var $this = this;
|
Display.clearSlides();
|
||||||
$this.clearSlides();
|
|
||||||
var slidesDiv = $(".slides")[0];
|
var slidesDiv = $(".slides")[0];
|
||||||
slides.forEach(function (slide, index) {
|
slides.forEach(function (slide, index) {
|
||||||
var section = document.createElement("section");
|
var section = document.createElement("section");
|
||||||
@ -340,9 +349,9 @@ var Display = {
|
|||||||
img.setAttribute("style", "height: 100%; width: 100%;");
|
img.setAttribute("style", "height: 100%; width: 100%;");
|
||||||
section.appendChild(img);
|
section.appendChild(img);
|
||||||
slidesDiv.appendChild(section);
|
slidesDiv.appendChild(section);
|
||||||
$this._slides[index.toString()] = index;
|
Display._slides[index.toString()] = index;
|
||||||
});
|
});
|
||||||
this.reinit();
|
Display.reinit();
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Set a video
|
* Set a video
|
||||||
@ -461,7 +470,12 @@ var Display = {
|
|||||||
* @param slide The slide number or name, e.g. "v1", 0
|
* @param slide The slide number or name, e.g. "v1", 0
|
||||||
*/
|
*/
|
||||||
goToSlide: function (slide) {
|
goToSlide: function (slide) {
|
||||||
|
if (this._slides.hasOwnProperty(slide)) {
|
||||||
Reveal.slide(this._slides[slide]);
|
Reveal.slide(this._slides[slide]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Reveal.slide(slide);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Go to the next slide in the list
|
* Go to the next slide in the list
|
||||||
|
@ -182,6 +182,14 @@ class DisplayWindow(QtWidgets.QWidget):
|
|||||||
QtWidgets.QApplication.instance().processEvents()
|
QtWidgets.QApplication.instance().processEvents()
|
||||||
return self.__script_result
|
return self.__script_result
|
||||||
|
|
||||||
|
def go_to_slide(self, verse):
|
||||||
|
"""
|
||||||
|
Go to a particular slide.
|
||||||
|
|
||||||
|
:param str verse: The verse to go to, e.g. "V1" for songs, or just "0" for other types
|
||||||
|
"""
|
||||||
|
self.run_javascript('Display.goToSlide("{verse}");'.format(verse=verse))
|
||||||
|
|
||||||
def load_verses(self, verses):
|
def load_verses(self, verses):
|
||||||
"""
|
"""
|
||||||
Set verses in the display
|
Set verses in the display
|
||||||
|
@ -24,7 +24,6 @@ The :mod:`serviceitem` provides the service item functionality including the
|
|||||||
type and capability of an item.
|
type and capability of an item.
|
||||||
"""
|
"""
|
||||||
import datetime
|
import datetime
|
||||||
import html
|
|
||||||
import logging
|
import logging
|
||||||
import ntpath
|
import ntpath
|
||||||
import os
|
import os
|
||||||
@ -36,9 +35,9 @@ from openlp.core.common import md5_hash
|
|||||||
from openlp.core.common.applocation import AppLocation
|
from openlp.core.common.applocation import AppLocation
|
||||||
from openlp.core.common.i18n import translate
|
from openlp.core.common.i18n import translate
|
||||||
from openlp.core.common.mixins import RegistryProperties
|
from openlp.core.common.mixins import RegistryProperties
|
||||||
from openlp.core.common.path import Path
|
from openlp.core.common.path import Path, path_to_str
|
||||||
from openlp.core.common.settings import Settings
|
from openlp.core.common.settings import Settings
|
||||||
from openlp.core.display.render import remove_tags, render_tags, render_chords
|
# from openlp.core.display.render import remove_tags, render_tags, render_chords
|
||||||
from openlp.core.lib import ImageSource, build_icon
|
from openlp.core.lib import ImageSource, build_icon
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -163,6 +162,7 @@ class ServiceItem(RegistryProperties):
|
|||||||
if plugin:
|
if plugin:
|
||||||
self.name = plugin.name
|
self.name = plugin.name
|
||||||
self.title = ''
|
self.title = ''
|
||||||
|
self.slides = []
|
||||||
self.processor = None
|
self.processor = None
|
||||||
self.audit = ''
|
self.audit = ''
|
||||||
self.items = []
|
self.items = []
|
||||||
@ -171,8 +171,8 @@ class ServiceItem(RegistryProperties):
|
|||||||
self.foot_text = ''
|
self.foot_text = ''
|
||||||
self.theme = None
|
self.theme = None
|
||||||
self.service_item_type = None
|
self.service_item_type = None
|
||||||
self._raw_frames = []
|
# self._raw_frames = []
|
||||||
self._display_frames = []
|
# self._display_frames = []
|
||||||
self.unique_identifier = 0
|
self.unique_identifier = 0
|
||||||
self.notes = ''
|
self.notes = ''
|
||||||
self.from_plugin = False
|
self.from_plugin = False
|
||||||
@ -234,91 +234,91 @@ class ServiceItem(RegistryProperties):
|
|||||||
self.icon = icon
|
self.icon = icon
|
||||||
self.iconic_representation = build_icon(icon)
|
self.iconic_representation = build_icon(icon)
|
||||||
|
|
||||||
def render(self, provides_own_theme_data=False):
|
# def render(self, provides_own_theme_data=False):
|
||||||
"""
|
# """
|
||||||
The render method is what generates the frames for the screen and obtains the display information from the
|
# The render method is what generates the frames for the screen and obtains the display information from the
|
||||||
renderer. At this point all slides are built for the given display size.
|
# renderer. At this point all slides are built for the given display size.
|
||||||
|
#
|
||||||
|
# :param provides_own_theme_data: This switch disables the usage of the item's theme. However, this is
|
||||||
|
# disabled by default. If this is used, it has to be taken care, that
|
||||||
|
# the renderer knows the correct theme data. However, this is needed
|
||||||
|
# for the theme manager.
|
||||||
|
# """
|
||||||
|
# log.debug('Render called')
|
||||||
|
# self._display_frames = []
|
||||||
|
# self.bg_image_bytes = None
|
||||||
|
# # if not provides_own_theme_data:
|
||||||
|
# # self.renderer.set_item_theme(self.theme)
|
||||||
|
# # self.theme_data, self.main, self.footer = self.renderer.pre_render()
|
||||||
|
# if self.service_item_type == ServiceItemType.Text:
|
||||||
|
# can_render_chords = hasattr(self, 'name') and self.name == 'songs' and Settings().value(
|
||||||
|
# 'songs/enable chords')
|
||||||
|
# log.debug('Formatting slides: {title}'.format(title=self.title))
|
||||||
|
# # Save rendered pages to this dict. In the case that a slide is used twice we can use the pages saved to
|
||||||
|
# # the dict instead of rendering them again.
|
||||||
|
# previous_pages = {}
|
||||||
|
# for slide in self._raw_frames:
|
||||||
|
# verse_tag = slide['verseTag']
|
||||||
|
# if verse_tag in previous_pages and previous_pages[verse_tag][0] == slide['raw_slide']:
|
||||||
|
# pages = previous_pages[verse_tag][1]
|
||||||
|
# else:
|
||||||
|
# # pages = self.renderer.format_slide(slide['raw_slide'], self)
|
||||||
|
# previous_pages[verse_tag] = (slide['raw_slide'], pages)
|
||||||
|
# for page in pages:
|
||||||
|
# page = page.replace('<br>', '{br}')
|
||||||
|
# html_data = render_tags(page.rstrip(), can_render_chords)
|
||||||
|
# new_frame = {
|
||||||
|
# 'title': remove_tags(page),
|
||||||
|
# 'text': remove_tags(page.rstrip(), can_render_chords),
|
||||||
|
# 'chords_text': render_chords(remove_tags(page.rstrip(), False)),
|
||||||
|
# 'html': html_data.replace('&nbsp;', ' '),
|
||||||
|
# 'printing_html': render_tags(html.escape(page.rstrip()), can_render_chords, is_printing=True),
|
||||||
|
# 'verseTag': verse_tag,
|
||||||
|
# }
|
||||||
|
# self._display_frames.append(new_frame)
|
||||||
|
# elif self.service_item_type == ServiceItemType.Image or self.service_item_type == ServiceItemType.Command:
|
||||||
|
# pass
|
||||||
|
# else:
|
||||||
|
# log.error('Invalid value renderer: {item}'.format(item=self.service_item_type))
|
||||||
|
# self.title = remove_tags(self.title)
|
||||||
|
# # The footer should never be None, but to be compatible with a few
|
||||||
|
# # nightly builds between 1.9.4 and 1.9.5, we have to correct this to
|
||||||
|
# # avoid tracebacks.
|
||||||
|
# if self.raw_footer is None:
|
||||||
|
# self.raw_footer = []
|
||||||
|
# self.foot_text = '<br>'.join([_f for _f in self.raw_footer if _f])
|
||||||
|
|
||||||
:param provides_own_theme_data: This switch disables the usage of the item's theme. However, this is
|
def add_from_image(self, filename, title, background=None, thumbnail=None):
|
||||||
disabled by default. If this is used, it has to be taken care, that
|
|
||||||
the renderer knows the correct theme data. However, this is needed
|
|
||||||
for the theme manager.
|
|
||||||
"""
|
|
||||||
log.debug('Render called')
|
|
||||||
self._display_frames = []
|
|
||||||
self.bg_image_bytes = None
|
|
||||||
# if not provides_own_theme_data:
|
|
||||||
# self.renderer.set_item_theme(self.theme)
|
|
||||||
# self.theme_data, self.main, self.footer = self.renderer.pre_render()
|
|
||||||
if self.service_item_type == ServiceItemType.Text:
|
|
||||||
can_render_chords = hasattr(self, 'name') and self.name == 'songs' and Settings().value(
|
|
||||||
'songs/enable chords')
|
|
||||||
log.debug('Formatting slides: {title}'.format(title=self.title))
|
|
||||||
# Save rendered pages to this dict. In the case that a slide is used twice we can use the pages saved to
|
|
||||||
# the dict instead of rendering them again.
|
|
||||||
previous_pages = {}
|
|
||||||
for slide in self._raw_frames:
|
|
||||||
verse_tag = slide['verseTag']
|
|
||||||
if verse_tag in previous_pages and previous_pages[verse_tag][0] == slide['raw_slide']:
|
|
||||||
pages = previous_pages[verse_tag][1]
|
|
||||||
else:
|
|
||||||
# pages = self.renderer.format_slide(slide['raw_slide'], self)
|
|
||||||
previous_pages[verse_tag] = (slide['raw_slide'], pages)
|
|
||||||
for page in pages:
|
|
||||||
page = page.replace('<br>', '{br}')
|
|
||||||
html_data = render_tags(page.rstrip(), can_render_chords)
|
|
||||||
new_frame = {
|
|
||||||
'title': remove_tags(page),
|
|
||||||
'text': remove_tags(page.rstrip(), can_render_chords),
|
|
||||||
'chords_text': render_chords(remove_tags(page.rstrip(), False)),
|
|
||||||
'html': html_data.replace('&nbsp;', ' '),
|
|
||||||
'printing_html': render_tags(html.escape(page.rstrip()), can_render_chords, is_printing=True),
|
|
||||||
'verseTag': verse_tag,
|
|
||||||
}
|
|
||||||
self._display_frames.append(new_frame)
|
|
||||||
elif self.service_item_type == ServiceItemType.Image or self.service_item_type == ServiceItemType.Command:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
log.error('Invalid value renderer: {item}'.format(item=self.service_item_type))
|
|
||||||
self.title = remove_tags(self.title)
|
|
||||||
# The footer should never be None, but to be compatible with a few
|
|
||||||
# nightly builds between 1.9.4 and 1.9.5, we have to correct this to
|
|
||||||
# avoid tracebacks.
|
|
||||||
if self.raw_footer is None:
|
|
||||||
self.raw_footer = []
|
|
||||||
self.foot_text = '<br>'.join([_f for _f in self.raw_footer if _f])
|
|
||||||
|
|
||||||
def add_from_image(self, path, title, background=None, thumbnail=None):
|
|
||||||
"""
|
"""
|
||||||
Add an image slide to the service item.
|
Add an image slide to the service item.
|
||||||
|
|
||||||
:param path: The directory in which the image file is located.
|
:param filename: The directory in which the image file is located.
|
||||||
:param title: A title for the slide in the service item.
|
:param title: A title for the slide in the service item.
|
||||||
:param background:
|
:param background: The background colour
|
||||||
:param thumbnail: Optional alternative thumbnail, used for remote thumbnails.
|
:param thumbnail: Optional alternative thumbnail, used for remote thumbnails.
|
||||||
"""
|
"""
|
||||||
if background:
|
if background:
|
||||||
self.image_border = background
|
self.image_border = background
|
||||||
self.service_item_type = ServiceItemType.Image
|
self.service_item_type = ServiceItemType.Image
|
||||||
if not thumbnail:
|
slide = {'title': title, 'filename': filename}
|
||||||
self._raw_frames.append({'title': title, 'path': path})
|
if thumbnail:
|
||||||
else:
|
slide['thumbnail'] = thumbnail
|
||||||
self._raw_frames.append({'title': title, 'path': path, 'image': thumbnail})
|
self.slides.append(slide)
|
||||||
self.image_manager.add_image(path, ImageSource.ImagePlugin, self.image_border)
|
# self.image_manager.add_image(path, ImageSource.ImagePlugin, self.image_border)
|
||||||
self._new_item()
|
self._new_item()
|
||||||
|
|
||||||
def add_from_text(self, raw_slide, verse_tag=None):
|
def add_from_text(self, text, verse_tag=None):
|
||||||
"""
|
"""
|
||||||
Add a text slide to the service item.
|
Add a text slide to the service item.
|
||||||
|
|
||||||
:param raw_slide: The raw text of the slide.
|
:param text: The raw text of the slide.
|
||||||
:param verse_tag:
|
:param verse_tag:
|
||||||
"""
|
"""
|
||||||
if verse_tag:
|
if verse_tag:
|
||||||
verse_tag = verse_tag.upper()
|
verse_tag = verse_tag.upper()
|
||||||
self.service_item_type = ServiceItemType.Text
|
self.service_item_type = ServiceItemType.Text
|
||||||
title = raw_slide[:30].split('\n')[0]
|
title = text[:30].split('\n')[0]
|
||||||
self._raw_frames.append({'title': title, 'raw_slide': raw_slide, 'verseTag': verse_tag})
|
self.slides.append({'title': title, 'text': text, 'verse': verse_tag})
|
||||||
self._new_item()
|
self._new_item()
|
||||||
|
|
||||||
def add_from_command(self, path, file_name, image, display_title=None, notes=None):
|
def add_from_command(self, path, file_name, image, display_title=None, notes=None):
|
||||||
@ -342,7 +342,7 @@ class ServiceItem(RegistryProperties):
|
|||||||
file_location_hash = md5_hash(file_location.encode('utf-8'))
|
file_location_hash = md5_hash(file_location.encode('utf-8'))
|
||||||
image = os.path.join(str(AppLocation.get_section_data_path(self.name)), 'thumbnails',
|
image = os.path.join(str(AppLocation.get_section_data_path(self.name)), 'thumbnails',
|
||||||
file_location_hash, ntpath.basename(image))
|
file_location_hash, ntpath.basename(image))
|
||||||
self._raw_frames.append({'title': file_name, 'image': image, 'path': path,
|
self.slides.append({'title': file_name, 'image': image, 'path': path,
|
||||||
'display_title': display_title, 'notes': notes})
|
'display_title': display_title, 'notes': notes})
|
||||||
if self.is_capable(ItemCapabilities.HasThumbnails):
|
if self.is_capable(ItemCapabilities.HasThumbnails):
|
||||||
self.image_manager.add_image(image, ImageSource.CommandPlugins, '#000000')
|
self.image_manager.add_image(image, ImageSource.CommandPlugins, '#000000')
|
||||||
@ -474,10 +474,10 @@ class ServiceItem(RegistryProperties):
|
|||||||
or self.is_capable(ItemCapabilities.CanEditTitle):
|
or self.is_capable(ItemCapabilities.CanEditTitle):
|
||||||
return self.title
|
return self.title
|
||||||
else:
|
else:
|
||||||
if len(self._raw_frames) > 1:
|
if len(self.slides) > 1:
|
||||||
return self.title
|
return self.title
|
||||||
else:
|
else:
|
||||||
return self._raw_frames[0]['title']
|
return self.slides[0]['title']
|
||||||
|
|
||||||
def merge(self, other):
|
def merge(self, other):
|
||||||
"""
|
"""
|
||||||
@ -665,22 +665,22 @@ class ServiceItem(RegistryProperties):
|
|||||||
Validates a service item to make sure it is valid
|
Validates a service item to make sure it is valid
|
||||||
"""
|
"""
|
||||||
self.is_valid = True
|
self.is_valid = True
|
||||||
for frame in self._raw_frames:
|
for slide in self.slides:
|
||||||
if self.is_image() and not os.path.exists(frame['path']):
|
if self.is_image() and not os.path.exists(slide['filename']):
|
||||||
self.is_valid = False
|
self.is_valid = False
|
||||||
break
|
break
|
||||||
elif self.is_command():
|
elif self.is_command():
|
||||||
if self.is_capable(ItemCapabilities.IsOptical):
|
if self.is_capable(ItemCapabilities.IsOptical):
|
||||||
if not os.path.exists(frame['title']):
|
if not os.path.exists(slide['title']):
|
||||||
self.is_valid = False
|
self.is_valid = False
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
file_name = os.path.join(frame['path'], frame['title'])
|
file_name = os.path.join(slide['path'], slide['title'])
|
||||||
if not os.path.exists(file_name):
|
if not os.path.exists(file_name):
|
||||||
self.is_valid = False
|
self.is_valid = False
|
||||||
break
|
break
|
||||||
if suffix_list and not self.is_text():
|
if suffix_list and not self.is_text():
|
||||||
file_suffix = frame['title'].split('.')[-1]
|
file_suffix = slide['title'].split('.')[-1]
|
||||||
if file_suffix.lower() not in suffix_list:
|
if file_suffix.lower() not in suffix_list:
|
||||||
self.is_valid = False
|
self.is_valid = False
|
||||||
break
|
break
|
||||||
|
@ -1165,7 +1165,7 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi
|
|||||||
# Repaint the screen
|
# Repaint the screen
|
||||||
self.service_manager_list.clear()
|
self.service_manager_list.clear()
|
||||||
self.service_manager_list.clearSelection()
|
self.service_manager_list.clearSelection()
|
||||||
for item_count, item in enumerate(self.service_items):
|
for item_index, item in enumerate(self.service_items):
|
||||||
service_item_from_item = item['service_item']
|
service_item_from_item = item['service_item']
|
||||||
tree_widget_item = QtWidgets.QTreeWidgetItem(self.service_manager_list)
|
tree_widget_item = QtWidgets.QTreeWidgetItem(self.service_manager_list)
|
||||||
if service_item_from_item.is_valid:
|
if service_item_from_item.is_valid:
|
||||||
@ -1211,17 +1211,17 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi
|
|||||||
tree_widget_item.setData(0, QtCore.Qt.UserRole, item['order'])
|
tree_widget_item.setData(0, QtCore.Qt.UserRole, item['order'])
|
||||||
tree_widget_item.setSelected(item['selected'])
|
tree_widget_item.setSelected(item['selected'])
|
||||||
# Add the children to their parent tree_widget_item.
|
# Add the children to their parent tree_widget_item.
|
||||||
for count, frame in enumerate(service_item_from_item.get_frames()):
|
for slide_index, slide in enumerate(service_item_from_item.slides):
|
||||||
child = QtWidgets.QTreeWidgetItem(tree_widget_item)
|
child = QtWidgets.QTreeWidgetItem(tree_widget_item)
|
||||||
# prefer to use a display_title
|
# prefer to use a display_title
|
||||||
if service_item_from_item.is_capable(ItemCapabilities.HasDisplayTitle):
|
if service_item_from_item.is_capable(ItemCapabilities.HasDisplayTitle):
|
||||||
text = frame['display_title'].replace('\n', ' ')
|
text = slide['display_title'].replace('\n', ' ')
|
||||||
else:
|
else:
|
||||||
text = frame['title'].replace('\n', ' ')
|
text = slide['title'].replace('\n', ' ')
|
||||||
child.setText(0, text[:40])
|
child.setText(0, text[:40])
|
||||||
child.setData(0, QtCore.Qt.UserRole, count)
|
child.setData(0, QtCore.Qt.UserRole, slide_index)
|
||||||
if service_item == item_count:
|
if service_item == item_index:
|
||||||
if item['expanded'] and service_item_child == count:
|
if item['expanded'] and service_item_child == slide_index:
|
||||||
self.service_manager_list.setCurrentItem(child)
|
self.service_manager_list.setCurrentItem(child)
|
||||||
elif service_item_child == -1:
|
elif service_item_child == -1:
|
||||||
self.service_manager_list.setCurrentItem(tree_widget_item)
|
self.service_manager_list.setCurrentItem(tree_widget_item)
|
||||||
@ -1339,7 +1339,7 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi
|
|||||||
self.repaint_service_list(s_item, child)
|
self.repaint_service_list(s_item, child)
|
||||||
self.live_controller.replace_service_manager_item(item)
|
self.live_controller.replace_service_manager_item(item)
|
||||||
else:
|
else:
|
||||||
item.render()
|
# item.render()
|
||||||
# nothing selected for dnd
|
# nothing selected for dnd
|
||||||
if self.drop_position == -1:
|
if self.drop_position == -1:
|
||||||
if isinstance(item, list):
|
if isinstance(item, list):
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
The :mod:`slidecontroller` module contains the most important part of OpenLP - the slide controller
|
The :mod:`slidecontroller` module contains the most important part of OpenLP - the slide controller
|
||||||
"""
|
"""
|
||||||
import copy
|
import copy
|
||||||
import os
|
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
|
||||||
@ -135,12 +134,15 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
"""
|
"""
|
||||||
Set up the display
|
Set up the display
|
||||||
"""
|
"""
|
||||||
|
if not self.is_live:
|
||||||
|
return
|
||||||
if self.displays:
|
if self.displays:
|
||||||
# Delete any existing displays
|
# Delete any existing displays
|
||||||
del self.displays[:]
|
del self.displays[:]
|
||||||
# for screen in self.screens:
|
for screen in self.screens:
|
||||||
# display = DisplayWindow(self, self.screens.current)
|
if screen.is_display:
|
||||||
# self.displays.append(display)
|
display = DisplayWindow(self, screen)
|
||||||
|
self.displays.append(display)
|
||||||
# display.media_watcher.progress.connect(self.on_audio_time_remaining)
|
# display.media_watcher.progress.connect(self.on_audio_time_remaining)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -574,8 +576,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
"""
|
"""
|
||||||
Settings dialog has changed the screen size of adjust output and screen previews.
|
Settings dialog has changed the screen size of adjust output and screen previews.
|
||||||
"""
|
"""
|
||||||
# rebuild display as screen size changed
|
if self.is_live and self.displays:
|
||||||
if self.displays:
|
|
||||||
for display in self.displays:
|
for display in self.displays:
|
||||||
display.resize(self.screens.current.display_geometry.size())
|
display.resize(self.screens.current.display_geometry.size())
|
||||||
# if self.is_live:
|
# if self.is_live:
|
||||||
@ -683,7 +684,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
if (Settings().value(self.main_window.songs_settings_section + '/display songbar') and
|
if (Settings().value(self.main_window.songs_settings_section + '/display songbar') and
|
||||||
not self.song_menu.menu().isEmpty()):
|
not self.song_menu.menu().isEmpty()):
|
||||||
self.toolbar.set_widget_visible(['song_menu'], True)
|
self.toolbar.set_widget_visible(['song_menu'], True)
|
||||||
if item.is_capable(ItemCapabilities.CanLoop) and len(item.get_frames()) > 1:
|
if item.is_capable(ItemCapabilities.CanLoop) and len(item.slides) > 1:
|
||||||
self.toolbar.set_widget_visible(LOOP_LIST)
|
self.toolbar.set_widget_visible(LOOP_LIST)
|
||||||
if item.is_media():
|
if item.is_media():
|
||||||
self.mediabar.show()
|
self.mediabar.show()
|
||||||
@ -737,14 +738,14 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
theme_name = item.theme if item.theme else Registry().get('theme_manager').global_theme
|
theme_name = item.theme if item.theme else Registry().get('theme_manager').global_theme
|
||||||
self.preview_display.set_theme(Registry().get('theme_manager').get_theme_data(theme_name))
|
self.preview_display.set_theme(Registry().get('theme_manager').get_theme_data(theme_name))
|
||||||
if item.is_text():
|
if item.is_text():
|
||||||
self.preview_display.load_verses([{'verse': f['verseTag'], 'text': f['raw_slide']}
|
self.preview_display.load_verses(item.slides)
|
||||||
for f in item._raw_frames])
|
elif item.is_image():
|
||||||
self.preview_display.show_display()
|
self.preview_display.load_images(item.slides)
|
||||||
# slide_no = 0
|
slide_no = 0
|
||||||
# if self.song_edit:
|
# if self.song_edit:
|
||||||
# slide_no = self.selected_row
|
# slide_no = self.selected_row
|
||||||
# self.song_edit = False
|
# self.song_edit = False
|
||||||
# self._process_item(item, slide_no)
|
self._process_item(item, slide_no)
|
||||||
|
|
||||||
def replace_service_manager_item(self, item):
|
def replace_service_manager_item(self, item):
|
||||||
"""
|
"""
|
||||||
@ -797,6 +798,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
old_item = self.service_item
|
old_item = self.service_item
|
||||||
# rest to allow the remote pick up verse 1 if large imaged
|
# rest to allow the remote pick up verse 1 if large imaged
|
||||||
self.selected_row = 0
|
self.selected_row = 0
|
||||||
|
self.preview_display.go_to_slide(0)
|
||||||
# take a copy not a link to the servicemanager copy.
|
# take a copy not a link to the servicemanager copy.
|
||||||
self.service_item = copy.copy(service_item)
|
self.service_item = copy.copy(service_item)
|
||||||
if self.service_item.is_command():
|
if self.service_item.is_command():
|
||||||
@ -811,40 +813,40 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
self.slide_list = {}
|
self.slide_list = {}
|
||||||
if self.is_live:
|
if self.is_live:
|
||||||
self.song_menu.menu().clear()
|
self.song_menu.menu().clear()
|
||||||
if self.display.audio_player:
|
# if self.display.audio_player:
|
||||||
self.display.audio_player.reset()
|
# self.display.audio_player.reset()
|
||||||
self.set_audio_items_visibility(False)
|
# self.set_audio_items_visibility(False)
|
||||||
self.audio_pause_item.setChecked(False)
|
# self.audio_pause_item.setChecked(False)
|
||||||
# If the current item has background audio
|
# # If the current item has background audio
|
||||||
if self.service_item.is_capable(ItemCapabilities.HasBackgroundAudio):
|
# if self.service_item.is_capable(ItemCapabilities.HasBackgroundAudio):
|
||||||
self.log_debug('Starting to play...')
|
# self.log_debug('Starting to play...')
|
||||||
self.display.audio_player.add_to_playlist(self.service_item.background_audio)
|
# self.display.audio_player.add_to_playlist(self.service_item.background_audio)
|
||||||
self.track_menu.clear()
|
# self.track_menu.clear()
|
||||||
for counter in range(len(self.service_item.background_audio)):
|
# for counter in range(len(self.service_item.background_audio)):
|
||||||
action = self.track_menu.addAction(
|
# action = self.track_menu.addAction(
|
||||||
os.path.basename(str(self.service_item.background_audio[counter])))
|
# os.path.basename(str(self.service_item.background_audio[counter])))
|
||||||
action.setData(counter)
|
# action.setData(counter)
|
||||||
action.triggered.connect(self.on_track_triggered)
|
# action.triggered.connect(self.on_track_triggered)
|
||||||
self.display.audio_player.repeat = \
|
# self.display.audio_player.repeat = \
|
||||||
Settings().value(self.main_window.general_settings_section + '/audio repeat list')
|
# Settings().value(self.main_window.general_settings_section + '/audio repeat list')
|
||||||
if Settings().value(self.main_window.general_settings_section + '/audio start paused'):
|
# if Settings().value(self.main_window.general_settings_section + '/audio start paused'):
|
||||||
self.audio_pause_item.setChecked(True)
|
# self.audio_pause_item.setChecked(True)
|
||||||
self.display.audio_player.pause()
|
# self.display.audio_player.pause()
|
||||||
else:
|
# else:
|
||||||
self.display.audio_player.play()
|
# self.display.audio_player.play()
|
||||||
self.set_audio_items_visibility(True)
|
# self.set_audio_items_visibility(True)
|
||||||
row = 0
|
row = 0
|
||||||
width = self.main_window.control_splitter.sizes()[self.split]
|
width = self.main_window.control_splitter.sizes()[self.split]
|
||||||
for frame_number, frame in enumerate(self.service_item.get_frames()):
|
for slide_index, slide in enumerate(self.service_item.slides):
|
||||||
if self.service_item.is_text():
|
if self.service_item.is_text():
|
||||||
if frame['verseTag']:
|
if slide['verse']:
|
||||||
# These tags are already translated.
|
# These tags are already translated.
|
||||||
verse_def = frame['verseTag']
|
verse_def = slide['verse']
|
||||||
verse_def = '{def1}{def2}'.format(def1=verse_def[0], def2=verse_def[1:])
|
verse_def = '{def1}{def2}'.format(def1=verse_def[0], def2=verse_def[1:])
|
||||||
two_line_def = '{def1}\n{def2}'.format(def1=verse_def[0], def2=verse_def[1:])
|
two_line_def = '{def1}\n{def2}'.format(def1=verse_def[0], def2=verse_def[1:])
|
||||||
row = two_line_def
|
row = two_line_def
|
||||||
if verse_def not in self.slide_list:
|
if verse_def not in self.slide_list:
|
||||||
self.slide_list[verse_def] = frame_number
|
self.slide_list[verse_def] = slide_index
|
||||||
if self.is_live:
|
if self.is_live:
|
||||||
self.song_menu.menu().addAction(verse_def, self.on_song_bar_handler)
|
self.song_menu.menu().addAction(verse_def, self.on_song_bar_handler)
|
||||||
else:
|
else:
|
||||||
@ -854,16 +856,16 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
row += 1
|
row += 1
|
||||||
self.slide_list[str(row)] = row - 1
|
self.slide_list[str(row)] = row - 1
|
||||||
# If current slide set background to image
|
# If current slide set background to image
|
||||||
if not self.service_item.is_command() and frame_number == slide_no:
|
if not self.service_item.is_command() and slide_index == slide_no:
|
||||||
self.service_item.bg_image_bytes = \
|
self.service_item.bg_image_bytes = \
|
||||||
self.image_manager.get_image_bytes(frame['path'], ImageSource.ImagePlugin)
|
self.image_manager.get_image_bytes(slide['filename'], ImageSource.ImagePlugin)
|
||||||
self.preview_widget.replace_service_item(self.service_item, width, slide_no)
|
self.preview_widget.replace_service_item(self.service_item, width, slide_no)
|
||||||
self.enable_tool_bar(self.service_item)
|
self.enable_tool_bar(self.service_item)
|
||||||
# Pass to display for viewing.
|
# Pass to display for viewing.
|
||||||
# Postpone image build, we need to do this later to avoid the theme
|
# Postpone image build, we need to do this later to avoid the theme
|
||||||
# flashing on the screen
|
# flashing on the screen
|
||||||
if not self.service_item.is_image():
|
# if not self.service_item.is_image():
|
||||||
self.display.build_html(self.service_item)
|
# self.display.build_html(self.service_item)
|
||||||
if self.service_item.is_media():
|
if self.service_item.is_media():
|
||||||
self.on_media_start(self.service_item)
|
self.on_media_start(self.service_item)
|
||||||
self.slide_selected(True)
|
self.slide_selected(True)
|
||||||
@ -1098,7 +1100,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
if not start:
|
if not start:
|
||||||
Registry().execute('slidecontroller_live_unblank')
|
Registry().execute('slidecontroller_live_unblank')
|
||||||
row = self.preview_widget.current_slide_number()
|
row = self.preview_widget.current_slide_number()
|
||||||
old_selected_row = self.selected_row
|
# old_selected_row = self.selected_row
|
||||||
self.selected_row = 0
|
self.selected_row = 0
|
||||||
if -1 < row < self.preview_widget.slide_count():
|
if -1 < row < self.preview_widget.slide_count():
|
||||||
if self.service_item.is_command():
|
if self.service_item.is_command():
|
||||||
@ -1106,20 +1108,26 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
Registry().execute('{text}_slide'.format(text=self.service_item.name.lower()),
|
Registry().execute('{text}_slide'.format(text=self.service_item.name.lower()),
|
||||||
[self.service_item, self.is_live, row])
|
[self.service_item, self.is_live, row])
|
||||||
else:
|
else:
|
||||||
to_display = self.service_item.get_rendered_frame(row)
|
# to_display = self.service_item.get_rendered_frame(row)
|
||||||
if self.service_item.is_text():
|
if self.service_item.is_text():
|
||||||
self.display.text(to_display, row != old_selected_row)
|
for display in self.displays:
|
||||||
|
display.go_to_slide(row)
|
||||||
|
# self.display.text(to_display, row != old_selected_row)
|
||||||
else:
|
else:
|
||||||
if start:
|
if start:
|
||||||
self.display.build_html(self.service_item, to_display)
|
for display in self.displays:
|
||||||
|
display.load_images([])
|
||||||
|
# self.display.build_html(self.service_item, to_display)
|
||||||
else:
|
else:
|
||||||
self.display.image(to_display)
|
for display in self.displays:
|
||||||
|
display.go_to_slide(row)
|
||||||
|
# self.display.image(to_display)
|
||||||
# reset the store used to display first image
|
# reset the store used to display first image
|
||||||
self.service_item.bg_image_bytes = None
|
self.service_item.bg_image_bytes = None
|
||||||
self.selected_row = row
|
self.selected_row = row
|
||||||
self.update_preview()
|
self.update_preview()
|
||||||
self.preview_widget.change_slide(row)
|
self.preview_widget.change_slide(row)
|
||||||
self.display.setFocus()
|
# TODO: self.display.setFocus()
|
||||||
# Release lock
|
# Release lock
|
||||||
self.slide_selected_lock.release()
|
self.slide_selected_lock.release()
|
||||||
|
|
||||||
@ -1137,7 +1145,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
"""
|
"""
|
||||||
This updates the preview frame, for example after changing a slide or using *Blank to Theme*.
|
This updates the preview frame, for example after changing a slide or using *Blank to Theme*.
|
||||||
"""
|
"""
|
||||||
self.log_debug('update_preview {text} '.format(text=self.screens.current['primary']))
|
self.log_debug('update_preview {text} '.format(text=self.screens.current))
|
||||||
if self.service_item and self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay):
|
if self.service_item and self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay):
|
||||||
if self.is_live:
|
if self.is_live:
|
||||||
# If live, grab screen-cap of main display now
|
# If live, grab screen-cap of main display now
|
||||||
@ -1155,9 +1163,11 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
self.slide_image.setDevicePixelRatio(self.main_window.devicePixelRatio())
|
self.slide_image.setDevicePixelRatio(self.main_window.devicePixelRatio())
|
||||||
self.slide_preview.setPixmap(self.slide_image)
|
self.slide_preview.setPixmap(self.slide_image)
|
||||||
else:
|
else:
|
||||||
self.slide_image = self.display.preview()
|
print('Updating preview ... need to figure out what is supposed to happen here')
|
||||||
self.slide_image.setDevicePixelRatio(self.main_window.devicePixelRatio())
|
self.preview_display.go_to_slide(self.selected_row)
|
||||||
self.slide_preview.setPixmap(self.slide_image)
|
# self.slide_image = self.display.preview()
|
||||||
|
# self.slide_image.setDevicePixelRatio(self.main_window.devicePixelRatio())
|
||||||
|
# self.slide_preview.setPixmap(self.slide_image)
|
||||||
self.slide_count += 1
|
self.slide_count += 1
|
||||||
|
|
||||||
def grab_maindisplay(self):
|
def grab_maindisplay(self):
|
||||||
|
@ -120,8 +120,8 @@ class ListPreviewWidget(QtWidgets.QTableWidget, RegistryProperties):
|
|||||||
self.auto_row_height = max(self.viewport().height() / (-1 * max_img_row_height), 100)
|
self.auto_row_height = max(self.viewport().height() / (-1 * max_img_row_height), 100)
|
||||||
height = min(height, self.auto_row_height)
|
height = min(height, self.auto_row_height)
|
||||||
# Apply new height to slides
|
# Apply new height to slides
|
||||||
for frame_number in range(len(self.service_item.get_frames())):
|
for slide_index in range(len(self.service_item.slides)):
|
||||||
self.setRowHeight(frame_number, height)
|
self.setRowHeight(slide_index, height)
|
||||||
|
|
||||||
def row_resized(self, row, old_height, new_height):
|
def row_resized(self, row, old_height, new_height):
|
||||||
"""
|
"""
|
||||||
@ -134,7 +134,8 @@ class ListPreviewWidget(QtWidgets.QTableWidget, RegistryProperties):
|
|||||||
# Get and validate label widget containing slide & adjust max width
|
# Get and validate label widget containing slide & adjust max width
|
||||||
try:
|
try:
|
||||||
self.cellWidget(row, 0).children()[1].setMaximumWidth(new_height * self.screen_ratio)
|
self.cellWidget(row, 0).children()[1].setMaximumWidth(new_height * self.screen_ratio)
|
||||||
except:
|
except Exception:
|
||||||
|
# TODO: Figure out what sort of exceptions are thrown
|
||||||
return
|
return
|
||||||
|
|
||||||
def screen_size_changed(self, screen_ratio):
|
def screen_size_changed(self, screen_ratio):
|
||||||
@ -160,20 +161,20 @@ class ListPreviewWidget(QtWidgets.QTableWidget, RegistryProperties):
|
|||||||
self.setColumnWidth(0, width)
|
self.setColumnWidth(0, width)
|
||||||
row = 0
|
row = 0
|
||||||
text = []
|
text = []
|
||||||
for frame_number, frame in enumerate(self.service_item.get_frames()):
|
for slide_index, slide in enumerate(self.service_item.slides):
|
||||||
self.setRowCount(self.slide_count() + 1)
|
self.setRowCount(self.slide_count() + 1)
|
||||||
item = QtWidgets.QTableWidgetItem()
|
item = QtWidgets.QTableWidgetItem()
|
||||||
slide_height = 0
|
slide_height = 0
|
||||||
if self.service_item.is_text():
|
if self.service_item.is_text():
|
||||||
if frame['verseTag']:
|
if slide['verse']:
|
||||||
# These tags are already translated.
|
# These tags are already translated.
|
||||||
verse_def = frame['verseTag']
|
verse_def = slide['verse']
|
||||||
verse_def = '%s%s' % (verse_def[0], verse_def[1:])
|
verse_def = '%s%s' % (verse_def[0], verse_def[1:])
|
||||||
two_line_def = '%s\n%s' % (verse_def[0], verse_def[1:])
|
two_line_def = '%s\n%s' % (verse_def[0], verse_def[1:])
|
||||||
row = two_line_def
|
row = two_line_def
|
||||||
else:
|
else:
|
||||||
row += 1
|
row += 1
|
||||||
item.setText(frame['text'])
|
item.setText(slide['text'])
|
||||||
else:
|
else:
|
||||||
label = QtWidgets.QLabel()
|
label = QtWidgets.QLabel()
|
||||||
label.setContentsMargins(4, 4, 4, 4)
|
label.setContentsMargins(4, 4, 4, 4)
|
||||||
@ -183,12 +184,12 @@ class ListPreviewWidget(QtWidgets.QTableWidget, RegistryProperties):
|
|||||||
label.setScaledContents(True)
|
label.setScaledContents(True)
|
||||||
if self.service_item.is_command():
|
if self.service_item.is_command():
|
||||||
if self.service_item.is_capable(ItemCapabilities.HasThumbnails):
|
if self.service_item.is_capable(ItemCapabilities.HasThumbnails):
|
||||||
image = self.image_manager.get_image(frame['image'], ImageSource.CommandPlugins)
|
image = self.image_manager.get_image(slide['image'], ImageSource.CommandPlugins)
|
||||||
pixmap = QtGui.QPixmap.fromImage(image)
|
pixmap = QtGui.QPixmap.fromImage(image)
|
||||||
else:
|
else:
|
||||||
pixmap = QtGui.QPixmap(frame['image'])
|
pixmap = QtGui.QPixmap(slide['image'])
|
||||||
else:
|
else:
|
||||||
image = self.image_manager.get_image(frame['path'], ImageSource.ImagePlugin)
|
image = self.image_manager.get_image(slide['filename'], ImageSource.ImagePlugin)
|
||||||
pixmap = QtGui.QPixmap.fromImage(image)
|
pixmap = QtGui.QPixmap.fromImage(image)
|
||||||
pixmap.setDevicePixelRatio(label.devicePixelRatio())
|
pixmap.setDevicePixelRatio(label.devicePixelRatio())
|
||||||
label.setPixmap(pixmap)
|
label.setPixmap(pixmap)
|
||||||
@ -212,15 +213,15 @@ class ListPreviewWidget(QtWidgets.QTableWidget, RegistryProperties):
|
|||||||
hbox.addStretch(0)
|
hbox.addStretch(0)
|
||||||
container.setLayout(hbox)
|
container.setLayout(hbox)
|
||||||
# Add to table
|
# Add to table
|
||||||
self.setCellWidget(frame_number, 0, container)
|
self.setCellWidget(slide_index, 0, container)
|
||||||
else:
|
else:
|
||||||
# Add to table
|
# Add to table
|
||||||
self.setCellWidget(frame_number, 0, label)
|
self.setCellWidget(slide_index, 0, label)
|
||||||
row += 1
|
row += 1
|
||||||
text.append(str(row))
|
text.append(str(row))
|
||||||
self.setItem(frame_number, 0, item)
|
self.setItem(slide_index, 0, item)
|
||||||
if slide_height:
|
if slide_height:
|
||||||
self.setRowHeight(frame_number, slide_height)
|
self.setRowHeight(slide_index, slide_height)
|
||||||
self.setVerticalHeaderLabels(text)
|
self.setVerticalHeaderLabels(text)
|
||||||
if self.service_item.is_text():
|
if self.service_item.is_text():
|
||||||
self.resizeRowsToContents()
|
self.resizeRowsToContents()
|
||||||
|
Loading…
Reference in New Issue
Block a user