網際內容管理系統在精密機械教學與研究上的應用

  • Home
    • Site Map
    • reveal
    • blog
  • About
  • 主機設定
    • Windows 10
      • Win 網站簽章
      • Win Oauth2
      • Oauth2 原理
      • Nginx
    • Ubuntu設定
      • Ubuntu 簽章
      • 配置 uwsgi
      • xrdp
  • fossiloauth
    • foauth_config
  • fossilapp
  • Fossil
  • 專題報告
  • Reference
    • Flutter
      • Flutter ref
    • discourse
      • 操作管理
    • cd2020pj1
      • Oauth2
    • Network
    • Ref
      • LaTeX
      • Automatic Control
      • 參考步驟
      • ebook1
      • Project
      • Ref2
      • Bond Graphs
      • KMOLBrowser
      • Glowscript
      • Rapydscript
      • Atoms
      • Samples
      • RLearning
      • Ebooks
      • Feedback
      • CMSiMDE
      • Git
      • Windows
      • Ubuntu
      • Heorku
      • Certbot
Bond Graphs << Previous Next >> Glowscript

KMOLBrowser

利用 pyside2 編寫的網際瀏覽器:

KMOLBrowser 原始碼來自 https://github.com/ralsina/devicenzo, 為了用於 KMOLab 中 cmsimde self-signed certificate 近端或遠端編輯, 特別使用 ignoreCertificateError(), 讓網頁可以直接導入. 執行時可攜系統需要 pip install pyside2

#!/usr/bin/env python3
"""
source from: https://github.com/ralsina/devicenzo
"""

import json
import os
import sys

from PySide2 import QtCore, QtGui, QtNetwork, QtWebEngineWidgets, QtWidgets

settings = QtCore.QSettings("ralsina", "devicenzo")


def set_ssl_protocol():
    default_config = QtNetwork.QSslConfiguration.defaultConfiguration()
    default_config.setProtocol(QtNetwork.QSsl.TlsV1_2)
    QtNetwork.QSslConfiguration.setDefaultConfiguration(default_config)


class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
    def certificateError(self, certificateError):
        """according to https://doc.qt.io/qtforpython/PySide2/QtWebEngineWidgets/QWebEngineCertificateError.html#PySide2.QtWebEngineWidgets.PySide2.QtWebEngineWidgets.QWebEngineCertificateError.ignoreCertificateError
        #PySide2.QtWebEngineWidgets.QWebEngineCertificateError.ignoreCertificateError()
        # here we allow self-signed certificate to load the web site directly
        """
        certificateError.ignoreCertificateError()
        return super(WebEnginePage, self).certificateError(certificateError)
        
        # the following is for printing error message and types
        print(certificateError.errorDescription(), certificateError.url(), certificateError.isOverridable())
        error = certificateError.error()
        if error == QtWebEngineWidgets.QWebEngineCertificateError.SslPinnedKeyNotInCertificateChain:
            print("SslPinnedKeyNotInCertificateChain")
        elif error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateCommonNameInvalid:
            print("CertificateCommonNameInvalid")
        elif error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateDateInvalid:
            print("CertificateDateInvalid")
        elif error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateAuthorityInvalid:
            print("CertificateAuthorityInvalid")
        elif error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateContainsErrors:
            print("CertificateContainsErrors")
        if error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateNoRevocationMechanism:
            print("CertificateNoRevocationMechanism")
        elif error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateUnableToCheckRevocation:
            print("CertificateUnableToCheckRevocation")
        elif error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateRevoked:
            print("CertificateRevoked")
        elif error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateInvalid:
            print("CertificateAuthorityInvalid")
        elif error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateWeakSignatureAlgorithm:
            print("CertificateWeakSignatureAlgorithm")
        elif error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateNonUniqueName:
            print("CertificateNonUniqueName")
        elif error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateWeakKey:
            print("CertificateWeakKey")
        elif error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateNameConstraintViolation:
            print("CertificateNameConstraintViolation")
        elif error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateValidityTooLong:
            print("CertificateValidityTooLong")
        elif error == QtWebEngineWidgets.QWebEngineCertificateError.CertificateTransparencyRequired:
            print("CertificateTransparencyRequired")

        return super(WebEnginePage, self).certificateError(certificateError)
        

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.tabs = QtWidgets.QTabWidget(
            self, tabsClosable=True, movable=True, elideMode=QtCore.Qt.ElideRight
        )
        self.tabs.tabCloseRequested.connect(
            lambda idx: self.tabs.widget(idx).deleteLater()
        )
        self.tabs.currentChanged.connect(self.currentTabChanged)
        self.close_current_tab = QtWidgets.QAction(shortcut=QtGui.QKeySequence.Close)
        self.close_current_tab.triggered.connect(
            lambda: self.tabs.currentWidget().deleteLater()
        )
        self.addAction(self.close_current_tab)
        self.setCentralWidget(self.tabs)
        self.bars = {}
        self.star_action = QtWidgets.QAction(
            QtGui.QIcon.fromTheme("user-bookmarks"),
            "Bookmark",
            self,
            checkable=True,
            triggered=self.bookmarkPage,
            shortcut="Ctrl+d",
        )
        self.tabs.setCornerWidget(
            QtWidgets.QToolButton(
                self,
                text="New Tab",
                icon=QtGui.QIcon.fromTheme("document-new"),
                clicked=lambda: self.addTab().url.setFocus(),
                shortcut=QtGui.QKeySequence.AddTab,
            )
        )
        self.full_screen_action = QtWidgets.QAction(
            "Full Screen", self, checkable=True, shortcut=QtGui.QKeySequence.FullScreen
        )
        self.full_screen_action.toggled.connect(
            lambda v: self.showFullScreen() if v else self.showNormal()
        )
        self.addAction(self.full_screen_action)
        self.bookmarks = self.get("bookmarks", {})
        # Bookmarks seem broken
        self.bookmarkPage()  # Load the bookmarks menu
        self.history = self.get("history", []) + list(self.bookmarks.keys())
        self.completer = QtWidgets.QCompleter(self.history)

        # Downloads bar at the bottom of the window
        self.downloads = QtWidgets.QToolBar("Downloads")
        self.addToolBar(QtCore.Qt.BottomToolBarArea, self.downloads)

        # Proxy support
        proxy_url = QtCore.QUrl(os.environ.get("http_proxy", ""))
        QtNetwork.QNetworkProxy.setApplicationProxy(
            QtNetwork.QNetworkProxy(
                QtNetwork.QNetworkProxy.HttpProxy
                if proxy_url.scheme().startswith("http")
                else QtNetwork.QNetworkProxy.Socks5Proxy,
                proxy_url.host(),
                proxy_url.port(),
                proxy_url.userName(),
                proxy_url.password(),
            )
        ) if "http_proxy" in os.environ else None

        [self.addTab(QtCore.QUrl(u)) for u in self.get("tabs", [])]

    def finished(self):
        url = self.sender().url().toString()
        bar, reply, fname, cancel = self.bars[url]
        redirURL = reply.attribute(
            QtNetwork.QNetworkRequest.RedirectionTargetAttribute
        ).toString()
        del self.bars[url]
        bar.deleteLater()
        cancel.deleteLater()
        if redirURL and redirURL != url:
            return self.fetch(redirURL, fname)

        with open(fname, "wb") as f:
            f.write(str(reply.readAll()))

    def progress(self, received, total):
        self.bars[self.sender().url().toString()][0].setValue(100.0 * received / total)

    def closeEvent(self, ev):
        self.put("history", self.history)
        self.put(
            "tabs", [self.tabs.widget(i).url.text() for i in range(self.tabs.count())]
        )
        return QtWidgets.QMainWindow.closeEvent(self, ev)

    def put(self, key, value):
        "Persist an object somewhere under a given key"
        settings.setValue(key, json.dumps(value))
        settings.sync()

    def get(self, key, default=None):
        "Get the object stored under 'key' in persistent storage, or the default value"
        v = settings.value(key)
        return json.loads(v) if v else default

    def addTab(self, url=QtCore.QUrl("")):
        self.tabs.setCurrentIndex(self.tabs.addTab(Tab(url, self), ""))
        return self.tabs.currentWidget()

    def currentTabChanged(self, idx):
        if self.tabs.widget(idx) is None:
            return self.close()

        self.setWindowTitle(self.tabs.widget(idx).web_view.title() or "De Vicenzo")

    def bookmarkPage(self, v=None):
        if v and v is not None:
            self.bookmarks[
                self.tabs.currentWidget().url.text()
            ] = self.tabs.currentWidget().web_view.title()
        elif v is not None:
            del (self.bookmarks[self.tabs.currentWidget().url.text()])
        self.star_action.setMenu(QtWidgets.QMenu())
        [
            self.star_action.menu().addAction(
                QtWidgets.QAction(
                    title,
                    self,
                    triggered=lambda u=QtCore.QUrl(url): self.tabs.currentWidget().load(
                        u
                    ),
                )
            )
            for url, title in self.bookmarks.items()
        ]
        self.put("bookmarks", self.bookmarks)

    def addToHistory(self, url):
        self.history.append(url)
        self.completer.setModel(
            QtCore.QStringListModel(
                list(set(list(self.bookmarks.keys()) + self.history))
            )
        )


class Tab(QtWidgets.QWidget):
    def __init__(self, url, container):
        super(Tab, self).__init__()
        self.container = container
        self.web_view = QtWebEngineWidgets.QWebEngineView()
        self.progress_bar = QtWidgets.QProgressBar(
            self.container.statusBar(), maximumWidth=120, visible=False
        )
        self.web_view.loadProgress.connect(
            lambda v: (self.progress_bar.show(), self.progress_bar.setValue(v))
            if self.amCurrent()
            else None
        )
        self.web_view.loadFinished.connect(self.progress_bar.hide)
        self.web_view.loadStarted.connect(
            lambda: self.progress_bar.show() if self.amCurrent() else None
        )
        self.web_view.titleChanged.connect(
            lambda t: container.tabs.setTabText(container.tabs.indexOf(self), t)
            or (container.setWindowTitle(t) if self.amCurrent() else None)
        )
        self.web_view.iconChanged.connect(
            lambda: container.tabs.setTabIcon(
                container.tabs.indexOf(self), self.web_view.icon()
            )
        )
        self.tb = QtWidgets.QToolBar("Main Toolbar", self)

        layout = QtWidgets.QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.tb, stretch=0)
        layout.addWidget(self.web_view, stretch=1000)
        layout.activate()
        self.setLayout(layout)
        for a, sc in [
            [QtWebEngineWidgets.QWebEnginePage.Back, QtGui.QKeySequence.Back],
            [QtWebEngineWidgets.QWebEnginePage.Forward, QtGui.QKeySequence.Forward],
            [QtWebEngineWidgets.QWebEnginePage.Reload, QtGui.QKeySequence.Refresh],
        ]:
            self.tb.addAction(self.web_view.pageAction(a))
            self.web_view.pageAction(a).setShortcut(sc)

        def save_page(*a, view=self.web_view):
            destination = QtWidgets.QFileDialog.getSaveFileName(self, "Save Page")
            print(repr(destination))
            if destination:
                view.page().save(destination[0])

        self.web_view.pageAction(
            QtWebEngineWidgets.QWebEnginePage.SavePage
        ).triggered.connect(save_page)

        self.url = QtWidgets.QLineEdit()
        self.url.returnPressed.connect(
            lambda: self.web_view.load(QtCore.QUrl.fromUserInput(self.url.text()))
        )
        self.url.setCompleter(container.completer)
        self.tb.addWidget(self.url)
        self.tb.addAction(container.star_action)

        self.web_view.urlChanged.connect(lambda u: self.url.setText(u.toString()))
        self.web_view.urlChanged.connect(lambda u: container.addToHistory(u.toString()))
        self.web_view.urlChanged.connect(
            lambda u: container.star_action.setChecked(
                u.toString() in container.bookmarks
            )
            if self.amCurrent()
            else None
        )

        self.web_view.page().linkHovered.connect(
            lambda l: container.statusBar().showMessage(l, 3000)
        )

        self.search = QtWidgets.QLineEdit(
            self.web_view, visible=False, maximumWidth=200
        )
        self.search.returnPressed.connect(
            lambda: self.web_view.findText(self.search.text())
        )
        self.search.textChanged.connect(
            lambda: self.web_view.findText(self.search.text())
        )
        self.showSearch = QtWidgets.QShortcut(QtGui.QKeySequence.Find, self)
        self.showSearch.activated.connect(
            lambda: self.search.show() or self.search.setFocus()
        )
        self.hideSearch = QtWidgets.QShortcut(
            "Esc", self, activated=lambda: (self.search.hide(), self.setFocus())
        )

        self.zoomIn = QtWidgets.QShortcut(QtGui.QKeySequence.ZoomIn, self)
        self.zoomIn.activated.connect(
            lambda: self.web_view.setZoomFactor(self.web_view.zoomFactor() + 0.2)
        )
        self.zoomOut = QtWidgets.QShortcut(QtGui.QKeySequence.ZoomOut, self)
        self.zoomOut.activated.connect(
            lambda: self.web_view.setZoomFactor(self.web_view.zoomFactor() - 0.2)
        )
        self.zoomOne = QtWidgets.QShortcut(
            "Ctrl+0", self, activated=lambda: self.web_view.setZoomFactor(1)
        )
        self.urlFocus = QtWidgets.QShortcut("Ctrl+l", self, activated=self.url.setFocus)

        page = WebEnginePage(self)
        self.web_view.setPage(page)
        page.load(QtCore.QUrl(url))
        


    def amCurrent(self):
        return self.container.tabs.currentWidget() == self

    def createWindow(self, windowType):
        return self.container.addTab()


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    wb = MainWindow()
    for url in sys.argv[1:]:
        wb.addTab(QtCore.QUrl.fromUserInput(url))
    if wb.tabs.count() == 0:
        wb.addTab(QtCore.QUrl("http://mde.tw"))
    wb.show()
    sys.exit(app.exec_())


Bond Graphs << Previous Next >> Glowscript

Copyright © All rights reserved | This template is made with by Colorlib