WizardDataUriEncoder/DataUriEncoderWizardDialog.py

Thu, 10 Jan 2019 14:21:11 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Thu, 10 Jan 2019 14:21:11 +0100
changeset 31
c73bdba5f9c7
parent 30
e32a140e48fb
child 32
6a6942486976
permissions
-rw-r--r--

Updated copyright for 2019.

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

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

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

from __future__ import unicode_literals

import os
import mimetypes
import base64
import getpass
import datetime

from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QApplication, \
    QInputDialog

from E5Gui.E5Completers import E5FileCompleter
from E5Gui import E5FileDialog, E5MessageBox

from .Ui_DataUriEncoderWizardDialog import Ui_DataUriEncoderWizardDialog

import Preferences
import Utilities
import UI.PixmapCache


Python2Template = """#!/usr/bin/env python
# -*- coding: utf-8 -*-

from base64 import b64decode
from cStringIO import StringIO

#metadata
__author__ = '{0}'
__date__ = '{1}'


embedded_file = StringIO(b64decode({2}))
print(embedded_file.read())
"""


Python3Template = """#!/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())
"""


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 (QWidget)
        """
        super(DataUriEncoderWizardDialog, self).__init__(parent)
        self.setupUi(self)
        
        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
        
        self.__fileCompleter = E5FileCompleter(self.fileEdit)
        
        self.fileButton.setIcon(UI.PixmapCache.getIcon("open.png"))
        
        self.embeddingComboBox.addItems([
            self.tr('Do not generate code'),
            self.tr('Generate CSS embed code'),
            self.tr('Generate Python3 embed code'),
            self.tr('Generate Python2 embed code'),
            self.tr('Generate HTML embed code'),
            self.tr('Generate JS embed code'),
            self.tr('Generate QML embed code'),
        ])
    
    def __getStartDir(self):
        """
        Private method to get the start directory for selection dialogs.
        
        @return start directory (string)
        """
        return (Preferences.getMultiProject("Workspace") or
                Utilities.getHomeDir())
    
    @pyqtSlot()
    def on_fileButton_clicked(self):
        """
        Private slot to select the file to be encoded via a selection dialog.
        """
        start = Utilities.fromNativeSeparators(self.fileEdit.text()) or \
            self.__getStartDir()
        inputFile = E5FileDialog.getOpenFileName(
            self,
            self.tr("Data URI Encoder"),
            start,
            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 (*)"
            )
        )
        if inputFile:
            self.fileEdit.setText(Utilities.toNativeSeparators(inputFile))
    
    @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 (integer)
        """
        if index in [1, 4]:
            self.encryptCheckBox.setChecked(False)
            self.dataCheckBox.setChecked(True)
        elif index in [0, 2, 3, 5, 6]:
            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 = Utilities.toNativeSeparators(self.fileEdit.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 = E5MessageBox.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!"""),
                E5MessageBox.StandardButtons(
                    E5MessageBox.Cancel |
                    E5MessageBox.Ok),
                E5MessageBox.Cancel)
            if res == E5MessageBox.Cancel:
                return
        
        try:
            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(open(filepath, "rb").read()).decode()
            )
        except (IOError, OSError) as err:
            E5MessageBox.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:
            output = ('html, body {{ margin:0; padding:0; background: url({0})'
                      ' no-repeat center center fixed; background-size:cover'
                      ' }}'.format(output))
        elif self.embeddingComboBox.currentIndex() == 2:
            output = Python3Template.format(
                getpass.getuser(),
                datetime.datetime.now().isoformat().split('.')[0], output)
        elif self.embeddingComboBox.currentIndex() == 3:
            output = Python2Template.format(
                getpass.getuser(),
                datetime.datetime.now().isoformat().split('.')[0], output)
        elif self.embeddingComboBox.currentIndex() == 4:
            output = '<img src={0} alt="{1}" title="{1}"/>'.format(
                output, os.path.basename(filepath))
        elif self.embeddingComboBox.currentIndex() == 5:
            output = 'var embedded_file = window.atob({0}); '.format(output)
        elif self.embeddingComboBox.currentIndex() == 6:
            output = 'Image {{ source: {0} }} '.format(output)
        
        if self.encryptCheckBox.isChecked():
            output = output.encode('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.Ok).setEnabled(enable)
    
    @pyqtSlot(str)
    def on_fileEdit_textChanged(self, txt):
        """
        Private slot to handle the editing of the file name.
        
        @param txt current file name (string)
        """
        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 (string)
        """
        mimetypesList = [""] + list(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 (string)
        """
        return self.outputTextEdit.toPlainText()

eric ide

mercurial