Sun, 22 Nov 2020 16:28:08 +0100
Changed code to not use the OSError aliases (IOError, EnvironmentError, socket.error and select.error) anymore.
# -*- coding: utf-8 -*- # Copyright (c) 2013 - 2020 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing the base64 data URI encoder wizard dialog. """ 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 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'), # 0 self.tr('Generate Python3 embed code'), # 1 self.tr('Generate CSS embed code'), # 2 self.tr('Generate HTML embed code'), # 3 self.tr('Generate JS embed code'), # 4 self.tr('Generate QML embed code'), # 5 ]) 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 [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 = 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 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: # Python 3 output = Python3Template.format( getpass.getuser(), datetime.datetime.now().isoformat().split('.')[0], output) elif self.embeddingComboBox.currentIndex() == 2: # CSS output = ('html, body {{ margin:0; padding:0; background: url({0})' ' no-repeat center center fixed; background-size:cover' ' }}'.format(output)) elif self.embeddingComboBox.currentIndex() == 3: # HTML output = '<img src={0} alt="{1}" title="{1}"/>'.format( output, os.path.basename(filepath)) elif self.embeddingComboBox.currentIndex() == 4: # JS output = 'var embedded_file = window.atob({0}); '.format(output) elif self.embeddingComboBox.currentIndex() == 5: # QML 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()