33 #include <QFileIconProvider>
40 #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
44 #include <QMimeDatabase>
48 #if defined Q_OS_WIN || defined Q_OS_MACOS
49 #define QBT_PIXMAP_CACHE_FOR_FILE_ICONS
50 #include <QPixmapCache>
71 using QFileIconProvider::icon;
73 QIcon
icon(
const QFileInfo &info)
const override
81 #ifdef QBT_PIXMAP_CACHE_FOR_FILE_ICONS
82 class CachingFileIconProvider :
public UnifiedFileIconProvider
85 using QFileIconProvider::icon;
87 QIcon icon(
const QFileInfo &info)
const final
89 const QString ext = info.suffix();
93 if (QPixmapCache::find(ext, &cached))
return {cached};
98 QPixmapCache::insert(ext, pixmap);
102 return UnifiedFileIconProvider::icon(info);
110 #if defined(Q_OS_WIN)
112 class WinShellFileIconProvider final :
public CachingFileIconProvider
116 const QString extWithDot = QLatin1Char(
'.') + ext;
118 HRESULT hr = ::SHGetFileInfoW(extWithDot.toStdWString().c_str(),
119 FILE_ATTRIBUTE_NORMAL, &sfi,
sizeof(sfi), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES);
123 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
124 auto iconPixmap = QPixmap::fromImage(QImage::fromHICON(sfi.hIcon));
126 QPixmap iconPixmap = QtWin::fromHICON(sfi.hIcon);
128 ::DestroyIcon(sfi.hIcon);
132 #elif defined(Q_OS_MACOS)
135 class MacFileIconProvider final :
public CachingFileIconProvider
153 QFileIconProvider provider;
154 const char PSEUDO_UNIQUE_FILE_NAME[] =
"/tmp/qBittorrent-test-QFileIconProvider-845eb448-7ad5-4cdb-b764-b3f322a266a9";
155 QIcon testIcon1 = provider.icon(QFileInfo(
156 QLatin1String(PSEUDO_UNIQUE_FILE_NAME) + QLatin1String(
".pdf")));
157 QIcon testIcon2 = provider.icon(QFileInfo(
158 QLatin1String(PSEUDO_UNIQUE_FILE_NAME) + QLatin1String(
".png")));
160 return (!testIcon1.isNull() || !testIcon2.isNull());
165 using QFileIconProvider::icon;
167 QIcon
icon(
const QFileInfo &info)
const override
169 const QMimeType mimeType = m_db.mimeTypeForFile(info, QMimeDatabase::MatchExtension);
170 QIcon res = QIcon::fromTheme(mimeType.iconName());
176 res = QIcon::fromTheme(mimeType.genericIconName());
182 return UnifiedFileIconProvider::icon(info);
192 : QAbstractItemModel(parent)
193 , m_rootItem(new
TorrentContentModelFolder(QVector<QString>({ tr(
"Name"), tr(
"Size"), tr(
"Progress"), tr(
"Download Priority"), tr(
"Remaining"), tr(
"Availability") })))
195 #if defined(Q_OS_WIN)
196 m_fileIconProvider =
new WinShellFileIconProvider();
197 #elif defined(Q_OS_MACOS)
198 m_fileIconProvider =
new MacFileIconProvider();
201 m_fileIconProvider = doesBuiltInProviderWork ?
new QFileIconProvider() : new MimeFileIconProvider();
217 emit layoutAboutToBeChanged();
218 for (
int i = 0; i < fp.size(); ++i)
233 emit layoutAboutToBeChanged();
234 for (
int i = 0; i < fprio.size(); ++i)
245 emit layoutAboutToBeChanged();
255 QVector<BitTorrent::DownloadPriority> prio;
258 prio.push_back(
file->priority());
266 return (fileItem->priority() == BitTorrent::DownloadPriority::Ignored);
280 if (!
index.isValid())
286 qDebug(
"setData(%s, %d)", qUtf8Printable(item->name()),
value.toInt());
289 if (
value.toInt() == Qt::PartiallyChecked)
291 else if (
value.toInt() == Qt::Unchecked)
294 if (item->priority() != prio)
296 item->setPriority(prio);
306 if (role == Qt::EditRole)
308 Q_ASSERT(
index.isValid());
310 switch (
index.column())
313 item->setName(
value.toString());
345 if (!
index.isValid())
352 case Qt::DecorationRole:
361 case Qt::CheckStateRole:
367 return Qt::Unchecked;
369 return Qt::PartiallyChecked;
372 case Qt::TextAlignmentRole:
375 return QVariant {Qt::AlignRight | Qt::AlignVCenter};
378 case Qt::DisplayRole:
379 case Qt::ToolTipRole:
380 return item->displayData(
index.column());
382 case Roles::UnderlyingDataRole:
383 return item->underlyingData(
index.column());
392 if (!
index.isValid())
393 return Qt::NoItemFlags;
395 Qt::ItemFlags
flags {Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable};
397 flags |= Qt::ItemIsAutoTristate;
399 flags |= Qt::ItemIsEditable;
406 if (orientation != Qt::Horizontal)
411 case Qt::DisplayRole:
414 case Qt::TextAlignmentRole:
417 return QVariant {Qt::AlignRight | Qt::AlignVCenter};
438 Q_ASSERT(parentItem);
445 return createIndex(row, column, childItem);
451 if (!
index.isValid())
462 return createIndex(parentItem->
row(), 0, parentItem);
476 return parentItem ? parentItem->
childCount() : 0;
481 qDebug(
"clear called");
490 qDebug(
"setup model data called");
495 emit layoutAboutToBeChanged();
497 qDebug(
"Torrent contains %d files", filesCount);
502 for (
int i = 0; i < filesCount; ++i)
508 QList<QStringView> pathFolders = QStringView(path).split(u
'/', Qt::SkipEmptyParts);
509 pathFolders.removeLast();
511 for (
const QStringView pathPart :
asConst(pathFolders))
513 const QString folderPath = pathPart.toString();
520 currentParent = newParent;
528 emit layoutChanged();
virtual int filesCount() const =0
virtual qlonglong fileSize(int index) const =0
virtual QString filePath(int index) const =0
TorrentContentModelFolder * childFolderWithName(const QString &name) const
void appendChild(TorrentContentModelItem *item)
TorrentContentModelItem * child(int row) const
void recalculateAvailability()
void recalculateProgress()
void updateFilesPriorities(const QVector< BitTorrent::DownloadPriority > &fprio)
QVector< BitTorrent::DownloadPriority > getFilePriorities() const
void filteredFilesChanged()
Qt::ItemFlags flags(const QModelIndex &index) const override
void updateFilesProgress(const QVector< qreal > &fp)
void setupModelData(const BitTorrent::AbstractFileStorage &info)
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
TorrentContentModelItem::ItemType itemType(const QModelIndex &index) const
TorrentContentModelFolder * m_rootItem
QFileIconProvider * m_fileIconProvider
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
QVector< TorrentContentModelFile * > m_filesIndex
QModelIndex index(int row, int column, const QModelIndex &parent={}) const override
int getFileIndex(const QModelIndex &index)
QModelIndex parent(const QModelIndex &index) const override
~TorrentContentModel() override
void updateFilesAvailability(const QVector< qreal > &fa)
int columnCount(const QModelIndex &parent={}) const override
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
int rowCount(const QModelIndex &parent={}) const override
TorrentContentModel(QObject *parent=nullptr)
BitTorrent::DownloadPriority priority() const
virtual void setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent=true)=0
QString displayData(int column) const
TorrentContentModelFolder * parent() const
static UIThemeManager * instance()
QIcon getIcon(const QString &iconId, const QString &fallback={}) const
QIcon icon(const QFileInfo &info) const override
QIcon icon(const QFileInfo &info) const override
constexpr std::add_const_t< T > & asConst(T &t) noexcept
QPixmap pixmapForExtension(const QString &ext, const QSize &size)
QString fileName(const QString &filePath)
QString toUniformPath(const QString &path)
T value(const QString &key, const T &defaultValue={})
bool doesQFileIconProviderWork()
Tests whether QFileIconProvider actually works.
file(GLOB QBT_TS_FILES "${qBittorrent_SOURCE_DIR}/src/lang/*.ts") set_source_files_properties($