mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
161 lines
3.0 KiB
C++
161 lines
3.0 KiB
C++
#include "iconfetcher.h"
|
|
#include "thread_utils.h"
|
|
#include "shared/util.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 = MOShared::startSafeThread([&]{ 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()
|
|
{
|
|
MOShared::SetThisThreadName("IconFetcher");
|
|
|
|
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 {};
|
|
}
|