Port the icon browser to GtkGridView

This commit is contained in:
Matthias Clasen 2020-06-08 14:25:54 -04:00
parent 511e5f39fa
commit 607f08e79b
9 changed files with 643 additions and 416 deletions

View File

@ -0,0 +1,156 @@
#include "iconbrowsercontext.h"
struct _IbContext
{
GObject parent_instance;
char *id;
char *name;
char *description;
};
struct _IbContextClass
{
GObjectClass parent_class;
};
enum {
PROP_ID = 1,
PROP_NAME,
PROP_DESCRIPTION,
PROP_NUM_PROPERTIES
};
G_DEFINE_TYPE (IbContext, ib_context, G_TYPE_OBJECT)
static void
ib_context_init (IbContext *context)
{
}
static void
ib_context_finalize (GObject *object)
{
IbContext *context = IB_CONTEXT (object);
g_free (context->id);
g_free (context->name);
g_free (context->description);
G_OBJECT_CLASS (ib_context_parent_class)->finalize (object);
}
static void
ib_context_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
IbContext *context = IB_CONTEXT (object);
switch (property_id)
{
case PROP_ID:
g_free (context->id);
context->id = g_value_dup_string (value);
break;
case PROP_NAME:
g_free (context->name);
context->name = g_value_dup_string (value);
break;
case PROP_DESCRIPTION:
g_free (context->description);
context->description = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ib_context_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
IbContext *context = IB_CONTEXT (object);
switch (property_id)
{
case PROP_ID:
g_value_set_string (value, context->id);
break;
case PROP_NAME:
g_value_set_string (value, context->name);
break;
case PROP_DESCRIPTION:
g_value_set_string (value, context->description);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ib_context_class_init (IbContextClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GParamSpec *pspec;
object_class->finalize = ib_context_finalize;
object_class->set_property = ib_context_set_property;
object_class->get_property = ib_context_get_property;
pspec = g_param_spec_string ("id", "Id", "Id",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_ID, pspec);
pspec = g_param_spec_string ("name", "Name", "Name",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_NAME, pspec);
pspec = g_param_spec_string ("description", "Description", "Description",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_DESCRIPTION, pspec);
}
IbContext *
ib_context_new (const char *id,
const char *name,
const char *description)
{
return g_object_new (IB_TYPE_CONTEXT,
"id", id,
"name", name,
"description", description,
NULL);
}
const char *
ib_context_get_id (IbContext *context)
{
return context->id;
}
const char *
ib_context_get_name (IbContext *context)
{
return context->name;
}
const char *
ib_context_get_description (IbContext *context)
{
return context->description;
}

View File

@ -0,0 +1,14 @@
#pragma once
#include <gtk.h>
#define IB_TYPE_CONTEXT (ib_context_get_type ())
G_DECLARE_FINAL_TYPE (IbContext, ib_context, IB, CONTEXT, GObject)
IbContext *ib_context_new (const char *id,
const char *name,
const char *description);
const char *ib_context_get_id (IbContext *context);
const char *ib_context_get_name (IbContext *context);
const char *ib_context_get_description (IbContext *context);

View File

@ -0,0 +1,228 @@
#include "iconbrowsericon.h"
struct _IbIcon
{
GObject parent_instance;
gboolean use_symbolic;
char *regular_name;
char *symbolic_name;
char *description;
char *context;
};
struct _IbIconClass
{
GObjectClass parent_class;
};
enum {
PROP_NAME = 1,
PROP_REGULAR_NAME,
PROP_SYMBOLIC_NAME,
PROP_USE_SYMBOLIC,
PROP_DESCRIPTION,
PROP_CONTEXT,
PROP_NUM_PROPERTIES
};
G_DEFINE_TYPE (IbIcon, ib_icon, G_TYPE_OBJECT)
static void
ib_icon_init (IbIcon *icon)
{
}
static void
ib_icon_finalize (GObject *object)
{
IbIcon *icon = IB_ICON (object);
g_free (icon->regular_name);
g_free (icon->symbolic_name);
g_free (icon->description);
g_free (icon->context);
G_OBJECT_CLASS (ib_icon_parent_class)->finalize (object);
}
static void
ib_icon_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
IbIcon *icon = IB_ICON (object);
switch (property_id)
{
case PROP_REGULAR_NAME:
g_free (icon->regular_name);
icon->regular_name = g_value_dup_string (value);
if (!icon->use_symbolic)
g_object_notify (object, "name");
break;
case PROP_SYMBOLIC_NAME:
g_free (icon->symbolic_name);
icon->symbolic_name = g_value_dup_string (value);
if (icon->use_symbolic)
g_object_notify (object, "name");
break;
case PROP_USE_SYMBOLIC:
icon->use_symbolic = g_value_get_boolean (value);
g_object_notify (object, "name");
break;
case PROP_DESCRIPTION:
g_free (icon->description);
icon->description = g_value_dup_string (value);
break;
case PROP_CONTEXT:
g_free (icon->context);
icon->context = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ib_icon_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
IbIcon *icon = IB_ICON (object);
switch (property_id)
{
case PROP_NAME:
g_value_set_string (value, ib_icon_get_name (icon));
break;
case PROP_REGULAR_NAME:
g_value_set_string (value, icon->regular_name);
break;
case PROP_SYMBOLIC_NAME:
g_value_set_string (value, icon->symbolic_name);
break;
case PROP_USE_SYMBOLIC:
g_value_set_boolean (value, icon->use_symbolic);
break;
case PROP_DESCRIPTION:
g_value_set_string (value, icon->description);
break;
case PROP_CONTEXT:
g_value_set_string (value, icon->context);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ib_icon_class_init (IbIconClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GParamSpec *pspec;
object_class->finalize = ib_icon_finalize;
object_class->set_property = ib_icon_set_property;
object_class->get_property = ib_icon_get_property;
pspec = g_param_spec_string ("name", "Name", "Name",
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_NAME, pspec);
pspec = g_param_spec_string ("regular-name", "Regular Name", "Regular Name",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_REGULAR_NAME, pspec);
pspec = g_param_spec_string ("symbolic-name", "Symbolic Name", "Symbolic Name",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_SYMBOLIC_NAME, pspec);
pspec = g_param_spec_boolean ("use-symbolic", "Use Symbolic", "Use Symbolic",
FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_USE_SYMBOLIC, pspec);
pspec = g_param_spec_string ("description", "Description", "Description",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_DESCRIPTION, pspec);
pspec = g_param_spec_string ("context", "Context", "Context",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_CONTEXT, pspec);
}
IbIcon *
ib_icon_new (const char *regular_name,
const char *symbolic_name,
const char *description,
const char *context)
{
return g_object_new (IB_TYPE_ICON,
"regular-name", regular_name,
"symbolic-name", symbolic_name,
"description", description,
"context", context,
NULL);
}
const char *
ib_icon_get_name (IbIcon *icon)
{
if (icon->use_symbolic)
return icon->symbolic_name;
else
return icon->regular_name;
}
const char *
ib_icon_get_regular_name (IbIcon *icon)
{
return icon->regular_name;
}
const char *
ib_icon_get_symbolic_name (IbIcon *icon)
{
return icon->symbolic_name;
}
gboolean
ib_icon_get_use_symbolic (IbIcon *icon)
{
return icon->use_symbolic;
}
const char *
ib_icon_get_description (IbIcon *icon)
{
return icon->description;
}
const char *
ib_icon_get_context (IbIcon *icon)
{
return icon->context;
}

View File

@ -0,0 +1,18 @@
#pragma once
#include <gtk.h>
#define IB_TYPE_ICON (ib_icon_get_type ())
G_DECLARE_FINAL_TYPE (IbIcon, ib_icon, IB, ICON, GObject)
IbIcon *ib_icon_new (const char *regular_name,
const char *symbolic_name,
const char *description,
const char *context);
const char *ib_icon_get_name (IbIcon *icon);
const char *ib_icon_get_regular_name (IbIcon *icon);
const char *ib_icon_get_symbolic_name (IbIcon *icon);
gboolean ib_icon_get_use_symbolic (IbIcon *icon);
const char *ib_icon_get_description (IbIcon *icon);
const char *ib_icon_get_context (IbIcon *icon);

View File

@ -1,48 +1,22 @@
#include <string.h>
#include "iconbrowserapp.h"
#include "iconbrowserwin.h"
#include "iconstore.h"
#include "iconbrowsericon.h"
#include "iconbrowsercontext.h"
#include <gtk/gtk.h>
/* Drag 'n Drop */
typedef struct
{
gchar *id;
gchar *name;
gchar *description;
} Context;
static void
context_free (gpointer data)
{
Context *context = data;
g_free (context->id);
g_free (context->name);
g_free (context->description);
g_free (context);
}
struct _IconBrowserWindow
{
GtkApplicationWindow parent;
GHashTable *contexts;
GtkWidget *context_list;
Context *current_context;
gboolean symbolic;
GtkWidget *symbolic_radio;
GtkTreeModelFilter *filter_model;
GtkWidget *details;
GtkListStore *store;
GtkCellRenderer *cell;
GtkCellRenderer *text_cell;
GtkWidget *search;
GtkWidget *searchbar;
GtkWidget *searchentry;
GtkWidget *list;
GListModel *icon_filter_model;
GListStore *icon_store;
GListStore *context_store;
GtkFilter *name_filter;
GtkWidget *details;
GtkWidget *image1;
GtkWidget *image2;
GtkWidget *image3;
@ -68,87 +42,6 @@ icon_browser_window_get_icon_theme (IconBrowserWindow *win)
return gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (win)));
}
static void
search_text_changed (GtkEntry *entry, IconBrowserWindow *win)
{
const gchar *text;
text = gtk_editable_get_text (GTK_EDITABLE (entry));
if (text[0] == '\0')
return;
gtk_tree_model_filter_refilter (win->filter_model);
}
static void
set_image (GtkWidget *image, const gchar *name, gint size)
{
gtk_image_set_from_icon_name (GTK_IMAGE (image), name);
gtk_image_set_pixel_size (GTK_IMAGE (image), size);
}
static void
item_activated (GtkIconView *icon_view, GtkTreePath *path, IconBrowserWindow *win)
{
GtkIconTheme *icon_theme = icon_browser_window_get_icon_theme (win);
GtkTreeIter iter;
gchar *name;
gchar *description;
gint column;
gtk_tree_model_get_iter (GTK_TREE_MODEL (win->filter_model), &iter, path);
if (win->symbolic)
column = ICON_STORE_SYMBOLIC_NAME_COLUMN;
else
column = ICON_STORE_NAME_COLUMN;
gtk_tree_model_get (GTK_TREE_MODEL (win->filter_model), &iter,
column, &name,
ICON_STORE_DESCRIPTION_COLUMN, &description,
-1);
if (name == NULL || !gtk_icon_theme_has_icon (icon_theme, name))
{
g_free (description);
return;
}
gtk_window_set_title (GTK_WINDOW (win->details), name);
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);
if (win->symbolic)
{
gtk_widget_show (win->image8);
gtk_widget_show (win->label8);
set_image (win->image8, name, 64);
}
else
{
gtk_widget_hide (win->image8);
gtk_widget_hide (win->label8);
}
if (description && description[0])
{
gtk_label_set_text (GTK_LABEL (win->description), description);
gtk_widget_show (win->description);
}
else
{
gtk_widget_hide (win->description);
}
gtk_window_present (GTK_WINDOW (win->details));
g_free (name);
g_free (description);
}
static void
add_icon (IconBrowserWindow *win,
const gchar *name,
@ -158,6 +51,7 @@ add_icon (IconBrowserWindow *win,
GtkIconTheme *icon_theme = icon_browser_window_get_icon_theme (win);
gchar *regular_name;
gchar *symbolic_name;
IbIcon *icon;
regular_name = g_strdup (name);
if (!gtk_icon_theme_has_icon (icon_theme, regular_name))
@ -173,12 +67,12 @@ add_icon (IconBrowserWindow *win,
symbolic_name = NULL;
}
gtk_list_store_insert_with_values (win->store, NULL, -1,
ICON_STORE_NAME_COLUMN, regular_name,
ICON_STORE_SYMBOLIC_NAME_COLUMN, symbolic_name,
ICON_STORE_DESCRIPTION_COLUMN, description,
ICON_STORE_CONTEXT_COLUMN, context,
-1);
icon = ib_icon_new (regular_name, symbolic_name, description, context);
g_object_bind_property (win->symbolic_radio, "active",
icon, "use-symbolic",
G_BINDING_DEFAULT);
g_list_store_append (win->icon_store, icon);
g_object_unref (icon);
}
static void
@ -187,50 +81,11 @@ add_context (IconBrowserWindow *win,
const gchar *name,
const gchar *description)
{
Context *c;
GtkWidget *row;
IbContext *context;
c = g_new (Context, 1);
c->id = g_strdup (id);
c->name = g_strdup (name);
c->description = g_strdup (description);
g_hash_table_insert (win->contexts, c->id, c);
row = gtk_label_new (name);
gtk_label_set_xalign (GTK_LABEL (row), 0);
g_object_set_data (G_OBJECT (row), "context", c);
gtk_widget_show (row);
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);
gtk_list_box_insert (GTK_LIST_BOX (win->context_list), row, -1);
/* set the tooltip on the list box row */
row = gtk_widget_get_parent (row);
gtk_widget_set_tooltip_text (row, description);
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));
if (row == NULL)
return;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (win->search), FALSE);
label = gtk_list_box_row_get_child (GTK_LIST_BOX_ROW (row));
win->current_context = g_object_get_data (G_OBJECT (label), "context");
gtk_tree_model_filter_refilter (win->filter_model);
context = ib_context_new (id, name, description);
g_list_store_append (win->context_store, context);
g_object_unref (context);
}
static void
@ -282,6 +137,19 @@ populate (IconBrowserWindow *win)
g_strfreev (groups);
}
static gboolean
filter_by_icon_name (gpointer item,
gpointer data)
{
return ib_icon_get_name (IB_ICON (item)) != NULL;
}
static void
symbolic_toggled (IconBrowserWindow *win)
{
gtk_filter_changed (win->name_filter, GTK_FILTER_CHANGE_DIFFERENT);
}
static void
copy_to_clipboard (GtkButton *button,
IconBrowserWindow *win)
@ -292,70 +160,60 @@ copy_to_clipboard (GtkButton *button,
gdk_clipboard_set_text (clipboard, gtk_window_get_title (GTK_WINDOW (win->details)));
}
static gboolean
icon_visible_func (GtkTreeModel *model,
GtkTreeIter *iter,
gpointer data)
static void
set_image (GtkWidget *image, const gchar *name, gint size)
{
IconBrowserWindow *win = data;
gchar *context;
gchar *name;
gint column;
gboolean search;
const gchar *search_text;
gboolean visible;
search = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (win->search));
search_text = gtk_editable_get_text (GTK_EDITABLE (win->searchentry));
if (win->symbolic)
column = ICON_STORE_SYMBOLIC_NAME_COLUMN;
else
column = ICON_STORE_NAME_COLUMN;
gtk_tree_model_get (model, iter,
column, &name,
ICON_STORE_CONTEXT_COLUMN, &context,
-1);
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;
g_free (name);
g_free (context);
return visible;
gtk_image_set_from_icon_name (GTK_IMAGE (image), name);
gtk_image_set_pixel_size (GTK_IMAGE (image), size);
}
static void
symbolic_toggled (GtkToggleButton *toggle, IconBrowserWindow *win)
item_activated (GtkGridView *view,
guint position,
IconBrowserWindow *win)
{
gint column;
GListModel *model = gtk_grid_view_get_model (view);
IbIcon *icon = g_list_model_get_item (model, position);
const char *name;
const char *description;
gboolean symbolic;
win->symbolic = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle));
name = ib_icon_get_name (icon);
description = ib_icon_get_description (icon);
symbolic = ib_icon_get_use_symbolic (icon);
if (win->symbolic)
column = ICON_STORE_SYMBOLIC_NAME_COLUMN;
gtk_window_set_title (GTK_WINDOW (win->details), name);
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);
if (symbolic)
{
gtk_widget_show (win->image8);
gtk_widget_show (win->label8);
set_image (win->image8, name, 64);
}
else
column = ICON_STORE_NAME_COLUMN;
{
gtk_widget_hide (win->image8);
gtk_widget_hide (win->label8);
}
if (description && description[0])
{
gtk_label_set_text (GTK_LABEL (win->description), description);
gtk_widget_show (win->description);
}
else
{
gtk_widget_hide (win->description);
}
icon_store_set_text_column (ICON_STORE (win->store), column);
gtk_window_present (GTK_WINDOW (win->details));
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);
gtk_tree_model_filter_refilter (win->filter_model);
gtk_widget_queue_draw (win->list);
}
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));
g_object_unref (icon);
}
static GdkPaintable *
@ -381,7 +239,10 @@ get_image_paintable (GtkImage *image)
gtk_widget_get_direction (GTK_WIDGET (image)),
0);
if (icon == NULL)
return NULL;
{
g_print ("no icon for %s\n", icon_name);
return NULL;
}
return GDK_PAINTABLE (icon);
case GTK_IMAGE_GICON:
case GTK_IMAGE_EMPTY:
@ -419,10 +280,10 @@ drag_prepare_texture (GtkDragSource *source,
{
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (widget));
if (!GDK_IS_TEXTURE (paintable))
if (!GDK_IS_PAINTABLE (paintable))
return NULL;
return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, paintable);
return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
}
static GdkContentProvider *
@ -476,17 +337,10 @@ setup_scalable_image_dnd (GtkWidget *image)
static void
icon_browser_window_init (IconBrowserWindow *win)
{
GdkContentFormats *list;
GtkFilter *filter;
gtk_widget_init_template (GTK_WIDGET (win));
list = gdk_content_formats_new_for_gtype (G_TYPE_STRING);
gtk_icon_view_enable_model_drag_source (GTK_ICON_VIEW (win->list),
GDK_BUTTON1_MASK,
list,
GDK_ACTION_COPY);
gdk_content_formats_unref (list);
setup_image_dnd (win->image1);
setup_image_dnd (win->image2);
setup_image_dnd (win->image3);
@ -496,19 +350,16 @@ icon_browser_window_init (IconBrowserWindow *win)
setup_image_dnd (win->image7);
setup_scalable_image_dnd (win->image8);
win->contexts = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, context_free);
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));
g_signal_connect (win->searchbar, "notify::search-mode-enabled",
G_CALLBACK (search_mode_toggled), win);
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (win->searchbar),
GTK_WIDGET (win));
symbolic_toggled (GTK_TOGGLE_BUTTON (win->symbolic_radio), win);
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (win->searchbar), GTK_WIDGET (win));
populate (win);
filter = gtk_filter_list_model_get_filter (GTK_FILTER_LIST_MODEL (win->icon_filter_model));
win->name_filter = gtk_custom_filter_new (filter_by_icon_name, NULL, NULL);
gtk_multi_filter_append (GTK_MULTI_FILTER (filter), g_object_ref (win->name_filter));
}
static void
@ -516,7 +367,7 @@ icon_browser_window_finalize (GObject *object)
{
IconBrowserWindow *win = ICON_BROWSER_WINDOW (object);
g_hash_table_unref (win->contexts);
g_clear_object (&win->name_filter);
G_OBJECT_CLASS (icon_browser_window_parent_class)->finalize (object);
}
@ -528,23 +379,19 @@ icon_browser_window_class_init (IconBrowserWindowClass *class)
object_class->finalize = icon_browser_window_finalize;
g_type_ensure (ICON_STORE_TYPE);
g_type_ensure (IB_TYPE_ICON);
g_type_ensure (IB_TYPE_CONTEXT);
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/iconbrowser/gtk/window.ui");
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);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, store);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, cell);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, text_cell);
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, icon_store);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, icon_filter_model);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, context_store);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, details);
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);
@ -556,11 +403,9 @@ icon_browser_window_class_init (IconBrowserWindowClass *class)
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, label8);
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);
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);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), copy_to_clipboard);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), symbolic_toggled);
}
IconBrowserWindow *

View File

@ -1,91 +0,0 @@
#include "iconstore.h"
#include <gtk/gtk.h>
struct _IconStore
{
GtkListStore parent;
gint text_column;
};
struct _IconStoreClass
{
GtkListStoreClass parent_class;
};
static void icon_store_drag_source_init (GtkTreeDragSourceIface *iface);
G_DEFINE_TYPE_WITH_CODE (IconStore, icon_store, GTK_TYPE_LIST_STORE,
G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
icon_store_drag_source_init))
static void
icon_store_init (IconStore *store)
{
GType types[4] = { G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING };
gtk_list_store_set_column_types (GTK_LIST_STORE (store), 4, types);
store->text_column = ICON_STORE_NAME_COLUMN;
}
static void
icon_store_class_init (IconStoreClass *class)
{
}
static gboolean
row_draggable (GtkTreeDragSource *drag_source,
GtkTreePath *path)
{
return TRUE;
}
static gboolean
drag_data_delete (GtkTreeDragSource *drag_source,
GtkTreePath *path)
{
GtkTreeIter iter;
if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source), &iter, path))
return gtk_list_store_remove (GTK_LIST_STORE (drag_source), &iter);
return FALSE;
}
static GdkContentProvider *
drag_data_get (GtkTreeDragSource *drag_source,
GtkTreePath *path)
{
GdkContentProvider *content;
GtkTreeIter iter;
gchar *text;
if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source), &iter, path))
return NULL;
gtk_tree_model_get (GTK_TREE_MODEL (drag_source), &iter,
ICON_STORE (drag_source)->text_column, &text,
-1);
content = gdk_content_provider_new_typed (G_TYPE_STRING, text);
g_free (text);
return content;
}
static void
icon_store_drag_source_init (GtkTreeDragSourceIface *iface)
{
iface->row_draggable = row_draggable;
iface->drag_data_delete = drag_data_delete;
iface->drag_data_get = drag_data_get;
}
void
icon_store_set_text_column (IconStore *store, gint text_column)
{
store->text_column = text_column;
}

View File

@ -1,26 +0,0 @@
#ifndef __ICON_STORE_H
#define __ICON_STORE_H
#include <gtk/gtk.h>
#define ICON_STORE_TYPE (icon_store_get_type ())
#define ICON_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ICON_STORE_TYPE, IconStore))
typedef struct _IconStore IconStore;
typedef struct _IconStoreClass IconStoreClass;
enum {
ICON_STORE_NAME_COLUMN,
ICON_STORE_SYMBOLIC_NAME_COLUMN,
ICON_STORE_DESCRIPTION_COLUMN,
ICON_STORE_CONTEXT_COLUMN
};
GType icon_store_get_type (void);
void icon_store_set_text_column (IconStore *store,
gint column);
#endif /* __ICON_STORE_H */

View File

@ -2,7 +2,8 @@ iconbrowser_sources = [
'main.c',
'iconbrowserapp.c',
'iconbrowserwin.c',
'iconstore.c'
'iconbrowsericon.c',
'iconbrowsercontext.c'
]
iconbrowser_resources = gnome.compile_resources('iconbrowser_resources',
@ -17,14 +18,3 @@ executable('gtk4-icon-browser',
gui_app: true,
link_args: extra_demo_ldflags,
install: true)
install_data('org.gtk.IconBrowser4.desktop', install_dir: gtk_applicationsdir)
# icons
icontheme_dir = join_paths(gtk_datadir, 'icons/hicolor')
foreach size: ['scalable', 'symbolic']
install_subdir('data/' + size,
install_dir: icontheme_dir
)
endforeach

View File

@ -12,10 +12,6 @@
</item>
</section>
</menu>
<object class="IconStore" id="store"/>
<object class="GtkTreeModelFilter" id="filter_model">
<property name="child-model">store</property>
</object>
<template class="IconBrowserWindow" parent="GtkApplicationWindow">
<style>
<class name="devel"/>
@ -42,7 +38,7 @@
<property name="draw-indicator">0</property>
<property name="label" translatable="yes">Symbolic</property>
<property name="group">normal_radio</property>
<signal name="toggled" handler="symbolic_toggled"/>
<signal name="notify::active" handler="symbolic_toggled" swapped="yes" after="yes"/>
</object>
</child>
</object>
@ -71,8 +67,44 @@
<child>
<object class="GtkBox">
<child>
<object class="GtkListBox" id="context_list">
<signal name="selected-rows-changed" handler="selected_context_changed"/>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkListView">
<property name="model">
<object class="GtkSingleSelection" id="context_model">
<property name="model">
<object class="GListStore" id="context_store">
<property name="item-type">IbContext</property>
</object>
</property>
</object>
</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes">
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<property name="xalign">0</property>
<binding name="label">
<lookup name="name" type="IbContext">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
]]>
</property>
</object>
</property>
</object>
</child>
</object>
</child>
<child>
@ -88,7 +120,6 @@
<property name="search-mode-enabled" bind-source="search" bind-property="active" bind-flags="bidirectional"/>
<child>
<object class="GtkSearchEntry" id="searchentry">
<signal name="search-changed" handler="search_text_changed"/>
</object>
</child>
</object>
@ -99,23 +130,91 @@
<property name="vexpand">1</property>
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkIconView" id="list">
<property name="model">filter_model</property>
<property name="selection-mode">none</property>
<property name="activate-on-single-click">1</property>
<signal name="item_activated" handler="item_activated"/>
<child>
<object class="GtkCellRendererPixbuf" id="cell">
<property name="xpad">10</property>
<property name="ypad">10</property>
<object class="GtkGridView" id="list">
<signal name="activate" handler="item_activated"/>
<property name="single-click-activate">1</property>
<property name="model">
<object class="GtkNoSelection">
<property name="model">
<object class="GtkFilterListModel" id="icon_filter_model">
<property name="filter">
<object class="GtkEveryFilter">
<child>
<object class="GtkStringFilter">
<property name="expression">
<lookup name="name" type="IbIcon"/>
</property>
<binding name="search">
<lookup name="text" type="GtkSearchEntry">
searchentry
</lookup>
</binding>
</object>
</child>
<child>
<object class="GtkStringFilter">
<property name="ignore-case">0</property>
<property name="match-mode">exact</property>
<property name="expression">
<lookup name="context" type="IbIcon"/>
</property>
<binding name="search">
<lookup name="id" type="IbContext">
<lookup name="selected-item" type="GtkSingleSelection">
context_model
</lookup>
</lookup>
</binding>
</object>
</child>
</object>
</property>
<property name="model">
<object class="GListStore" id="icon_store">
<property name="item-type">IbIcon</property>
</object>
</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkCellRendererText" id="text_cell">
<property name="xpad">10</property>
<property name="ypad">10</property>
</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes">
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkImage">
<property name="pixel-size">48</property>
<binding name="icon-name">
<lookup name="name" type="IbIcon">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</child>
<child>
<object class="GtkLabel">
<binding name="label">
<lookup name="name" type="IbIcon">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</child>
</object>
</property>
</template>
</interface>
]]>
</property>
</object>
</child>
</property>
</object>
</child>
</object>
@ -125,14 +224,7 @@
</object>
</child>
</template>
<object class="GtkSizeGroup">
<property name="mode">vertical</property>
<widgets>
<widget name="normal_radio"/>
<widget name="symbolic_radio"/>
<widget name="search"/>
</widgets>
</object>
<object class="GtkDialog" id="details">
<property name="modal">1</property>
<property name="use-header-bar">1</property>
@ -164,7 +256,7 @@
</object>
</child>
<child>
<object class="GtkImage" id="image2">
<object class="GtkImage" id="image2">
<property name="halign">center</property>
<property name="valign">end</property>
<accessibility>
@ -373,7 +465,7 @@
</layout>
</object>
</child>
<child>
<child>
<object class="GtkLabel" id="label8">
<property name="halign">center</property>
<property name="valign">baseline</property>
@ -404,7 +496,7 @@
<signal name="clicked" handler="copy_to_clipboard"/>
</object>
</child>
<child>
<child>
<object class="GtkLabel" id="description">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
@ -419,3 +511,4 @@
</child>
</object>
</interface>