2014-11-01 02:28:17 +00:00
|
|
|
#include <string.h>
|
2014-06-24 22:36:29 +00:00
|
|
|
#include "iconbrowserapp.h"
|
|
|
|
#include "iconbrowserwin.h"
|
2015-02-22 17:30:49 +00:00
|
|
|
#include "iconstore.h"
|
2014-06-24 22:36:29 +00:00
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
2017-08-07 21:33:42 +00:00
|
|
|
/* Drag 'n Drop */
|
|
|
|
|
2014-07-27 07:32:10 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2017-06-02 01:52:50 +00:00
|
|
|
gchar *id;
|
|
|
|
gchar *name;
|
|
|
|
gchar *description;
|
2014-07-27 07:32:10 +00:00
|
|
|
} Context;
|
|
|
|
|
2017-06-02 01:52:50 +00:00
|
|
|
static void
|
|
|
|
context_free (gpointer data)
|
|
|
|
{
|
|
|
|
Context *context = data;
|
|
|
|
|
|
|
|
g_free (context->id);
|
|
|
|
g_free (context->name);
|
|
|
|
g_free (context->description);
|
|
|
|
g_free (context);
|
|
|
|
}
|
|
|
|
|
2014-06-24 22:36:29 +00:00
|
|
|
struct _IconBrowserWindow
|
|
|
|
{
|
|
|
|
GtkApplicationWindow parent;
|
|
|
|
GHashTable *contexts;
|
|
|
|
|
2014-07-27 07:32:10 +00:00
|
|
|
GtkWidget *context_list;
|
|
|
|
Context *current_context;
|
|
|
|
gboolean symbolic;
|
|
|
|
GtkWidget *symbolic_radio;
|
|
|
|
GtkTreeModelFilter *filter_model;
|
|
|
|
GtkWidget *details;
|
|
|
|
|
2014-06-24 22:36:29 +00:00
|
|
|
GtkListStore *store;
|
|
|
|
GtkCellRenderer *cell;
|
2014-07-27 11:44:41 +00:00
|
|
|
GtkCellRenderer *text_cell;
|
2014-06-24 22:36:29 +00:00
|
|
|
GtkWidget *search;
|
|
|
|
GtkWidget *searchbar;
|
|
|
|
GtkWidget *searchentry;
|
|
|
|
GtkWidget *list;
|
|
|
|
GtkWidget *image1;
|
|
|
|
GtkWidget *image2;
|
|
|
|
GtkWidget *image3;
|
|
|
|
GtkWidget *image4;
|
|
|
|
GtkWidget *image5;
|
2017-08-07 21:33:42 +00:00
|
|
|
GtkWidget *image6;
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
GtkWidget *image7;
|
|
|
|
GtkWidget *image8;
|
|
|
|
GtkWidget *label8;
|
2014-06-24 22:36:29 +00:00
|
|
|
GtkWidget *description;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _IconBrowserWindowClass
|
|
|
|
{
|
|
|
|
GtkApplicationWindowClass parent_class;
|
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE(IconBrowserWindow, icon_browser_window, GTK_TYPE_APPLICATION_WINDOW);
|
|
|
|
|
2020-02-01 22:38:49 +00:00
|
|
|
static GtkIconTheme *
|
|
|
|
icon_browser_window_get_icon_theme (IconBrowserWindow *win)
|
|
|
|
{
|
|
|
|
return gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (win)));
|
|
|
|
}
|
|
|
|
|
2014-06-24 22:36:29 +00:00
|
|
|
static void
|
2014-11-01 02:28:17 +00:00
|
|
|
search_text_changed (GtkEntry *entry, IconBrowserWindow *win)
|
2014-06-24 22:36:29 +00:00
|
|
|
{
|
|
|
|
const gchar *text;
|
|
|
|
|
2019-02-28 19:31:36 +00:00
|
|
|
text = gtk_editable_get_text (GTK_EDITABLE (entry));
|
2014-06-24 22:36:29 +00:00
|
|
|
|
|
|
|
if (text[0] == '\0')
|
|
|
|
return;
|
2014-11-01 02:28:17 +00:00
|
|
|
|
|
|
|
gtk_tree_model_filter_refilter (win->filter_model);
|
2014-06-24 22:36:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_image (GtkWidget *image, const gchar *name, gint size)
|
|
|
|
{
|
2017-11-15 00:43:13 +00:00
|
|
|
gtk_image_set_from_icon_name (GTK_IMAGE (image), name);
|
2014-06-24 22:36:29 +00:00
|
|
|
gtk_image_set_pixel_size (GTK_IMAGE (image), size);
|
|
|
|
}
|
|
|
|
|
2014-07-27 07:32:10 +00:00
|
|
|
static void
|
|
|
|
item_activated (GtkIconView *icon_view, GtkTreePath *path, IconBrowserWindow *win)
|
2014-06-24 22:36:29 +00:00
|
|
|
{
|
2020-02-01 22:38:49 +00:00
|
|
|
GtkIconTheme *icon_theme = icon_browser_window_get_icon_theme (win);
|
2014-06-24 22:36:29 +00:00
|
|
|
GtkTreeIter iter;
|
2014-07-27 07:32:10 +00:00
|
|
|
gchar *name;
|
|
|
|
gchar *description;
|
2014-07-27 11:44:41 +00:00
|
|
|
gint column;
|
2014-07-27 07:32:10 +00:00
|
|
|
|
|
|
|
gtk_tree_model_get_iter (GTK_TREE_MODEL (win->filter_model), &iter, path);
|
|
|
|
|
2014-07-27 11:44:41 +00:00
|
|
|
if (win->symbolic)
|
2015-02-22 17:30:49 +00:00
|
|
|
column = ICON_STORE_SYMBOLIC_NAME_COLUMN;
|
2014-07-27 11:44:41 +00:00
|
|
|
else
|
2015-02-22 17:30:49 +00:00
|
|
|
column = ICON_STORE_NAME_COLUMN;
|
2014-07-27 07:32:10 +00:00
|
|
|
gtk_tree_model_get (GTK_TREE_MODEL (win->filter_model), &iter,
|
2014-07-27 11:44:41 +00:00
|
|
|
column, &name,
|
2015-02-22 17:30:49 +00:00
|
|
|
ICON_STORE_DESCRIPTION_COLUMN, &description,
|
2014-07-27 07:32:10 +00:00
|
|
|
-1);
|
2015-02-22 19:42:26 +00:00
|
|
|
|
2020-02-01 22:38:49 +00:00
|
|
|
if (name == NULL || !gtk_icon_theme_has_icon (icon_theme, name))
|
2014-07-27 07:32:10 +00:00
|
|
|
{
|
2014-07-27 11:44:41 +00:00
|
|
|
g_free (description);
|
|
|
|
return;
|
2014-07-27 07:32:10 +00:00
|
|
|
}
|
2014-06-24 22:36:29 +00:00
|
|
|
|
2014-07-27 11:44:41 +00:00
|
|
|
gtk_window_set_title (GTK_WINDOW (win->details), name);
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
set_image (win->image1, name, 8);
|
|
|
|
set_image (win->image2, name, 16);
|
|
|
|
set_image (win->image3, name, 18);
|
|
|
|
set_image (win->image4, name, 24);
|
|
|
|
set_image (win->image5, name, 32);
|
|
|
|
set_image (win->image6, name, 48);
|
|
|
|
set_image (win->image7, name, 64);
|
2017-08-07 21:33:42 +00:00
|
|
|
if (win->symbolic)
|
|
|
|
{
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
gtk_widget_show (win->image8);
|
|
|
|
gtk_widget_show (win->label8);
|
|
|
|
set_image (win->image8, name, 64);
|
2017-08-07 21:33:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
gtk_widget_hide (win->image8);
|
|
|
|
gtk_widget_hide (win->label8);
|
2017-08-07 21:33:42 +00:00
|
|
|
}
|
2014-07-29 12:57:28 +00:00
|
|
|
if (description && description[0])
|
|
|
|
{
|
|
|
|
gtk_label_set_text (GTK_LABEL (win->description), description);
|
|
|
|
gtk_widget_show (win->description);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gtk_widget_hide (win->description);
|
|
|
|
}
|
2014-07-27 07:32:10 +00:00
|
|
|
|
|
|
|
gtk_window_present (GTK_WINDOW (win->details));
|
|
|
|
|
|
|
|
g_free (name);
|
|
|
|
g_free (description);
|
2014-06-24 22:36:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
add_icon (IconBrowserWindow *win,
|
|
|
|
const gchar *name,
|
|
|
|
const gchar *description,
|
|
|
|
const gchar *context)
|
|
|
|
{
|
2020-02-01 22:38:49 +00:00
|
|
|
GtkIconTheme *icon_theme = icon_browser_window_get_icon_theme (win);
|
2014-07-27 07:32:10 +00:00
|
|
|
gchar *regular_name;
|
|
|
|
gchar *symbolic_name;
|
|
|
|
|
|
|
|
regular_name = g_strdup (name);
|
2020-02-01 22:38:49 +00:00
|
|
|
if (!gtk_icon_theme_has_icon (icon_theme, regular_name))
|
2014-07-27 07:32:10 +00:00
|
|
|
{
|
|
|
|
g_free (regular_name);
|
|
|
|
regular_name = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
symbolic_name = g_strconcat (name, "-symbolic", NULL);
|
2020-02-01 22:38:49 +00:00
|
|
|
if (!gtk_icon_theme_has_icon (icon_theme, symbolic_name))
|
2014-07-27 07:32:10 +00:00
|
|
|
{
|
|
|
|
g_free (symbolic_name);
|
|
|
|
symbolic_name = NULL;
|
|
|
|
}
|
2017-06-02 01:52:50 +00:00
|
|
|
|
2014-07-27 07:32:10 +00:00
|
|
|
gtk_list_store_insert_with_values (win->store, NULL, -1,
|
2015-02-22 17:30:49 +00:00
|
|
|
ICON_STORE_NAME_COLUMN, regular_name,
|
|
|
|
ICON_STORE_SYMBOLIC_NAME_COLUMN, symbolic_name,
|
|
|
|
ICON_STORE_DESCRIPTION_COLUMN, description,
|
|
|
|
ICON_STORE_CONTEXT_COLUMN, context,
|
2014-07-27 07:32:10 +00:00
|
|
|
-1);
|
2014-06-24 22:36:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
add_context (IconBrowserWindow *win,
|
|
|
|
const gchar *id,
|
|
|
|
const gchar *name,
|
|
|
|
const gchar *description)
|
|
|
|
{
|
|
|
|
Context *c;
|
2014-07-27 07:32:10 +00:00
|
|
|
GtkWidget *row;
|
2014-06-24 22:36:29 +00:00
|
|
|
|
|
|
|
c = g_new (Context, 1);
|
2017-06-02 01:52:50 +00:00
|
|
|
c->id = g_strdup (id);
|
|
|
|
c->name = g_strdup (name);
|
|
|
|
c->description = g_strdup (description);
|
2014-06-24 22:36:29 +00:00
|
|
|
|
2017-06-02 01:52:50 +00:00
|
|
|
g_hash_table_insert (win->contexts, c->id, c);
|
2014-07-27 07:32:10 +00:00
|
|
|
|
|
|
|
row = gtk_label_new (name);
|
2019-04-17 01:00:47 +00:00
|
|
|
gtk_label_set_xalign (GTK_LABEL (row), 0);
|
2014-07-27 07:32:10 +00:00
|
|
|
g_object_set_data (G_OBJECT (row), "context", c);
|
|
|
|
gtk_widget_show (row);
|
2020-02-26 01:57:20 +00:00
|
|
|
gtk_widget_set_margin_start (row, 10);
|
|
|
|
gtk_widget_set_margin_end (row, 10);
|
|
|
|
gtk_widget_set_margin_top (row, 10);
|
|
|
|
gtk_widget_set_margin_bottom (row, 10);
|
2014-07-27 07:32:10 +00:00
|
|
|
|
|
|
|
gtk_list_box_insert (GTK_LIST_BOX (win->context_list), row, -1);
|
|
|
|
|
2014-08-02 11:55:44 +00:00
|
|
|
/* set the tooltip on the list box row */
|
|
|
|
row = gtk_widget_get_parent (row);
|
|
|
|
gtk_widget_set_tooltip_text (row, description);
|
|
|
|
|
2014-07-27 07:32:10 +00:00
|
|
|
if (win->current_context == NULL)
|
|
|
|
win->current_context = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
selected_context_changed (GtkListBox *list, IconBrowserWindow *win)
|
|
|
|
{
|
|
|
|
GtkWidget *row;
|
|
|
|
GtkWidget *label;
|
|
|
|
|
|
|
|
row = GTK_WIDGET (gtk_list_box_get_selected_row (list));
|
2014-07-29 12:50:10 +00:00
|
|
|
if (row == NULL)
|
|
|
|
return;
|
|
|
|
|
2014-11-01 02:28:17 +00:00
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (win->search), FALSE);
|
|
|
|
|
2014-07-27 07:32:10 +00:00
|
|
|
label = gtk_bin_get_child (GTK_BIN (row));
|
|
|
|
win->current_context = g_object_get_data (G_OBJECT (label), "context");
|
|
|
|
gtk_tree_model_filter_refilter (win->filter_model);
|
2014-06-24 22:36:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
populate (IconBrowserWindow *win)
|
|
|
|
{
|
2017-06-02 01:52:50 +00:00
|
|
|
GFile *file;
|
|
|
|
GKeyFile *kf;
|
|
|
|
char *data;
|
|
|
|
gsize length;
|
|
|
|
char **groups;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
file = g_file_new_for_uri ("resource:/org/gtk/iconbrowser/gtk/icon.list");
|
|
|
|
g_file_load_contents (file, NULL, &data, &length, NULL, NULL);
|
|
|
|
|
|
|
|
kf = g_key_file_new ();
|
|
|
|
g_key_file_load_from_data (kf, data, length, G_KEY_FILE_NONE, NULL);
|
|
|
|
|
|
|
|
groups = g_key_file_get_groups (kf, &length);
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
{
|
|
|
|
const char *context;
|
|
|
|
const char *name;
|
|
|
|
const char *description;
|
|
|
|
char **keys;
|
|
|
|
gsize len;
|
|
|
|
int j;
|
|
|
|
|
|
|
|
context = groups[i];
|
|
|
|
name = g_key_file_get_string (kf, context, "Name", NULL);
|
|
|
|
description = g_key_file_get_string (kf, context, "Description", NULL);
|
|
|
|
add_context (win, context, name, description);
|
|
|
|
|
|
|
|
keys = g_key_file_get_keys (kf, context, &len, NULL);
|
|
|
|
for (j = 0; j < len; j++)
|
|
|
|
{
|
|
|
|
const char *key = keys[j];
|
|
|
|
const char *value;
|
|
|
|
|
|
|
|
if (strcmp (key, "Name") == 0 || strcmp (key, "Description") == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
value = g_key_file_get_string (kf, context, key, NULL);
|
|
|
|
|
|
|
|
add_icon (win, key, value, context);
|
|
|
|
}
|
|
|
|
g_strfreev (keys);
|
|
|
|
}
|
|
|
|
g_strfreev (groups);
|
2014-06-24 22:36:29 +00:00
|
|
|
}
|
|
|
|
|
2017-06-02 19:39:39 +00:00
|
|
|
static void
|
|
|
|
copy_to_clipboard (GtkButton *button,
|
|
|
|
IconBrowserWindow *win)
|
|
|
|
{
|
2017-12-02 14:41:22 +00:00
|
|
|
GdkClipboard *clipboard;
|
2017-06-02 19:39:39 +00:00
|
|
|
|
2017-12-02 14:41:22 +00:00
|
|
|
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (win));
|
|
|
|
gdk_clipboard_set_text (clipboard, gtk_window_get_title (GTK_WINDOW (win->details)));
|
2017-06-02 19:39:39 +00:00
|
|
|
}
|
|
|
|
|
2014-07-27 07:32:10 +00:00
|
|
|
static gboolean
|
|
|
|
icon_visible_func (GtkTreeModel *model,
|
|
|
|
GtkTreeIter *iter,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
IconBrowserWindow *win = data;
|
|
|
|
gchar *context;
|
|
|
|
gchar *name;
|
|
|
|
gint column;
|
2014-11-01 02:28:17 +00:00
|
|
|
gboolean search;
|
|
|
|
const gchar *search_text;
|
2014-07-27 07:32:10 +00:00
|
|
|
gboolean visible;
|
|
|
|
|
2014-11-01 02:28:17 +00:00
|
|
|
search = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (win->search));
|
2019-02-28 19:31:36 +00:00
|
|
|
search_text = gtk_editable_get_text (GTK_EDITABLE (win->searchentry));
|
2014-11-01 02:28:17 +00:00
|
|
|
|
2014-07-27 07:32:10 +00:00
|
|
|
if (win->symbolic)
|
2015-02-22 17:30:49 +00:00
|
|
|
column = ICON_STORE_SYMBOLIC_NAME_COLUMN;
|
2014-07-27 07:32:10 +00:00
|
|
|
else
|
2015-02-22 17:30:49 +00:00
|
|
|
column = ICON_STORE_NAME_COLUMN;
|
2014-07-27 07:32:10 +00:00
|
|
|
|
|
|
|
gtk_tree_model_get (model, iter,
|
|
|
|
column, &name,
|
2015-02-22 17:30:49 +00:00
|
|
|
ICON_STORE_CONTEXT_COLUMN, &context,
|
2014-07-27 07:32:10 +00:00
|
|
|
-1);
|
2014-11-01 02:28:17 +00:00
|
|
|
if (!name)
|
|
|
|
visible = FALSE;
|
|
|
|
else if (search)
|
|
|
|
visible = strstr (name, search_text) != NULL;
|
|
|
|
else
|
|
|
|
visible = win->current_context != NULL && g_strcmp0 (context, win->current_context->id) == 0;
|
2014-07-27 07:32:10 +00:00
|
|
|
|
|
|
|
g_free (name);
|
|
|
|
g_free (context);
|
|
|
|
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
symbolic_toggled (GtkToggleButton *toggle, IconBrowserWindow *win)
|
|
|
|
{
|
2014-07-27 11:44:41 +00:00
|
|
|
gint column;
|
|
|
|
|
2014-07-27 07:32:10 +00:00
|
|
|
win->symbolic = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle));
|
2014-07-27 11:44:41 +00:00
|
|
|
|
|
|
|
if (win->symbolic)
|
2015-02-22 17:30:49 +00:00
|
|
|
column = ICON_STORE_SYMBOLIC_NAME_COLUMN;
|
2014-07-27 11:44:41 +00:00
|
|
|
else
|
2015-02-22 17:30:49 +00:00
|
|
|
column = ICON_STORE_NAME_COLUMN;
|
|
|
|
|
|
|
|
icon_store_set_text_column (ICON_STORE (win->store), column);
|
2014-07-27 11:44:41 +00:00
|
|
|
|
|
|
|
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (win->list), win->cell, "icon-name", column, NULL);
|
|
|
|
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (win->list), win->text_cell, "text", column, NULL);
|
2017-06-02 01:52:50 +00:00
|
|
|
|
2014-07-27 07:32:10 +00:00
|
|
|
gtk_tree_model_filter_refilter (win->filter_model);
|
|
|
|
gtk_widget_queue_draw (win->list);
|
|
|
|
}
|
|
|
|
|
2014-11-01 02:28:17 +00:00
|
|
|
static void
|
|
|
|
search_mode_toggled (GObject *searchbar, GParamSpec *pspec, IconBrowserWindow *win)
|
|
|
|
{
|
|
|
|
if (gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (searchbar)))
|
|
|
|
gtk_list_box_unselect_all (GTK_LIST_BOX (win->context_list));
|
|
|
|
}
|
|
|
|
|
2020-01-01 02:06:43 +00:00
|
|
|
static GdkPaintable *
|
|
|
|
get_image_paintable (GtkImage *image)
|
|
|
|
{
|
|
|
|
const gchar *icon_name;
|
|
|
|
GtkIconTheme *icon_theme;
|
2020-02-04 16:19:22 +00:00
|
|
|
GtkIconPaintable *icon;
|
2020-01-01 02:06:43 +00:00
|
|
|
int size;
|
|
|
|
|
|
|
|
switch (gtk_image_get_storage_type (image))
|
|
|
|
{
|
|
|
|
case GTK_IMAGE_PAINTABLE:
|
|
|
|
return g_object_ref (gtk_image_get_paintable (image));
|
|
|
|
case GTK_IMAGE_ICON_NAME:
|
|
|
|
icon_name = gtk_image_get_icon_name (image);
|
|
|
|
size = gtk_image_get_pixel_size (image);
|
|
|
|
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (image)));
|
2020-02-01 23:27:14 +00:00
|
|
|
icon = gtk_icon_theme_lookup_icon (icon_theme,
|
|
|
|
icon_name,
|
2020-02-04 02:53:22 +00:00
|
|
|
NULL,
|
2020-02-01 23:27:14 +00:00
|
|
|
size, 1,
|
|
|
|
gtk_widget_get_direction (GTK_WIDGET (image)),
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
0);
|
2020-01-30 09:52:09 +00:00
|
|
|
if (icon == NULL)
|
2020-01-01 02:06:43 +00:00
|
|
|
return NULL;
|
2020-01-30 09:52:09 +00:00
|
|
|
return GDK_PAINTABLE (icon);
|
2020-03-06 17:53:05 +00:00
|
|
|
case GTK_IMAGE_GICON:
|
|
|
|
case GTK_IMAGE_EMPTY:
|
2020-01-01 02:06:43 +00:00
|
|
|
default:
|
|
|
|
g_warning ("Image storage type %d not handled",
|
|
|
|
gtk_image_get_storage_type (image));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-22 19:42:26 +00:00
|
|
|
static void
|
2020-01-01 02:06:43 +00:00
|
|
|
drag_begin (GtkDragSource *source,
|
2020-01-06 18:28:25 +00:00
|
|
|
GdkDrag *drag,
|
2020-01-01 02:06:43 +00:00
|
|
|
GtkWidget *widget)
|
2015-02-22 19:42:26 +00:00
|
|
|
{
|
2020-01-01 02:06:43 +00:00
|
|
|
GdkPaintable *paintable;
|
2015-02-22 19:42:26 +00:00
|
|
|
|
2020-01-01 02:06:43 +00:00
|
|
|
paintable = get_image_paintable (GTK_IMAGE (widget));
|
|
|
|
if (paintable)
|
|
|
|
{
|
|
|
|
int w, h;
|
2015-02-22 19:42:26 +00:00
|
|
|
|
2020-01-01 02:06:43 +00:00
|
|
|
w = gdk_paintable_get_intrinsic_width (paintable);
|
|
|
|
h = gdk_paintable_get_intrinsic_height (paintable);
|
|
|
|
gtk_drag_source_set_icon (source, paintable, w, h);
|
|
|
|
g_object_unref (paintable);
|
|
|
|
}
|
|
|
|
}
|
2015-02-22 19:42:26 +00:00
|
|
|
|
2020-02-16 15:22:37 +00:00
|
|
|
static GdkContentProvider *
|
|
|
|
drag_prepare_texture (GtkDragSource *source,
|
|
|
|
double x,
|
|
|
|
double y,
|
|
|
|
GtkWidget *widget)
|
2020-01-01 02:06:43 +00:00
|
|
|
{
|
2020-02-16 15:22:37 +00:00
|
|
|
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (widget));
|
|
|
|
|
|
|
|
if (!GDK_IS_TEXTURE (paintable))
|
|
|
|
return NULL;
|
2020-01-01 02:06:43 +00:00
|
|
|
|
2020-02-16 15:22:37 +00:00
|
|
|
return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, paintable);
|
2015-02-22 19:42:26 +00:00
|
|
|
}
|
|
|
|
|
2020-02-16 15:22:37 +00:00
|
|
|
static GdkContentProvider *
|
|
|
|
drag_prepare_file (GtkDragSource *source,
|
|
|
|
double x,
|
|
|
|
double y,
|
|
|
|
GtkWidget *widget)
|
2017-08-07 21:33:42 +00:00
|
|
|
{
|
2020-02-16 15:22:37 +00:00
|
|
|
GdkContentProvider *content;
|
2020-02-01 22:38:49 +00:00
|
|
|
GtkIconTheme *icon_theme;
|
2020-01-01 02:06:43 +00:00
|
|
|
const char *name;
|
2020-02-04 16:19:22 +00:00
|
|
|
GtkIconPaintable *info;
|
2017-08-07 21:33:42 +00:00
|
|
|
|
2020-02-16 15:22:37 +00:00
|
|
|
name = gtk_image_get_icon_name (GTK_IMAGE (widget));
|
|
|
|
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget));
|
2017-08-07 21:33:42 +00:00
|
|
|
|
2020-02-01 23:27:14 +00:00
|
|
|
info = gtk_icon_theme_lookup_icon (icon_theme,
|
|
|
|
name,
|
2020-02-04 02:53:22 +00:00
|
|
|
NULL,
|
2020-02-01 23:27:14 +00:00
|
|
|
32, 1,
|
2020-02-16 15:22:37 +00:00
|
|
|
gtk_widget_get_direction (widget),
|
2020-02-01 23:27:14 +00:00
|
|
|
0);
|
2020-02-16 15:22:37 +00:00
|
|
|
content = gdk_content_provider_new_typed (G_TYPE_FILE, gtk_icon_paintable_get_file (info));
|
2020-01-01 02:06:43 +00:00
|
|
|
g_object_unref (info);
|
2020-02-16 15:22:37 +00:00
|
|
|
|
|
|
|
return content;
|
2017-08-07 21:33:42 +00:00
|
|
|
}
|
|
|
|
|
2015-02-22 19:42:26 +00:00
|
|
|
static void
|
|
|
|
setup_image_dnd (GtkWidget *image)
|
|
|
|
{
|
2020-01-01 02:06:43 +00:00
|
|
|
GtkDragSource *source;
|
|
|
|
|
2020-01-06 19:46:14 +00:00
|
|
|
source = gtk_drag_source_new ();
|
2020-02-16 15:22:37 +00:00
|
|
|
g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare_texture), image);
|
2020-01-01 02:06:43 +00:00
|
|
|
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
|
2020-01-07 06:07:02 +00:00
|
|
|
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
|
2015-02-22 19:42:26 +00:00
|
|
|
}
|
|
|
|
|
2017-08-07 21:33:42 +00:00
|
|
|
static void
|
|
|
|
setup_scalable_image_dnd (GtkWidget *image)
|
|
|
|
{
|
2020-01-01 02:06:43 +00:00
|
|
|
GtkDragSource *source;
|
2017-08-07 21:33:42 +00:00
|
|
|
|
2020-01-06 19:46:14 +00:00
|
|
|
source = gtk_drag_source_new ();
|
2020-02-16 15:22:37 +00:00
|
|
|
g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare_file), image);
|
2020-01-01 02:06:43 +00:00
|
|
|
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
|
2020-01-07 06:07:02 +00:00
|
|
|
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
|
2017-08-07 21:33:42 +00:00
|
|
|
}
|
|
|
|
|
2014-06-24 22:36:29 +00:00
|
|
|
static void
|
|
|
|
icon_browser_window_init (IconBrowserWindow *win)
|
|
|
|
{
|
2017-11-18 01:19:53 +00:00
|
|
|
GdkContentFormats *list;
|
2015-02-22 17:30:49 +00:00
|
|
|
|
2014-06-24 22:36:29 +00:00
|
|
|
gtk_widget_init_template (GTK_WIDGET (win));
|
|
|
|
|
2020-01-07 05:44:50 +00:00
|
|
|
list = gdk_content_formats_new_for_gtype (G_TYPE_STRING);
|
2015-02-22 17:30:49 +00:00
|
|
|
gtk_icon_view_enable_model_drag_source (GTK_ICON_VIEW (win->list),
|
|
|
|
GDK_BUTTON1_MASK,
|
2017-11-14 21:32:23 +00:00
|
|
|
list,
|
2015-02-22 17:30:49 +00:00
|
|
|
GDK_ACTION_COPY);
|
2017-11-18 01:19:53 +00:00
|
|
|
gdk_content_formats_unref (list);
|
2015-02-22 17:30:49 +00:00
|
|
|
|
2015-02-22 19:42:26 +00:00
|
|
|
setup_image_dnd (win->image1);
|
|
|
|
setup_image_dnd (win->image2);
|
|
|
|
setup_image_dnd (win->image3);
|
|
|
|
setup_image_dnd (win->image4);
|
|
|
|
setup_image_dnd (win->image5);
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
setup_image_dnd (win->image6);
|
|
|
|
setup_image_dnd (win->image7);
|
|
|
|
setup_scalable_image_dnd (win->image8);
|
2015-02-22 19:42:26 +00:00
|
|
|
|
2017-06-02 01:52:50 +00:00
|
|
|
win->contexts = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, context_free);
|
2014-06-24 22:36:29 +00:00
|
|
|
|
2014-07-27 07:32:10 +00:00
|
|
|
gtk_tree_model_filter_set_visible_func (win->filter_model, icon_visible_func, win, NULL);
|
|
|
|
gtk_window_set_transient_for (GTK_WINDOW (win->details), GTK_WINDOW (win));
|
|
|
|
|
2014-11-01 02:28:17 +00:00
|
|
|
g_signal_connect (win->searchbar, "notify::search-mode-enabled",
|
|
|
|
G_CALLBACK (search_mode_toggled), win);
|
2019-04-03 11:18:37 +00:00
|
|
|
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (win->searchbar),
|
|
|
|
GTK_WIDGET (win));
|
2014-11-01 02:28:17 +00:00
|
|
|
|
2014-07-27 11:44:41 +00:00
|
|
|
symbolic_toggled (GTK_TOGGLE_BUTTON (win->symbolic_radio), win);
|
|
|
|
|
2014-06-24 22:36:29 +00:00
|
|
|
populate (win);
|
|
|
|
}
|
|
|
|
|
2018-02-04 21:21:37 +00:00
|
|
|
static void
|
|
|
|
icon_browser_window_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
IconBrowserWindow *win = ICON_BROWSER_WINDOW (object);
|
|
|
|
|
|
|
|
g_hash_table_unref (win->contexts);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (icon_browser_window_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
2014-06-24 22:36:29 +00:00
|
|
|
static void
|
|
|
|
icon_browser_window_class_init (IconBrowserWindowClass *class)
|
|
|
|
{
|
2018-02-04 21:21:37 +00:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
|
|
|
|
|
|
object_class->finalize = icon_browser_window_finalize;
|
|
|
|
|
2015-02-22 17:30:49 +00:00
|
|
|
g_type_ensure (ICON_STORE_TYPE);
|
|
|
|
|
2014-06-24 22:36:29 +00:00
|
|
|
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
|
2016-01-25 01:01:33 +00:00
|
|
|
"/org/gtk/iconbrowser/gtk/window.ui");
|
2014-06-24 22:36:29 +00:00
|
|
|
|
2014-07-27 07:32:10 +00:00
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, context_list);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, filter_model);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, symbolic_radio);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, details);
|
|
|
|
|
2014-06-24 22:36:29 +00:00
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, store);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, cell);
|
2014-07-27 11:44:41 +00:00
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, text_cell);
|
2014-06-24 22:36:29 +00:00
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, search);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, searchbar);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, searchentry);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, list);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image1);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image2);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image3);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image4);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image5);
|
2017-08-07 21:33:42 +00:00
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image6);
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image7);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image8);
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, label8);
|
2014-06-24 22:36:29 +00:00
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, description);
|
|
|
|
|
|
|
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), search_text_changed);
|
2014-07-27 07:32:10 +00:00
|
|
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), item_activated);
|
|
|
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), selected_context_changed);
|
|
|
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), symbolic_toggled);
|
2017-06-02 19:39:39 +00:00
|
|
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), copy_to_clipboard);
|
2014-06-24 22:36:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
IconBrowserWindow *
|
|
|
|
icon_browser_window_new (IconBrowserApp *app)
|
|
|
|
{
|
|
|
|
return g_object_new (ICON_BROWSER_WINDOW_TYPE, "application", app, NULL);
|
|
|
|
}
|