Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite the GUI to use a Qt webview (HTML+Javascript) #7736

Closed
qstokkink opened this issue Nov 30, 2023 · 9 comments
Closed

Rewrite the GUI to use a Qt webview (HTML+Javascript) #7736

qstokkink opened this issue Nov 30, 2023 · 9 comments
Assignees

Comments

@qstokkink
Copy link
Contributor

Currently, our GUI uses a mix of Qt XML (QML), custom Qt Python widgets and CSS. Modifying or extending this XML (which can be up to 6000 lines) is rather painful. Furthermore, implementing custom Python Qt widgets takes a lot of time and tends to be error-prone, just for the end-goal of reinventing the wheel to mimick common web interfaces.

We can downsize and simplify our code base by switching from XML+custom Python to HTML and Javascript. The latter combo has very mature (and bug free!) libraries. We can make this switch relatively easily and without sacrificing features by using Qt's WebViews, which allows us to keep tray icons etc.

As an aside, more people understand HTML and Javascript so this should also make it easier for developers to contribute to our code base.

@drew2a
Copy link
Contributor

drew2a commented Nov 30, 2023

From my very first day of working with Tribler, I believed that we should change our direction towards HTML and Javascript. The way QT is used in Tribler has led to the fact that none of the developers want to (and sometimes can) work with it. This leads to us not changing our UI and not fixing bugs in the GUI, preferring instead to work with the core.

Our GUI does not look quite attractive. To make it attractive, we should spend a lot of effort. Having a lot of effort to make on one hand and no wish from developers to apply this effort on the other hand means the Tribler GUI in QT will never be good.

In contrast, if you choose HTML+Javascript, you have so many templates that will make the UI look and feel cool and modern with almost no effort from the developer's side.

So, @qstokkink you have my full support on this topic.

@egbertbouman
Copy link
Member

We have some old (Angular) prototypes:
https://github.com/egbertbouman/tribler-webui for the main UI
https://github.com/egbertbouman/tribler-debug-ui for the debug panel

@synctext
Copy link
Member

synctext commented Dec 1, 2023

Big investment in het past of re-writing our wxPython in favor of PyQt. Adding Javascript is something I would like to avoid, but we're living in modern times.
Just QT +Webviewer + Javascript seems "clean" on our 3 supported OSes.

https://stackoverflow.com/questions/34184704/qwebview-not-loading-external-javascript

    QString html = readFile(":/qt.html");
    view->setHtml(html, QUrl("qrc:/"));

application.qrc

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
    <file alias="qt.png">resource/qt.png</file>
    <file alias="image.html">resource/image.html</file>
    <file alias="qt.html">resource/qt.html</file>
    <file alias="qt.js">resource/qt.js</file>
</qresource>
</RCC>

@qstokkink
Copy link
Contributor Author

I used a spare 5 minutes to hook in @egbertbouman's debug UI:

# Install the Python API
pip install git+ssh://[email protected]/egbertbouman/tribler-debug-ui.git/

# Pull in the latest release
UIDIR="$(pip show tribler-debug-ui | sed -n "/Location: /s/Location: //p")"
wget https://github.com/egbertbouman/tribler-debug-ui/archive/refs/tags/v7.6.0.zip
unzip v7.6.0.zip 'tribler-debug-ui-7.6.0/*' -d "$UIDIR/tribler_debug_ui"
mv "$UIDIR/tribler_debug_ui/tribler-debug-ui-7.6.0" "$UIDIR/tribler_debug_ui/app"
rm -r "$UIDIR/tribler_debug_ui/tribler-debug-ui-master"
rm v7.6.0.zip
Tribler patch file
diff --git a/src/tribler/core/components/restapi/restapi_component.py b/src/tribler/core/components/restapi/restapi_component.py
index a43ff2bdf..19c452266 100644
--- a/src/tribler/core/components/restapi/restapi_component.py
+++ b/src/tribler/core/components/restapi/restapi_component.py
@@ -2,6 +2,8 @@ from itertools import chain
 from typing import Type
 
 from ipv8.REST.root_endpoint import RootEndpoint as IPV8RootEndpoint
+from tribler_debug_ui.endpoint import DebugUIEndpoint
+
 from tribler.core.components.bandwidth_accounting.bandwidth_accounting_component import BandwidthAccountingComponent
 from tribler.core.components.bandwidth_accounting.restapi.bandwidth_endpoint import BandwidthEndpoint
 from tribler.core.components.component import Component
@@ -36,6 +38,10 @@ from tribler.core.components.tunnel.tunnel_component import TunnelsComponent
 from tribler.core.utilities.unicode import hexlify
 
 
+class TriblerDebugUIEndpoint(DebugUIEndpoint):
+    path = "/debugui"
+
+
 class RESTComponent(Component):
     rest_manager: RESTManager = None
     root_endpoint: RootEndpoint = None
@@ -105,6 +111,7 @@ class RESTComponent(Component):
                        tag_rules_processor=knowledge_component.rules_processor)
         self.maybe_add(SearchEndpoint, content_discovery_component.community)
         self.maybe_add(KnowledgeEndpoint, db=db_component.db, community=knowledge_component.community)
+        self.maybe_add(TriblerDebugUIEndpoint, session=None)
 
         if not isinstance(ipv8_component, NoneComponent):
             ipv8_root_endpoint = IPV8RootEndpoint()
diff --git a/src/tribler/gui/debug_window.py b/src/tribler/gui/debug_window.py
index c6544dc77..f50340b12 100644
--- a/src/tribler/gui/debug_window.py
+++ b/src/tribler/gui/debug_window.py
@@ -11,8 +11,9 @@ from typing import Dict
 import libtorrent
 import psutil
 from PyQt5 import QtGui, uic
-from PyQt5.QtCore import QTimer, Qt, pyqtSignal
+from PyQt5.QtCore import QTimer, Qt, pyqtSignal, QUrl
 from PyQt5.QtGui import QBrush, QColor, QTextCursor
+from PyQt5.QtWebEngineWidgets import QWebEngineView
 from PyQt5.QtWidgets import QDesktopWidget, QFileDialog, QHeaderView, QMainWindow, QMessageBox, QTreeWidgetItem
 
 from tribler.core.utilities.utilities import has_bep33_support
@@ -51,6 +52,18 @@ class CPUPlot(TimeSeriesPlot):
 
 
 class DebugWindow(QMainWindow):
+
+    def __init__(self, settings, gui_settings, tribler_version):
+        QMainWindow.__init__(self)
+
+        we_view = QWebEngineView(self)
+        port = settings['api']['http_port']
+        we_view.setUrl(QUrl(f"http://127.0.0.1:{port}/debugui/?apikey={settings['api']['key']}"))
+        self.setCentralWidget(we_view)
+        self.setGeometry(0, 0, 640, 480)
+
+
+class DebugWindowOld(QMainWindow):
     """
     The debug window shows various statistics about Tribler such as performed requests, IPv8 statistics and
     community information.

Looking almost functional already. I think the endpoints may still be hooked up wrong though because I'm not seeing any data.

screenshot

@synctext
Copy link
Member

synctext commented Dec 20, 2023

Very impressive!
Now we can even incrementally deploy this big change. First EgbertAngular debug screen and install scripts. Later full Tribler.
Tentatively scheduled when the new ClickLog, randevouz, and Simple MeritRank are finished. Plus do website makeover. Website same style as GUI, hire an actual professional designer.

@ichorid
Copy link
Contributor

ichorid commented Jan 5, 2024

I'd say go even further, the same way Deluge and other clients do: don't even use QT WebView, just display the UI directly in the system browser. That way, you will only need a tray icon for managing the Core, and skip all the problems associated with running QT for GUI altogether. Also, you get all the modern Web UI testing frameworks, e.g. Selenium.

@jkaberg
Copy link

jkaberg commented Mar 14, 2024

I'd say go even further, the same way Deluge and other clients do: don't even use QT WebView, just display the UI directly in the system browser. That way, you will only need a tray icon for managing the Core, and skip all the problems associated with running QT for GUI altogether. Also, you get all the modern Web UI testing frameworks, e.g. Selenium.

I'd like to add an +1 to this comment; This is the modern way of doing these things, Tribler can be seen as an alternative to Deluge, qBittorrent etc which I think in 9 out of 10 cases will run on headless servers. There is an big upside to support headless devices due to the distributed nature of the Tribler network (headless are more often left alone/online than typical desktop devices - and thus serves the network in an better way)

@egbertbouman
Copy link
Member

I've started working on a new web interface in React:

tribler_webui_dark

And light mode:

tribler_webui_light

Things are nowhere near completed, and once it is it's probably going to be deployed in Tribler Experimental first. So, we'll still be using Qt for the time being.

@qstokkink
Copy link
Contributor Author

This issue has been resolved. 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

6 participants