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

Use system file type specific icons in contents tab #6156

Merged
merged 3 commits into from
Jul 3, 2017
Merged

Use system file type specific icons in contents tab #6156

merged 3 commits into from
Jul 3, 2017

Conversation

zeule
Copy link
Contributor

@zeule zeule commented Dec 30, 2016

Again a bit of eye-candy. Torrent contents tab shows icons for items, but icons of two types only: directory and text file. But we can get correct icon from the system mime database. The icon is determined via QFileIconProvider using filename extension only.

Perhaps default icon without mime database should be changed to "application/octet-stream" too.

@okeatime
Copy link
Contributor

Sample screen shot please?

@zeule
Copy link
Contributor Author

zeule commented Dec 31, 2016

Please:
qbt-file-types

qbt-file-types-add

@zeule
Copy link
Contributor Author

zeule commented Jan 3, 2017

PR Updated: replace QMimeDatabase with QFileIconProvider that results in Qt 4 and all OSes support.

@okeatime
Copy link
Contributor

okeatime commented Jan 4, 2017

👍 good job

@sledgehammer999
Copy link
Member

I was so pumped but unfortunately this doesn't work on Windows with Qt 5.7.1(didn't test qt4).
It seems to return an empty image.

@sledgehammer999 sledgehammer999 added the Look and feel Affect UI "Look and feel" only without changing the logic label Jan 18, 2017
@sledgehammer999
Copy link
Member

Possible explanation here. It seems QFileIconProvider works if the file actually exists on disk.

@sledgehammer999
Copy link
Member

And a stale Qt bug report: https://bugreports.qt.io/browse/QTBUG-25319

@zeule
Copy link
Contributor Author

zeule commented Jan 18, 2017

This is pity, of course. The feature is really nice and useful.... Except of patched Qt for the Windows builds or custom implementation of the same function I have no other ideas so far.

@sledgehammer999
Copy link
Member

The only choice here it to do this only for the platforms that support it and fallback to our current code for Windows. I'm in no mood to implement it in WINAPI.

Supposedly macOS should work too.

@zeule
Copy link
Contributor Author

zeule commented Jan 19, 2017

@okeatime, can you tell us, please, does it work in OSX?

virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
virtual QModelIndex parent(const QModelIndex &index) const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
Copy link
Contributor

Choose a reason for hiding this comment

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

override's instead of virtual? No class seems to inherit from this one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just reformatted the code, that was written before C++11.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yea, was just wondering if you want to change it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope, sorry. Not in this PR.

@zeule
Copy link
Contributor Author

zeule commented Apr 20, 2017

PR Updated: add a naïve WIN32 API based implementation for Windows.
qbt-file-icons-windows

@zeule zeule requested review from glassez and Chocobo1 April 20, 2017 16:36
@zeule
Copy link
Contributor Author

zeule commented Apr 20, 2017

@Chocobo1, @glassez: could you help me to fix qmake build on Windows, please?

@zeule
Copy link
Contributor Author

zeule commented Apr 20, 2017

Will this feature work for 64-bit qBittorrent on Windows?

Yes, it does.

@zeule
Copy link
Contributor Author

zeule commented Apr 20, 2017

@Chocobo1, @glassez: could you help me to fix qmake build on Windows, please?

Apparently, Qt build from cache in AppVeyor does not contain qwinextras module (why qmake is silent on this during its run?). If I use pre-installed Qt (see the last commit) it compiles, but fails during linking because QtSingleApplication was linked with static runtime (BTW, why?) while the pre-installled Qt is linked with dynamic one. I give up.

@zeule
Copy link
Contributor Author

zeule commented Apr 20, 2017

I can do kind of a hack: declare

Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon);

(which is exported from QtGui library) and use it without QWinExtras module. What do you think?

@zeule
Copy link
Contributor Author

zeule commented Apr 20, 2017

The hack is in its own commit now.

@zeule
Copy link
Contributor Author

zeule commented Apr 20, 2017

@sledgehammer999, I think we need your, as Windows packages, opinion here regarding this hack: would you prefer to use the additional Qt module WinExtras (albeit very small one) and update AppVeyor cached Qt package to include it, or use this hack? Actually, the hack is identical to the internals of WinExtras module.

@zywo
Copy link
Contributor

zywo commented Apr 20, 2017

Just tested on Ubuntu 17.04 and I don't know why it's not working.

1

2

@zeule
Copy link
Contributor Author

zeule commented Apr 20, 2017

Thanks, will check one more time a bit later.

@Chocobo1
Copy link
Member

would you prefer to use the additional Qt module WinExtras (albeit very small one) and update AppVeyor cached Qt package to include it

I prefer this option.

@zeule
Copy link
Contributor Author

zeule commented Apr 21, 2017

Just tested on Ubuntu 17.04 and I don't know why it's not working.

Because I forgot that for a long time I'm applying this patch locally. Obviously, current implementation will not work outside of Plasma even if that patch get accepted. Probably, I better return to QMimeDatabase-based implementation for Linux.

@zeule
Copy link
Contributor Author

zeule commented Apr 21, 2017

@zywo, tell, please, in what environment did you test?

@zeule zeule self-assigned this Apr 21, 2017
@zywo
Copy link
Contributor

zywo commented Apr 21, 2017

@evsh
Tested under Unity7 and Gnome DEs.

@zeule zeule mentioned this pull request Apr 26, 2017
12 tasks
@sledgehammer999
Copy link
Member

…if we remove the option, the bug will be gone too.

+1

Just wait a bit, I'm in the process of building+uploading new package for appveyor with WinExtras. Then you can also remove the winextras check too.

@zeule
Copy link
Contributor Author

zeule commented Jul 2, 2017

Super! Could you ping me, please, when the new image is ready?

@sledgehammer999
Copy link
Member

@evsh new files are uploaded. I also updated the appveyor config you use msvc2017, so be sure to rebase on top of master.

@zeule zeule dismissed stale reviews from glassez and Chocobo1 via b834ac1 July 3, 2017 09:54
@zeule
Copy link
Contributor Author

zeule commented Jul 3, 2017

@sledgehammer999: thanks!

PR updated: QWinExtras module is used unconditionally, icons are shown unconditionally.

@zeule zeule changed the title Optionally use system file type specific icons in contents tab Use system file type specific icons in contents tab Jul 3, 2017
Copy link
Member

@sledgehammer999 sledgehammer999 left a comment

Choose a reason for hiding this comment

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

Some minor things due to the rebase.
Otherwise, it is good for merging.

@@ -37,6 +37,7 @@
#include "base/bittorrent/session.h"
#include "base/preferences.h"
#include "gui/mainwindow.h"
#include "gui/torrentcontentmodel.h"
Copy link
Member

Choose a reason for hiding this comment

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

Is this a leftover?

@@ -41,27 +50,60 @@

namespace
{
const char showSystemFileIconsSettingKey[] = "Preferences/Advanced/showSystemFileIcons";
Copy link
Member

Choose a reason for hiding this comment

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

I think this is a leftover too.

@@ -37,8 +37,10 @@
#include <QVariant>

#include "base/bittorrent/torrentinfo.h"
#include "base/settingvalue.h"
Copy link
Member

Choose a reason for hiding this comment

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

leftover

@@ -74,6 +77,7 @@ namespace
class WinShellFileIconProvider: public UnifiedFileIconProvider
{
public:
using QFileIconProvider::icon;
Copy link
Member

Choose a reason for hiding this comment

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

maybe this belongs to the previous commit?

* @brief Tests whether QFileIconProvider actually works
*
* Some QPA plugins do not implement QPlatformTheme::fileIcon(), and
* QFileIconProvider::icon() returns empty icons as the result. Here we asks it for
Copy link
Member

Choose a reason for hiding this comment

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

Typo: "ask"

@zeule
Copy link
Contributor Author

zeule commented Jul 3, 2017

@sledgehammer999: done. Sorry for the carelessness.

#include "guiiconprovider.h"
#include "base/settingsstorage.h"
Copy link
Member

Choose a reason for hiding this comment

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

I think both of us missed this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

zeule added 2 commits July 3, 2017 16:49
The icon is determined via QFileIconProvider using filename extension only.
If built-in QFileIconProvider does not seem to work, use custom
implementation which queries mime database.
@sledgehammer999
Copy link
Member

Thx

@sledgehammer999 sledgehammer999 merged commit 8e6df57 into qbittorrent:master Jul 3, 2017
@zeule
Copy link
Contributor Author

zeule commented Jul 3, 2017

Thanks everyone!

@zeule zeule deleted the file-icons branch July 3, 2017 16:20
@zeule
Copy link
Contributor Author

zeule commented Jul 10, 2017

Fix for QTBUG-25319 will be in Qt 5.9.2. I'll submit a corresponding PR.

@sledgehammer999
Copy link
Member

Fix for QTBUG-25319 will be in Qt 5.9.2. I'll submit a corresponding PR.

Finally. Although that Qt shortcoming was mentioned/known a long while ago. At least the fixed it.

@vit9696
Copy link
Contributor

vit9696 commented Jul 15, 2017

@evsh I have just realised that this always returns blank icons on macOS for anything but folders.

@vit9696 vit9696 mentioned this pull request Jul 16, 2017
13 tasks
@zeule
Copy link
Contributor Author

zeule commented Jul 16, 2017

@vit9696 thanks for pointing this out.

Unfortunately, I can't build qBt in MacOS so can not look into it right now. Maybe next week...

@vit9696
Copy link
Contributor

vit9696 commented Jul 16, 2017

@evsh yes, it just gives iconForFile: empty path here. And that's even when the files are definitely available on disk. Cannot promise to look any soon on this either though.

@vit9696
Copy link
Contributor

vit9696 commented Jul 19, 2017

@evsh, ok, I tracked the issue down, and the merged code simply makes no sense to me from now on.

This line building QFileInfo from the item does nothing but appends the current working directory to a relative name. To elaborate, imagine name() return debian-9.0.0-amd64-netinst.iso, in this case given working dir set to /Users/MyUser/ the newly created QFileInfo will be built with /Users/MyUser/debian-9.0.0-amd64-netinst.iso path. And the actual file location could be /Users/MyUser/Downloads/debian-9.0.0-amd64-netinst.iso.

Obviously icon lookup will always fail when the downloaded file resides in a folder different from the working directory. That's because iconForFile: needs an actual file, and you give it a completely invalid path. How does it even work on the other platforms? I do not understand why QFileInfo is even used here, especially since the detection could only happen by an extension, and since QFileInfo is believed to be slow.

What needs to be done here (especially given that one should be able to see the icons before downloading anything) is just a plain extension-based lookup. So I enforced MimeFileIconProvider, simplified it a little to avoid QFileInfo, and added some prints of the icon names and mimes:

"debian-9.0.0-amd64-netinst.iso"  has  "application/x-cd-image" mime
"application/x-cd-image"  has  "application-x-cd-image"  icon
"application/x-cd-image"  has  "application-x-generic"  genicon

So far so good, but QIcon::fromTheme from both of those returns a null icon. The docs say that this function appears to be a Linux hack compatible with some kind of Linux-only spec with an ability of gluing to a local icon database @_@. Sounds mad and of course does not work, on macOS you have iconForFileType:, which should be used in a similar way to iconForFile: :/.

Given the overall code craziness, could you please rework this? If you want to use file-based icon matching, please provide a valid file path. Otherwise this should be eliminated for good, along with the ugly test attempting to achieve nothing.

Here is a basic patch required to get things work on macOS. I could submit a pull-request with just this to make it in time for 3.4.0. Or it could be used as a reference for the refactoring of this code by somebody else.

CC @Chocobo1, @glassez, @LordNyriox, @sledgehammer999, @thalieht.

@zeule
Copy link
Contributor Author

zeule commented Jul 19, 2017

@vit9696, thanks for the investigation!

This line building QFileInfo from the item does nothing but appends the current working directory to a relative name.

This makes no sense to me. Are you saying that the QFileInfo objects contain actual full path (with the current directory for he moment of its creation)?

Obviously icon lookup will always fail when the downloaded file resides in a folder different from the working directory.

Lookup by file extension has to work with non-existing files.

That's because iconForFile: needs an actual file, and you give it a completely invalid path.

This means QTBUG-25319 affects MacOS too.

I do not understand why QFileInfo is even used here, especially since the detection could only happen by an extension, and since QFileInfo is believed to be slow.

Because it's a part of QFileIconProvider interface.

@vit9696
Copy link
Contributor

vit9696 commented Jul 19, 2017

This makes no sense for me. Are you saying that the QFileInfo objects contain actual full path (with the current directory for he moment of its creation)?

I am only talking about absoluteFilePath() used by Qt internally and by the Windows icon lookup here. From what I can tell QFileInfo changes nothing itself and just does what you ask it. Want absolute path → working dir gets appended unless the original path has already been absolute. In this case all the files are just filenames without even a torrent subdir prefix (see the prints above).

Lookup by file extension has to work with non-existing files.

Yes, but what is the point of doing this when you already have mime-based search? This is not going to do any better unless you actually have the file at least partially downloaded, pass the valid path, have the data-based detection enabled. Otherwise it is just unnecessary code duplication.

Because it's a part of QFileIconProvider interface.

QFileIconProvider is just a spike that helps nothing when you provide invalid paths that will never become valid to it.

@zeule
Copy link
Contributor Author

zeule commented Jul 19, 2017

I am only talking about absoluteFilePath() used by Qt internally and by the Windows icon lookup here…

Thanks, understood.

Yes, but what is the point of doing this when you already have mime-based search?

Mime database does not exist on Windows, while QFileIconProvider give a uniform interface on all platforms.

QFileIconProvider is just a spike that helps nothing when you provide invalid paths that will never become valid to it.

Uniform interface.

So, QFileIconProvider::icon() does not work on MacOS for non-existing files. You probably should submit a bug report to Qt and submit a PR here basing on your investigation. Also, I would recommend you to subclass QFileIconProvider instead of hooking up with #ifdef into the MimeFileIconProvider. That would keep code cleaner and allow our descendants to easily remove the workaround when Qt fixes the problem.

@vit9696
Copy link
Contributor

vit9696 commented Jul 19, 2017

Uniform interface.

That does not work on anything but a couple of Linux distros :D
Anyway, no reason for any further discussion. Created #7118.
As for bugreports there are way too many terrible and obvious Qt bugs on macOS for me to bother reporting them.

@zeule
Copy link
Contributor Author

zeule commented Jul 19, 2017

That does not work on anything but a couple of Linux distros

It works on Windows too (Qt 5.9.2 and later).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Look and feel Affect UI "Look and feel" only without changing the logic
Projects
None yet
Development

Successfully merging this pull request may close these issues.