src/eric7/WebBrowser/Tools/WebBrowserTools.py

Wed, 13 Jul 2022 14:55:47 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 13 Jul 2022 14:55:47 +0200
branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9473
3f23dbf37dbe
permissions
-rw-r--r--

Reformatted the source code using the 'Black' utility.

# -*- 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