1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-27 01:57:52 +00:00
transmission/gtk/IconCache.cc

214 lines
4.9 KiB
C++
Raw Normal View History

/*
* icons.[ch] written by Paolo Bacchilega, who writes:
* "There is no problem for me, you can license my code
* under whatever licence you wish :)"
*
*/
#include <array>
#include <memory>
#include <unordered_map>
#include <glibmm.h>
#include <giomm.h>
#include "IconCache.h"
#include "Utils.h"
using namespace std::literals;
Glib::ustring const DirectoryMimeType = "folder"s;
Glib::ustring const UnknownMimeType = "unknown"s;
namespace
{
auto const VoidPixbufKey = "void-pixbuf"s;
struct IconCache
{
Glib::RefPtr<Gtk::IconTheme> icon_theme;
int icon_size;
std::unordered_map<std::string, Glib::RefPtr<Gdk::Pixbuf>> cache;
};
std::array<std::unique_ptr<IconCache>, 7> icon_cache;
Glib::RefPtr<Gdk::Pixbuf> create_void_pixbuf(int width, int height)
{
auto const p = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, width, height);
p->fill(0xFFFFFF00);
return p;
}
int get_size_in_pixels(Gtk::IconSize icon_size)
{
int width = 0;
int height = 0;
Gtk::IconSize::lookup(icon_size, width, height);
return std::max(width, height);
}
std::unique_ptr<IconCache> icon_cache_new(Gtk::Widget& for_widget, Gtk::IconSize icon_size)
{
auto icons = std::make_unique<IconCache>();
icons->icon_theme = Gtk::IconTheme::get_for_screen(for_widget.get_screen());
icons->icon_size = get_size_in_pixels(icon_size);
2022-01-17 18:39:50 +00:00
icons->cache.try_emplace(VoidPixbufKey, create_void_pixbuf(icons->icon_size, icons->icon_size));
return icons;
}
std::string _icon_cache_get_icon_key(Glib::RefPtr<Gio::Icon> const& icon)
{
std::string key;
if (auto* const ticon = dynamic_cast<Gio::ThemedIcon*>(gtr_get_ptr(icon)); ticon != nullptr)
{
std::ostringstream names;
for (auto const& name : ticon->get_names())
{
names << name << ',';
}
key = names.str();
}
else if (auto* const ficon = dynamic_cast<Gio::FileIcon*>(gtr_get_ptr(icon)); ficon != nullptr)
{
key = ficon->get_file()->get_path();
}
return key;
}
Glib::RefPtr<Gdk::Pixbuf> get_themed_icon_pixbuf(Gio::ThemedIcon& icon, int size, Gtk::IconTheme& icon_theme)
{
auto const icon_names = icon.get_names();
auto icon_info = icon_theme.choose_icon(icon_names, size);
if (!bool{ icon_info })
{
icon_info = icon_theme.lookup_icon("text-x-generic", size, Gtk::ICON_LOOKUP_USE_BUILTIN);
}
try
{
return icon_info.load_icon();
}
catch (Glib::Error const& e)
{
g_warning("could not load icon pixbuf: %s\n", e.what().c_str());
return {};
}
}
Glib::RefPtr<Gdk::Pixbuf> get_file_icon_pixbuf(Gio::FileIcon& icon, int size)
{
try
{
return Gdk::Pixbuf::create_from_file(icon.get_file()->get_path(), size, -1, false);
}
fix: sonarcloud (#2860) * fix: break will never be executed * fix: rewrite rimraf() to be non-throwing * fix: conditional operation returns same value whether condition is true or false * fix: use std::array instead of a C-style array * fix: remove redundant access specifier * fix: replace switch with if for readability * fix: convert integer literal to a bool literal * fix: replace const std::string reference to std::string_view * fix: remove redundant access specifier * fix: replace const std::string reference to std::string_view * fix: remove unused parameter * fix: remove redundant access specifier * fix: use std::array instead of C-style array * fix: remove redundant access specifier * fix: replace const std::string reference with std::string_view * fix: remove redundant access specifier * fix: use std::array instead of C-style array * fix: remove redundant access specifier * fix: replace const std::string reference to std::string_view * fix: remove redundant access specifier * fix: merge if statement with enclosing one * chore: clang-format * chore: clang-format * Revert "fix: remove redundant access specifier" This reverts commit 054e4e7eecbbc6d1108fd15de10f39cd8aad2aa6. * Revert "fix: remove redundant access specifier" This reverts commit 2c92f227e8220447a5a2658c758c61888d5a62a1. * Revert "fix: remove redundant access specifier" This reverts commit a0710202a8195a8617f454f21450040d8ae07813. * Revert "fix: remove redundant access specifier" This reverts commit 54da1d93972f662697a2811631d9760757319abc. * Revert "fix: remove redundant access specifier" This reverts commit f7b1777578acf0caa5f5b87af0b5715b0a0d1c1a. * Revert "fix: remove redundant access specifier" This reverts commit ad8e3dfff4a7fb41a7d14ed30759317f7f77b455. * chore: revert access specifier change
2022-04-01 19:16:33 +00:00
catch (Glib::Error const&)
{
return {};
}
}
Glib::RefPtr<Gdk::Pixbuf> _get_icon_pixbuf(Glib::RefPtr<Gio::Icon> const& icon, int size, Gtk::IconTheme& theme)
{
if (icon == nullptr)
{
return {};
}
if (auto* const ticon = dynamic_cast<Gio::ThemedIcon*>(gtr_get_ptr(icon)); ticon != nullptr)
{
return get_themed_icon_pixbuf(*ticon, size, theme);
}
if (auto* const ficon = dynamic_cast<Gio::FileIcon*>(gtr_get_ptr(icon)); ficon != nullptr)
{
return get_file_icon_pixbuf(*ficon, size);
}
return {};
}
Glib::RefPtr<Gdk::Pixbuf> icon_cache_get_mime_type_icon(IconCache& icons, Glib::ustring const& mime_type)
{
auto icon = Gio::content_type_get_icon(mime_type);
auto key = _icon_cache_get_icon_key(icon);
if (key.empty())
{
key = VoidPixbufKey;
}
if (auto pixbuf_it = icons.cache.find(key); pixbuf_it != icons.cache.end())
{
return pixbuf_it->second;
}
2009-07-27 18:48:21 +00:00
auto const pixbuf = _get_icon_pixbuf(icon, icons.icon_size, *gtr_get_ptr(icons.icon_theme));
if (pixbuf != nullptr)
{
2022-01-17 18:39:50 +00:00
icons.cache.try_emplace(key, pixbuf);
}
return pixbuf;
}
} // namespace
Glib::RefPtr<Gdk::Pixbuf> gtr_get_mime_type_icon(
Glib::ustring const& mime_type,
Gtk::IconSize icon_size,
Gtk::Widget& for_widget)
{
int n;
switch (icon_size)
{
case Gtk::ICON_SIZE_MENU:
n = 1;
break;
case Gtk::ICON_SIZE_SMALL_TOOLBAR:
n = 2;
break;
case Gtk::ICON_SIZE_LARGE_TOOLBAR:
n = 3;
break;
case Gtk::ICON_SIZE_BUTTON:
n = 4;
break;
case Gtk::ICON_SIZE_DND:
n = 5;
break;
case Gtk::ICON_SIZE_DIALOG:
n = 6;
break;
default: /*GTK_ICON_SIZE_INVALID*/
n = 0;
break;
}
if (icon_cache[n] == nullptr)
{
icon_cache[n] = icon_cache_new(for_widget, icon_size);
}
return icon_cache_get_mime_type_icon(*icon_cache[n], mime_type);
}
Glib::ustring gtr_get_mime_type_from_filename(std::string const& file)
{
bool result_uncertain;
return Gio::content_type_guess(file, {}, result_uncertain);
}