src/eric7/WebBrowser/Tools/WebBrowserTools.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 9167
2d2b9a26e904
child 9221
bf71ee032bb4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/WebBrowser/Tools/WebBrowserTools.py	Thu Jul 07 11:23:56 2022 +0200
@@ -0,0 +1,293 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2016 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing tool functions for the web browser.
+"""
+
+import os
+import re
+import mimetypes
+
+from PyQt6.QtCore import (
+    QByteArray, QUrl, QCoreApplication, QBuffer, QIODevice
+)
+from PyQt6.QtGui import QPixmap
+
+
+WebBrowserDataDirectory = {
+    "html": os.path.join(os.path.dirname(__file__), "..", "data", "html"),
+    "icons": os.path.join(os.path.dirname(__file__), "..", "data", "icons"),
+    "js": os.path.join(os.path.dirname(__file__), "..", "data", "javascript"),
+}
+
+
+def readAllFileContents(filename):
+    """
+    Function to read the string contents of the given file.
+    
+    @param filename name of the file
+    @type str
+    @return contents of the file
+    @rtype str
+    """
+    try:
+        with open(filename, "r", encoding="utf-8") as f:
+            return f.read()
+    except OSError:
+        return ""
+
+
+def containsSpace(string):
+    """
+    Function to check, if a string contains whitespace characters.
+    
+    @param string string to be checked
+    @type str
+    @return flag indicating the presence of at least one whitespace character
+    @rtype bool
+    """
+    return any(ch.isspace() for ch in string)
+
+
+def ensureUniqueFilename(name, appendFormat="({0})"):
+    """
+    Module function to generate an unique file name based on a pattern.
+    
+    @param name desired file name (string)
+    @param appendFormat format pattern to be used to make the unique name
+        (string)
+    @return unique file name
+    """
+    if not os.path.exists(name):
+        return name
+    
+    tmpFileName = name
+    i = 1
+    while os.path.exists(tmpFileName):
+        tmpFileName = name
+        index = tmpFileName.rfind(".")
+        
+        appendString = appendFormat.format(i)
+        if index == -1:
+            tmpFileName += appendString
+        else:
+            tmpFileName = (
+                tmpFileName[:index] + appendString + tmpFileName[index:]
+            )
+        i += 1
+    
+    return tmpFileName
+
+
+def getFileNameFromUrl(url):
+    """
+    Module function to generate a file name based on the given URL.
+    
+    @param url URL (QUrl)
+    @return file name (string)
+    """
+    fileName = url.toString(
+        QUrl.UrlFormattingOption.RemoveFragment |
+        QUrl.UrlFormattingOption.RemoveQuery |
+        QUrl.UrlFormattingOption.RemoveScheme |
+        QUrl.UrlFormattingOption.RemovePort
+    )
+    if fileName.find("/") != -1:
+        pos = fileName.rfind("/")
+        fileName = fileName[pos:]
+        fileName = fileName.replace("/", "")
+    
+    fileName = filterCharsFromFilename(fileName)
+    
+    if not fileName:
+        fileName = filterCharsFromFilename(url.host().replace(".", "_"))
+    
+    return fileName
+
+
+def filterCharsFromFilename(name):
+    """
+    Module function to filter illegal characters.
+    
+    @param name name to be sanitized (string)
+    @return sanitized name (string)
+    """
+    return (
+        name
+        .replace("/", "_")
+        .replace("\\", "")
+        .replace(":", "")
+        .replace("*", "")
+        .replace("?", "")
+        .replace('"', "")
+        .replace("<", "")
+        .replace(">", "")
+        .replace("|", "")
+    )
+
+
+def pixmapFromByteArray(data):
+    """
+    Module function to convert a byte array to a pixmap.
+    
+    @param data data for the pixmap
+    @type bytes or QByteArray
+    @return extracted pixmap
+    @rtype QPixmap
+    """
+    pixmap = QPixmap()
+    barray = QByteArray.fromBase64(data)
+    pixmap.loadFromData(barray)
+    
+    return pixmap
+
+
+def pixmapToByteArray(pixmap):
+    """
+    Module function to convert a pixmap to a byte array containing the pixmap
+    as a PNG encoded as base64.
+    
+    @param pixmap pixmap to be converted
+    @type QPixmap
+    @return byte array containing the pixmap
+    @rtype QByteArray
+    """
+    byteArray = QByteArray()
+    buffer = QBuffer(byteArray)
+    buffer.open(QIODevice.OpenModeFlag.WriteOnly)
+    if pixmap.save(buffer, "PNG"):
+        return buffer.buffer().toBase64()
+    
+    return QByteArray()
+
+
+def pixmapToDataUrl(pixmap, mimetype="image/png"):
+    """
+    Module function to convert a pixmap to a data: URL.
+    
+    @param pixmap pixmap to be converted
+    @type QPixmap
+    @param mimetype MIME type to be used
+    @type str
+    @return data: URL
+    @rtype QUrl
+    """
+    data = bytes(pixmapToByteArray(pixmap)).decode()
+    if data:
+        return QUrl("data:{0};base64,{1}".format(mimetype, data))
+    else:
+        return QUrl()
+
+
+def pixmapFileToDataUrl(pixmapFile, asString=False):
+    """
+    Module function to load a pixmap file and convert the pixmap to a
+    data: URL.
+    
+    Note: If the given pixmap file path is not absolute, it is assumed to
+    denote a pixmap file in the icons data directory.
+    
+    @param pixmapFile file name of the pixmap file
+    @type str
+    @param asString flag indicating a string representation is requested
+    @type bool
+    @return data: URL
+    @rtype QUrl or str
+    """
+    if not os.path.isabs(pixmapFile):
+        pixmapFile = os.path.join(WebBrowserDataDirectory["icons"], pixmapFile)
+    
+    mime = mimetypes.guess_type(pixmapFile, strict=False)[0]
+    if mime is None:
+        # assume PNG file
+        mime = "image/png"
+    url = pixmapToDataUrl(QPixmap(pixmapFile), mimetype=mime)
+    
+    if asString:
+        return url.toString()
+    else:
+        return url
+
+
+def getWebEngineVersions():
+    """
+    Module function to extract the web engine related versions from the default
+    user agent string.
+    
+    Note: For PyQt 6.3.1 or newer the data is extracted via some Qt functions.
+    
+    @return tuple containing the Chromium version, the Chromium security patch
+        version and the QtWebEngine version
+    @rtype tuple of (str, str, str)
+    """
+    try:
+        from PyQt6.QtWebEngineCore import (
+            qWebEngineVersion, qWebEngineChromiumVersion,
+            qWebEngineChromiumSecurityPatchVersion
+        )
+        chromiumVersion = qWebEngineChromiumVersion()
+        chromiumSecurityVersion = qWebEngineChromiumSecurityPatchVersion()
+        webengineVersion = qWebEngineVersion()
+    except ImportError:
+        # backwards compatibility for PyQt < 6.3.1
+        from PyQt6.QtWebEngineCore import QWebEngineProfile
+        
+        useragent = QWebEngineProfile.defaultProfile().httpUserAgent()
+        match = re.search(r"""Chrome/([\d.]+)""", useragent)
+        chromiumVersion = (
+            match.group(1)
+            if match else
+            QCoreApplication.translate("WebBrowserTools", "<unknown>")
+        )
+        match = re.search(r"""QtWebEngine/([\d.]+)""", useragent)
+        webengineVersion = (
+            match.group(1)
+            if match else
+            QCoreApplication.translate("WebBrowserTools", "<unknown>")
+        )
+        chromiumSecurityVersion = ""
+        # not available via the user agent string
+    
+    return (chromiumVersion, chromiumSecurityVersion, webengineVersion)
+
+
+def getHtmlPage(pageFileName):
+    """
+    Module function to load a HTML page.
+    
+    Note: If the given HTML file path is not absolute, it is assumed to
+    denote a HTML file in the html data directory.
+    
+    @param pageFileName file name of the HTML file
+    @type str
+    @return HTML page
+    @rtype str
+    """
+    if not os.path.isabs(pageFileName):
+        pageFileName = os.path.join(
+            WebBrowserDataDirectory["html"], pageFileName)
+    
+    return readAllFileContents(pageFileName)
+
+
+def getJavascript(jsFileName):
+    """
+    Module function to load a JavaScript source file.
+    
+    Note: If the given JavaScript source file path is not absolute, it is
+    assumed to denote a JavaScript source file in the javascript data
+    directory.
+    
+    @param jsFileName file name of the JavaScript source file
+    @type str
+    @return JavaScript source
+    @rtype str
+    """
+    if not os.path.isabs(jsFileName):
+        jsFileName = os.path.join(
+            WebBrowserDataDirectory["js"], jsFileName)
+    
+    return readAllFileContents(jsFileName)

eric ide

mercurial