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

New Tribler PyQt GUI #2153

Merged
merged 9 commits into from
Nov 21, 2016
Merged

New Tribler PyQt GUI #2153

merged 9 commits into from
Nov 21, 2016

Conversation

devos50
Copy link
Contributor

@devos50 devos50 commented May 1, 2016

Please make sure to backup your .Tribler directory before trying out the new GUI! Things might not work out as expected.

In this PR, I add the new GUI, written in pyQt to Tribler. Unfortunately, the new GUI and Tribler core should be in the same repo since we want only one issue tracker.

General info

The GUI is written using the Qt framework with PyQt bindings so Python can be used to program the GUI. I tried to create as much as possible elements using the Qt Designer application. The designer files (ending with the .ui file extension) can be found in the qt_resources directory. Images used by the new GUI can be found in the images directory.

Running the GUI

Before you run the GUI, make sure you have Qt5 and pyQt installed. cd to the tribler directory and enter the following commands:

python run_gui.py

Additionally, you can use any IDE (I’m using PyCharm) to run the GUI.

In order to test the GUI while developing, I’ve created a separate project that provides fake data to the new Tribler GUI such as channels, torrents and downloads. This project can be found here. Note that not all endpoints are currently implemented and this project is during development, the main source of data for the GUI. I’m also planning to use this project for the automated GUI tests. Running this project is easy, checkout the project from GitHub, cd to the TestTriblerAPI directory and execute python main.py. Generating the random data will take around 20-30 seconds.

Progress

There are many endpoints that should be implemented in the GUI, the fake API provider and the real Tribler project. Below, I will keep track of the progress for each endpoint, categorised by functionality.

General

I will implement the save settings endpoint in Triblerafter we are making use of ConfigObj.

Functionality In GUI? In fake API provider? In Tribler?
Get settings
Save settings
Get variables

Channels

Functionality In GUI? In fake API provider? In Tribler?
Get all channels
Get subscribed channels
Get popular channels
Subscribe to a channel
Unsubscribe from a channel
Edit someone else's channels

Torrents

Functionality In GUI? In fake API provider? In Tribler?
Get torrents in channel
Get random torrents
Add a torrent to download
Create a torrent file

Search

Functionality In GUI? In fake API provider? In Tribler?
Search channels and torrents
Get search completion terms

My Channel

Functionality In GUI? In fake API provider? In Tribler?
Get channel overview
Get channel torrents
Get channel playlists
Get channel rss feeds
Create new channel
Edit channel properties
Remove torrent(s)
Add torrent(s)
Create playlist(s)
Edit playlist(s)
Remove playlist(s)
Add torrent to playlist(s)
Remove torrent from playlist(s)
Add rss feed
Remove rss feed
Recheck rss feed

Downloads

Functionality in GUI? In fake API provider? In Tribler?
Get downloads
Remove download
Start/resume download
Stop download
Force recheck download
Export download to .torrent
Change anonymity level of download

Other tasks

  • Distinguish between handled and unhanded exceptions when performing requests on the side of the server
  • Create a design for the home page
  • Create a loading screen -> see https://gyazo.com/3d6174191214aaee9b3991de406d4a45
  • Create a feedback window when Tribler crashes -> see https://gyazo.com/63456453b54325bf7ea706c86ea78382
  • Make use of the model-view-delegation pattern Qt provides. This will improve performance when rendering (big) lists tremendously. not feasible, I had bad performance when working with model-view. This is due to the fact that custom widgets have to be created for every item in the list. I've implemented a lazy-loaded list that is working very well.
  • Implement the search result ranking algorithm as described in The relevance ranking algorithm when searching in Tribler needs to be redesigned #2250.
  • Show a notification in the GUI if a newer version of Tribler is available.
  • Integrate the twistd Tribler plugin so it gets started when the GUI boots.

Fixes #1802, fixes #2190, fixes #14

@brussee
Copy link
Member

brussee commented May 13, 2016

  • Distinguish between handled and unhanded exceptions when performing requests on the side of the server

I took care of this in PR #2175 with RESTRequest.processingFailed() in restapi/rest_manager.py
Compare to MyChannelEndpoint.render_PUT() in case of a DuplicateChannelNameError.

@jkaberg
Copy link

jkaberg commented May 17, 2016

Hey guys, love the work beeing done here! I noticed this one "Create a design for the home page", and I'm guessing you're referring to an Web UI (?)

Might I suggest baseing this of something like (my personal favourite) ruTorrent or the orginal uTorrent Web UI

@whirm
Copy link
Contributor

whirm commented May 17, 2016

@jkaberg Only the Qt and Android GUI are being implemented for nowt We would love to see a community developed web UI for Tribler. The REST interface should make it pretty easy.

@whirm
Copy link
Contributor

whirm commented May 17, 2016

retest this please

@synctext
Copy link
Member

Quite a bunch of errors when running your code. First Dispersy blocks and (again) converts all torrents. Then these errors popup:

Tribler version: 6.5.2-GIT
Traceback (most recent call last):
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Main/tribler_main.py", line 154, in __init__
    session.start()
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Core/Session.py", line 458, in start
    self.lm.register(self, self.sesslock)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Core/APIImplementation/LaunchManyCore.py", line 172, in register
    self.init()
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Core/APIImplementation/LaunchManyCore.py", line 269, in init
    load_communities()
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/util.py", line 47, in helper
    return blockingCallFromThread(reactor, func, *args, **kargs)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/util.py", line 238, in blockingCallFromThread
    result.raiseException()
  File "<string>", line 2, in raiseException
type: __init__() got an unexpected keyword argument 'split_payload_func'
 Traceback from this thread:
  File "Tribler/Main/tribler.py", line 95, in <module>
    __main__()
  File "Tribler/Main/tribler.py", line 85, in __main__
    run()
  File "Tribler/Main/tribler.py", line 68, in run
    run_main()
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Main/tribler_main.py", line 1002, in run
    use_torrent_search=use_torrent_search, use_channel_search=use_channel_search)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Main/tribler_main.py", line 154, in __init__
    session.start()
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Core/Session.py", line 458, in start
    self.lm.register(self, self.sesslock)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Core/APIImplementation/LaunchManyCore.py", line 172, in register
    self.init()
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Core/APIImplementation/LaunchManyCore.py", line 269, in init
    load_communities()
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/util.py", line 47, in helper
    return blockingCallFromThread(reactor, func, *args, **kargs)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/util.py", line 234, in blockingCallFromThread
    this_thread_tb = traceback.extract_stack()

 Traceback from the reactor's thread:
   File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 150, in maybeDeferred
    result = f(*args, **kw)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Core/APIImplementation/LaunchManyCore.py", line 251, in load_communities
    self.dispersy.define_auto_load(MultiChainCommunity, dispersy_member, load=True)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/dispersy.py", line 388, in define_auto_load
    community = community_cls.init_community(self, master, my_member, *args, **kargs)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/community.py", line 226, in init_community
    community.initialize(*args, **kargs)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/community.py", line 347, in initialize
    self._initialize_meta_messages()
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/community.py", line 505, in _initialize_meta_messages
    for meta_message in self.initiate_meta_messages():
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/community/multichain/community.py", line 89, in initiate_meta_messages
    allow_signature_func=self.allow_signature_request, split_payload_func=split_function),

Traceback (most recent call last):
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Main/tribler_main.py", line 154, in __init__
    session.start()
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Core/Session.py", line 458, in start
    self.lm.register(self, self.sesslock)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Core/APIImplementation/LaunchManyCore.py", line 172, in register
    self.init()
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Core/APIImplementation/LaunchManyCore.py", line 269, in init
    load_communities()
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/util.py", line 47, in helper
    return blockingCallFromThread(reactor, func, *args, **kargs)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/util.py", line 238, in blockingCallFromThread
    result.raiseException()
  File "<string>", line 2, in raiseException
TypeError: __init__() got an unexpected keyword argument 'split_payload_func'
ERROR   1465831779.31        dispersy:1728  exception during handle_callback for torrent-collect-response
Traceback (most recent call last):
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/dispersy.py", line 1723, in _update
    messages[0].handle_callback(messages)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/community/search/community.py", line 486, in on_torrent_collect_response
    self._process_collect_request_response(messages)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/community/search/community.py", line 525, in _process_collect_request_response
    timeout=CANDIDATE_WALK_LIFETIME)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/util.py", line 35, in helper
    return func(*args, **kargs)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Core/RemoteTorrentHandler.py", line 131, in download_torrent
    self.torrent_requesters[priority].add_request(infohash, candidate, timeout)
ERROR   1465831797.27        dispersy:1728  exception during handle_callback for torrent-collect-response
Traceback (most recent call last):
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/dispersy.py", line 1723, in _update
    messages[0].handle_callback(messages)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/community/search/community.py", line 486, in on_torrent_collect_response
    self._process_collect_request_response(messages)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/community/search/community.py", line 525, in _process_collect_request_response
    timeout=CANDIDATE_WALK_LIFETIME)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/dispersy/util.py", line 35, in helper
    return func(*args, **kargs)
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_endpoints/Tribler/Core/RemoteTorrentHandler.py", line 131, in download_torrent
    self.torrent_requesters[priority].add_request(infohash, candidate, timeout)
KeyError: 0
ERROR   1465831798.46        dispersy:1728  exception during handle_callback for torrent-collect-response

@synctext
Copy link
Member

GUI part also complains:

/TriblerGUI>env PYTHONPATH=..: python Main.py
ERROR:root:Traceback (most recent call last):
  File "Main.py", line 104, in received_variables
    self.video_player_page.video_player_port = variables["variables"]["ports"]["video~port"]
TypeError: 'NoneType' object has no attribute '__getitem__'

ERROR:root:Traceback (most recent call last):
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_gui/TriblerGUI/homepage.py", line 41, in received_popular_torrents
    for torrent in result["torrents"]:
TypeError: 'NoneType' object has no attribute '__getitem__'

ERROR:root:No JSON object could be decoded
Traceback (most recent call last):
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_gui/TriblerGUI/tribler_request_manager.py", line 81, in on_finished
    json_result = json.loads(str(data))
  File "/usr/lib/python2.7/json/__init__.py", line 339, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 364, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded
GOT EVENT ERROR
1
ERROR:root:Traceback (most recent call last):
  File "/home/pouwelse/GITHUB/gui_in_QT_tribler-NEW-June2016/tribler_gui/TriblerGUI/downloadspage.py", line 50, in received_downloads
    for download in downloads["downloads"]:
TypeError: 'NoneType' object has no attribute '__getitem__'

@devos50
Copy link
Contributor Author

devos50 commented Jun 13, 2016

@synctext regarding the 2nd error: this is currently expected when Tribler (with the old GUI) is not running/crashes when starting the new GUI. I should have some better error handling/retry mechanism which I will tackle the same time as integrating the twistd plugin.

For the first error, I will try to do the same steps on an Ubuntu machine in a moment to see whether the same error is raised.

@devos50
Copy link
Contributor Author

devos50 commented Jun 14, 2016

@synctext you should enable the HTTP API. This is turned off by default and we currently have no option to turn it on from the GUI. Please modify ~/.Tribler/libtribler.conf and enable the API by replacing the following section:

[http_api]
enabled = True
port = 8085

After that, first start the old GUI and next you can try to start the new GUI.

I got it working on a proxmox (ubuntu) machine: https://gyazo.com/2f5350f5ccf7b26e22510882b73bd2b9

@devos50
Copy link
Contributor Author

devos50 commented Jun 20, 2016

A progress update: I've fixed some minor and major bugs and integrated the Tribler twistd plugin! This means that it is no longer necessary to have two separate GUIs besides each other to test this PR. You still need two repositories (I will update the instructions in the first post in a moment).

Moreover, I created a bunch of GUI tests. They are using the fake API provider and are not complete yet. During the run, screenshots are taken, like the old GUI tests. Running these on Linux, Windows and OS X will be my next priority.

Other work:

  • Tested the GUI on Windows and Linux. On Linux, it worked out of the box with only a minor difference (but that was easily fixed by a CSS rule). On Windows, it required some more work since the twistd executable is not always available so I had to rewrite some parts of the startup process.
  • Implemented a mechanism so only one instance of the Tribler GUI runs. If the user attempts to open a second Tribler instance, the already opened GUI is activated instead.
  • Implemented the dialog when a new Tribler version is available in the new GUI.
  • Created a loading screen when a user starts the GUI. This is not a splash screen but instead, integrated in the main GUI window. It also displays the status of the upgrader.
  • Fixed some minor layout bugs

@vi
Copy link
Contributor

vi commented Jul 1, 2016

Will old GUI and this GUI coexist for a couple of versious?

I don't believe that new GUI will cover 100% of features from the day one, even if the developer tries to achieve that. There will probably missing sorting here, missing option there which would need to use old GUI as workaround.

@devos50
Copy link
Contributor Author

devos50 commented Jul 1, 2016

@vi as far as I know, we don't have any plans to let the old GUI co-exists. We are too understaffed to manage two GUIs. However, it's not very hard to extend the new GUI with features since it's written in Qt. Also, we try to make extending the REST API as easy as possible which means that these missing features can be implemented by some other developers.

Running the new GUI at the moment is not easy since you need two repositories besides each other. I will work on some installers next week and I will let you know when they are ready :)

@lfdversluis
Copy link
Contributor

@vi However, the next experimental release (I think 6.6) will have the old wx GUI and will still receive bug fixes for now.

@vi
Copy link
Contributor

vi commented Jul 1, 2016

Is it only the GUI or also some internal changes?

May one run this GUI and traditional GUI interchangeably?

GUI-only changes should not suppose to require .Tribler backups...

@synctext
Copy link
Member

synctext commented Jul 2, 2016

@vi the way the GUI talks to the core was a mess. It's now nice and tidy instead of one big bag of code. So new GUI is also about superior code organisation and detecting bugs faster.

@vi
Copy link
Contributor

vi commented Jul 2, 2016

Shall I suggest those checkboxes (what is an "endpoiont"?) for features I use (or want) to ensure they will not be missing?

Downloads

  • Sorting by size, download status, anonymity, name, date added
  • View segmented bar showing which fragments are fully/partially present and which are not yet downloaded
  • Toggle files between included and excluded (it would be nice if there would be third mode: "included, download sequentially");
  • View downloaded % for each file in a torrent
  • Copy magnet links (there is already "export torrent" in checkboxes)
  • Ability to work with very big torrents;
  • Quick filter by name or size
  • Adding new download from file, magnet, http or https link

Network

  • Edit bandwidth limits, including per-torrent
  • View current total upload/download limit, balance, etc.
  • View port/NAT status, number of connected peers

@synctext
Copy link
Member

synctext commented Jul 2, 2016

that is a big list @vi :-)
first focus is now a minimal viable GUI: search,select and stream.
all with a Youtube feel. Next release will add further features.

@vi
Copy link
Contributor

vi commented Jul 2, 2016

So until this next release with further features the old Tribler UI should be supported.

My use case of Tribler seems to be far away from Youtube...

@devos50 devos50 force-pushed the qt-gui branch 2 times, most recently from 5281b72 to 3dcd360 Compare July 9, 2016 10:25
@brussee
Copy link
Member

brussee commented Jul 14, 2016

The create torrent endpoint is done: #2242 as well as the add torrent to download: #2464.

@ardhipoetra
Copy link
Contributor

Credit mining GUIDBTuples can be removed if #2398 is merged. Mind to check it?

@devos50
Copy link
Contributor Author

devos50 commented Jul 14, 2016

@brussee thanks, I've updated the checkboxes (was a bit outdated).

@devos50
Copy link
Contributor Author

devos50 commented Jul 24, 2016

@synctext
Copy link
Member

solid progress!
if you don't mind I'll post highlights on the forum.

@devos50
Copy link
Contributor Author

devos50 commented Jul 25, 2016

@synctext np, go ahead :)

Just managed to get the first OS X builder working with this new GUI + PyInstaller: https://jenkins.tribler.org/job/pers/job/Build-Tribler7_OSX/. note that this build is quite unstable and needs more polishing.

@vi
Copy link
Contributor

vi commented Aug 29, 2016

  1. Is usual (legacy) Tribler GUI usable with this merged?
  2. Can both legacy GUI and this GUI be used at the same time? Two windows - one Tribler.

@devos50
Copy link
Contributor Author

devos50 commented Nov 16, 2016

I've created a separate job for the GUI tests: https://jenkins.tribler.org/job/GH_Tribler_PR_tests_GUI/. When this PR is merged, we can execute this multi-job on every PR.

@devos50 devos50 force-pushed the qt-gui branch 10 times, most recently from 624434f to 3e6258c Compare November 20, 2016 20:28
@devos50
Copy link
Contributor Author

devos50 commented Nov 20, 2016

After 6.5 months, this PR is finally ready to be merged! I cleaned up the code as much as I can and fixed many Pylint errors.

Regarding the code coverage: the GUI tests are executed in a separate job and this will test the code in the TriblerGUI directory.

I will merge this PR tomorrow if no-one has further comments on it.

@devos50 devos50 changed the title WIP: New GUI READY: New Tribler PyQt GUI Nov 20, 2016
@devos50 devos50 changed the title READY: New Tribler PyQt GUI New Tribler PyQt GUI Nov 21, 2016
@devos50 devos50 merged commit 6bda08f into Tribler:devel Nov 21, 2016
@devos50 devos50 deleted the qt-gui branch November 21, 2016 13:20
@devos50 devos50 moved this from In progress to Done in Tribler 7 Feb 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
8 participants