1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 
3 /* caja-ui-utilities.c - helper functions for GtkUIManager stuff
4 
5    Copyright (C) 2004 Red Hat, Inc.
6 
7    The Mate Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11 
12    The Mate 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 Library General Public
18    License along with the Mate Library; see the file COPYING.LIB.  If not,
19    write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20    Boston, MA 02110-1301, USA.
21 
22    Authors: Alexander Larsson <alexl@redhat.com>
23 */
24 
25 #include <config.h>
26 
27 #include <gtk/gtk.h>
28 #include <gdk-pixbuf/gdk-pixbuf.h>
29 #include <gio/gio.h>
30 
31 #include <eel/eel-debug.h>
32 #include <eel/eel-graphic-effects.h>
33 
34 #include "caja-ui-utilities.h"
35 #include "caja-file-utilities.h"
36 #include "caja-icon-info.h"
37 
38 void
caja_ui_unmerge_ui(GtkUIManager * ui_manager,guint * merge_id,GtkActionGroup ** action_group)39 caja_ui_unmerge_ui (GtkUIManager *ui_manager,
40                     guint *merge_id,
41                     GtkActionGroup **action_group)
42 {
43     if (*merge_id != 0)
44     {
45         gtk_ui_manager_remove_ui (ui_manager,
46                                   *merge_id);
47         *merge_id = 0;
48     }
49     if (*action_group != NULL)
50     {
51         gtk_ui_manager_remove_action_group (ui_manager,
52                                             *action_group);
53         *action_group = NULL;
54     }
55 }
56 
57 void
caja_ui_prepare_merge_ui(GtkUIManager * ui_manager,const char * name,guint * merge_id,GtkActionGroup ** action_group)58 caja_ui_prepare_merge_ui (GtkUIManager *ui_manager,
59                           const char *name,
60                           guint *merge_id,
61                           GtkActionGroup **action_group)
62 {
63     *merge_id = gtk_ui_manager_new_merge_id (ui_manager);
64     G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
65     *action_group = gtk_action_group_new (name);
66 #ifdef ENABLE_NLS
67     gtk_action_group_set_translation_domain (*action_group, GETTEXT_PACKAGE);
68 #endif /* ENABLE_NLS */
69     G_GNUC_END_IGNORE_DEPRECATIONS;
70     gtk_ui_manager_insert_action_group (ui_manager, *action_group, 0);
71     g_object_unref (*action_group); /* owned by ui manager */
72 }
73 
74 
75 char *
caja_get_ui_directory(void)76 caja_get_ui_directory (void)
77 {
78     return g_strdup (DATADIR "/caja/ui");
79 }
80 
81 char *
caja_ui_file(const char * partial_path)82 caja_ui_file (const char *partial_path)
83 {
84     char *path;
85 
86     path = g_build_filename (DATADIR "/caja/ui", partial_path, NULL);
87     if (g_file_test (path, G_FILE_TEST_EXISTS))
88     {
89         return path;
90     }
91     g_free (path);
92     return NULL;
93 }
94 
95 const char *
caja_ui_string_get(const char * filename)96 caja_ui_string_get (const char *filename)
97 {
98     static GHashTable *ui_cache = NULL;
99     char *ui;
100 
101     if (ui_cache == NULL)
102     {
103         ui_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
104         eel_debug_call_at_shutdown_with_data ((GFreeFunc)g_hash_table_destroy, ui_cache);
105     }
106 
107     ui = g_hash_table_lookup (ui_cache, filename);
108     if (ui == NULL)
109     {
110         char *path;
111 
112         path = caja_ui_file (filename);
113         if (path == NULL || !g_file_get_contents (path, &ui, NULL, NULL))
114         {
115             g_warning ("Unable to load ui file %s\n", filename);
116         }
117         g_free (path);
118         g_hash_table_insert (ui_cache,
119                              g_strdup (filename),
120                              ui);
121     }
122 
123     return ui;
124 }
125 
126 static void
extension_action_callback(GtkAction * action,gpointer callback_data)127 extension_action_callback (GtkAction *action,
128                            gpointer callback_data)
129 {
130     caja_menu_item_activate (CAJA_MENU_ITEM (callback_data));
131 }
132 
133 static void
extension_action_sensitive_callback(CajaMenuItem * item,GParamSpec * arg1,gpointer user_data)134 extension_action_sensitive_callback (CajaMenuItem *item,
135                                      GParamSpec *arg1,
136                                      gpointer user_data)
137 {
138     gboolean value;
139 
140     g_object_get (G_OBJECT (item),
141                   "sensitive", &value,
142                   NULL);
143 
144     G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
145     gtk_action_set_sensitive (GTK_ACTION (user_data), value);
146     G_GNUC_END_IGNORE_DEPRECATIONS;
147 }
148 
149 static cairo_surface_t *
get_action_icon(const char * icon_name,int size,GtkWidget * parent_widget)150 get_action_icon (const char *icon_name,
151                  int         size,
152                  GtkWidget  *parent_widget)
153 {
154     CajaIconInfo *info;
155     cairo_surface_t *surface;
156     int scale;
157 
158     scale = gtk_widget_get_scale_factor (parent_widget);
159 
160     if (g_path_is_absolute (icon_name))
161     {
162         info = caja_icon_info_lookup_from_path (icon_name, size, scale);
163     }
164     else
165     {
166         info = caja_icon_info_lookup_from_name (icon_name, size, scale);
167     }
168     surface = caja_icon_info_get_surface_nodefault_at_size (info, size);
169     g_object_unref (info);
170 
171     return surface;
172 }
173 
174 GtkAction *
caja_action_from_menu_item(CajaMenuItem * item,GtkWidget * parent_widget)175 caja_action_from_menu_item (CajaMenuItem *item,
176                             GtkWidget    *parent_widget)
177 {
178     char *name, *label, *tip, *icon_name;
179     gboolean sensitive, priority;
180     GtkAction *action;
181 
182     g_object_get (G_OBJECT (item),
183                   "name", &name, "label", &label,
184                   "tip", &tip, "icon", &icon_name,
185                   "sensitive", &sensitive,
186                   "priority", &priority,
187                   NULL);
188 
189     G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
190     action = gtk_action_new (name,
191                              label,
192                              tip,
193                              icon_name);
194     G_GNUC_END_IGNORE_DEPRECATIONS;
195 
196     if (icon_name != NULL)
197     {
198         cairo_surface_t *surface;
199 
200         surface = get_action_icon (icon_name,
201                                    caja_get_icon_size_for_stock_size (GTK_ICON_SIZE_MENU),
202                                    parent_widget);
203         if (surface != NULL)
204         {
205             g_object_set_data_full (G_OBJECT (action), "menu-icon",
206                                     surface,
207                                     (GDestroyNotify)cairo_surface_destroy);
208         }
209     }
210 
211     G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
212     gtk_action_set_sensitive (action, sensitive);
213     G_GNUC_END_IGNORE_DEPRECATIONS;
214     g_object_set (action, "is-important", priority, NULL);
215 
216     g_signal_connect_data (action, "activate",
217                            G_CALLBACK (extension_action_callback),
218                            g_object_ref (item),
219                            (GClosureNotify)g_object_unref, 0);
220 
221     g_free (name);
222     g_free (label);
223     g_free (tip);
224     g_free (icon_name);
225 
226     return action;
227 }
228 
229 GtkAction *
caja_toolbar_action_from_menu_item(CajaMenuItem * item,GtkWidget * parent_widget)230 caja_toolbar_action_from_menu_item (CajaMenuItem *item, GtkWidget *parent_widget)
231 {
232     char *name, *label, *tip, *icon_name;
233     gboolean sensitive, priority;
234     GtkAction *action;
235 
236     g_object_get (G_OBJECT (item),
237                   "name", &name, "label", &label,
238                   "tip", &tip, "icon", &icon_name,
239                   "sensitive", &sensitive,
240                   "priority", &priority,
241                   NULL);
242 
243     G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
244     action = gtk_action_new (name,
245                              label,
246                              tip,
247                              icon_name);
248     G_GNUC_END_IGNORE_DEPRECATIONS;
249 
250     if (icon_name != NULL)
251     {
252         cairo_surface_t *surface;
253 
254         surface = get_action_icon (icon_name,
255                                    caja_get_icon_size_for_stock_size (GTK_ICON_SIZE_LARGE_TOOLBAR),
256                                    parent_widget);
257         if (surface != NULL)
258         {
259             g_object_set_data_full (G_OBJECT (action), "toolbar-icon",
260                                     surface,
261                                     (GDestroyNotify)cairo_surface_destroy);
262         }
263     }
264 
265     G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
266     gtk_action_set_sensitive (action, sensitive);
267     G_GNUC_END_IGNORE_DEPRECATIONS;
268     g_object_set (action, "is-important", priority, NULL);
269 
270     g_signal_connect_data (action, "activate",
271                            G_CALLBACK (extension_action_callback),
272                            g_object_ref (item),
273                            (GClosureNotify)g_object_unref, 0);
274 
275     g_signal_connect_object (item, "notify::sensitive",
276                              G_CALLBACK (extension_action_sensitive_callback),
277                              action,
278                              0);
279 
280     g_free (name);
281     g_free (label);
282     g_free (tip);
283     g_free (icon_name);
284 
285     return action;
286 }
287 
288 static GdkPixbuf *
caja_get_thumbnail_frame(void)289 caja_get_thumbnail_frame (void)
290 {
291     static GdkPixbuf *thumbnail_frame = NULL;
292 
293     if (thumbnail_frame == NULL)
294     {
295         char *image_path;
296 
297         image_path = caja_pixmap_file ("thumbnail_frame.png");
298         if (image_path != NULL)
299         {
300             thumbnail_frame = gdk_pixbuf_new_from_file (image_path, NULL);
301         }
302         g_free (image_path);
303     }
304 
305     return thumbnail_frame;
306 }
307 
308 #define CAJA_THUMBNAIL_FRAME_LEFT 3
309 #define CAJA_THUMBNAIL_FRAME_TOP 3
310 #define CAJA_THUMBNAIL_FRAME_RIGHT 3
311 #define CAJA_THUMBNAIL_FRAME_BOTTOM 3
312 
313 void
caja_ui_frame_image(GdkPixbuf ** pixbuf)314 caja_ui_frame_image (GdkPixbuf **pixbuf)
315 {
316     GdkPixbuf *pixbuf_with_frame, *frame;
317     int left_offset, top_offset, right_offset, bottom_offset;
318 
319     frame = caja_get_thumbnail_frame ();
320     if (frame == NULL) {
321         return;
322     }
323 
324     left_offset = CAJA_THUMBNAIL_FRAME_LEFT;
325     top_offset = CAJA_THUMBNAIL_FRAME_TOP;
326     right_offset = CAJA_THUMBNAIL_FRAME_RIGHT;
327     bottom_offset = CAJA_THUMBNAIL_FRAME_BOTTOM;
328 
329     pixbuf_with_frame = eel_embed_image_in_frame
330         (*pixbuf, frame,
331          left_offset, top_offset, right_offset, bottom_offset);
332     g_object_unref (*pixbuf);
333 
334     *pixbuf = pixbuf_with_frame;
335 }
336