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