mirror of https://github.com/GNOME/gimp.git
315 lines
9.1 KiB
C
315 lines
9.1 KiB
C
/* LIBGIMP - The GIMP Library
|
|
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
|
*
|
|
* gimpicons.c
|
|
* Copyright (C) 2001-2015 Michael Natterer <mitch@gimp.org>
|
|
*
|
|
* This library is free software: you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see
|
|
* <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "libgimpbase/gimpbase.h"
|
|
|
|
#include "gimpicons.h"
|
|
|
|
#include "libgimp/libgimp-intl.h"
|
|
|
|
|
|
/**
|
|
* SECTION: gimpicons
|
|
* @title: GimpIcons
|
|
* @short_description: Prebuilt common menu/toolbar items and
|
|
* corresponding icons
|
|
*
|
|
* GIMP registers a set of menu/toolbar items and corresponding icons
|
|
* in addition to the standard GTK+ stock items. These can be used
|
|
* just like GTK+ stock items. GIMP also overrides a few of the GTK+
|
|
* icons (namely the ones in dialog size).
|
|
*
|
|
* Stock icons may have a RTL variant which gets used for
|
|
* right-to-left locales.
|
|
**/
|
|
|
|
|
|
#define LIBGIMP_DOMAIN GETTEXT_PACKAGE "-libgimp"
|
|
#define GIMP_TOILET_PAPER "gimp-toilet-paper"
|
|
#define GIMP_DEFAULT_ICON_THEME "Symbolic"
|
|
|
|
|
|
static GFile *icon_theme_path = NULL;
|
|
static GFile *default_search_path = NULL;
|
|
|
|
|
|
static void
|
|
gimp_icons_change_icon_theme (GFile *new_search_path)
|
|
{
|
|
GFile *old_search_path = g_file_get_parent (icon_theme_path);
|
|
|
|
if (! default_search_path)
|
|
default_search_path = gimp_data_directory_file ("icons", NULL);
|
|
|
|
if (! g_file_equal (new_search_path, old_search_path))
|
|
{
|
|
GtkIconTheme *icon_theme = gtk_icon_theme_get_default ();
|
|
|
|
if (g_file_equal (old_search_path, default_search_path))
|
|
{
|
|
/* if the old icon theme is in the default search path,
|
|
* simply prepend the new theme's path
|
|
*/
|
|
gchar *path_str = g_file_get_path (new_search_path);
|
|
|
|
gtk_icon_theme_prepend_search_path (icon_theme, path_str);
|
|
g_free (path_str);
|
|
}
|
|
else
|
|
{
|
|
/* if the old theme is not in the default search path,
|
|
* we need to deal with the search path's first element
|
|
*/
|
|
gchar **paths;
|
|
gint n_paths;
|
|
|
|
gtk_icon_theme_get_search_path (icon_theme, &paths, &n_paths);
|
|
|
|
if (g_file_equal (new_search_path, default_search_path))
|
|
{
|
|
/* when switching to a theme in the default path, remove
|
|
* the first search path element, the default search path
|
|
* is still in the search path
|
|
*/
|
|
gtk_icon_theme_set_search_path (icon_theme,
|
|
(const gchar **) paths + 1,
|
|
n_paths - 1);
|
|
}
|
|
else
|
|
{
|
|
/* when switching between two non-default search paths, replace
|
|
* the first element of the search path with the new
|
|
* theme's path
|
|
*/
|
|
g_free (paths[0]);
|
|
paths[0] = g_file_get_path (new_search_path);
|
|
|
|
gtk_icon_theme_set_search_path (icon_theme,
|
|
(const gchar **) paths, n_paths);
|
|
}
|
|
|
|
g_strfreev (paths);
|
|
}
|
|
}
|
|
|
|
g_object_unref (old_search_path);
|
|
}
|
|
|
|
static void
|
|
gimp_icons_notify_system_icon_theme (GObject *settings,
|
|
GParamSpec *param,
|
|
gpointer unused)
|
|
{
|
|
GdkScreen *screen = gdk_screen_get_default ();
|
|
GValue value = G_VALUE_INIT;
|
|
|
|
g_value_init (&value, G_TYPE_STRING);
|
|
|
|
if (gdk_screen_get_setting (screen, "gtk-icon-theme-name", &value))
|
|
{
|
|
const gchar *new_system_icon_theme = g_value_get_string (&value);
|
|
gchar *cur_system_icon_theme = NULL;
|
|
|
|
g_object_get (settings,
|
|
"gtk-fallback-icon-theme", &cur_system_icon_theme,
|
|
NULL);
|
|
if (g_strcmp0 (cur_system_icon_theme, new_system_icon_theme))
|
|
{
|
|
g_object_set (settings,
|
|
"gtk-fallback-icon-theme", new_system_icon_theme,
|
|
NULL);
|
|
|
|
g_object_notify (settings, "gtk-icon-theme-name");
|
|
}
|
|
|
|
g_free (cur_system_icon_theme);
|
|
}
|
|
|
|
g_value_unset (&value);
|
|
}
|
|
|
|
static gboolean
|
|
gimp_icons_sanity_check (GFile *path,
|
|
const gchar *theme_name)
|
|
{
|
|
gboolean exists = FALSE;
|
|
GFile *child = g_file_get_child (path, theme_name);
|
|
|
|
if (g_file_query_exists (child, NULL))
|
|
{
|
|
GFile *index = g_file_get_child (child, "index.theme");
|
|
|
|
if (g_file_query_exists (index, NULL))
|
|
exists = TRUE;
|
|
else
|
|
g_printerr ("%s: Icon theme path has no '%s/index.theme': %s\n",
|
|
G_STRFUNC, theme_name, gimp_file_get_utf8_name (path));
|
|
|
|
g_object_unref (index);
|
|
}
|
|
else
|
|
g_printerr ("%s: Icon theme path has no '%s' subdirectory: %s\n",
|
|
G_STRFUNC, theme_name, gimp_file_get_utf8_name (path));
|
|
|
|
g_object_unref (child);
|
|
|
|
return exists;
|
|
}
|
|
|
|
void
|
|
gimp_icons_set_icon_theme (GFile *path)
|
|
{
|
|
gchar *icon_theme_name;
|
|
GFile *search_path;
|
|
|
|
g_return_if_fail (path == NULL || G_IS_FILE (path));
|
|
|
|
if (path)
|
|
path = g_object_ref (path);
|
|
else
|
|
path = gimp_data_directory_file ("icons", GIMP_DEFAULT_ICON_THEME, NULL);
|
|
|
|
search_path = g_file_get_parent (path);
|
|
icon_theme_name = g_file_get_basename (path);
|
|
|
|
if (gimp_icons_sanity_check (search_path, "hicolor") &&
|
|
gimp_icons_sanity_check (search_path, icon_theme_name))
|
|
{
|
|
if (icon_theme_path)
|
|
{
|
|
/* this is an icon theme change */
|
|
gimp_icons_change_icon_theme (search_path);
|
|
|
|
if (! g_file_equal (icon_theme_path, path))
|
|
{
|
|
g_object_unref (icon_theme_path);
|
|
icon_theme_path = g_object_ref (path);
|
|
}
|
|
|
|
g_object_set (gtk_settings_get_for_screen (gdk_screen_get_default ()),
|
|
"gtk-icon-theme-name", icon_theme_name,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
/* this is the first call upon initialization */
|
|
icon_theme_path = g_object_ref (path);
|
|
}
|
|
}
|
|
|
|
g_free (icon_theme_name);
|
|
g_object_unref (search_path);
|
|
g_object_unref (path);
|
|
}
|
|
|
|
/**
|
|
* gimp_icons_init:
|
|
*
|
|
* Initializes the GIMP stock icon factory.
|
|
*
|
|
* You don't need to call this function as gimp_ui_init() already does
|
|
* this for you.
|
|
*/
|
|
void
|
|
gimp_icons_init (void)
|
|
{
|
|
static gboolean initialized = FALSE;
|
|
|
|
GtkSettings *settings;
|
|
GdkPixbuf *pixbuf;
|
|
GError *error = NULL;
|
|
gchar *icons_dir;
|
|
gchar *system_icon_theme;
|
|
gchar *gimp_icon_theme;
|
|
|
|
if (initialized)
|
|
return;
|
|
|
|
/* always prepend the default icon theme, it's never removed from
|
|
* the path again and acts as fallback for missing icons in other
|
|
* themes.
|
|
*/
|
|
if (! default_search_path)
|
|
default_search_path = gimp_data_directory_file ("icons",
|
|
NULL);
|
|
|
|
icons_dir = g_file_get_path (default_search_path);
|
|
gtk_icon_theme_prepend_search_path (gtk_icon_theme_get_default (),
|
|
icons_dir);
|
|
g_free (icons_dir);
|
|
|
|
/* if an icon theme was chosen before init(), change to it */
|
|
if (icon_theme_path)
|
|
{
|
|
GFile *search_path = g_file_get_parent (icon_theme_path);
|
|
|
|
if (!g_file_equal (search_path, default_search_path))
|
|
{
|
|
gchar *icon_dir = g_file_get_path (search_path);
|
|
|
|
gtk_icon_theme_prepend_search_path (gtk_icon_theme_get_default (),
|
|
icon_dir);
|
|
g_free (icon_dir);
|
|
}
|
|
g_object_unref (search_path);
|
|
|
|
gimp_icon_theme = g_file_get_basename (icon_theme_path);
|
|
}
|
|
else
|
|
{
|
|
gimp_icon_theme = g_strdup (GIMP_DEFAULT_ICON_THEME);
|
|
}
|
|
|
|
settings = gtk_settings_get_for_screen (gdk_screen_get_default ());
|
|
|
|
g_object_get (settings, "gtk-icon-theme-name", &system_icon_theme, NULL);
|
|
|
|
g_object_set (settings,
|
|
"gtk-fallback-icon-theme", system_icon_theme,
|
|
"gtk-icon-theme-name", gimp_icon_theme,
|
|
NULL);
|
|
|
|
g_free (gimp_icon_theme);
|
|
g_free (system_icon_theme);
|
|
|
|
g_signal_connect (settings, "notify::gtk-icon-theme-name",
|
|
G_CALLBACK (gimp_icons_notify_system_icon_theme), NULL);
|
|
pixbuf = gdk_pixbuf_new_from_resource ("/org/gimp/icons/64/gimp-wilber-eek.png",
|
|
&error);
|
|
|
|
if (pixbuf)
|
|
{
|
|
gtk_icon_theme_add_builtin_icon (GIMP_ICON_WILBER_EEK, 64, pixbuf);
|
|
g_object_unref (pixbuf);
|
|
}
|
|
else
|
|
{
|
|
g_critical ("Failed to create icon image: %s", error->message);
|
|
g_clear_error (&error);
|
|
}
|
|
|
|
initialized = TRUE;
|
|
}
|