1 /* LIBGIMP - The GIMP Library
2  * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
3  *
4  * gimpicons.c
5  * Copyright (C) 2001-2015 Michael Natterer <mitch@gimp.org>
6  *
7  * This library is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 3 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library.  If not, see
19  * <https://www.gnu.org/licenses/>.
20  */
21 
22 #include "config.h"
23 
24 #include <gtk/gtk.h>
25 
26 #include "libgimpbase/gimpbase.h"
27 
28 #undef GIMP_DISABLE_DEPRECATED
29 #include "gimpicons.h"
30 
31 #include "icons/Color/gimp-icon-pixbufs.c"
32 
33 #include "libgimp/libgimp-intl.h"
34 
35 
36 /**
37  * SECTION: gimpicons
38  * @title: GimpIcons
39  * @short_description: Prebuilt common menu/toolbar items and
40  *                     corresponding icons
41  *
42  * GIMP registers a set of menu/toolbar items and corresponding icons
43  * in addition to the standard GTK+ stock items. These can be used
44  * just like GTK+ stock items. GIMP also overrides a few of the GTK+
45  * icons (namely the ones in dialog size).
46  *
47  * Stock icons may have a RTL variant which gets used for
48  * right-to-left locales.
49  **/
50 
51 
52 #define LIBGIMP_DOMAIN          GETTEXT_PACKAGE "-libgimp"
53 #define GIMP_TOILET_PAPER       "gimp-toilet-paper"
54 #define GIMP_DEFAULT_ICON_THEME "Symbolic"
55 
56 
57 static GtkIconFactory *gimp_stock_factory = NULL;
58 
59 
60 static const GtkStockItem gimp_stock_items[] =
61 {
62   { GIMP_STOCK_ANCHOR,         N_("Anchor"),          0, 0, LIBGIMP_DOMAIN },
63   { GIMP_STOCK_CENTER,         N_("C_enter"),         0, 0, LIBGIMP_DOMAIN },
64   { GIMP_STOCK_DUPLICATE,      N_("_Duplicate"),      0, 0, LIBGIMP_DOMAIN },
65   { GIMP_STOCK_LINKED,         N_("Linked"),          0, 0, LIBGIMP_DOMAIN },
66   { GIMP_STOCK_PASTE_AS_NEW,   N_("Paste as New"),    0, 0, LIBGIMP_DOMAIN },
67   { GIMP_STOCK_PASTE_INTO,     N_("Paste Into"),      0, 0, LIBGIMP_DOMAIN },
68   { GIMP_STOCK_RESET,          N_("_Reset"),          0, 0, LIBGIMP_DOMAIN },
69   { GIMP_STOCK_VISIBLE,        N_("Visible"),         0, 0, LIBGIMP_DOMAIN },
70 
71   { GIMP_STOCK_GRADIENT_LINEAR,               NULL,   0, 0, LIBGIMP_DOMAIN },
72   { GIMP_STOCK_GRADIENT_BILINEAR,             NULL,   0, 0, LIBGIMP_DOMAIN },
73   { GIMP_STOCK_GRADIENT_RADIAL,               NULL,   0, 0, LIBGIMP_DOMAIN },
74   { GIMP_STOCK_GRADIENT_SQUARE,               NULL,   0, 0, LIBGIMP_DOMAIN },
75   { GIMP_STOCK_GRADIENT_CONICAL_SYMMETRIC,    NULL,   0, 0, LIBGIMP_DOMAIN },
76   { GIMP_STOCK_GRADIENT_CONICAL_ASYMMETRIC,   NULL,   0, 0, LIBGIMP_DOMAIN },
77   { GIMP_STOCK_GRADIENT_SHAPEBURST_ANGULAR,   NULL,   0, 0, LIBGIMP_DOMAIN },
78   { GIMP_STOCK_GRADIENT_SHAPEBURST_SPHERICAL, NULL,   0, 0, LIBGIMP_DOMAIN },
79   { GIMP_STOCK_GRADIENT_SHAPEBURST_DIMPLED,   NULL,   0, 0, LIBGIMP_DOMAIN },
80   { GIMP_STOCK_GRADIENT_SPIRAL_CLOCKWISE,     NULL,   0, 0, LIBGIMP_DOMAIN },
81   { GIMP_STOCK_GRADIENT_SPIRAL_ANTICLOCKWISE, NULL,   0, 0, LIBGIMP_DOMAIN },
82 
83   { GIMP_STOCK_GRAVITY_EAST,             NULL,        0, 0, LIBGIMP_DOMAIN },
84   { GIMP_STOCK_GRAVITY_NORTH,            NULL,        0, 0, LIBGIMP_DOMAIN },
85   { GIMP_STOCK_GRAVITY_NORTH_EAST,       NULL,        0, 0, LIBGIMP_DOMAIN },
86   { GIMP_STOCK_GRAVITY_NORTH_WEST,       NULL,        0, 0, LIBGIMP_DOMAIN },
87   { GIMP_STOCK_GRAVITY_SOUTH,            NULL,        0, 0, LIBGIMP_DOMAIN },
88   { GIMP_STOCK_GRAVITY_SOUTH_EAST,       NULL,        0, 0, LIBGIMP_DOMAIN },
89   { GIMP_STOCK_GRAVITY_SOUTH_WEST,       NULL,        0, 0, LIBGIMP_DOMAIN },
90   { GIMP_STOCK_GRAVITY_WEST,             NULL,        0, 0, LIBGIMP_DOMAIN },
91 
92   { GIMP_STOCK_HCENTER,                  NULL,        0, 0, LIBGIMP_DOMAIN },
93   { GIMP_STOCK_VCENTER,                  NULL,        0, 0, LIBGIMP_DOMAIN },
94 
95   { GIMP_STOCK_HCHAIN,                   NULL,        0, 0, LIBGIMP_DOMAIN },
96   { GIMP_STOCK_HCHAIN_BROKEN,            NULL,        0, 0, LIBGIMP_DOMAIN },
97   { GIMP_STOCK_VCHAIN,                   NULL,        0, 0, LIBGIMP_DOMAIN },
98   { GIMP_STOCK_VCHAIN_BROKEN,            NULL,        0, 0, LIBGIMP_DOMAIN },
99 
100   { GIMP_STOCK_SELECTION,                NULL,        0, 0, LIBGIMP_DOMAIN },
101   { GIMP_STOCK_SELECTION_REPLACE,        NULL,        0, 0, LIBGIMP_DOMAIN },
102   { GIMP_STOCK_SELECTION_ADD,            NULL,        0, 0, LIBGIMP_DOMAIN },
103   { GIMP_STOCK_SELECTION_SUBTRACT,       NULL,        0, 0, LIBGIMP_DOMAIN },
104   { GIMP_STOCK_SELECTION_INTERSECT,      NULL,        0, 0, LIBGIMP_DOMAIN },
105   { GIMP_STOCK_SELECTION_STROKE,       N_("_Stroke"), 0, 0, LIBGIMP_DOMAIN },
106   { GIMP_STOCK_SELECTION_TO_CHANNEL,     NULL,        0, 0, LIBGIMP_DOMAIN },
107   { GIMP_STOCK_SELECTION_TO_PATH,        NULL,        0, 0, LIBGIMP_DOMAIN },
108 
109   { GIMP_STOCK_PATH_STROKE,            N_("_Stroke"), 0, 0, LIBGIMP_DOMAIN },
110 
111   { GIMP_STOCK_CURVE_FREE,               NULL,        0, 0, LIBGIMP_DOMAIN },
112   { GIMP_STOCK_CURVE_SMOOTH,             NULL,        0, 0, LIBGIMP_DOMAIN },
113 
114   { GIMP_STOCK_COLOR_PICKER_BLACK,       NULL,        0, 0, LIBGIMP_DOMAIN },
115   { GIMP_STOCK_COLOR_PICKER_GRAY,        NULL,        0, 0, LIBGIMP_DOMAIN },
116   { GIMP_STOCK_COLOR_PICKER_WHITE,       NULL,        0, 0, LIBGIMP_DOMAIN },
117   { GIMP_STOCK_COLOR_TRIANGLE,           NULL,        0, 0, LIBGIMP_DOMAIN },
118   { GIMP_STOCK_COLOR_PICK_FROM_SCREEN,   NULL,        0, 0, LIBGIMP_DOMAIN },
119 
120   { GIMP_STOCK_CHAR_PICKER,              NULL,        0, 0, LIBGIMP_DOMAIN },
121   { GIMP_STOCK_LETTER_SPACING, N_("L_etter Spacing"), 0, 0, LIBGIMP_DOMAIN },
122   { GIMP_STOCK_LINE_SPACING,   N_("L_ine Spacing"),   0, 0, LIBGIMP_DOMAIN },
123 
124   { GIMP_STOCK_TEXT_DIR_LTR,             NULL,        0, 0, LIBGIMP_DOMAIN },
125   { GIMP_STOCK_TEXT_DIR_RTL,             NULL,        0, 0, LIBGIMP_DOMAIN },
126   { GIMP_STOCK_PATTERN,                  NULL,        0, 0, LIBGIMP_DOMAIN },
127 
128   { GIMP_STOCK_CONVERT_RGB,              NULL,        0, 0, LIBGIMP_DOMAIN },
129   { GIMP_STOCK_CONVERT_GRAYSCALE,        NULL,        0, 0, LIBGIMP_DOMAIN },
130   { GIMP_STOCK_CONVERT_INDEXED,          NULL,        0, 0, LIBGIMP_DOMAIN },
131   { GIMP_STOCK_INVERT,                   NULL,        0, 0, LIBGIMP_DOMAIN },
132   { GIMP_STOCK_MERGE_DOWN,               NULL,        0, 0, LIBGIMP_DOMAIN },
133   { GIMP_STOCK_LAYER_TO_IMAGESIZE,       NULL,        0, 0, LIBGIMP_DOMAIN },
134   { GIMP_STOCK_PLUGIN,                   NULL,        0, 0, LIBGIMP_DOMAIN },
135   { GIMP_STOCK_RESHOW_FILTER,            NULL,        0, 0, LIBGIMP_DOMAIN },
136   { GIMP_STOCK_ROTATE_90,                NULL,        0, 0, LIBGIMP_DOMAIN },
137   { GIMP_STOCK_ROTATE_180,               NULL,        0, 0, LIBGIMP_DOMAIN },
138   { GIMP_STOCK_ROTATE_270,               NULL,        0, 0, LIBGIMP_DOMAIN },
139   { GIMP_STOCK_RESIZE,         N_("Re_size"),         0, 0, LIBGIMP_DOMAIN },
140   { GIMP_STOCK_SCALE,          N_("_Scale"),          0, 0, LIBGIMP_DOMAIN },
141   { GIMP_STOCK_FLIP_HORIZONTAL,          NULL,        0, 0, LIBGIMP_DOMAIN },
142   { GIMP_STOCK_FLIP_VERTICAL,            NULL,        0, 0, LIBGIMP_DOMAIN },
143 
144   { GIMP_STOCK_IMAGES,                   NULL,        0, 0, LIBGIMP_DOMAIN },
145   { GIMP_STOCK_LAYERS,                   NULL,        0, 0, LIBGIMP_DOMAIN },
146   { GIMP_STOCK_CHANNELS,                 NULL,        0, 0, LIBGIMP_DOMAIN },
147   { GIMP_STOCK_PATHS,                    NULL,        0, 0, LIBGIMP_DOMAIN },
148   { GIMP_STOCK_TOOLS,                    NULL,        0, 0, LIBGIMP_DOMAIN },
149   { GIMP_STOCK_TOOL_OPTIONS,             NULL,        0, 0, LIBGIMP_DOMAIN },
150   { GIMP_STOCK_DEVICE_STATUS,            NULL,        0, 0, LIBGIMP_DOMAIN },
151   { GIMP_STOCK_INPUT_DEVICE,             NULL,        0, 0, LIBGIMP_DOMAIN },
152   { GIMP_STOCK_CURSOR,                   NULL,        0, 0, LIBGIMP_DOMAIN },
153   { GIMP_STOCK_SAMPLE_POINT,             NULL,        0, 0, LIBGIMP_DOMAIN },
154   { GIMP_STOCK_DYNAMICS,                 NULL,        0, 0, LIBGIMP_DOMAIN },
155   { GIMP_STOCK_TOOL_PRESET,              NULL,        0, 0, LIBGIMP_DOMAIN },
156 
157   { GIMP_STOCK_IMAGE,                    NULL,        0, 0, LIBGIMP_DOMAIN },
158   { GIMP_STOCK_LAYER,                    NULL,        0, 0, LIBGIMP_DOMAIN },
159   { GIMP_STOCK_TEXT_LAYER,               NULL,        0, 0, LIBGIMP_DOMAIN },
160   { GIMP_STOCK_FLOATING_SELECTION,       NULL,        0, 0, LIBGIMP_DOMAIN },
161   { GIMP_STOCK_CHANNEL,                  NULL,        0, 0, LIBGIMP_DOMAIN },
162   { GIMP_STOCK_CHANNEL_RED,              NULL,        0, 0, LIBGIMP_DOMAIN },
163   { GIMP_STOCK_CHANNEL_GREEN,            NULL,        0, 0, LIBGIMP_DOMAIN },
164   { GIMP_STOCK_CHANNEL_BLUE,             NULL,        0, 0, LIBGIMP_DOMAIN },
165   { GIMP_STOCK_CHANNEL_GRAY,             NULL,        0, 0, LIBGIMP_DOMAIN },
166   { GIMP_STOCK_CHANNEL_INDEXED,          NULL,        0, 0, LIBGIMP_DOMAIN },
167   { GIMP_STOCK_CHANNEL_ALPHA,            NULL,        0, 0, LIBGIMP_DOMAIN },
168   { GIMP_STOCK_LAYER_MASK,               NULL,        0, 0, LIBGIMP_DOMAIN },
169   { GIMP_STOCK_PATH,                     NULL,        0, 0, LIBGIMP_DOMAIN },
170   { GIMP_STOCK_TEMPLATE,                 NULL,        0, 0, LIBGIMP_DOMAIN },
171   { GIMP_STOCK_COLORMAP,                 NULL,        0, 0, LIBGIMP_DOMAIN },
172   { GIMP_STOCK_HISTOGRAM,                NULL,        0, 0, LIBGIMP_DOMAIN },
173   { GIMP_STOCK_HISTOGRAM_LINEAR,         NULL,        0, 0, LIBGIMP_DOMAIN },
174   { GIMP_STOCK_HISTOGRAM_LOGARITHMIC,    NULL,        0, 0, LIBGIMP_DOMAIN },
175   { GIMP_STOCK_UNDO_HISTORY,             NULL,        0, 0, LIBGIMP_DOMAIN },
176   { GIMP_STOCK_TRANSPARENCY,             NULL,        0, 0, LIBGIMP_DOMAIN },
177 
178   { GIMP_STOCK_SELECTION_ALL,            NULL,        0, 0, LIBGIMP_DOMAIN },
179   { GIMP_STOCK_SELECTION_NONE,           NULL,        0, 0, LIBGIMP_DOMAIN },
180   { GIMP_STOCK_SELECTION_GROW,           NULL,        0, 0, LIBGIMP_DOMAIN },
181   { GIMP_STOCK_SELECTION_SHRINK,         NULL,        0, 0, LIBGIMP_DOMAIN },
182   { GIMP_STOCK_SELECTION_BORDER,         NULL,        0, 0, LIBGIMP_DOMAIN },
183 
184   { GIMP_STOCK_NAVIGATION,               NULL,        0, 0, LIBGIMP_DOMAIN },
185   { GIMP_STOCK_QUICK_MASK_OFF,           NULL,        0, 0, LIBGIMP_DOMAIN },
186   { GIMP_STOCK_QUICK_MASK_ON,            NULL,        0, 0, LIBGIMP_DOMAIN },
187 
188   { GIMP_STOCK_CONTROLLER,               NULL,        0, 0, LIBGIMP_DOMAIN },
189   { GIMP_STOCK_CONTROLLER_KEYBOARD,      NULL,        0, 0, LIBGIMP_DOMAIN },
190   { GIMP_STOCK_CONTROLLER_LINUX_INPUT,   NULL,        0, 0, LIBGIMP_DOMAIN },
191   { GIMP_STOCK_CONTROLLER_MIDI,          NULL,        0, 0, LIBGIMP_DOMAIN },
192   { GIMP_STOCK_CONTROLLER_WHEEL,         NULL,        0, 0, LIBGIMP_DOMAIN },
193 
194   { GIMP_STOCK_DISPLAY_FILTER,           NULL,        0, 0, LIBGIMP_DOMAIN },
195   { GIMP_STOCK_DISPLAY_FILTER_COLORBLIND, NULL,       0, 0, LIBGIMP_DOMAIN },
196   { GIMP_STOCK_DISPLAY_FILTER_CONTRAST,  NULL,        0, 0, LIBGIMP_DOMAIN },
197   { GIMP_STOCK_DISPLAY_FILTER_GAMMA,     NULL,        0, 0, LIBGIMP_DOMAIN },
198   { GIMP_STOCK_DISPLAY_FILTER_LCMS,      NULL,        0, 0, LIBGIMP_DOMAIN },
199   { GIMP_STOCK_DISPLAY_FILTER_PROOF,     NULL,        0, 0, LIBGIMP_DOMAIN },
200 
201   { GIMP_STOCK_LIST,                     NULL,        0, 0, LIBGIMP_DOMAIN },
202   { GIMP_STOCK_GRID,                     NULL,        0, 0, LIBGIMP_DOMAIN },
203 
204   { GIMP_STOCK_PORTRAIT,                 NULL,        0, 0, LIBGIMP_DOMAIN },
205   { GIMP_STOCK_LANDSCAPE,                NULL,        0, 0, LIBGIMP_DOMAIN },
206 
207   { GIMP_TOILET_PAPER,                   NULL,        0, 0, LIBGIMP_DOMAIN },
208   { GIMP_STOCK_GEGL,                     NULL,        0, 0, LIBGIMP_DOMAIN },
209   { GIMP_STOCK_WEB,                      NULL,        0, 0, LIBGIMP_DOMAIN },
210   { GIMP_STOCK_VIDEO,                    NULL,        0, 0, LIBGIMP_DOMAIN },
211 
212   { GIMP_STOCK_SHAPE_CIRCLE,             NULL,        0, 0, LIBGIMP_DOMAIN },
213   { GIMP_STOCK_SHAPE_DIAMOND,            NULL,        0, 0, LIBGIMP_DOMAIN },
214   { GIMP_STOCK_SHAPE_SQUARE,             NULL,        0, 0, LIBGIMP_DOMAIN },
215 
216   { GIMP_STOCK_CAP_BUTT,                 NULL,        0, 0, LIBGIMP_DOMAIN },
217   { GIMP_STOCK_CAP_ROUND,                NULL,        0, 0, LIBGIMP_DOMAIN },
218   { GIMP_STOCK_CAP_SQUARE,               NULL,        0, 0, LIBGIMP_DOMAIN },
219 
220   { GIMP_STOCK_JOIN_MITER,               NULL,        0, 0, LIBGIMP_DOMAIN },
221   { GIMP_STOCK_JOIN_ROUND,               NULL,        0, 0, LIBGIMP_DOMAIN },
222   { GIMP_STOCK_JOIN_BEVEL,               NULL,        0, 0, LIBGIMP_DOMAIN },
223 
224   { GIMP_STOCK_ERROR,                    NULL,        0, 0, LIBGIMP_DOMAIN },
225   { GIMP_STOCK_INFO,                     NULL,        0, 0, LIBGIMP_DOMAIN },
226   { GIMP_STOCK_QUESTION,                 NULL,        0, 0, LIBGIMP_DOMAIN },
227   { GIMP_STOCK_USER_MANUAL,              NULL,        0, 0, LIBGIMP_DOMAIN },
228   { GIMP_STOCK_WARNING,                  NULL,        0, 0, LIBGIMP_DOMAIN },
229   { GIMP_STOCK_WILBER,                   NULL,        0, 0, LIBGIMP_DOMAIN },
230   { GIMP_STOCK_WILBER_EEK,               NULL,        0, 0, LIBGIMP_DOMAIN },
231 
232   { GIMP_STOCK_FRAME,                    NULL,        0, 0, LIBGIMP_DOMAIN },
233   { GIMP_STOCK_TEXTURE,                  NULL,        0, 0, LIBGIMP_DOMAIN },
234 
235   { GIMP_STOCK_TOOL_AIRBRUSH,            NULL,        0, 0, LIBGIMP_DOMAIN },
236   { GIMP_STOCK_TOOL_ALIGN,               NULL,        0, 0, LIBGIMP_DOMAIN },
237   { GIMP_STOCK_TOOL_BLEND,               NULL,        0, 0, LIBGIMP_DOMAIN },
238   { GIMP_STOCK_TOOL_BLUR,                NULL,        0, 0, LIBGIMP_DOMAIN },
239   { GIMP_STOCK_TOOL_BRIGHTNESS_CONTRAST, NULL,        0, 0, LIBGIMP_DOMAIN },
240   { GIMP_STOCK_TOOL_BUCKET_FILL,         NULL,        0, 0, LIBGIMP_DOMAIN },
241   { GIMP_STOCK_TOOL_BY_COLOR_SELECT,     NULL,        0, 0, LIBGIMP_DOMAIN },
242   { GIMP_STOCK_TOOL_CAGE,                NULL,        0, 0, LIBGIMP_DOMAIN },
243   { GIMP_STOCK_TOOL_CLONE,               NULL,        0, 0, LIBGIMP_DOMAIN },
244   { GIMP_STOCK_TOOL_COLOR_BALANCE,       NULL,        0, 0, LIBGIMP_DOMAIN },
245   { GIMP_STOCK_TOOL_COLOR_PICKER,        NULL,        0, 0, LIBGIMP_DOMAIN },
246   { GIMP_STOCK_TOOL_COLORIZE,            NULL,        0, 0, LIBGIMP_DOMAIN },
247   { GIMP_STOCK_TOOL_CROP,         N_("Cr_op"),        0, 0, LIBGIMP_DOMAIN },
248   { GIMP_STOCK_TOOL_CURVES,              NULL,        0, 0, LIBGIMP_DOMAIN },
249   { GIMP_STOCK_TOOL_DESATURATE,          NULL,        0, 0, LIBGIMP_DOMAIN },
250   { GIMP_STOCK_TOOL_DODGE,               NULL,        0, 0, LIBGIMP_DOMAIN },
251   { GIMP_STOCK_TOOL_ELLIPSE_SELECT,      NULL,        0, 0, LIBGIMP_DOMAIN },
252   { GIMP_STOCK_TOOL_ERASER,              NULL,        0, 0, LIBGIMP_DOMAIN },
253   { GIMP_STOCK_TOOL_FLIP,                NULL,        0, 0, LIBGIMP_DOMAIN },
254   { GIMP_STOCK_TOOL_FREE_SELECT,         NULL,        0, 0, LIBGIMP_DOMAIN },
255   { GIMP_STOCK_TOOL_FOREGROUND_SELECT, N_("_Select"), 0, 0, LIBGIMP_DOMAIN },
256   { GIMP_STOCK_TOOL_FUZZY_SELECT,        NULL,        0, 0, LIBGIMP_DOMAIN },
257   { GIMP_STOCK_TOOL_HUE_SATURATION,      NULL,        0, 0, LIBGIMP_DOMAIN },
258   { GIMP_STOCK_TOOL_HEAL,                NULL,        0, 0, LIBGIMP_DOMAIN },
259   { GIMP_STOCK_TOOL_INK,                 NULL,        0, 0, LIBGIMP_DOMAIN },
260   { GIMP_STOCK_TOOL_ISCISSORS,           NULL,        0, 0, LIBGIMP_DOMAIN },
261   { GIMP_STOCK_TOOL_LEVELS,              NULL,        0, 0, LIBGIMP_DOMAIN },
262   { GIMP_STOCK_TOOL_MEASURE,             NULL,        0, 0, LIBGIMP_DOMAIN },
263   { GIMP_STOCK_TOOL_MOVE,                NULL,        0, 0, LIBGIMP_DOMAIN },
264   { GIMP_STOCK_TOOL_PAINTBRUSH,          NULL,        0, 0, LIBGIMP_DOMAIN },
265   { GIMP_STOCK_TOOL_PATH,                NULL,        0, 0, LIBGIMP_DOMAIN },
266   { GIMP_STOCK_TOOL_PENCIL,              NULL,        0, 0, LIBGIMP_DOMAIN },
267   { GIMP_STOCK_TOOL_PERSPECTIVE,  N_("_Transform"),   0, 0, LIBGIMP_DOMAIN },
268   { GIMP_STOCK_TOOL_PERSPECTIVE_CLONE,   NULL,        0, 0, LIBGIMP_DOMAIN },
269   { GIMP_STOCK_TOOL_POSTERIZE,           NULL,        0, 0, LIBGIMP_DOMAIN },
270   { GIMP_STOCK_TOOL_RECT_SELECT,         NULL,        0, 0, LIBGIMP_DOMAIN },
271   { GIMP_STOCK_TOOL_ROTATE,       N_("_Rotate"),      0, 0, LIBGIMP_DOMAIN },
272   { GIMP_STOCK_TOOL_SCALE,        N_("_Scale"),       0, 0, LIBGIMP_DOMAIN },
273   { GIMP_STOCK_TOOL_SHEAR,        N_("_Shear"),       0, 0, LIBGIMP_DOMAIN },
274   { GIMP_STOCK_TOOL_SMUDGE,              NULL,        0, 0, LIBGIMP_DOMAIN },
275   { GIMP_STOCK_TOOL_TEXT,                NULL,        0, 0, LIBGIMP_DOMAIN },
276   { GIMP_STOCK_TOOL_THRESHOLD,           NULL,        0, 0, LIBGIMP_DOMAIN },
277   { GIMP_STOCK_TOOL_ZOOM,                NULL,        0, 0, LIBGIMP_DOMAIN }
278 };
279 
280 static const GtkStockItem gimp_compat_stock_items[] =
281 {
282   { "gimp-indexed-palette", NULL, 0, 0, LIBGIMP_DOMAIN },
283   { "gimp-qmask-off",       NULL, 0, 0, LIBGIMP_DOMAIN },
284   { "gimp-qmask-on",        NULL, 0, 0, LIBGIMP_DOMAIN }
285 };
286 
287 
288 static void
register_stock_icon(GtkIconFactory * factory,const gchar * stock_id,const gchar * icon_name)289 register_stock_icon (GtkIconFactory *factory,
290                      const gchar    *stock_id,
291                      const gchar    *icon_name)
292 {
293   GtkIconSet    *set    = gtk_icon_set_new ();
294   GtkIconSource *source = gtk_icon_source_new ();
295 
296   gtk_icon_source_set_direction_wildcarded (source, TRUE);
297   gtk_icon_source_set_size_wildcarded (source, TRUE);
298   gtk_icon_source_set_state_wildcarded (source, TRUE);
299   gtk_icon_source_set_icon_name (source, icon_name);
300 
301   gtk_icon_set_add_source (set, source);
302   gtk_icon_source_free (source);
303 
304   gtk_icon_factory_add (factory, stock_id, set);
305   gtk_icon_set_unref (set);
306 }
307 
308 static void
register_bidi_stock_icon(GtkIconFactory * factory,const gchar * stock_id,const gchar * icon_name_ltr,const gchar * icon_name_rtl)309 register_bidi_stock_icon (GtkIconFactory *factory,
310                           const gchar    *stock_id,
311                           const gchar    *icon_name_ltr,
312                           const gchar    *icon_name_rtl)
313 {
314   GtkIconSet    *set    = gtk_icon_set_new ();
315   GtkIconSource *source = gtk_icon_source_new ();
316 
317   gtk_icon_source_set_direction (source, GTK_TEXT_DIR_LTR);
318   gtk_icon_source_set_direction_wildcarded (source, FALSE);
319   gtk_icon_source_set_size_wildcarded (source, TRUE);
320   gtk_icon_source_set_state_wildcarded (source, TRUE);
321   gtk_icon_source_set_icon_name (source, icon_name_ltr);
322 
323   gtk_icon_set_add_source (set, source);
324   gtk_icon_source_free (source);
325 
326   source = gtk_icon_source_new ();
327 
328   gtk_icon_source_set_direction (source, GTK_TEXT_DIR_RTL);
329   gtk_icon_source_set_direction_wildcarded (source, FALSE);
330   gtk_icon_source_set_size_wildcarded (source, TRUE);
331   gtk_icon_source_set_state_wildcarded (source, TRUE);
332   gtk_icon_source_set_icon_name (source, icon_name_rtl);
333 
334   gtk_icon_set_add_source (set, source);
335   gtk_icon_source_free (source);
336 
337   gtk_icon_factory_add (factory, stock_id, set);
338   gtk_icon_set_unref (set);
339 }
340 
341 
342 static GFile *icon_theme_path     = NULL;
343 static GFile *default_search_path = NULL;
344 
345 
346 static void
gimp_icons_change_icon_theme(GFile * new_search_path)347 gimp_icons_change_icon_theme (GFile *new_search_path)
348 {
349   GFile *old_search_path = g_file_get_parent (icon_theme_path);
350 
351   if (! default_search_path)
352     default_search_path = gimp_data_directory_file ("icons", NULL);
353 
354   if (! g_file_equal (new_search_path, old_search_path))
355     {
356       GtkIconTheme *icon_theme = gtk_icon_theme_get_default ();
357 
358       if (g_file_equal (old_search_path, default_search_path))
359         {
360           /*  if the old icon theme is in the default search path,
361            *  simply prepend the new theme's path
362            */
363           gchar *path_str = g_file_get_path (new_search_path);
364 
365           gtk_icon_theme_prepend_search_path (icon_theme, path_str);
366           g_free (path_str);
367         }
368       else
369         {
370           /*  if the old theme is not in the default search path,
371            *  we need to deal with the search path's first element
372            */
373           gchar **paths;
374           gint    n_paths;
375 
376           gtk_icon_theme_get_search_path (icon_theme, &paths, &n_paths);
377 
378           if (g_file_equal (new_search_path, default_search_path))
379             {
380               /*  when switching to a theme in the default path, remove
381                *  the first search path element, the default search path
382                *  is still in the search path
383                */
384               gtk_icon_theme_set_search_path (icon_theme,
385                                               (const gchar **) paths + 1,
386                                               n_paths - 1);
387             }
388           else
389             {
390               /*  when switching between two non-default search paths, replace
391                *  the first element of the search path with the new
392                *  theme's path
393                */
394               g_free (paths[0]);
395               paths[0] = g_file_get_path (new_search_path);
396 
397               gtk_icon_theme_set_search_path (icon_theme,
398                                               (const gchar **) paths, n_paths);
399             }
400 
401           g_strfreev (paths);
402         }
403     }
404 
405   g_object_unref (old_search_path);
406 }
407 
408 static void
gimp_icons_notify_system_icon_theme(GObject * settings,GParamSpec * param,gpointer unused)409 gimp_icons_notify_system_icon_theme (GObject    *settings,
410                                      GParamSpec *param,
411                                      gpointer    unused)
412 {
413   GdkScreen *screen = gdk_screen_get_default ();
414   GValue     value  = G_VALUE_INIT;
415 
416   g_value_init (&value, G_TYPE_STRING);
417 
418   if (gdk_screen_get_setting (screen, "gtk-icon-theme-name", &value))
419     {
420       const gchar *new_system_icon_theme = g_value_get_string (&value);
421       gchar *cur_system_icon_theme = NULL;
422 
423       g_object_get (settings,
424                     "gtk-fallback-icon-theme", &cur_system_icon_theme,
425                     NULL);
426       if (g_strcmp0 (cur_system_icon_theme, new_system_icon_theme))
427         {
428           g_object_set (settings,
429                         "gtk-fallback-icon-theme", new_system_icon_theme,
430                         NULL);
431 
432           g_object_notify (settings, "gtk-icon-theme-name");
433         }
434 
435       g_free (cur_system_icon_theme);
436     }
437 
438   g_value_unset (&value);
439 }
440 
441 static gboolean
gimp_icons_sanity_check(GFile * path,const gchar * theme_name)442 gimp_icons_sanity_check (GFile       *path,
443                          const gchar *theme_name)
444 {
445   gboolean exists = FALSE;
446   GFile *child = g_file_get_child (path, theme_name);
447 
448   if (g_file_query_exists (child, NULL))
449     {
450       GFile *index = g_file_get_child (child, "index.theme");
451 
452       if (g_file_query_exists (index, NULL))
453         exists = TRUE;
454       else
455         g_printerr ("%s: Icon theme path has no '%s/index.theme': %s\n",
456                     G_STRFUNC, theme_name, gimp_file_get_utf8_name (path));
457 
458       g_object_unref (index);
459     }
460   else
461     g_printerr ("%s: Icon theme path has no '%s' subdirectory: %s\n",
462                 G_STRFUNC, theme_name, gimp_file_get_utf8_name (path));
463 
464   g_object_unref (child);
465 
466   return exists;
467 }
468 
469 void
gimp_icons_set_icon_theme(GFile * path)470 gimp_icons_set_icon_theme (GFile *path)
471 {
472   gchar *icon_theme_name;
473   GFile *search_path;
474 
475   g_return_if_fail (path == NULL || G_IS_FILE (path));
476 
477   if (path)
478     path = g_object_ref (path);
479   else
480     path = gimp_data_directory_file ("icons", GIMP_DEFAULT_ICON_THEME, NULL);
481 
482   search_path = g_file_get_parent (path);
483   icon_theme_name = g_file_get_basename (path);
484 
485   if (gimp_icons_sanity_check (search_path, "hicolor") &&
486       gimp_icons_sanity_check (search_path, icon_theme_name))
487     {
488       if (icon_theme_path)
489         {
490           /*  this is an icon theme change  */
491           gimp_icons_change_icon_theme (search_path);
492 
493           if (! g_file_equal (icon_theme_path, path))
494             {
495               g_object_unref (icon_theme_path);
496               icon_theme_path = g_object_ref (path);
497             }
498 
499           g_object_set (gtk_settings_get_for_screen (gdk_screen_get_default ()),
500                         "gtk-icon-theme-name", icon_theme_name,
501                         NULL);
502         }
503       else
504         {
505           /*  this is the first call upon initialization  */
506           icon_theme_path = g_object_ref (path);
507         }
508     }
509 
510   g_free (icon_theme_name);
511   g_object_unref (search_path);
512   g_object_unref (path);
513 }
514 
515 /**
516  * gimp_stock_init:
517  *
518  * Initializes the GIMP stock icon factory.
519  *
520  * You don't need to call this function as gimp_ui_init() already does
521  * this for you.
522  *
523  * Deprecated: 2.10: Use gimp_icons_init() instead.
524  */
525 void
gimp_stock_init(void)526 gimp_stock_init (void)
527 {
528   gimp_icons_init ();
529 }
530 
531 /**
532  * gimp_icons_init:
533  *
534  * Initializes the GIMP stock icon factory.
535  *
536  * You don't need to call this function as gimp_ui_init() already does
537  * this for you.
538  */
539 void
gimp_icons_init(void)540 gimp_icons_init (void)
541 {
542   static gboolean initialized = FALSE;
543 
544   GtkSettings *settings;
545   GdkPixbuf   *pixbuf;
546   GError      *error = NULL;
547   gchar       *icons_dir;
548   gchar       *system_icon_theme;
549   gchar       *gimp_icon_theme;
550   gint         i;
551 
552   if (initialized)
553     return;
554 
555   gimp_stock_factory = gtk_icon_factory_new ();
556 
557   for (i = 0; i < G_N_ELEMENTS (gimp_stock_items); i++)
558     {
559       register_stock_icon (gimp_stock_factory,
560                            gimp_stock_items[i].stock_id,
561                            gimp_stock_items[i].stock_id);
562     }
563 
564   register_bidi_stock_icon (gimp_stock_factory,
565                             GIMP_STOCK_MENU_LEFT,
566                             GIMP_STOCK_MENU_LEFT, GIMP_STOCK_MENU_RIGHT);
567   register_bidi_stock_icon (gimp_stock_factory,
568                             GIMP_STOCK_MENU_RIGHT,
569                             GIMP_STOCK_MENU_RIGHT, GIMP_STOCK_MENU_LEFT);
570 
571   register_stock_icon (gimp_stock_factory,
572                        "gimp-indexed-palette", GIMP_STOCK_COLORMAP);
573   register_stock_icon (gimp_stock_factory,
574                        "gimp-qmask-off", GIMP_STOCK_QUICK_MASK_OFF);
575   register_stock_icon (gimp_stock_factory,
576                        "gimp-qmask-on", GIMP_STOCK_QUICK_MASK_ON);
577   register_stock_icon (gimp_stock_factory,
578                        "gimp-tool-blend", GIMP_STOCK_TOOL_BLEND);
579 
580   gtk_icon_factory_add_default (gimp_stock_factory);
581 
582   gtk_stock_add_static (gimp_stock_items,
583                         G_N_ELEMENTS (gimp_stock_items));
584   gtk_stock_add_static (gimp_compat_stock_items,
585                         G_N_ELEMENTS (gimp_compat_stock_items));
586 
587   /*  always prepend the default icon theme, it's never removed from
588    *  the path again and acts as fallback for missing icons in other
589    *  themes.
590    */
591   if (! default_search_path)
592     default_search_path = gimp_data_directory_file ("icons",
593                                                     NULL);
594 
595   icons_dir = g_file_get_path (default_search_path);
596   gtk_icon_theme_prepend_search_path (gtk_icon_theme_get_default (),
597                                       icons_dir);
598   g_free (icons_dir);
599 
600   /*  if an icon theme was chosen before init(), change to it  */
601   if (icon_theme_path)
602     {
603       GFile *search_path = g_file_get_parent (icon_theme_path);
604 
605       if (!g_file_equal (search_path, default_search_path))
606         {
607           gchar *icon_dir = g_file_get_path (search_path);
608 
609           gtk_icon_theme_prepend_search_path (gtk_icon_theme_get_default (),
610                                               icon_dir);
611           g_free (icon_dir);
612         }
613       g_object_unref (search_path);
614 
615       gimp_icon_theme = g_file_get_basename (icon_theme_path);
616     }
617   else
618     {
619       gimp_icon_theme = g_strdup (GIMP_DEFAULT_ICON_THEME);
620     }
621 
622   settings = gtk_settings_get_for_screen (gdk_screen_get_default ());
623 
624   g_object_get (settings, "gtk-icon-theme-name", &system_icon_theme, NULL);
625 
626   g_object_set (settings,
627                 "gtk-fallback-icon-theme", system_icon_theme,
628                 "gtk-icon-theme-name", gimp_icon_theme,
629                 NULL);
630 
631   g_free (gimp_icon_theme);
632   g_free (system_icon_theme);
633 
634   g_signal_connect (settings, "notify::gtk-icon-theme-name",
635                     G_CALLBACK (gimp_icons_notify_system_icon_theme), NULL);
636   pixbuf = gdk_pixbuf_new_from_resource ("/org/gimp/icons/64/gimp-wilber-eek.png",
637                                          &error);
638 
639   if (pixbuf)
640     {
641       gtk_icon_theme_add_builtin_icon (GIMP_STOCK_WILBER_EEK, 64, pixbuf);
642       g_object_unref (pixbuf);
643     }
644   else
645     {
646       g_critical ("Failed to create icon image: %s", error->message);
647       g_clear_error (&error);
648     }
649 
650   initialized = TRUE;
651 }
652