From 8318f72a9ef0ae30182d7886214b5be5a14cb6c9 Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Thu, 29 Dec 2016 23:03:01 +0100 Subject: [PATCH 1/3] Follow project coding style. Issue #2192. --- src/gui/torrentcontentmodel.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/gui/torrentcontentmodel.h b/src/gui/torrentcontentmodel.h index 8fa9ac565..31baa9f50 100644 --- a/src/gui/torrentcontentmodel.h +++ b/src/gui/torrentcontentmodel.h @@ -54,16 +54,16 @@ public: void updateFilesAvailability(const QVector &fa); QVector getFilePriorities() const; bool allFiltered() const; - virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; - virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; TorrentContentModelItem::ItemType itemType(const QModelIndex& index) const; int getFileIndex(const QModelIndex& index); - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; - virtual Qt::ItemFlags flags(const QModelIndex& index) const; - 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; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex& index) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; void clear(); void setupModelData(const BitTorrent::TorrentInfo &info); From 30bf6e958fbd61afc7a1049568ec53efc2a93f6d Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Fri, 30 Dec 2016 01:14:13 +0100 Subject: [PATCH 2/3] Use system file type specific icons in contents tab The icon is determined via QFileIconProvider using filename extension only. --- src/CMakeLists.txt | 3 ++ src/gui/CMakeLists.txt | 3 ++ src/gui/torrentcontentmodel.cpp | 50 +++++++++++++++++++++++++++++---- src/gui/torrentcontentmodel.h | 2 ++ src/src.pro | 3 ++ 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 606a8de68..b8e9cd6d7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,6 +14,9 @@ find_package(LibtorrentRasterbar REQUIRED) list(APPEND QBT_QT_COMPONENTS Core Network Xml) if (GUI) list (APPEND QBT_QT_COMPONENTS Concurrent Gui Widgets) + if (WIN32) + list (APPEND QBT_QT_COMPONENTS WinExtras) + endif(WIN32) endif (GUI) if (DBUS) list (APPEND QBT_QT_COMPONENTS DBus) diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 66b84381f..4d3bb152d 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -150,3 +150,6 @@ target_link_libraries(qbt_gui qbt_lineedit qbt_powermanagement qbt_rss qbt_prope ${QBT_GUI_OPTIONAL_LINK_LIBRARIES} qbt_base QtSingleApplication::QtSingleApplication ) +if(WIN32) + target_link_libraries(qbt_gui Qt5::WinExtras) +endif(WIN32) diff --git a/src/gui/torrentcontentmodel.cpp b/src/gui/torrentcontentmodel.cpp index bae6d58be..c69d7dbda 100644 --- a/src/gui/torrentcontentmodel.cpp +++ b/src/gui/torrentcontentmodel.cpp @@ -29,8 +29,16 @@ */ #include +#include +#include #include +#ifdef Q_OS_WIN +#include +#include +#include +#endif + #include "guiiconprovider.h" #include "base/utils/misc.h" #include "base/utils/fs.h" @@ -47,21 +55,53 @@ namespace return cached; } - QIcon getFileIcon() + class UnifiedFileIconProvider: public QFileIconProvider { - static QIcon cached = GuiIconProvider::instance()->getIcon("text-plain"); - return cached; - } + public: + using QFileIconProvider::icon; + QIcon icon(const QFileInfo &info) const override + { + Q_UNUSED(info); + static QIcon cached = GuiIconProvider::instance()->getIcon("text-plain"); + return cached; + } + }; +#ifdef Q_OS_WIN + // See QTBUG-25319 for explanation why this is required + class WinShellFileIconProvider: public UnifiedFileIconProvider + { + public: + using QFileIconProvider::icon; + QIcon icon(const QFileInfo &info) const override + { + SHFILEINFO sfi = { 0 }; + HRESULT hr = ::SHGetFileInfoW(info.absoluteFilePath().toStdWString().c_str(), + FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES); + if (FAILED(hr)) + return UnifiedFileIconProvider::icon(info); + + QPixmap iconPixmap = QtWin::fromHICON(sfi.hIcon); + ::DestroyIcon(sfi.hIcon); + return QIcon(iconPixmap); + } + }; +#endif } TorrentContentModel::TorrentContentModel(QObject *parent) : QAbstractItemModel(parent) , m_rootItem(new TorrentContentModelFolder(QList({ tr("Name"), tr("Size"), tr("Progress"), tr("Download Priority"), tr("Remaining"), tr("Availability") }))) { +#ifdef Q_OS_WIN + m_fileIconProvider = new WinShellFileIconProvider(); +#else + m_fileIconProvider = new QFileIconProvider(); +#endif } TorrentContentModel::~TorrentContentModel() { + delete m_fileIconProvider; delete m_rootItem; } @@ -202,7 +242,7 @@ QVariant TorrentContentModel::data(const QModelIndex& index, int role) const if (item->itemType() == TorrentContentModelItem::FolderType) return getDirectoryIcon(); else - return getFileIcon(); + return m_fileIconProvider->icon(QFileInfo(item->name())); } if ((index.column() == TorrentContentModelItem::COL_NAME) && (role == Qt::CheckStateRole)) { diff --git a/src/gui/torrentcontentmodel.h b/src/gui/torrentcontentmodel.h index 31baa9f50..cd6ef3966 100644 --- a/src/gui/torrentcontentmodel.h +++ b/src/gui/torrentcontentmodel.h @@ -39,6 +39,7 @@ #include "base/bittorrent/torrentinfo.h" #include "torrentcontentmodelitem.h" +class QFileIconProvider; class TorrentContentModelFile; class TorrentContentModel: public QAbstractItemModel @@ -77,6 +78,7 @@ public slots: private: TorrentContentModelFolder *m_rootItem; QVector m_filesIndex; + QFileIconProvider *m_fileIconProvider; }; #endif // TORRENTCONTENTMODEL_H diff --git a/src/src.pro b/src/src.pro index 9a296d258..71914081a 100644 --- a/src/src.pro +++ b/src/src.pro @@ -28,6 +28,9 @@ nogui { DEFINES += QBT_STATIC_QT QTPLUGIN += qico } + win32 { + QT += winextras + } TARGET = qbittorrent } nowebui: DEFINES += DISABLE_WEBUI From 57493c555666f0867f0879bf55eedcf593fa34d8 Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Tue, 2 May 2017 11:38:04 +0200 Subject: [PATCH 3/3] Add QFileIconProvider implementation using mime database If built-in QFileIconProvider does not seem to work, use custom implementation which queries mime database. --- src/gui/torrentcontentmodel.cpp | 49 ++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/gui/torrentcontentmodel.cpp b/src/gui/torrentcontentmodel.cpp index c69d7dbda..df668be61 100644 --- a/src/gui/torrentcontentmodel.cpp +++ b/src/gui/torrentcontentmodel.cpp @@ -37,6 +37,9 @@ #include #include #include +#else +#include +#include #endif #include "guiiconprovider.h" @@ -85,6 +88,49 @@ namespace return QIcon(iconPixmap); } }; +#else + /** + * @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 ask it for + * two icons for probably absent files and when both icons are null, we assume that + * the current QPA plugin does not implement QPlatformTheme::fileIcon(). + */ + bool doesQFileIconProviderWork() + { + QFileIconProvider provider; + const char PSEUDO_UNIQUE_FILE_NAME[] = "/tmp/qBittorrent-test-QFileIconProvider-845eb448-7ad5-4cdb-b764-b3f322a266a9"; + QIcon testIcon1 = provider.icon(QFileInfo( + QLatin1String(PSEUDO_UNIQUE_FILE_NAME) + QLatin1String(".pdf"))); + QIcon testIcon2 = provider.icon(QFileInfo( + QLatin1String(PSEUDO_UNIQUE_FILE_NAME) + QLatin1String(".png"))); + + return (!testIcon1.isNull() || !testIcon2.isNull()); + } + + class MimeFileIconProvider: public UnifiedFileIconProvider + { + using QFileIconProvider::icon; + QIcon icon(const QFileInfo &info) const override + { + const QMimeType mimeType = m_db.mimeTypeForFile(info, QMimeDatabase::MatchExtension); + QIcon res = QIcon::fromTheme(mimeType.iconName()); + if (!res.isNull()) { + return res; + } + + res = QIcon::fromTheme(mimeType.genericIconName()); + if (!res.isNull()) { + return res; + } + + return UnifiedFileIconProvider::icon(info); + } + + private: + QMimeDatabase m_db; + }; #endif } @@ -95,7 +141,8 @@ TorrentContentModel::TorrentContentModel(QObject *parent) #ifdef Q_OS_WIN m_fileIconProvider = new WinShellFileIconProvider(); #else - m_fileIconProvider = new QFileIconProvider(); + static bool doesBuiltInProviderWork = doesQFileIconProviderWork(); + m_fileIconProvider = doesBuiltInProviderWork ? new QFileIconProvider() : new MimeFileIconProvider(); #endif }