Миграция PyFladesk


Я хотел внести свой вклад в PyFladesk проекта. Цель заключается в том, чтобы иметь функцию, которая получает колбу приложение и внедряет его в Qt приложения.

Я уже создать pull-запрос на основной репозиторий, индивидуальный commmits и изменения можно посмотреть здесь

Это была первоначальная версия: 83 линии - 3 класс - 1 функция - использует в составе PyQt4

import sys,webbrowser

from PyQt4.QtCore import QThread, QUrl,SIGNAL,QSize
from PyQt4.QtGui import QApplication,QMainWindow,QIcon
from PyQt4.QtWebKit import QWebView,QWebPage

# CONFIG
PORT = 5000
ROOT_URL = 'http://localhost:{}'.format(PORT)
WIDTH = 300
HEIGHT = 400
WINDOW_TITLE = "PyFladesk"
ICON = 'appicon.png'


# run flask on seperate theared
class FlaskThread(QThread):
    def __init__(self, application):
        QThread.__init__(self)
        self.application = application

    def __del__(self):
        self.wait()

    def run(self):
        self.application.run(port=PORT)


class MainWindow(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)
        self.resize (WIDTH , HEIGHT)
        self.setWindowTitle(WINDOW_TITLE)
        self.webView = WebView(self)
        self.setCentralWidget(self.webView)



class WebView(QWebView):
    def __init__(self ,parent=None):
        super(WebView,self).__init__(parent)

    def dragEnterEvent(self,e):
        e.ignore()

    def dropEvent(self,e):
        e.ignore()

    def contextMenuEvent(self,e):
        pass

    # open links in default browser 
    # stolen from http://stackoverflow.com/a/3188942/1103397 :D
    def linkClicked(self,url): 
        webbrowser.open(url.toEncoded().data())


def provide_GUI_for(application):
    qtapp = QApplication(sys.argv)

    webapp = FlaskThread(application)
    webapp.start()

    qtapp.aboutToQuit.connect(webapp.terminate)

    mainWindow = MainWindow()
    # set app icon    
    mainWindow.setWindowIcon(QIcon(ICON))

    # prevent open urls in QWebView.
    mainWindow.webView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
    mainWindow.webView.connect(mainWindow.webView, SIGNAL("linkClicked (const QUrl&)"), mainWindow.webView.linkClicked)

    mainWindow.webView.load(QUrl(ROOT_URL))
    mainWindow.show()

    return qtapp.exec_()


if __name__ == '__main__':
    from routes import app
    provide_GUI_for(app)

И это обновленная версия: 50 строк - функции 1 - использует PyQt 5.10.0

import sys
from PyQt5 import QtCore, QtWidgets, QtGui, QtWebEngineWidgets


def init_gui(application, port=5000, width=300, height=400,
            window_title="PyFladesk", icon="appicon.png"):

    ROOT_URL = 'http://localhost:{}'.format(port)

    # open links in browser from http://stackoverflow.com/a/3188942/1103397 :D
    # thanks to https://github.com/marczellm/qhangups/blob/cfed73ee4383caed1568c0183a9906180f01cb00/qhangups/WebEnginePage.py
    def link_clicked(url, typ, ismainframe):
        ready_url = url.toEncoded().data().decode()
        is_clicked = typ == QtWebEngineWidgets.QWebEnginePage.NavigationTypeLinkClicked
        is_not_internal = ROOT_URL not in ready_url
        if is_clicked and is_not_internal:
            QtGui.QDesktopServices.openUrl(url)
            return False
        return True

    def run_app():
        application.run(port=port, threaded=True)

    # Application Level
    qtapp = QtWidgets.QApplication(sys.argv)
    webapp = QtCore.QThread()
    webapp.__del__ = webapp.wait
    webapp.run = run_app
    webapp.start()
    qtapp.aboutToQuit.connect(webapp.terminate)

    # Main Window Level
    window = QtWidgets.QMainWindow()
    window.resize(width, height)
    window.setWindowTitle(window_title)
    window.setWindowIcon(QtGui.QIcon(icon))

    # WebView Level
    window.webView = QtWebEngineWidgets.QWebEngineView(window)
    window.setCentralWidget(window.webView)

    # WebPage Level
    page = QtWebEngineWidgets.QWebEnginePage()
    page.acceptNavigationRequest = link_clicked
    page.load(QtCore.QUrl(ROOT_URL))
    window.webView.setPage(page)

    window.show()

    return qtapp.exec_()

Некоторые мои соображения:

  • Это хорошее решение не использовать классы вообще?

  • Код читаемым и ремонтопригодны?

  • Есть ли предложения по улучшению?

Это был комментарий здесь



248
6
задан 22 февраля 2018 в 02:02 Источник Поделиться
Комментарии
1 ответ

Я тоже не нашел, положить все это в один метод, как:


  1. это, кажется, слишком много обязанностей;

  2. строительство некоторых объектов (QThread, QWebEnginePage) это очень неприятно, когда методы переназначаются.

Мне очень нравится использовать значения по умолчанию для параметров вместо глобальных констант, хотя.

Вместо этого я бы выбрал промежуточное состояние, где я используйте соответствующие подклассы вместо назначения методов:

import sys
from PyQt5 import QtCore, QtWidgets, QtGui, QtWebEngineWidgets

class ApplicationThread(QtCore.QThread):
def __init__(self, application, port=5000):
super(ApplicationThread, self).__init__()
self.application = application
self.port = port

def __del__(self):
self.wait()

def run(self):
self.application.run(port=self.port, threaded=True)

class WebPage(QtWebEngineWidgets.QWebEnginePage):
def __init__(self, root_url):
super(WebPage, self).__init__()
self.root_url = root_url

def home(self):
self.load(QtCore.QUrl(self.root_url))

def acceptNavigationRequest(self, url, kind, is_main_frame):
"""open external links in browser and internal links in the regular webview"""
# thanks to https://github.com/marczellm/qhangups/blob/cfed73ee4383caed1568c0183a9906180f01cb00/qhangups/WebEnginePage.py
ready_url = url.toEncoded().data().decode()
is_clicked = kind == self.NavigationTypeLinkClicked
if is_clicked and self.root_url not in ready_url:
QtGui.QDesktopServices.openUrl(url)
return False
return super(WebPage, self).acceptNavigationRequest(url, kind, is_main_frame)

def init_gui(application, port=5000, width=300, height=400,
window_title="PyFladesk", icon="appicon.png", argv=None):
if argv is None:
argv = sys.argv

# Application Level
qtapp = QtWidgets.QApplication(argv)
webapp = ApplicationThread(application, port)
webapp.start()
qtapp.aboutToQuit.connect(webapp.terminate)

# Main Window Level
window = QtWidgets.QMainWindow()
window.resize(width, height)
window.setWindowTitle(window_title)
window.setWindowIcon(QtGui.QIcon(icon))

# WebView Level
webView = QtWebEngineWidgets.QWebEngineView(window)
window.setCentralWidget(webView)

# WebPage Level
page = WebPage('http://localhost:{}'.format(port))
page.home()
webView.setPage(page)

window.show()
return qtapp.exec_()

Обратно на два класса и еще несколько линий, но подклассы действительно чувствует себя лучше здесь. Я также удалил назначение веб-представление как window атрибут как я не вижу в этом необходимости.

Наконец, я добавил поддержку для пользователей-при условии, argv (для целей тестирования), на всякий случай; не уверен, что действительно нужен.

2
ответ дан 22 февраля 2018 в 05:02 Источник Поделиться