Use a live webengine widget when previwing themes.

This commit is contained in:
Tomas Groth 2019-05-28 22:37:50 +02:00
parent 6800490995
commit 7558fb6e64
4 changed files with 72 additions and 60 deletions

View File

@ -425,7 +425,7 @@ def get_start_tags(raw_text):
return raw_text + ''.join(end_tags), ''.join(start_tags), ''.join(html_tags) return raw_text + ''.join(end_tags), ''.join(start_tags), ''.join(html_tags)
class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow): class ThemePreviewRenderer(LogMixin, DisplayWindow):
""" """
A virtual display used for rendering thumbnails and other offscreen tasks A virtual display used for rendering thumbnails and other offscreen tasks
""" """
@ -435,24 +435,6 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow):
""" """
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.force_page = False self.force_page = False
for screen in ScreenList():
if screen.is_display:
self.setGeometry(screen.display_geometry.x(), screen.display_geometry.y(),
screen.display_geometry.width(), screen.display_geometry.height())
break
# If the display is not show'ed and hidden like this webegine will not render
self.show()
self.hide()
self.theme_height = 0
self.theme_level = ThemeLevel.Global
def set_theme_level(self, theme_level):
"""
Sets the theme level.
:param theme_level: The theme level to be used.
"""
self.theme_level = theme_level
def calculate_line_count(self): def calculate_line_count(self):
""" """
@ -466,7 +448,7 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow):
""" """
return self.run_javascript('Display.clearSlides();') return self.run_javascript('Display.clearSlides();')
def generate_preview(self, theme_data, force_page=False): def generate_preview(self, theme_data, force_page=False, generate_screenshot=True):
""" """
Generate a preview of a theme. Generate a preview of a theme.
@ -486,7 +468,8 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow):
verses['verse'] = 'V1' verses['verse'] = 'V1'
self.load_verses([verses]) self.load_verses([verses])
self.force_page = False self.force_page = False
return self.save_screenshot() if generate_screenshot:
return self.save_screenshot()
self.force_page = False self.force_page = False
return None return None
@ -745,3 +728,33 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow):
pixmap.save(fname, ext) pixmap.save(fname, ext)
else: else:
return pixmap return pixmap
class Renderer(RegistryBase, RegistryProperties, ThemePreviewRenderer):
"""
A virtual display used for rendering thumbnails and other offscreen tasks
"""
def __init__(self, *args, **kwargs):
"""
Constructor
"""
super().__init__(*args, **kwargs)
self.force_page = False
for screen in ScreenList():
if screen.is_display:
self.setGeometry(screen.display_geometry.x(), screen.display_geometry.y(),
screen.display_geometry.width(), screen.display_geometry.height())
break
# If the display is not show'ed and hidden like this webegine will not render
self.show()
self.hide()
self.theme_height = 0
self.theme_level = ThemeLevel.Global
def set_theme_level(self, theme_level):
"""
Sets the theme level.
:param theme_level: The theme level to be used.
"""
self.theme_level = theme_level

View File

@ -174,16 +174,12 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
if not event: if not event:
event = QtGui.QResizeEvent(self.size(), self.size()) event = QtGui.QResizeEvent(self.size(), self.size())
QtWidgets.QWizard.resizeEvent(self, event) QtWidgets.QWizard.resizeEvent(self, event)
if hasattr(self, 'preview_page') and self.currentPage() == self.preview_page: try:
frame_width = self.preview_box_label.lineWidth() self.display_aspect_ratio = self.renderer.width() / self.renderer.height()
pixmap_width = self.preview_area.width() - 2 * frame_width except ZeroDivisionError:
pixmap_height = self.preview_area.height() - 2 * frame_width self.display_aspect_ratio = 1
aspect_ratio = float(pixmap_width) / pixmap_height self.preview_area_layout.set_aspect_ratio(self.display_aspect_ratio)
if aspect_ratio < self.display_aspect_ratio: self.preview_box.set_scale(float(self.preview_box.width()) / self.renderer.width())
pixmap_height = int(pixmap_width / self.display_aspect_ratio + 0.5)
else:
pixmap_width = int(pixmap_height * self.display_aspect_ratio + 0.5)
self.preview_box_label.setFixedSize(pixmap_width + 2 * frame_width, pixmap_height + 2 * frame_width)
def validateCurrentPage(self): def validateCurrentPage(self):
""" """
@ -208,10 +204,16 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
self.setOption(QtWidgets.QWizard.HaveCustomButton1, enabled) self.setOption(QtWidgets.QWizard.HaveCustomButton1, enabled)
if self.page(page_id) == self.preview_page: if self.page(page_id) == self.preview_page:
self.update_theme() self.update_theme()
frame = self.theme_manager.generate_image(self.theme) self.preview_box.set_theme(self.theme)
frame.setDevicePixelRatio(self.devicePixelRatio()) self.preview_box.clear_slides()
self.preview_box_label.setPixmap(frame) self.preview_box.set_scale(float(self.preview_box.width()) / self.renderer.width())
self.display_aspect_ratio = float(frame.width()) / frame.height() try:
self.display_aspect_ratio = self.renderer.width() / self.renderer.height()
except ZeroDivisionError:
self.display_aspect_ratio = 1
self.preview_area_layout.set_aspect_ratio(self.display_aspect_ratio)
self.preview_box.generate_preview(self.theme, False, False)
self.preview_box.show()
self.resizeEvent() self.resizeEvent()
def on_custom_1_button_clicked(self, number): def on_custom_1_button_clicked(self, number):
@ -400,6 +402,7 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
Handle the display and state of the Preview page. Handle the display and state of the Preview page.
""" """
self.setField('name', self.theme.theme_name) self.setField('name', self.theme.theme_name)
self.preview_box.set_theme(self.theme)
def on_background_combo_box_current_index_changed(self, index): def on_background_combo_box_current_index_changed(self, index):
""" """
@ -560,5 +563,5 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
source_path = self.theme.background_filename source_path = self.theme.background_filename
if not self.edit_mode and not self.theme_manager.check_if_theme_exists(self.theme.theme_name): if not self.edit_mode and not self.theme_manager.check_if_theme_exists(self.theme.theme_name):
return return
self.theme_manager.save_theme(self.theme, source_path, destination_path) self.theme_manager.save_theme(self.theme, source_path, destination_path, self.preview_box.save_screenshot())
return QtWidgets.QDialog.accept(self) return QtWidgets.QDialog.accept(self)

View File

@ -639,24 +639,14 @@ class ThemeManager(QtWidgets.QWidget, RegistryBase, Ui_ThemeManager, LogMixin, R
return False return False
return True return True
def save_theme(self, theme, image_source_path, image_destination_path): def save_theme(self, theme, image_source_path, image_destination_path, image=None):
"""
Called by theme maintenance Dialog to save the theme and to trigger the reload of the theme list
:param Theme theme: The theme data object.
:param Path image_source_path: Where the theme image is currently located.
:param Path image_destination_path: Where the Theme Image is to be saved to
:rtype: None
"""
self._write_theme(theme, image_source_path, image_destination_path)
def _write_theme(self, theme, image_source_path=None, image_destination_path=None):
""" """
Writes the theme to the disk and handles the background image if necessary Writes the theme to the disk and handles the background image if necessary
:param Theme theme: The theme data object. :param Theme theme: The theme data object.
:param Path image_source_path: Where the theme image is currently located. :param Path image_source_path: Where the theme image is currently located.
:param Path image_destination_path: Where the Theme Image is to be saved to :param Path image_destination_path: Where the Theme Image is to be saved to
:param image: The example image of the theme. Optionally.
:rtype: None :rtype: None
""" """
name = theme.theme_name name = theme.theme_name
@ -676,7 +666,15 @@ class ThemeManager(QtWidgets.QWidget, RegistryBase, Ui_ThemeManager, LogMixin, R
shutil.copyfile(image_source_path, image_destination_path) shutil.copyfile(image_source_path, image_destination_path)
except OSError: except OSError:
self.log_exception('Failed to save theme image') self.log_exception('Failed to save theme image')
self.generate_and_save_image(name, theme) if image:
sample_path_name = self.theme_path / '{file_name}.png'.format(file_name=name)
if sample_path_name.exists():
sample_path_name.unlink()
image.save(str(sample_path_name), 'png')
thumb_path = self.thumb_path / '{name}.png'.format(name=name)
create_thumb(sample_path_name, thumb_path, False)
else:
self.generate_and_save_image(name, theme)
def generate_and_save_image(self, theme_name, theme): def generate_and_save_image(self, theme_name, theme):
""" """

View File

@ -31,7 +31,8 @@ from openlp.core.lib.ui import add_welcome_page, create_valign_selection_widgets
from openlp.core.ui.icons import UiIcons from openlp.core.ui.icons import UiIcons
from openlp.core.widgets.buttons import ColorButton from openlp.core.widgets.buttons import ColorButton
from openlp.core.widgets.edits import PathEdit from openlp.core.widgets.edits import PathEdit
from openlp.core.widgets.layouts import AspectRatioLayout
from openlp.core.display.render import ThemePreviewRenderer
class Ui_ThemeWizard(object): class Ui_ThemeWizard(object):
""" """
@ -363,16 +364,13 @@ class Ui_ThemeWizard(object):
self.preview_layout.addLayout(self.theme_name_layout) self.preview_layout.addLayout(self.theme_name_layout)
self.preview_area = QtWidgets.QWidget(self.preview_page) self.preview_area = QtWidgets.QWidget(self.preview_page)
self.preview_area.setObjectName('PreviewArea') self.preview_area.setObjectName('PreviewArea')
self.preview_area_layout = QtWidgets.QGridLayout(self.preview_area) self.preview_area_layout = AspectRatioLayout(self.preview_area, 0.75) # Dummy ratio, will be update
self.preview_area_layout.setContentsMargins(0, 0, 0, 0) self.preview_area_layout.margin = 8
self.preview_area_layout.setColumnStretch(0, 1) self.preview_area_layout.setSpacing(0)
self.preview_area_layout.setRowStretch(0, 1) self.preview_area_layout.setObjectName('preview_web_layout')
self.preview_area_layout.setObjectName('preview_area_layout') self.preview_box = ThemePreviewRenderer(self)
self.preview_box_label = QtWidgets.QLabel(self.preview_area) self.preview_box.setObjectName('preview_box')
self.preview_box_label.setFrameShape(QtWidgets.QFrame.Box) self.preview_area_layout.addWidget(self.preview_box)
self.preview_box_label.setScaledContents(True)
self.preview_box_label.setObjectName('preview_box_label')
self.preview_area_layout.addWidget(self.preview_box_label)
self.preview_layout.addWidget(self.preview_area) self.preview_layout.addWidget(self.preview_area)
theme_wizard.addPage(self.preview_page) theme_wizard.addPage(self.preview_page)
self.retranslate_ui(theme_wizard) self.retranslate_ui(theme_wizard)