53 |
51 |
54 |
52 |
55 def ensureUniqueFilename(name, appendFormat="({0})"): |
53 def ensureUniqueFilename(name, appendFormat="({0})"): |
56 """ |
54 """ |
57 Module function to generate an unique file name based on a pattern. |
55 Module function to generate an unique file name based on a pattern. |
58 |
56 |
59 @param name desired file name (string) |
57 @param name desired file name (string) |
60 @param appendFormat format pattern to be used to make the unique name |
58 @param appendFormat format pattern to be used to make the unique name |
61 (string) |
59 (string) |
62 @return unique file name |
60 @return unique file name |
63 """ |
61 """ |
64 if not os.path.exists(name): |
62 if not os.path.exists(name): |
65 return name |
63 return name |
66 |
64 |
67 tmpFileName = name |
65 tmpFileName = name |
68 i = 1 |
66 i = 1 |
69 while os.path.exists(tmpFileName): |
67 while os.path.exists(tmpFileName): |
70 tmpFileName = name |
68 tmpFileName = name |
71 index = tmpFileName.rfind(".") |
69 index = tmpFileName.rfind(".") |
72 |
70 |
73 appendString = appendFormat.format(i) |
71 appendString = appendFormat.format(i) |
74 if index == -1: |
72 if index == -1: |
75 tmpFileName += appendString |
73 tmpFileName += appendString |
76 else: |
74 else: |
77 tmpFileName = ( |
75 tmpFileName = tmpFileName[:index] + appendString + tmpFileName[index:] |
78 tmpFileName[:index] + appendString + tmpFileName[index:] |
|
79 ) |
|
80 i += 1 |
76 i += 1 |
81 |
77 |
82 return tmpFileName |
78 return tmpFileName |
83 |
79 |
84 |
80 |
85 def getFileNameFromUrl(url): |
81 def getFileNameFromUrl(url): |
86 """ |
82 """ |
87 Module function to generate a file name based on the given URL. |
83 Module function to generate a file name based on the given URL. |
88 |
84 |
89 @param url URL (QUrl) |
85 @param url URL (QUrl) |
90 @return file name (string) |
86 @return file name (string) |
91 """ |
87 """ |
92 fileName = url.toString( |
88 fileName = url.toString( |
93 QUrl.UrlFormattingOption.RemoveFragment | |
89 QUrl.UrlFormattingOption.RemoveFragment |
94 QUrl.UrlFormattingOption.RemoveQuery | |
90 | QUrl.UrlFormattingOption.RemoveQuery |
95 QUrl.UrlFormattingOption.RemoveScheme | |
91 | QUrl.UrlFormattingOption.RemoveScheme |
96 QUrl.UrlFormattingOption.RemovePort |
92 | QUrl.UrlFormattingOption.RemovePort |
97 ) |
93 ) |
98 if fileName.find("/") != -1: |
94 if fileName.find("/") != -1: |
99 pos = fileName.rfind("/") |
95 pos = fileName.rfind("/") |
100 fileName = fileName[pos:] |
96 fileName = fileName[pos:] |
101 fileName = fileName.replace("/", "") |
97 fileName = fileName.replace("/", "") |
102 |
98 |
103 fileName = filterCharsFromFilename(fileName) |
99 fileName = filterCharsFromFilename(fileName) |
104 |
100 |
105 if not fileName: |
101 if not fileName: |
106 fileName = filterCharsFromFilename(url.host().replace(".", "_")) |
102 fileName = filterCharsFromFilename(url.host().replace(".", "_")) |
107 |
103 |
108 return fileName |
104 return fileName |
109 |
105 |
110 |
106 |
111 def filterCharsFromFilename(name): |
107 def filterCharsFromFilename(name): |
112 """ |
108 """ |
113 Module function to filter illegal characters. |
109 Module function to filter illegal characters. |
114 |
110 |
115 @param name name to be sanitized (string) |
111 @param name name to be sanitized (string) |
116 @return sanitized name (string) |
112 @return sanitized name (string) |
117 """ |
113 """ |
118 return ( |
114 return ( |
119 name |
115 name.replace("/", "_") |
120 .replace("/", "_") |
|
121 .replace("\\", "") |
116 .replace("\\", "") |
122 .replace(":", "") |
117 .replace(":", "") |
123 .replace("*", "") |
118 .replace("*", "") |
124 .replace("?", "") |
119 .replace("?", "") |
125 .replace('"', "") |
120 .replace('"', "") |
130 |
125 |
131 |
126 |
132 def pixmapFromByteArray(data): |
127 def pixmapFromByteArray(data): |
133 """ |
128 """ |
134 Module function to convert a byte array to a pixmap. |
129 Module function to convert a byte array to a pixmap. |
135 |
130 |
136 @param data data for the pixmap |
131 @param data data for the pixmap |
137 @type bytes or QByteArray |
132 @type bytes or QByteArray |
138 @return extracted pixmap |
133 @return extracted pixmap |
139 @rtype QPixmap |
134 @rtype QPixmap |
140 """ |
135 """ |
141 pixmap = QPixmap() |
136 pixmap = QPixmap() |
142 barray = QByteArray.fromBase64(data) |
137 barray = QByteArray.fromBase64(data) |
143 pixmap.loadFromData(barray) |
138 pixmap.loadFromData(barray) |
144 |
139 |
145 return pixmap |
140 return pixmap |
146 |
141 |
147 |
142 |
148 def pixmapToByteArray(pixmap): |
143 def pixmapToByteArray(pixmap): |
149 """ |
144 """ |
150 Module function to convert a pixmap to a byte array containing the pixmap |
145 Module function to convert a pixmap to a byte array containing the pixmap |
151 as a PNG encoded as base64. |
146 as a PNG encoded as base64. |
152 |
147 |
153 @param pixmap pixmap to be converted |
148 @param pixmap pixmap to be converted |
154 @type QPixmap |
149 @type QPixmap |
155 @return byte array containing the pixmap |
150 @return byte array containing the pixmap |
156 @rtype QByteArray |
151 @rtype QByteArray |
157 """ |
152 """ |
158 byteArray = QByteArray() |
153 byteArray = QByteArray() |
159 buffer = QBuffer(byteArray) |
154 buffer = QBuffer(byteArray) |
160 buffer.open(QIODevice.OpenModeFlag.WriteOnly) |
155 buffer.open(QIODevice.OpenModeFlag.WriteOnly) |
161 if pixmap.save(buffer, "PNG"): |
156 if pixmap.save(buffer, "PNG"): |
162 return buffer.buffer().toBase64() |
157 return buffer.buffer().toBase64() |
163 |
158 |
164 return QByteArray() |
159 return QByteArray() |
165 |
160 |
166 |
161 |
167 def pixmapToDataUrl(pixmap, mimetype="image/png"): |
162 def pixmapToDataUrl(pixmap, mimetype="image/png"): |
168 """ |
163 """ |
169 Module function to convert a pixmap to a data: URL. |
164 Module function to convert a pixmap to a data: URL. |
170 |
165 |
171 @param pixmap pixmap to be converted |
166 @param pixmap pixmap to be converted |
172 @type QPixmap |
167 @type QPixmap |
173 @param mimetype MIME type to be used |
168 @param mimetype MIME type to be used |
174 @type str |
169 @type str |
175 @return data: URL |
170 @return data: URL |
184 |
179 |
185 def pixmapFileToDataUrl(pixmapFile, asString=False): |
180 def pixmapFileToDataUrl(pixmapFile, asString=False): |
186 """ |
181 """ |
187 Module function to load a pixmap file and convert the pixmap to a |
182 Module function to load a pixmap file and convert the pixmap to a |
188 data: URL. |
183 data: URL. |
189 |
184 |
190 Note: If the given pixmap file path is not absolute, it is assumed to |
185 Note: If the given pixmap file path is not absolute, it is assumed to |
191 denote a pixmap file in the icons data directory. |
186 denote a pixmap file in the icons data directory. |
192 |
187 |
193 @param pixmapFile file name of the pixmap file |
188 @param pixmapFile file name of the pixmap file |
194 @type str |
189 @type str |
195 @param asString flag indicating a string representation is requested |
190 @param asString flag indicating a string representation is requested |
196 @type bool |
191 @type bool |
197 @return data: URL |
192 @return data: URL |
198 @rtype QUrl or str |
193 @rtype QUrl or str |
199 """ |
194 """ |
200 if not os.path.isabs(pixmapFile): |
195 if not os.path.isabs(pixmapFile): |
201 pixmapFile = os.path.join(WebBrowserDataDirectory["icons"], pixmapFile) |
196 pixmapFile = os.path.join(WebBrowserDataDirectory["icons"], pixmapFile) |
202 |
197 |
203 mime = mimetypes.guess_type(pixmapFile, strict=False)[0] |
198 mime = mimetypes.guess_type(pixmapFile, strict=False)[0] |
204 if mime is None: |
199 if mime is None: |
205 # assume PNG file |
200 # assume PNG file |
206 mime = "image/png" |
201 mime = "image/png" |
207 url = pixmapToDataUrl(QPixmap(pixmapFile), mimetype=mime) |
202 url = pixmapToDataUrl(QPixmap(pixmapFile), mimetype=mime) |
208 |
203 |
209 if asString: |
204 if asString: |
210 return url.toString() |
205 return url.toString() |
211 else: |
206 else: |
212 return url |
207 return url |
213 |
208 |
214 |
209 |
215 def getWebEngineVersions(): |
210 def getWebEngineVersions(): |
216 """ |
211 """ |
217 Module function to extract the web engine related versions from the default |
212 Module function to extract the web engine related versions from the default |
218 user agent string. |
213 user agent string. |
219 |
214 |
220 Note: For PyQt 6.3.1 or newer the data is extracted via some Qt functions. |
215 Note: For PyQt 6.3.1 or newer the data is extracted via some Qt functions. |
221 |
216 |
222 @return tuple containing the Chromium version, the Chromium security patch |
217 @return tuple containing the Chromium version, the Chromium security patch |
223 version and the QtWebEngine version |
218 version and the QtWebEngine version |
224 @rtype tuple of (str, str, str) |
219 @rtype tuple of (str, str, str) |
225 """ |
220 """ |
226 try: |
221 try: |
227 from PyQt6.QtWebEngineCore import ( |
222 from PyQt6.QtWebEngineCore import ( |
228 qWebEngineVersion, qWebEngineChromiumVersion, |
223 qWebEngineVersion, |
229 qWebEngineChromiumSecurityPatchVersion |
224 qWebEngineChromiumVersion, |
|
225 qWebEngineChromiumSecurityPatchVersion, |
230 ) |
226 ) |
|
227 |
231 chromiumVersion = qWebEngineChromiumVersion() |
228 chromiumVersion = qWebEngineChromiumVersion() |
232 chromiumSecurityVersion = qWebEngineChromiumSecurityPatchVersion() |
229 chromiumSecurityVersion = qWebEngineChromiumSecurityPatchVersion() |
233 webengineVersion = qWebEngineVersion() |
230 webengineVersion = qWebEngineVersion() |
234 except ImportError: |
231 except ImportError: |
235 # backwards compatibility for PyQt < 6.3.1 |
232 # backwards compatibility for PyQt < 6.3.1 |
236 from PyQt6.QtWebEngineCore import QWebEngineProfile |
233 from PyQt6.QtWebEngineCore import QWebEngineProfile |
237 |
234 |
238 useragent = QWebEngineProfile.defaultProfile().httpUserAgent() |
235 useragent = QWebEngineProfile.defaultProfile().httpUserAgent() |
239 match = re.search(r"""Chrome/([\d.]+)""", useragent) |
236 match = re.search(r"""Chrome/([\d.]+)""", useragent) |
240 chromiumVersion = ( |
237 chromiumVersion = ( |
241 match.group(1) |
238 match.group(1) |
242 if match else |
239 if match |
243 QCoreApplication.translate("WebBrowserTools", "<unknown>") |
240 else QCoreApplication.translate("WebBrowserTools", "<unknown>") |
244 ) |
241 ) |
245 match = re.search(r"""QtWebEngine/([\d.]+)""", useragent) |
242 match = re.search(r"""QtWebEngine/([\d.]+)""", useragent) |
246 webengineVersion = ( |
243 webengineVersion = ( |
247 match.group(1) |
244 match.group(1) |
248 if match else |
245 if match |
249 QCoreApplication.translate("WebBrowserTools", "<unknown>") |
246 else QCoreApplication.translate("WebBrowserTools", "<unknown>") |
250 ) |
247 ) |
251 chromiumSecurityVersion = "" |
248 chromiumSecurityVersion = "" |
252 # not available via the user agent string |
249 # not available via the user agent string |
253 |
250 |
254 return (chromiumVersion, chromiumSecurityVersion, webengineVersion) |
251 return (chromiumVersion, chromiumSecurityVersion, webengineVersion) |
255 |
252 |
256 |
253 |
257 def getHtmlPage(pageFileName): |
254 def getHtmlPage(pageFileName): |
258 """ |
255 """ |
259 Module function to load a HTML page. |
256 Module function to load a HTML page. |
260 |
257 |
261 Note: If the given HTML file path is not absolute, it is assumed to |
258 Note: If the given HTML file path is not absolute, it is assumed to |
262 denote a HTML file in the html data directory. |
259 denote a HTML file in the html data directory. |
263 |
260 |
264 @param pageFileName file name of the HTML file |
261 @param pageFileName file name of the HTML file |
265 @type str |
262 @type str |
266 @return HTML page |
263 @return HTML page |
267 @rtype str |
264 @rtype str |
268 """ |
265 """ |
269 if not os.path.isabs(pageFileName): |
266 if not os.path.isabs(pageFileName): |
270 pageFileName = os.path.join( |
267 pageFileName = os.path.join(WebBrowserDataDirectory["html"], pageFileName) |
271 WebBrowserDataDirectory["html"], pageFileName) |
268 |
272 |
|
273 return readAllFileContents(pageFileName) |
269 return readAllFileContents(pageFileName) |
274 |
270 |
275 |
271 |
276 def getJavascript(jsFileName): |
272 def getJavascript(jsFileName): |
277 """ |
273 """ |
278 Module function to load a JavaScript source file. |
274 Module function to load a JavaScript source file. |
279 |
275 |
280 Note: If the given JavaScript source file path is not absolute, it is |
276 Note: If the given JavaScript source file path is not absolute, it is |
281 assumed to denote a JavaScript source file in the javascript data |
277 assumed to denote a JavaScript source file in the javascript data |
282 directory. |
278 directory. |
283 |
279 |
284 @param jsFileName file name of the JavaScript source file |
280 @param jsFileName file name of the JavaScript source file |
285 @type str |
281 @type str |
286 @return JavaScript source |
282 @return JavaScript source |
287 @rtype str |
283 @rtype str |
288 """ |
284 """ |
289 if not os.path.isabs(jsFileName): |
285 if not os.path.isabs(jsFileName): |
290 jsFileName = os.path.join( |
286 jsFileName = os.path.join(WebBrowserDataDirectory["js"], jsFileName) |
291 WebBrowserDataDirectory["js"], jsFileName) |
287 |
292 |
|
293 return readAllFileContents(jsFileName) |
288 return readAllFileContents(jsFileName) |