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