diff --git a/openlp/core/display/render.py b/openlp/core/display/render.py index 05b7b97fc..f90bcebca 100644 --- a/openlp/core/display/render.py +++ b/openlp/core/display/render.py @@ -425,7 +425,7 @@ def get_start_tags(raw_text): 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 """ @@ -435,24 +435,6 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow): """ 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 def calculate_line_count(self): """ @@ -466,7 +448,7 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow): """ 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. @@ -486,7 +468,8 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow): verses['verse'] = 'V1' self.load_verses([verses]) self.force_page = False - return self.save_screenshot() + if generate_screenshot: + return self.save_screenshot() self.force_page = False return None @@ -745,3 +728,33 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow): pixmap.save(fname, ext) else: 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 diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index 0dfb53aab..1e6dd54b1 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -174,16 +174,12 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties): if not event: event = QtGui.QResizeEvent(self.size(), self.size()) QtWidgets.QWizard.resizeEvent(self, event) - if hasattr(self, 'preview_page') and self.currentPage() == self.preview_page: - frame_width = self.preview_box_label.lineWidth() - pixmap_width = self.preview_area.width() - 2 * frame_width - pixmap_height = self.preview_area.height() - 2 * frame_width - aspect_ratio = float(pixmap_width) / pixmap_height - if aspect_ratio < self.display_aspect_ratio: - 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) + 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.set_scale(float(self.preview_box.width()) / self.renderer.width()) def validateCurrentPage(self): """ @@ -208,10 +204,16 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties): self.setOption(QtWidgets.QWizard.HaveCustomButton1, enabled) if self.page(page_id) == self.preview_page: self.update_theme() - frame = self.theme_manager.generate_image(self.theme) - frame.setDevicePixelRatio(self.devicePixelRatio()) - self.preview_box_label.setPixmap(frame) - self.display_aspect_ratio = float(frame.width()) / frame.height() + self.preview_box.set_theme(self.theme) + self.preview_box.clear_slides() + self.preview_box.set_scale(float(self.preview_box.width()) / self.renderer.width()) + 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() 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. """ self.setField('name', self.theme.theme_name) + self.preview_box.set_theme(self.theme) 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 if not self.edit_mode and not self.theme_manager.check_if_theme_exists(self.theme.theme_name): 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) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index fd003ed2e..3c8aee1e6 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -639,24 +639,14 @@ class ThemeManager(QtWidgets.QWidget, RegistryBase, Ui_ThemeManager, LogMixin, R return False return True - def save_theme(self, theme, image_source_path, image_destination_path): - """ - 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): + def save_theme(self, theme, image_source_path, image_destination_path, image=None): """ Writes the theme to the disk and handles the background image if necessary :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 + :param image: The example image of the theme. Optionally. :rtype: None """ 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) except OSError: 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): """ diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py index e6a7ac2c5..1414e3f46 100644 --- a/openlp/core/ui/themewizard.py +++ b/openlp/core/ui/themewizard.py @@ -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.widgets.buttons import ColorButton 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): """ @@ -363,16 +364,13 @@ class Ui_ThemeWizard(object): self.preview_layout.addLayout(self.theme_name_layout) self.preview_area = QtWidgets.QWidget(self.preview_page) self.preview_area.setObjectName('PreviewArea') - self.preview_area_layout = QtWidgets.QGridLayout(self.preview_area) - self.preview_area_layout.setContentsMargins(0, 0, 0, 0) - self.preview_area_layout.setColumnStretch(0, 1) - self.preview_area_layout.setRowStretch(0, 1) - self.preview_area_layout.setObjectName('preview_area_layout') - self.preview_box_label = QtWidgets.QLabel(self.preview_area) - self.preview_box_label.setFrameShape(QtWidgets.QFrame.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_area_layout = AspectRatioLayout(self.preview_area, 0.75) # Dummy ratio, will be update + self.preview_area_layout.margin = 8 + self.preview_area_layout.setSpacing(0) + self.preview_area_layout.setObjectName('preview_web_layout') + self.preview_box = ThemePreviewRenderer(self) + self.preview_box.setObjectName('preview_box') + self.preview_area_layout.addWidget(self.preview_box) self.preview_layout.addWidget(self.preview_area) theme_wizard.addPage(self.preview_page) self.retranslate_ui(theme_wizard)