#include "iconinfo.h" #include "iconinfo_p.h" namespace Fm { std::unordered_map, IconInfo::GIconHash, IconInfo::GIconEqual> IconInfo::cache_; std::mutex IconInfo::mutex_; QIcon IconInfo::fallbackQicon_; static const char* fallbackIconNames[] = { "unknown", "application-octet-stream", "application-x-generic", "text-x-generic", nullptr }; IconInfo::IconInfo(const char* name): gicon_{g_themed_icon_new(name), false} { } IconInfo::IconInfo(const GIconPtr gicon): gicon_{std::move(gicon)} { } IconInfo::~IconInfo() { } // static std::shared_ptr IconInfo::fromName(const char* name) { GObjectPtr gicon{g_themed_icon_new(name), false}; return fromGIcon(gicon); } // static std::shared_ptr IconInfo::fromGIcon(GIconPtr gicon) { if(Q_LIKELY(gicon)) { std::lock_guard lock{mutex_}; auto it = cache_.find(gicon.get()); if(it != cache_.end()) { return it->second; } // not found in the cache, create a new entry for it. auto icon = std::make_shared(std::move(gicon)); cache_.insert(std::make_pair(icon->gicon_.get(), icon)); return icon; } return std::shared_ptr{}; } void IconInfo::updateQIcons() { std::lock_guard lock{mutex_}; fallbackQicon_ = QIcon(); for(auto& elem: cache_) { auto& info = elem.second; info->internalQicon_ = QIcon(); } } QIcon IconInfo::qicon(const bool& transparent) const { if(Q_LIKELY(!transparent)) { if(Q_UNLIKELY(qicon_.isNull() && gicon_)) { if(!G_IS_FILE_ICON(gicon_.get())) { qicon_ = QIcon(new IconEngine{shared_from_this()}); } else { qicon_ = internalQicon_; } } } else { // transparent == true if(Q_UNLIKELY(qiconTransparent_.isNull() && gicon_)) { if(!G_IS_FILE_ICON(gicon_.get())) { qiconTransparent_ = QIcon(new IconEngine{shared_from_this(), transparent}); } else { qiconTransparent_ = internalQicon_; } } } return !transparent ? qicon_ : qiconTransparent_; } QIcon IconInfo::qiconFromNames(const char* const* names) { const gchar* const* name; // qDebug("names: %p", names); for(name = names; *name; ++name) { // qDebug("icon name=%s", *name); QIcon qicon = QIcon::fromTheme(*name); if(!qicon.isNull()) { return qicon; } } return QIcon(); } std::forward_list> IconInfo::emblems() const { std::forward_list> result; if(hasEmblems()) { const GList* emblems_glist = g_emblemed_icon_get_emblems(G_EMBLEMED_ICON(gicon_.get())); for(auto l = emblems_glist; l; l = l->next) { auto gemblem = G_EMBLEM(l->data); GIconPtr gemblem_icon{g_emblem_get_icon(gemblem), true}; result.emplace_front(fromGIcon(gemblem_icon)); } result.reverse(); } return result; } QIcon IconInfo::internalQicon() const { if(Q_UNLIKELY(internalQicon_.isNull())) { GIcon* gicon = gicon_.get(); if(G_IS_EMBLEMED_ICON(gicon_.get())) { gicon = g_emblemed_icon_get_icon(G_EMBLEMED_ICON(gicon)); } if(G_IS_THEMED_ICON(gicon)) { const gchar* const* names = g_themed_icon_get_names(G_THEMED_ICON(gicon)); internalQicon_ = qiconFromNames(names); } else if(G_IS_FILE_ICON(gicon)) { GFile* file = g_file_icon_get_file(G_FILE_ICON(gicon)); CStrPtr fpath{g_file_get_path(file)}; internalQicon_ = QIcon(fpath.get()); } // fallback to default icon if(Q_UNLIKELY(internalQicon_.isNull())) { if(Q_UNLIKELY(fallbackQicon_.isNull())) { fallbackQicon_ = qiconFromNames(fallbackIconNames); } internalQicon_ = fallbackQicon_; } } return internalQicon_; } } // namespace Fm