You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libfm-qt-packaging/src/core/iconinfo.cpp

139 lines
4.1 KiB

#include "iconinfo.h"
#include "iconinfo_p.h"
namespace Fm {
std::unordered_map<GIcon*, std::shared_ptr<IconInfo>, 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<const IconInfo> IconInfo::fromName(const char* name) {
GObjectPtr<GIcon> gicon{g_themed_icon_new(name), false};
return fromGIcon(gicon);
}
// static
std::shared_ptr<const IconInfo> IconInfo::fromGIcon(GIconPtr gicon) {
if(Q_LIKELY(gicon)) {
std::lock_guard<std::mutex> 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<IconInfo>(std::move(gicon));
cache_.insert(std::make_pair(icon->gicon_.get(), icon));
return icon;
}
return std::shared_ptr<const IconInfo>{};
}
void IconInfo::updateQIcons() {
std::lock_guard<std::mutex> 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<std::shared_ptr<const IconInfo>> IconInfo::emblems() const {
std::forward_list<std::shared_ptr<const IconInfo>> 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