eric7/QScintilla/MarkupProviders/ImageMarkupDialog.py

Wed, 19 May 2021 19:53:36 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 19 May 2021 19:53:36 +0200
branch
eric7
changeset 8327
666c2b81cbb7
parent 8318
962bce857696
child 8356
68ec9c3d4de5
permissions
-rw-r--r--

Continued porting eric to PyQt6.

# -*- coding: utf-8 -*-

# Copyright (c) 2017 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing a dialog to enter data for an image markup.
"""

import contextlib

from PyQt6.QtCore import pyqtSlot, QSize
from PyQt6.QtGui import QImage, QImageReader
from PyQt6.QtWidgets import QDialog, QDialogButtonBox

from E5Gui.E5PathPicker import E5PathPickerModes

from .Ui_ImageMarkupDialog import Ui_ImageMarkupDialog


class ImageMarkupDialog(QDialog, Ui_ImageMarkupDialog):
    """
    Class implementing a dialog to enter data for an image markup.
    """
    HtmlMode = 0
    MarkDownMode = 1
    RestMode = 2
    
    def __init__(self, mode, parent=None):
        """
        Constructor
        
        @param mode mode of the dialog
        @type int
        @param parent reference to the parent widget
        @type QWidget
        """
        super().__init__(parent)
        self.setupUi(self)
        
        if mode == ImageMarkupDialog.MarkDownMode:
            self.sizeCheckBox.setEnabled(False)
            self.aspectRatioCheckBox.setEnabled(False)
            self.widthSpinBox.setEnabled(False)
            self.heightSpinBox.setEnabled(False)
        elif mode == ImageMarkupDialog.RestMode:
            self.titleEdit.setEnabled(False)
        
        self.__mode = mode
        self.__originalImageSize = QSize()
    
        filters = {
            'bmp': self.tr("Windows Bitmap File (*.bmp)"),
            'cur': self.tr("Windows Cursor File (*.cur)"),
            'dds': self.tr("DirectDraw-Surface File (*.dds)"),
            'gif': self.tr("Graphic Interchange Format File (*.gif)"),
            'icns': self.tr("Apple Icon File (*.icns)"),
            'ico': self.tr("Windows Icon File (*.ico)"),
            'jp2': self.tr("JPEG2000 File (*.jp2)"),
            'jpg': self.tr("JPEG File (*.jpg)"),
            'jpeg': self.tr("JPEG File (*.jpeg)"),
            'mng': self.tr("Multiple-Image Network Graphics File (*.mng)"),
            'pbm': self.tr("Portable Bitmap File (*.pbm)"),
            'pcx': self.tr("Paintbrush Bitmap File (*.pcx)"),
            'pgm': self.tr("Portable Graymap File (*.pgm)"),
            'png': self.tr("Portable Network Graphics File (*.png)"),
            'ppm': self.tr("Portable Pixmap File (*.ppm)"),
            'sgi': self.tr("Silicon Graphics Image File (*.sgi)"),
            'svg': self.tr("Scalable Vector Graphics File (*.svg)"),
            'svgz': self.tr("Compressed Scalable Vector Graphics File"
                            " (*.svgz)"),
            'tga': self.tr("Targa Graphic File (*.tga)"),
            'tif': self.tr("TIFF File (*.tif)"),
            'tiff': self.tr("TIFF File (*.tiff)"),
            'wbmp': self.tr("WAP Bitmap File (*.wbmp)"),
            'webp': self.tr("WebP Image File (*.webp)"),
            'xbm': self.tr("X11 Bitmap File (*.xbm)"),
            'xpm': self.tr("X11 Pixmap File (*.xpm)"),
        }
        
        inputFormats = []
        readFormats = QImageReader.supportedImageFormats()
        for readFormat in readFormats:
            with contextlib.suppress(KeyError):
                inputFormats.append(filters[bytes(readFormat).decode()])
        inputFormats.sort()
        inputFormats.append(self.tr("All Files (*)"))
        if filters["png"] in inputFormats:
            inputFormats.remove(filters["png"])
            inputFormats.insert(0, filters["png"])
        self.imagePicker.setFilters(';;'.join(inputFormats))
        self.imagePicker.setMode(E5PathPickerModes.OPEN_FILE_MODE)
        
        self.sizeCheckBox.setChecked(True)
        self.aspectRatioCheckBox.setChecked(True)
        
        msh = self.minimumSizeHint()
        self.resize(max(self.width(), msh.width()), msh.height())
        
        self.__updateOkButton()
    
    def __updateOkButton(self):
        """
        Private slot to set the state of the OK button.
        """
        enable = bool(self.imagePicker.text())
        if self.__mode == ImageMarkupDialog.MarkDownMode:
            enable = enable and bool(self.altTextEdit.text())
        
        self.buttonBox.button(
            QDialogButtonBox.StandardButton.Ok).setEnabled(enable)
    
    @pyqtSlot(str)
    def on_imagePicker_textChanged(self, address):
        """
        Private slot handling changes of the image path.
        
        @param address image address (URL or local path)
        @type str
        """
        if address and "://" not in address:
            image = QImage(address)
            # load the file to set the size spin boxes
            if image.isNull():
                self.widthSpinBox.setValue(0)
                self.heightSpinBox.setValue(0)
                self.__originalImageSize = QSize()
                self.__aspectRatio = 1
            else:
                self.widthSpinBox.setValue(image.width())
                self.heightSpinBox.setValue(image.height())
                self.__originalImageSize = image.size()
                self.__aspectRatio = (
                    float(self.__originalImageSize.height()) /
                    self.__originalImageSize.width()
                )
        else:
            self.widthSpinBox.setValue(0)
            self.heightSpinBox.setValue(0)
            self.__originalImageSize = QSize()
            self.__aspectRatio = 1
        
        self.__updateOkButton()
    
    @pyqtSlot(str)
    def on_altTextEdit_textChanged(self, txt):
        """
        Private slot handling changes of the alternative text.
        
        @param txt alternative text
        @type str
        """
        self.__updateOkButton()

    @pyqtSlot(bool)
    def on_sizeCheckBox_toggled(self, checked):
        """
        Private slot to reset the width and height spin boxes.
        
        @param checked flag indicating the state of the check box
        @type bool
        """
        if checked:
            self.widthSpinBox.setValue(self.__originalImageSize.width())
            self.heightSpinBox.setValue(self.__originalImageSize.height())
    
    @pyqtSlot(bool)
    def on_aspectRatioCheckBox_toggled(self, checked):
        """
        Private slot to adjust the height to match the original aspect ratio.
        
        @param checked flag indicating the state of the check box
        @type bool
        """
        if checked and self.__originalImageSize.isValid():
            height = self.widthSpinBox.value() * self.__aspectRatio
            self.heightSpinBox.setValue(height)
    
    @pyqtSlot(int)
    def on_widthSpinBox_valueChanged(self, width):
        """
        Private slot to adjust the height spin box.
        
        @param width width for the image
        @type int
        """
        if (
            self.aspectRatioCheckBox.isChecked() and
            self.widthSpinBox.hasFocus()
        ):
            height = width * self.__aspectRatio
            self.heightSpinBox.setValue(height)
    
    @pyqtSlot(int)
    def on_heightSpinBox_valueChanged(self, height):
        """
        Private slot to adjust the width spin box.
        
        @param height height for the image
        @type int
        """
        if (
            self.aspectRatioCheckBox.isChecked() and
            self.heightSpinBox.hasFocus()
        ):
            width = height / self.__aspectRatio
            self.widthSpinBox.setValue(width)
    
    def getData(self):
        """
        Public method to get the entered data.
        
        @return tuple containing the image address, alternative text,
            title text, flag to keep the original size, width and height
        @rtype tuple of (str, str, str, bool, int, int)
        """
        return (
            self.imagePicker.text(),
            self.altTextEdit.text(),
            self.titleEdit.text(),
            self.sizeCheckBox.isChecked(),
            self.widthSpinBox.value(),
            self.heightSpinBox.value(),
        )

eric ide

mercurial