summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorisanae <14251494+isanae@users.noreply.github.com>2019-12-13 15:13:19 -0500
committerisanae <14251494+isanae@users.noreply.github.com>2020-02-04 03:33:17 -0500
commitb6e91484ba90f95c67fcb0f31b966357daf3d709 (patch)
treea514d83b3542c28cb3a6e25f97be5d2b68b1caac
parentc5f98f9756ed9ba5b2241fa11215d99c8bf52461 (diff)
split IconFetcher
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/filetree.cpp206
-rw-r--r--src/filetree.h6
-rw-r--r--src/iconfetcher.h76
4 files changed, 84 insertions, 207 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ad791e79..38b4fac6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -146,6 +146,7 @@ SET(organizer_SRCS
filterlist.cpp
datatab.cpp
filetree.cpp
+ iconfetcher.cpp
shared/windows_error.cpp
shared/error_report.cpp
@@ -272,6 +273,7 @@ SET(organizer_HDRS
filterlist.h
datatab.h
filetree.h
+ iconfetcher.h
shared/windows_error.h
shared/error_report.h
@@ -403,6 +405,7 @@ set(loot
set(mainwindow
datatab
+ iconfetcher
filetree
filterlist
mainwindow
diff --git a/src/filetree.cpp b/src/filetree.cpp
index cf40e01c..f99ae8cd 100644
--- a/src/filetree.cpp
+++ b/src/filetree.cpp
@@ -170,209 +170,9 @@ QString FileTreeItem::debugName() const
}
-class FileTreeModel::IconFetcher
-{
-public:
- IconFetcher()
- : m_iconSize(GetSystemMetrics(SM_CXSMICON)), m_stop(false)
- {
- m_quickCache.file = getPixmapIcon(QFileIconProvider::File);
- m_quickCache.directory = getPixmapIcon(QFileIconProvider::Folder);
-
- m_thread = std::thread([&]{ threadFun(); });
- }
-
- ~IconFetcher()
- {
- stop();
- m_thread.join();
- }
-
- void stop()
- {
- m_stop = true;
- m_waiter.wakeUp();
- }
-
- QVariant icon(const QString& path) const
- {
- if (hasOwnIcon(path)) {
- return fileIcon(path);
- } else {
- const auto dot = path.lastIndexOf(".");
-
- if (dot == -1) {
- // no extension
- return m_quickCache.file;
- }
-
- return extensionIcon(path.midRef(dot));
- }
- }
-
- QPixmap genericFileIcon() const
- {
- return m_quickCache.file;
- }
-
- QPixmap genericDirectoryIcon() const
- {
- return m_quickCache.directory;
- }
-
-private:
- struct QuickCache
- {
- QPixmap file;
- QPixmap directory;
- };
-
- struct Cache
- {
- std::map<QString, QPixmap, std::less<>> map;
- std::mutex mapMutex;
-
- std::set<QString> queue;
- std::mutex queueMutex;
- };
-
- struct Waiter
- {
- mutable std::mutex m_wakeUpMutex;
- std::condition_variable m_wakeUp;
- bool m_queueAvailable = false;
-
- void wait()
- {
- std::unique_lock lock(m_wakeUpMutex);
- m_wakeUp.wait(lock, [&]{ return m_queueAvailable; });
- m_queueAvailable = false;
- }
-
- void wakeUp()
- {
- {
- std::scoped_lock lock(m_wakeUpMutex);
- m_queueAvailable = true;
- }
-
- m_wakeUp.notify_one();
- }
- };
-
- const int m_iconSize;
- QFileIconProvider m_provider;
- std::thread m_thread;
- std::atomic<bool> m_stop;
-
- mutable QuickCache m_quickCache;
- mutable Cache m_extensionCache;
- mutable Cache m_fileCache;
- mutable Waiter m_waiter;
-
-
- bool hasOwnIcon(const QString& path) const
- {
- static const QString exe = ".exe";
- static const QString lnk = ".lnk";
- static const QString ico = ".ico";
-
- return
- path.endsWith(exe, Qt::CaseInsensitive) ||
- path.endsWith(lnk, Qt::CaseInsensitive) ||
- path.endsWith(ico, Qt::CaseInsensitive);
- }
-
- template <class T>
- QPixmap getPixmapIcon(T&& t) const
- {
- return m_provider.icon(t).pixmap({m_iconSize, m_iconSize});
- }
-
- void threadFun()
- {
- while (!m_stop) {
- m_waiter.wait();
- if (m_stop) {
- break;
- }
-
- checkCache(m_extensionCache);
- checkCache(m_fileCache);
- }
- }
-
- void checkCache(Cache& cache)
- {
- std::set<QString> queue;
-
- {
- std::scoped_lock lock(cache.queueMutex);
- queue = std::move(cache.queue);
- cache.queue.clear();
- }
-
- if (queue.empty()) {
- return;
- }
-
- std::map<QString, QPixmap> map;
- for (auto&& ext : queue) {
- map.emplace(std::move(ext), getPixmapIcon(ext));
- }
-
- {
- std::scoped_lock lock(cache.mapMutex);
- for (auto&& p : map) {
- cache.map.insert(std::move(p));
- }
- }
- }
-
- void queue(Cache& cache, QString path) const
- {
- {
- std::scoped_lock lock(cache.queueMutex);
- cache.queue.insert(std::move(path));
- }
-
- m_waiter.wakeUp();
- }
-
- QVariant fileIcon(const QString& path) const
- {
- {
- std::scoped_lock lock(m_fileCache.mapMutex);
- auto itor = m_fileCache.map.find(path);
- if (itor != m_fileCache.map.end()) {
- return itor->second;
- }
- }
-
- queue(m_fileCache, path);
- return {};
- }
-
- QVariant extensionIcon(const QStringRef& ext) const
- {
- {
- std::scoped_lock lock(m_extensionCache.mapMutex);
- auto itor = m_extensionCache.map.find(ext);
- if (itor != m_extensionCache.map.end()) {
- return itor->second;
- }
- }
-
- queue(m_extensionCache, ext.toString());
- return {};
- }
-};
-
-
FileTreeModel::FileTreeModel(OrganizerCore& core, QObject* parent)
: QAbstractItemModel(parent), m_core(core), m_flags(NoFlags)
{
- m_iconFetcher.reset(new IconFetcher);
connect(&m_iconPendingTimer, &QTimer::timeout, [&]{ updatePendingIcons(); });
}
@@ -825,10 +625,10 @@ QVariant FileTreeModel::makeIcon(
const FileTreeItem& item, const QModelIndex& index) const
{
if (item.isDirectory()) {
- return m_iconFetcher->genericDirectoryIcon();
+ return m_iconFetcher.genericDirectoryIcon();
}
- auto v = m_iconFetcher->icon(item.realPath());
+ auto v = m_iconFetcher.icon(item.realPath());
if (!v.isNull()) {
return v;
}
@@ -836,7 +636,7 @@ QVariant FileTreeModel::makeIcon(
m_iconPending.push_back(index);
m_iconPendingTimer.start(std::chrono::milliseconds(1));
- return m_iconFetcher->genericFileIcon();
+ return m_iconFetcher.genericFileIcon();
}
void FileTreeModel::updatePendingIcons()
diff --git a/src/filetree.h b/src/filetree.h
index 4fbd5a2b..108c5843 100644
--- a/src/filetree.h
+++ b/src/filetree.h
@@ -1,6 +1,6 @@
#include "directoryentry.h"
+#include "iconfetcher.h"
#include <QAbstractItemModel>
-#include <QFileIconProvider>
class OrganizerCore;
@@ -106,13 +106,11 @@ private:
Q_DECLARE_FLAGS(FillFlags, FillFlag);
- class IconFetcher;
-
using DirectoryIterator = std::vector<MOShared::DirectoryEntry*>::const_iterator;
OrganizerCore& m_core;
mutable FileTreeItem m_root;
Flags m_flags;
- mutable std::unique_ptr<IconFetcher> m_iconFetcher;
+ mutable IconFetcher m_iconFetcher;
mutable std::vector<QModelIndex> m_iconPending;
mutable QTimer m_iconPendingTimer;
diff --git a/src/iconfetcher.h b/src/iconfetcher.h
new file mode 100644
index 00000000..030bfb79
--- /dev/null
+++ b/src/iconfetcher.h
@@ -0,0 +1,76 @@
+#ifndef MODORGANIZER_ICONFETCHER_INCLUDED
+#define MODORGANIZER_ICONFETCHER_INCLUDED
+
+#include <QFileIconProvider>
+#include <mutex>
+
+class IconFetcher
+{
+public:
+ IconFetcher();
+ ~IconFetcher();
+
+ void stop();
+
+ QVariant icon(const QString& path) const;
+ QPixmap genericFileIcon() const;
+ QPixmap genericDirectoryIcon() const;
+
+private:
+ struct QuickCache
+ {
+ QPixmap file;
+ QPixmap directory;
+ };
+
+ struct Cache
+ {
+ std::map<QString, QPixmap, std::less<>> map;
+ std::mutex mapMutex;
+
+ std::set<QString> queue;
+ std::mutex queueMutex;
+ };
+
+ class Waiter
+ {
+ public:
+ void wait();
+ void wakeUp();
+
+ private:
+ mutable std::mutex m_wakeUpMutex;
+ std::condition_variable m_wakeUp;
+ bool m_queueAvailable = false;
+ };
+
+
+ const int m_iconSize;
+ QFileIconProvider m_provider;
+ std::thread m_thread;
+ std::atomic<bool> m_stop;
+
+ mutable QuickCache m_quickCache;
+ mutable Cache m_extensionCache;
+ mutable Cache m_fileCache;
+ mutable Waiter m_waiter;
+
+
+ bool hasOwnIcon(const QString& path) const;
+
+ template <class T>
+ QPixmap getPixmapIcon(T&& t) const
+ {
+ return m_provider.icon(t).pixmap({m_iconSize, m_iconSize});
+ }
+
+ void threadFun();
+
+ void checkCache(Cache& cache);
+ void queue(Cache& cache, QString path) const;
+
+ QVariant fileIcon(const QString& path) const;
+ QVariant extensionIcon(const QStringRef& ext) const;
+};
+
+#endif // MODORGANIZER_ICONFETCHER_INCLUDED