I wanted to contribute to the PyFladesk project. The objective is to have a function that receives a Flask's app and embeds it in a Qt desktop app.
I've already create a Pull Request on the main repository, individual commmits and changes can be viewed there
This was the initial version: 83 lines - 3 Classes - 1 Function - Uses 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)
And this is the updated version: 50 lines - 1 Function - Uses 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_()
Some of my concerns are:
Is it a good decision not to use classes at all?
Is the code readable and maintainable?
Are there any suggestions to improve it?
This was once review here