summaryrefslogtreecommitdiff
path: root/src/iconfetcher.cpp
diff options
context:
space:
mode:
authorisanae <14251494+isanae@users.noreply.github.com>2019-12-14 14:28:17 -0500
committerisanae <14251494+isanae@users.noreply.github.com>2020-02-04 03:33:17 -0500
commit87868e1b22c27ebf10646269e89cc2848431c0b6 (patch)
treef98a371ee6abdb03f38514d9e4573d7508a902eb /src/iconfetcher.cpp
parentb6e91484ba90f95c67fcb0f31b966357daf3d709 (diff)
added a few missing consts
removed incorrect assert about an empty game edition added FileTree to wrap a QTreeView and a FileTreeModel, moved some context menu actions over
Diffstat (limited to 'src/iconfetcher.cpp')
-rw-r--r--src/iconfetcher.cpp156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/iconfetcher.cpp b/src/iconfetcher.cpp
new file mode 100644
index 00000000..9f8e348a
--- /dev/null
+++ b/src/iconfetcher.cpp
@@ -0,0 +1,156 @@
+#include "iconfetcher.h"
+
+void IconFetcher::Waiter::wait()
+{
+ std::unique_lock lock(m_wakeUpMutex);
+ m_wakeUp.wait(lock, [&]{ return m_queueAvailable; });
+ m_queueAvailable = false;
+}
+
+void IconFetcher::Waiter::wakeUp()
+{
+ {
+ std::scoped_lock lock(m_wakeUpMutex);
+ m_queueAvailable = true;
+ }
+
+ m_wakeUp.notify_one();
+}
+
+
+IconFetcher::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::~IconFetcher()
+{
+ stop();
+ m_thread.join();
+}
+
+void IconFetcher::stop()
+{
+ m_stop = true;
+ m_waiter.wakeUp();
+}
+
+QVariant IconFetcher::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 IconFetcher::genericFileIcon() const
+{
+ return m_quickCache.file;
+}
+
+QPixmap IconFetcher::genericDirectoryIcon() const
+{
+ return m_quickCache.directory;
+}
+
+bool IconFetcher::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);
+}
+
+void IconFetcher::threadFun()
+{
+ while (!m_stop) {
+ m_waiter.wait();
+ if (m_stop) {
+ break;
+ }
+
+ checkCache(m_extensionCache);
+ checkCache(m_fileCache);
+ }
+}
+
+void IconFetcher::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 IconFetcher::queue(Cache& cache, QString path) const
+{
+ {
+ std::scoped_lock lock(cache.queueMutex);
+ cache.queue.insert(std::move(path));
+ }
+
+ m_waiter.wakeUp();
+}
+
+QVariant IconFetcher::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 IconFetcher::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 {};
+}