Load symbolic icons as a fallback
Now there are no missing items in the browsers.
This commit is contained in:
parent
6eb78f1a5c
commit
3e9a388537
|
@ -67,6 +67,7 @@ static const int g_item_spacing = 1;
|
||||||
struct entry {
|
struct entry {
|
||||||
char *filename; ///< Absolute path
|
char *filename; ///< Absolute path
|
||||||
cairo_surface_t *thumbnail; ///< Prescaled thumbnail
|
cairo_surface_t *thumbnail; ///< Prescaled thumbnail
|
||||||
|
GIcon *icon; ///< If no thumbnail, use this icon
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -75,6 +76,7 @@ entry_free(Entry *self)
|
||||||
g_free(self->filename);
|
g_free(self->filename);
|
||||||
if (self->thumbnail)
|
if (self->thumbnail)
|
||||||
cairo_surface_destroy(self->thumbnail);
|
cairo_surface_destroy(self->thumbnail);
|
||||||
|
g_clear_object(&self->icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -244,10 +246,15 @@ draw_row(FastivBrowser *self, cairo_t *cr, const Row *row)
|
||||||
GdkRectangle extents = item_extents(item, row);
|
GdkRectangle extents = item_extents(item, row);
|
||||||
cairo_translate(cr, extents.x - border.left, extents.y - border.top);
|
cairo_translate(cr, extents.x - border.left, extents.y - border.top);
|
||||||
|
|
||||||
gdk_cairo_set_source_rgba(cr, &glow_color);
|
gtk_style_context_save(style);
|
||||||
draw_outer_border(self, cr,
|
if (item->entry->icon) {
|
||||||
border.left + extents.width + border.right,
|
gtk_style_context_add_class(style, "symbolic");
|
||||||
border.top + extents.height + border.bottom);
|
} else {
|
||||||
|
gdk_cairo_set_source_rgba(cr, &glow_color);
|
||||||
|
draw_outer_border(self, cr,
|
||||||
|
border.left + extents.width + border.right,
|
||||||
|
border.top + extents.height + border.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
gtk_render_background(
|
gtk_render_background(
|
||||||
style, cr, border.left, border.top, extents.width, extents.height);
|
style, cr, border.left, border.top, extents.width, extents.height);
|
||||||
|
@ -256,10 +263,20 @@ draw_row(FastivBrowser *self, cairo_t *cr, const Row *row)
|
||||||
border.left + extents.width + border.right,
|
border.left + extents.width + border.right,
|
||||||
border.top + extents.height + border.bottom);
|
border.top + extents.height + border.bottom);
|
||||||
|
|
||||||
cairo_set_source_surface(
|
if (item->entry->icon) {
|
||||||
cr, item->entry->thumbnail, border.left, border.top);
|
GdkRGBA color = {};
|
||||||
cairo_paint(cr);
|
gtk_style_context_get_color(style, state, &color);
|
||||||
|
gdk_cairo_set_source_rgba(cr, &color);
|
||||||
|
cairo_mask_surface(
|
||||||
|
cr, item->entry->thumbnail, border.left, border.top);
|
||||||
|
} else {
|
||||||
|
cairo_set_source_surface(
|
||||||
|
cr, item->entry->thumbnail, border.left, border.top);
|
||||||
|
cairo_paint(cr);
|
||||||
|
}
|
||||||
|
|
||||||
cairo_restore(cr);
|
cairo_restore(cr);
|
||||||
|
gtk_style_context_restore(style);
|
||||||
}
|
}
|
||||||
gtk_style_context_restore(style);
|
gtk_style_context_restore(style);
|
||||||
}
|
}
|
||||||
|
@ -590,6 +607,23 @@ entry_add_thumbnail(gpointer data, G_GNUC_UNUSED gpointer user_data)
|
||||||
Entry *self = data;
|
Entry *self = data;
|
||||||
self->thumbnail =
|
self->thumbnail =
|
||||||
rescale_thumbnail(fastiv_io_lookup_thumbnail(self->filename));
|
rescale_thumbnail(fastiv_io_lookup_thumbnail(self->filename));
|
||||||
|
if (self->thumbnail)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Fall back to symbolic icons, though there's only so much we can do
|
||||||
|
// in parallel--GTK+ isn't thread-safe.
|
||||||
|
GFile *file = g_file_new_for_path(self->filename);
|
||||||
|
GFileInfo *info = g_file_query_info(file,
|
||||||
|
G_FILE_ATTRIBUTE_STANDARD_NAME
|
||||||
|
"," G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON,
|
||||||
|
G_FILE_QUERY_INFO_NONE, NULL, NULL);
|
||||||
|
g_object_unref(file);
|
||||||
|
if (info) {
|
||||||
|
GIcon *icon = g_file_info_get_symbolic_icon(info);
|
||||||
|
if (icon)
|
||||||
|
self->icon = g_object_ref(icon);
|
||||||
|
g_object_unref(info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -619,6 +653,50 @@ fastiv_browser_load(FastivBrowser *self, const char *path)
|
||||||
g_thread_pool_push(pool, &g_array_index(self->entries, Entry, i), NULL);
|
g_thread_pool_push(pool, &g_array_index(self->entries, Entry, i), NULL);
|
||||||
g_thread_pool_free(pool, FALSE, TRUE);
|
g_thread_pool_free(pool, FALSE, TRUE);
|
||||||
|
|
||||||
// TODO(p): Sort the entries.
|
for (guint i = 0; i < self->entries->len; i++) {
|
||||||
|
Entry *entry = &g_array_index(self->entries, Entry, i);
|
||||||
|
if (!entry->icon)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Fucker will still give us non-symbolic icons, no more playing nice.
|
||||||
|
// TODO(p): Investigate a bit closer. We may want to abandon the idea
|
||||||
|
// of using GLib to look up icons for us, derive a list from a guessed
|
||||||
|
// MIME type, with "-symbolic" prefixes and fallbacks,
|
||||||
|
// and use gtk_icon_theme_choose_icon() instead.
|
||||||
|
// TODO(p): Make sure we have /some/ icon for every entry.
|
||||||
|
// TODO(p): GtkSettings -> notify::gtk-icon-theme-name?
|
||||||
|
// TODO(p): We might want to populate these on an as-needed basis.
|
||||||
|
GtkIconInfo *icon_info =
|
||||||
|
gtk_icon_theme_lookup_by_gicon(gtk_icon_theme_get_default(),
|
||||||
|
entry->icon, g_row_height / 2, GTK_ICON_LOOKUP_FORCE_SYMBOLIC);
|
||||||
|
if (!icon_info)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Bílá, bílá, bílá, bílá... komu by se nelíbí-lá...
|
||||||
|
// We do not want any highlights, nor do we want to remember the style.
|
||||||
|
const GdkRGBA white = {1, 1, 1, 1};
|
||||||
|
GdkPixbuf *pixbuf = gtk_icon_info_load_symbolic(
|
||||||
|
icon_info, &white, &white, &white, &white, NULL, NULL);
|
||||||
|
if (pixbuf) {
|
||||||
|
int outer_size = g_row_height;
|
||||||
|
entry->thumbnail = cairo_image_surface_create(
|
||||||
|
CAIRO_FORMAT_A8, outer_size, outer_size);
|
||||||
|
|
||||||
|
// "Note that the resulting pixbuf may not be exactly this size;"
|
||||||
|
// though GTK_ICON_LOOKUP_FORCE_SIZE is also an option.
|
||||||
|
int x = (outer_size - gdk_pixbuf_get_width(pixbuf)) / 2;
|
||||||
|
int y = (outer_size - gdk_pixbuf_get_height(pixbuf)) / 2;
|
||||||
|
|
||||||
|
cairo_t *cr = cairo_create(entry->thumbnail);
|
||||||
|
gdk_cairo_set_source_pixbuf(cr, pixbuf, x, y);
|
||||||
|
cairo_paint(cr);
|
||||||
|
cairo_destroy(cr);
|
||||||
|
|
||||||
|
g_object_unref(pixbuf);
|
||||||
|
}
|
||||||
|
g_object_unref(icon_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(p): Sort and filter the entries.
|
||||||
gtk_widget_queue_resize(GTK_WIDGET(self));
|
gtk_widget_queue_resize(GTK_WIDGET(self));
|
||||||
}
|
}
|
||||||
|
|
6
fastiv.c
6
fastiv.c
|
@ -489,7 +489,7 @@ main(int argc, char *argv[])
|
||||||
fastiv-view, fastiv-browser { background: #222; } \
|
fastiv-view, fastiv-browser { background: #222; } \
|
||||||
fastiv-browser { padding: 5px; } \
|
fastiv-browser { padding: 5px; } \
|
||||||
fastiv-browser.item { \
|
fastiv-browser.item { \
|
||||||
border: 1px solid rgba(255, 255, 255, 0.5); \
|
border: 1px solid rgba(255, 255, 255, 0.375); \
|
||||||
margin: 10px; color: #000; \
|
margin: 10px; color: #000; \
|
||||||
background: #333; \
|
background: #333; \
|
||||||
background-image: \
|
background-image: \
|
||||||
|
@ -499,6 +499,10 @@ main(int argc, char *argv[])
|
||||||
linear-gradient(-45deg, transparent 74%, @fastiv-tile 74%); \
|
linear-gradient(-45deg, transparent 74%, @fastiv-tile 74%); \
|
||||||
background-size: 40px 40px; \
|
background-size: 40px 40px; \
|
||||||
background-position: 0 0, 0 20px, 20px -20px, -20px 0px; \
|
background-position: 0 0, 0 20px, 20px -20px, -20px 0px; \
|
||||||
|
} \
|
||||||
|
fastiv-browser.item.symbolic { \
|
||||||
|
border-color: transparent; color: #222; \
|
||||||
|
background: #2c2c2c; background-image: none; \
|
||||||
}";
|
}";
|
||||||
|
|
||||||
GtkCssProvider *provider = gtk_css_provider_new();
|
GtkCssProvider *provider = gtk_css_provider_new();
|
||||||
|
|
Loading…
Reference in New Issue