WizardDataUriEncoder/DataUriEncoderWizardDialog.py

branch
eric7
changeset 44
1ab3e76972e6
parent 41
f7634f688a52
child 47
2d49cd593939
equal deleted inserted replaced
43:dbb86ed48634 44:1ab3e76972e6
5 5
6 """ 6 """
7 Module implementing the base64 data URI encoder wizard dialog. 7 Module implementing the base64 data URI encoder wizard dialog.
8 """ 8 """
9 9
10 import base64
11 import codecs
12 import datetime
13 import getpass
14 import mimetypes
10 import os 15 import os
11 import mimetypes 16
12 import base64 17 from PyQt6.QtCore import pyqtSlot
13 import getpass 18 from PyQt6.QtWidgets import (
14 import datetime
15
16 from PyQt5.QtCore import pyqtSlot
17 from PyQt5.QtWidgets import (
18 QDialog, QDialogButtonBox, QApplication, QInputDialog 19 QDialog, QDialogButtonBox, QApplication, QInputDialog
19 ) 20 )
20 21
21 from E5Gui.E5Completers import E5FileCompleter 22 from EricWidgets import EricMessageBox
22 from E5Gui import E5FileDialog, E5MessageBox 23 from EricWidgets.EricPathPicker import EricPathPickerModes
23 24
24 from .Ui_DataUriEncoderWizardDialog import Ui_DataUriEncoderWizardDialog 25 from .Ui_DataUriEncoderWizardDialog import Ui_DataUriEncoderWizardDialog
25 26
26 import Preferences 27 import Preferences
27 import Utilities 28 import Utilities
28 import UI.PixmapCache 29
29 30
30 31 DataUriTemplates = {
31 Python3Template = """#!/usr/bin/env python3 32 "Python3": "\n".join([
32 # -*- coding: utf-8 -*- 33 "#!/usr/bin/env python3",
33 34 "# -*- coding: utf-8 -*-",
34 from base64 import b64decode 35 "",
35 from io import BytesIO 36 "from base64 import b64decode",
36 37 "from io import BytesIO",
37 #metadata 38 "",
38 __author__ = '{0}' 39 "#metadata",
39 __date__ = '{1}' 40 "__author__ = '{0}'",
40 41 "__date__ = '{1}'",
41 42 "",
42 embedded_file = BytesIO(b64decode({2})) 43 "",
43 print(embedded_file.read()) 44 "embedded_file = BytesIO(b64decode(",
44 """ 45 " {2}",
45 46 "))",
47 "print(embedded_file.read())",
48 ]),
49
50 "CSS":
51 "html, body {{ margin:0; padding:0; background: url({0})"
52 " no-repeat center center fixed; background-size:cover"
53 " }}",
54
55 "HTML": '<img src={0} alt="{1}" title="{1}"/>',
56
57 "JavaScript": "var embedded_file = window.atob({0}); ",
58
59 "QML": "Image {{ source: {0} }} "
60 }
46 61
47 class DataUriEncoderWizardDialog(QDialog, Ui_DataUriEncoderWizardDialog): 62 class DataUriEncoderWizardDialog(QDialog, Ui_DataUriEncoderWizardDialog):
48 """ 63 """
49 Class implementing the base64 data URI encoder wizard dialog. 64 Class implementing the base64 data URI encoder wizard dialog.
50 """ 65 """
51 def __init__(self, parent=None): 66 def __init__(self, parent=None):
52 """ 67 """
53 Constructor 68 Constructor
54 69
55 @param parent reference to the parent widget (QWidget) 70 @param parent reference to the parent widget
71 @type QWidget
56 """ 72 """
57 super().__init__(parent) 73 super().__init__(parent)
58 self.setupUi(self) 74 self.setupUi(self)
59 75
60 self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) 76 self.buttonBox.button(
61 77 QDialogButtonBox.StandardButton.Ok).setEnabled(False)
62 self.__fileCompleter = E5FileCompleter(self.fileEdit) 78
63 79 self.filePicker.setWindowTitle(self.tr("Data URI Encoder"))
64 self.fileButton.setIcon(UI.PixmapCache.getIcon("open.png")) 80 self.filePicker.setMode(EricPathPickerModes.OPEN_FILE_MODE)
81 self.filePicker.setFilters(self.tr(
82 "Audio Files (*.flac *.mp3 *.ogg *.wav *.weba *.wma);;"
83 "Image Files (*.gif *.ico *.jpg *.png *.svg *.tif *.webp"
84 " *.xpm);;"
85 "Video Files (*.3gp *.avi *.flv *.mp4 *.ogv *.webm *.wmv);;"
86 "All Files (*)"
87 ))
88 self.filePicker.setDefaultDirectory(
89 Preferences.getMultiProject("Workspace") or
90 Utilities.getHomeDir()
91 )
65 92
66 self.embeddingComboBox.addItems([ 93 self.embeddingComboBox.addItems([
67 self.tr('Do not generate code'), # 0 94 self.tr('Do not generate code'), # 0
68 self.tr('Generate Python3 embed code'), # 1 95 self.tr('Generate Python3 embedding code'), # 1
69 self.tr('Generate CSS embed code'), # 2 96 self.tr('Generate CSS embedding code'), # 2
70 self.tr('Generate HTML embed code'), # 3 97 self.tr('Generate HTML embedding code'), # 3
71 self.tr('Generate JS embed code'), # 4 98 self.tr('Generate JavaScript embedding code'), # 4
72 self.tr('Generate QML embed code'), # 5 99 self.tr('Generate QML embedding code'), # 5
73 ]) 100 ])
74
75 def __getStartDir(self):
76 """
77 Private method to get the start directory for selection dialogs.
78
79 @return start directory (string)
80 """
81 return (Preferences.getMultiProject("Workspace") or
82 Utilities.getHomeDir())
83
84 @pyqtSlot()
85 def on_fileButton_clicked(self):
86 """
87 Private slot to select the file to be encoded via a selection dialog.
88 """
89 start = (
90 Utilities.fromNativeSeparators(self.fileEdit.text()) or
91 self.__getStartDir()
92 )
93 inputFile = E5FileDialog.getOpenFileName(
94 self,
95 self.tr("Data URI Encoder"),
96 start,
97 self.tr(
98 "Audio Files (*.flac *.mp3 *.ogg *.wav *.weba *.wma);;"
99 "Image Files (*.gif *.ico *.jpg *.png *.svg *.tif *.webp"
100 " *.xpm);;"
101 "Video Files (*.3gp *.avi *.flv *.mp4 *.ogv *.webm *.wmv);;"
102 "All Files (*)"
103 )
104 )
105 if inputFile:
106 self.fileEdit.setText(Utilities.toNativeSeparators(inputFile))
107 101
108 @pyqtSlot(int) 102 @pyqtSlot(int)
109 def on_embeddingComboBox_currentIndexChanged(self, index): 103 def on_embeddingComboBox_currentIndexChanged(self, index):
110 """ 104 """
111 Private slot to handle the selection of an embedding method. 105 Private slot to handle the selection of an embedding method.
112 106
113 @param index index of the selected entry (integer) 107 @param index index of the selected entry
108 @type int
114 """ 109 """
115 if index in [2, 3]: 110 if index in [2, 3]:
116 self.encryptCheckBox.setChecked(False) 111 self.encryptCheckBox.setChecked(False)
117 self.dataCheckBox.setChecked(True) 112 self.dataCheckBox.setChecked(True)
118 else: 113 else:
122 @pyqtSlot() 117 @pyqtSlot()
123 def on_encodeButton_clicked(self): 118 def on_encodeButton_clicked(self):
124 """ 119 """
125 Private slot to encode the contents of the given file. 120 Private slot to encode the contents of the given file.
126 """ 121 """
127 filepath = Utilities.toNativeSeparators(self.fileEdit.text().strip()) 122 filepath = self.filePicker.text().strip()
128 mime = mimetypes.guess_type(filepath, strict=False) 123 mime = mimetypes.guess_type(filepath, strict=False)
129 mimetype = mime if mime is not None else self.__askMime() 124 mimetype = mime if mime is not None else self.__askMime()
130 125
131 if os.path.getsize(filepath) // 1024 // 1024 >= 1: 126 if os.path.getsize(filepath) // 1024 // 1024 >= 1:
132 res = E5MessageBox.warning( 127 res = EricMessageBox.warning(
133 self, 128 self,
134 self.tr("Data URI Encoder"), 129 self.tr("Data URI Encoder"),
135 self.tr( 130 self.tr(
136 """The file size is > 1 Megabyte. Encoding this will""" 131 """The file size is > 1 Megabyte. Encoding this will"""
137 """ take some time depending on your CPU processing""" 132 """ take some time depending on your CPU processing"""
138 """ power!"""), 133 """ power!"""),
139 E5MessageBox.StandardButtons( 134 EricMessageBox.Cancel |
140 E5MessageBox.Cancel | 135 EricMessageBox.Ok,
141 E5MessageBox.Ok), 136 EricMessageBox.Cancel)
142 E5MessageBox.Cancel) 137 if res == EricMessageBox.Cancel:
143 if res == E5MessageBox.Cancel:
144 return 138 return
145 139
146 try: 140 try:
147 with open(filepath, "rb") as f: 141 with open(filepath, "rb") as f:
148 output = '"{0}{1}{2}{3}"'.format( 142 output = '"{0}{1}{2}{3}"'.format(
151 ';charset=utf-8;base64,' if self.dataCheckBox.isChecked() 145 ';charset=utf-8;base64,' if self.dataCheckBox.isChecked()
152 else '', 146 else '',
153 base64.b64encode(f.read()).decode() 147 base64.b64encode(f.read()).decode()
154 ) 148 )
155 except OSError as err: 149 except OSError as err:
156 E5MessageBox.critical( 150 EricMessageBox.critical(
157 self, 151 self,
158 self.tr("Data URI Encoder"), 152 self.tr("Data URI Encoder"),
159 self.tr( 153 self.tr(
160 """<p>The file <b>{0}</b> could not be read.</p>""" 154 """<p>The file <b>{0}</b> could not be read.</p>"""
161 """<p>Reason: {1}</p>""").format(filepath, str(err))) 155 """<p>Reason: {1}</p>""").format(filepath, str(err)))
162 return 156 return
163 if self.embeddingComboBox.currentIndex() == 1: # Python 3 157 if self.embeddingComboBox.currentIndex() == 1: # Python 3
164 output = Python3Template.format( 158 output = DataUriTemplates["Python3"].format(
165 getpass.getuser(), 159 getpass.getuser(),
166 datetime.datetime.now().isoformat().split('.')[0], output) 160 datetime.datetime.now().isoformat().split('.')[0], output)
167 elif self.embeddingComboBox.currentIndex() == 2: # CSS 161 elif self.embeddingComboBox.currentIndex() == 2: # CSS
168 output = ('html, body {{ margin:0; padding:0; background: url({0})' 162 output = DataUriTemplates["CSS"].format(output)
169 ' no-repeat center center fixed; background-size:cover'
170 ' }}'.format(output))
171 elif self.embeddingComboBox.currentIndex() == 3: # HTML 163 elif self.embeddingComboBox.currentIndex() == 3: # HTML
172 output = '<img src={0} alt="{1}" title="{1}"/>'.format( 164 output = DataUriTemplates["HTML"].format(
173 output, os.path.basename(filepath)) 165 output, os.path.basename(filepath))
174 elif self.embeddingComboBox.currentIndex() == 4: # JS 166 elif self.embeddingComboBox.currentIndex() == 4: # JS
175 output = 'var embedded_file = window.atob({0}); '.format(output) 167 output = DataUriTemplates["JavaScript"].format(output)
176 elif self.embeddingComboBox.currentIndex() == 5: # QML 168 elif self.embeddingComboBox.currentIndex() == 5: # QML
177 output = 'Image {{ source: {0} }} '.format(output) 169 output = DataUriTemplates["QML"].format(output)
178 170
179 if self.encryptCheckBox.isChecked(): 171 if self.encryptCheckBox.isChecked():
180 output = output.encode('rot_13') 172 output = codecs.encode(output, 'rot_13')
181 173
182 self.outputTextEdit.setPlainText(output) 174 self.outputTextEdit.setPlainText(output)
183 175
184 @pyqtSlot() 176 @pyqtSlot()
185 def on_copyButton_clicked(self): 177 def on_copyButton_clicked(self):
193 """ 185 """
194 Private slot to handle the existence of some output text. 186 Private slot to handle the existence of some output text.
195 """ 187 """
196 enable = bool(self.outputTextEdit.toPlainText()) 188 enable = bool(self.outputTextEdit.toPlainText())
197 self.copyButton.setEnabled(enable) 189 self.copyButton.setEnabled(enable)
198 self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enable) 190 self.buttonBox.button(
191 QDialogButtonBox.StandardButton.Ok).setEnabled(enable)
199 192
200 @pyqtSlot(str) 193 @pyqtSlot(str)
201 def on_fileEdit_textChanged(self, txt): 194 def on_filePicker_textChanged(self, txt):
202 """ 195 """
203 Private slot to handle the editing of the file name. 196 Private slot to handle the editing of the file name.
204 197
205 @param txt current file name (string) 198 @param txt current file name
199 @type str
206 """ 200 """
207 self.encodeButton.setEnabled(bool(txt) and os.path.isfile(txt)) 201 self.encodeButton.setEnabled(bool(txt) and os.path.isfile(txt))
208 202
209 def __askMime(self): 203 def __askMime(self):
210 """ 204 """
211 Private method to get the mime type from the user. 205 Private method to get the mime type from the user.
212 206
213 @return entered mime type (string) 207 @return entered mime type
208 @rtype str
214 """ 209 """
215 mimetypesList = [""] + list(sorted( 210 mimetypesList = [""] + list(sorted(
216 set(mimetypes.types_map.values()).union( 211 set(mimetypes.types_map.values()).union(
217 set(mimetypes.common_types.values())))) 212 set(mimetypes.common_types.values()))))
218 try: 213 try:
232 227
233 def getCode(self): 228 def getCode(self):
234 """ 229 """
235 Public method to get the code. 230 Public method to get the code.
236 231
237 @return generated code (string) 232 @return generated code
233 @rtype str
238 """ 234 """
239 return self.outputTextEdit.toPlainText() 235 return self.outputTextEdit.toPlainText()

eric ide

mercurial