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

Add additional tracker info to WebUI #9375

Merged
merged 10 commits into from
Dec 12, 2018

Conversation

Piccirello
Copy link
Member

@Piccirello Piccirello commented Aug 20, 2018

Note: This does not break anything in the existing /torrents/trackers API; it only adds additional info

Before:
screen shot 2018-08-20 at 12 15 27 am

After:
screen shot 2018-08-20 at 1 31 46 am

GUI, for comparison:
screen shot 2018-08-20 at 12 33 03 am

Context menu:

webui:
screen shot 2018-09-02 at 6 35 26 pm

gui:
screen shot 2018-09-02 at 6 44 04 pm

Category editing

webui:
screen shot 2018-09-02 at 6 30 49 pm

gui:
screen shot 2018-09-02 at 6 31 52 pm

  • Update WebAPI documentation

Closes #7934, closes #6797, closes #3024

@glassez glassez added WebUI WebUI-related issues/changes WebAPI WebAPI-related issues/changes labels Aug 20, 2018
@@ -304,6 +312,8 @@ void TorrentsController::trackersAction()
if (!torrent)
throw APIError(APIErrorType::NotFound);

trackerList << getStickyTrackers(torrent);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QVariantList trackerList {getStickyTrackers(torrent)};

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change results in the getStickyTrackers QList being added as an element of trackerList, rather than the elements of getStickyTrackers being added.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, it is because using the braces, can you give it one last try:

QVariantList trackerList = getStickyTrackers(torrent);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That worked!

@@ -30,6 +30,8 @@

#include "apicontroller.h"

#include "base/bittorrent/torrenthandle.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forward declare it instead: class BitTorrent::TorrentHandle; and revert this and also in cpp file.

@@ -73,4 +75,7 @@ private slots:
void setForceStartAction();
void toggleSequentialDownloadAction();
void toggleFirstLastPiecePrioAction();

private:
QVariantList getStickyTrackers(const BitTorrent::TorrentHandle* torrent);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QVariantList getStickyTrackers(const BitTorrent::TorrentHandle* torrent) const;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my previous comment.

{
static const QString working("Working");
static const QString disabled("Disabled");
static const QString privateMsg("This torrent is private");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove statics, no point doing so IMO.

QVariantList stickyTrackers;

QVariantMap dht;
dht[KEY_TRACKER_URL] = "** [DHT] **";
Copy link
Member

@Chocobo1 Chocobo1 Aug 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not accustomed to list initialization?

QVariantMap dht = {
    {KEY_TRACKER_URL, "** [DHT] **"},
    // ...
};

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't quite figure out the syntax for this. Thanks!

lsd[KEY_TRACKER_DOWNLOADED] = "";

if (BitTorrent::Session::instance()->isDHTEnabled() && !torrent->isPrivate())
dht[KEY_TRACKER_STATUS] = "Working";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?? you're not using the constant defined above...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also I would write it:

dht[KEY_TRACKER_STATUS] = (BitTorrent::Session::instance()->isDHTEnabled() && !torrent->isPrivate())
    ? "Working"
    : "Disabled";

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definite goof on my end

lsd[KEY_TRACKER_SEEDS] = seedsLSD;
lsd[KEY_TRACKER_PEERS] = peersLSD;

stickyTrackers << dht;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move stickyTrackers declaration above this line and initialize it, seems you're following C rules in modern C++ code... :\

}

uint seedsDHT = 0, seedsPeX = 0, seedsLSD = 0, peersDHT = 0, peersPeX = 0, peersLSD = 0;
foreach (const BitTorrent::PeerInfo &peer, torrent->peers()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use range-based for loop.

row[1] = tracker.status;
row[2] = tracker.num_peers;
row[3] = escapeHtml(tracker.msg);
row[0] = tracker.tier;
Copy link
Member

@Chocobo1 Chocobo1 Aug 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, how about:

var row = [
    tracker.tier,
    // ...
];

const char KEY_TRACKER_MSG[] = "msg";
const char KEY_TRACKER_PEERS[] = "num_peers";
const char KEY_TRACKER_RECEIVED[] = "num_peers";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TRACKER_RECEIVED == "num_peers" ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value associated with this key is used to display the tracker "Received" count, but for legacy reasons the key is num_peers. We can't change this without breaking the api.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you'd better add four new keys and leave "num_peers" for a deprecation later on?

@@ -292,7 +296,11 @@ void TorrentsController::propertiesAction()
// The dictionary keys are:
// - "url": Tracker URL
// - "status": Tracker status
// - "num_peers": Tracker peer count
// - "tier": Tracker tier
// - "num_peers": Tracker received count
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Received count of what?

Copy link
Member Author

@Piccirello Piccirello Aug 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite sure, but this is the nomenclature used in the GUI. It looks like it might be the total number of other clients we're connected to.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I investigated further, it's the total number of peers the torrent is connected to. It's documented here for torrent_status::numPeers.


QVariantList TorrentsController::getStickyTrackers(const BitTorrent::TorrentHandle* torrent)
{
static const QString working("Working");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const QString working {QLatin1String("Working")};
Etc.

@@ -835,3 +856,91 @@ void TorrentsController::removeCategoriesAction()
for (const QString &category : categories)
BitTorrent::Session::instance()->removeCategory(category);
}

QVariantList TorrentsController::getStickyTrackers(const BitTorrent::TorrentHandle* torrent)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const BitTorrent::TorrentHandle *torrent

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this function depend on TorrentsController? If not, it would be better to have it in an anonymous namespace instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will move it to an anonymous namespace

@@ -73,4 +75,7 @@ private slots:
void setForceStartAction();
void toggleSequentialDownloadAction();
void toggleFirstLastPiecePrioAction();

private:
QVariantList getStickyTrackers(const BitTorrent::TorrentHandle* torrent);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my previous comment.

@Piccirello
Copy link
Member Author

All comments addressed. These new changes need more testing, will update once complete.

{
const QString working {QLatin1String("Working")};
const QString disabled {QLatin1String("Disabled")};
const QString privateMsg {QLatin1String("This torrent is private")};
Copy link
Member

@Chocobo1 Chocobo1 Aug 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems these strings need to be translated, try const QString privateMsg {QCoreApplication::translate("TrackerListWidget", "This torrent is private")}; see if it works.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The translation works now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hell, I really don't like the tendency of recent changes to return translated text from an API (and generally, return anything visible directly to the user). You generate unnecessary dependencies again. But I guess you all don't care...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Piccirello
Or maybe return some constant (integers?) here and do the translation at client side? However I'm not sure how to fetch translated strings at javascript... or this need some html tricks...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However I'm not sure how to fetch translated strings at javascript...

JavaScript sources are translatable as well. You can easily create error code to description text mapping there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just fix old ones? We need to learn from other people's mistakes, not repeat them.

But changing it now will surely break API... We should enforce correct design for new code, but the issue here is old, personally I would turn a blind eye for this specific case.

@Piccirello
Just asking for your opinion here, what do you think about the idea (do i18n strings replacement in HTML file) in #9375 (comment), is it much hassle to do it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's easy to do for static strings in HTML files, but more difficult to do for api responses. We end up with code that's very tightly coupled to specific api versions, such as

var status;
switch (tracker.status) {
    case "Working":
        status = "QBT_TR(Working)QBT_TR[CONTEXT=TrackerListWidget]";
        break;
    case "Disabled":
        status = "QBT_TR(Disabled)QBT_TR[CONTEXT=TrackerListWidget]";
        break;
    case "This torrent is private":
        status = "QBT_TR(This torrent is private)QBT_TR[CONTEXT=TrackerListWidget]";
        break;
    default:
        status = tracker.status;
}

I would think it's considered a feature that the current APIs return translated string values.

Copy link
Member

@Chocobo1 Chocobo1 Sep 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's easy to do for static strings in HTML files, but more difficult to do for api responses.

Thank you, I hope that doesn't mean impossible for api responses.

I would think it's considered a feature that the current APIs return translated string values.

I think it might be a feature if there are 2 seperate values returned, such as:

tracker.status = "working"
tracker.statusI18N = "<translated string>"

My point is, if we always only return translated strings, then it is cumbersome to write code for the API, as one will need to take locale settings into consideration.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think it's considered a feature that the current APIs return translated string values.

Disagree.
We should not spawn such flaws where we have the ability to get around it without breaking API. And we have to seriously consider the need to get rid of this "feature" with the next more or less big API update.

In this particular case let it be as is.

You really like jumping on my PRs to report your issues with the general qbittorent architecture. Please, open a separate PR fixing the issues that you see. It should not hold back new features that follow the existing architecture.

It's nothing personal. This is our usual practice.
Unfortunately, our resources are too limited to allow us to make major architectural changes at a time. None of the project members knows exactly all the code (especially if it has a long history). We often detect some problems in some parts of the code affected by some (possible unrelated) changes. And we try to solve them along the way, if possible (usually offer to do it to the author of the affected PR).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's create issues for these large architectural changes, rather than holding up individual features. In certain cases it might be reasonable, but there's no point in holding back a new feature because we can't decide if the API should return translated strings. Just one example, but the point being that we can still make incremental progress while acknowledging large changes that need to occur.

@WolfganP
Copy link

@Piccirello thx for these continuous improvements to the WebUI. Is it possible to implement the "remove tracker" functionality in the WebUI?

@Piccirello
Copy link
Member Author

@WolfganP It shouldn't be too difficult to implement the entire tracker context menu. Possibly in this PR if I can get it done quickly enough.
screen shot 2018-08-31 at 2 06 09 pm 2

I also plan to target having trackers in the sidebar, but that may take a bit longer.

@zero77
Copy link

zero77 commented Aug 31, 2018

@Piccirello
I don’t want to cause problems as you clearly have put a lot of time and effort in to the current system. But, whilst you are working on trackers I think it would be nice to see whether the connection to the tracker is encrypted or not like the E flag next to pears.

@Piccirello
Copy link
Member Author

@zero77 I'm not sure that libtorrent exposes this information directly. The announce_entry doesn't contain any info related to encryption, though tracker traffic is usually unencrypted anyway. You can try to infer this yourself by seeing if any of the tracker urls being with https.

@Piccirello
Copy link
Member Author

Context menu implemented. I've also finished my testing of these new features.

Please review the new commits.

@zero77
Copy link

zero77 commented Sep 2, 2018

@Piccirello
Thanks anyway.

@Piccirello Piccirello force-pushed the webui-trackers branch 3 times, most recently from be77247 to d0ceca2 Compare September 3, 2018 09:43
@Piccirello
Copy link
Member Author

If no more comments, please approve

@Piccirello
Copy link
Member Author

Added one commit to implement the changes from #9461

for (QString urlStr : params()["urls"].split('\n')) {
urlStr = urlStr.trimmed();
QUrl url(urlStr);
if (!urlStr.isEmpty() && url.isValid())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this overchecking? How can empty string be valid URL? Isn't if (url.isValid()) enough?

@glassez
Copy link
Member

glassez commented Sep 11, 2018

If no more comments, please approve

There is at least one old unresolved conversation (about translated strings). It won't go away on its own just because you're ignoring it.

glassez
glassez previously approved these changes Dec 8, 2018
{KEY_TRACKER_STATUS, static_cast<int>(tracker.status())},
{KEY_TRACKER_PEERS_COUNT, data.numPeers},
{KEY_TRACKER_MSG, data.lastMessage.trimmed()},
{KEY_TRACKER_SEEDS_COUNT, tracker.nativeEntry().scrape_complete},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nativeEntry() is for internal use! If someone need these fields they should be provided via BitTorrent::TrackerEntry interface.
I can see that you just copied the code from GUI, so the questions are not to you, but to who added it originally.
You're free to not fixing it here.

@Chocobo1
Copy link
Member

Please squash commits.

@Piccirello
Copy link
Member Author

Fixup commits were squashed

glassez
glassez previously approved these changes Dec 11, 2018
Chocobo1
Chocobo1 previously approved these changes Dec 11, 2018
sledgehammer999 and others added 5 commits December 11, 2018 00:41
"Received" renamed to "Peers", "Peers" renamed to "Leeches".
Adds an ellipses to indicate that the Edit option opens a dialog. Also moves Edit to top of the list to convey action's prominence.
@Piccirello
Copy link
Member Author

Fixed conflict

@Chocobo1 Chocobo1 merged commit 1c525d9 into qbittorrent:master Dec 12, 2018
@Chocobo1
Copy link
Member

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WebAPI WebAPI-related issues/changes WebUI WebUI-related issues/changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Request] Webui Tracker Status Simple tracker management in Web UI Edit trackers through the Web UI
8 participants