WizardDataUriEncoder/DataUriEncoderWizardDialog.py

Tue, 20 Sep 2022 17:00:19 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Tue, 20 Sep 2022 17:00:19 +0200
branch
eric7
changeset 50
4d34c264a71d
parent 48
d9cd58b1e0c8
child 51
619765dd3aa8
permissions
-rw-r--r--

Reformatted sources with 'Black'.

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

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

"""
Module implementing the base64 data URI encoder wizard dialog.
"""

import base64
import codecs
import datetime
import getpass
import mimetypes
import os

from PyQt6.QtCore import pyqtSlot
from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QApplication, QInputDialog

from EricWidgets import EricMessageBox
from EricWidgets.EricPathPicker import EricPathPickerModes

from .Ui_DataUriEncoderWizardDialog import Ui_DataUriEncoderWizardDialog

import Preferences
import Utilities


DataUriTemplates = {
    "Python3": "\n".join(
        [
            "#!/usr/bin/env python3",
            "# -*- coding: utf-8 -*-",
            "",
            "from base64 import b64decode",
            "from io import BytesIO",
            "",
            "#metadata",
            "__author__ = '{0}'",
            "__date__ = '{1}'",
            "",
            "",
            "embedded_file = BytesIO(b64decode(",
            "    {2}",
            "))",
            "print(embedded_file.read())",
        ]
    ),
    "CSS": "html, body {{ margin:0; padding:0; background: url({0})"
    " no-repeat center center fixed; background-size:cover"
    " }}",
    "HTML": '<img src={0} alt="{1}" title="{1}"/>',
    "JavaScript": "var embedded_file = window.atob({0}); ",
    "QML": "Image {{ source: {0} }} ",
}


class DataUriEncoderWizardDialog(QDialog, Ui_DataUriEncoderWizardDialog):
    """
    Class implementing the base64 data URI encoder wizard dialog.
    """

    def __init__(self, parent=None):
        """
        Constructor

        @param parent reference to the parent widget
        @type QWidget
        """
        super().__init__(parent)
        self.setupUi(self)

        self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(False)

        self.filePicker.setWindowTitle(self.tr("Data URI Encoder"))
        self.filePicker.setMode(EricPathPickerModes.OPEN_FILE_MODE)
        self.filePicker.setFilters(
            self.tr(
                "Audio Files (*.flac *.mp3 *.ogg *.wav *.weba *.wma);;"
                "Image Files (*.gif *.ico *.jpg *.png *.svg *.tif *.webp"
                " *.xpm);;"
                "Video Files (*.3gp *.avi *.flv *.mp4 *.ogv *.webm *.wmv);;"
                "All Files (*)"
            )
        )
        self.filePicker.setDefaultDirectory(
            Preferences.getMultiProject("Workspace") or Utilities.getHomeDir()
        )

        self.embeddingComboBox.addItems(
            [
                self.tr("Do not generate code"),  # 0
                self.tr("Generate Python3 embedding code"),  # 1
                self.tr("Generate CSS embedding code"),  # 2
                self.tr("Generate HTML embedding code"),  # 3
                self.tr("Generate JavaScript embedding code"),  # 4
                self.tr("Generate QML embedding code"),  # 5
            ]
        )

    @pyqtSlot(int)
    def on_embeddingComboBox_currentIndexChanged(self, index):
        """
        Private slot to handle the selection of an embedding method.

        @param index index of the selected entry
        @type int
        """
        if index in [2, 3]:
            self.encryptCheckBox.setChecked(False)
            self.dataCheckBox.setChecked(True)
        else:
            self.encryptCheckBox.setChecked(False)
            self.dataCheckBox.setChecked(False)

    @pyqtSlot()
    def on_encodeButton_clicked(self):
        """
        Private slot to encode the contents of the given file.
        """
        filepath = self.filePicker.text().strip()
        mime = mimetypes.guess_type(filepath, strict=False)
        mimetype = mime if mime is not None else self.__askMime()

        if os.path.getsize(filepath) // 1024 // 1024 >= 1:
            res = EricMessageBox.warning(
                self,
                self.tr("Data URI Encoder"),
                self.tr(
                    """The file size is > 1 Megabyte. Encoding this will"""
                    """ take some time depending on your CPU processing"""
                    """ power!"""
                ),
                EricMessageBox.Cancel | EricMessageBox.Ok,
                EricMessageBox.Cancel,
            )
            if res == EricMessageBox.Cancel:
                return

        try:
            with open(filepath, "rb") as f:
                output = '"{0}{1}{2}{3}"'.format(
                    "data:" if self.dataCheckBox.isChecked() else "",
                    mimetype if self.dataCheckBox.isChecked() else "",
                    ";charset=utf-8;base64," if self.dataCheckBox.isChecked() else "",
                    base64.b64encode(f.read()).decode(),
                )
        except OSError as err:
            EricMessageBox.critical(
                self,
                self.tr("Data URI Encoder"),
                self.tr(
                    """<p>The file <b>{0}</b> could not be read.</p>"""
                    """<p>Reason: {1}</p>"""
                ).format(filepath, str(err)),
            )
            return
        if self.embeddingComboBox.currentIndex() == 1:  # Python 3
            output = DataUriTemplates["Python3"].format(
                getpass.getuser(),
                datetime.datetime.now().isoformat().split(".")[0],
                output,
            )
        elif self.embeddingComboBox.currentIndex() == 2:  # CSS
            output = DataUriTemplates["CSS"].format(output)
        elif self.embeddingComboBox.currentIndex() == 3:  # HTML
            output = DataUriTemplates["HTML"].format(output, os.path.basename(filepath))
        elif self.embeddingComboBox.currentIndex() == 4:  # JS
            output = DataUriTemplates["JavaScript"].format(output)
        elif self.embeddingComboBox.currentIndex() == 5:  # QML
            output = DataUriTemplates["QML"].format(output)

        if self.encryptCheckBox.isChecked():
            output = codecs.encode(output, "rot_13")

        self.outputTextEdit.setPlainText(output)

    @pyqtSlot()
    def on_copyButton_clicked(self):
        """
        Private slot to copy the output to the clipboard.
        """
        QApplication.clipboard().setText(self.outputTextEdit.toPlainText())

    @pyqtSlot()
    def on_outputTextEdit_textChanged(self):
        """
        Private slot to handle the existence of some output text.
        """
        enable = bool(self.outputTextEdit.toPlainText())
        self.copyButton.setEnabled(enable)
        self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(enable)

    @pyqtSlot(str)
    def on_filePicker_textChanged(self, txt):
        """
        Private slot to handle the editing of the file name.

        @param txt current file name
        @type str
        """
        self.encodeButton.setEnabled(bool(txt) and os.path.isfile(txt))

    def __askMime(self):
        """
        Private method to get the mime type from the user.

        @return entered mime type
        @rtype str
        """
        mimetypesList = [""] + sorted(
            set(mimetypes.types_map.values()).union(
                set(mimetypes.common_types.values())
            )
        )
        try:
            index = mimetypesList.index("application/octet-stream")
        except ValueError:
            index = 0
        mimetype, ok = QInputDialog.getItem(
            self,
            self.tr("Data URI Encoder"),
            self.tr("Enter a mime type:"),
            mimetypesList,
            index,
            True,
        )
        if ok:
            return mimetype.lower()
        else:
            return ""

    def getCode(self):
        """
        Public method to get the code.

        @return generated code
        @rtype str
        """
        return self.outputTextEdit.toPlainText()

eric ide

mercurial