1 /*-
2  * Copyright (c) 2004-2006 os-cillation e.K.
3  *
4  * Written by Benedikt Meurer <benny@xfce.org>.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301 USA
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #endif
29 
30 #include <exo/exo-gtk-extensions.h>
31 #include <exo/exo-private.h>
32 #include <exo/exo-thumbnail-preview.h>
33 #include <exo/exo-alias.h>
34 
35 /**
36  * SECTION: exo-gtk-extensions
37  * @title: Extensions to Gtk+
38  * @short_description: Miscelleanous extensions to the Gtk+ library
39  * @include: exo/exo.h
40  *
41  * Various additional functions to the core API provided by the Gtk+ library.
42  *
43  * For example, exo_gtk_file_chooser_add_thumbnail_preview() is a
44  * convenience method to add a thumbnail based preview widget to a
45  * #GtkFileChooser, which will display a preview of the selected file if
46  * either a thumbnail is available or a thumbnail could be generated using
47  * the GdkPixbuf library.
48  **/
49 
50 
51 
52 static gboolean
later_destroy(gpointer object)53 later_destroy (gpointer object)
54 {
55   gtk_widget_destroy (GTK_WIDGET (object));
56   g_object_unref (G_OBJECT (object));
57   return FALSE;
58 }
59 
60 
61 
62 /**
63  * exo_gtk_object_destroy_later:
64  * @object : a #GtkObject.
65  *
66  * Schedules an idle function to destroy the specified @object
67  * when the application enters the main loop the next time.
68  **/
69 void
exo_gtk_object_destroy_later(GtkWidget * object)70 exo_gtk_object_destroy_later (GtkWidget *object)
71 {
72   g_return_if_fail (GTK_IS_WIDGET (object));
73 
74   g_idle_add_full (G_PRIORITY_HIGH, later_destroy, object, NULL);
75   g_object_ref_sink (object);
76 }
77 
78 
79 
80 static void
update_preview(GtkFileChooser * chooser,ExoThumbnailPreview * thumbnail_preview)81 update_preview (GtkFileChooser      *chooser,
82                 ExoThumbnailPreview *thumbnail_preview)
83 {
84   gchar *uri;
85 
86   _exo_return_if_fail (EXO_IS_THUMBNAIL_PREVIEW (thumbnail_preview));
87   _exo_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
88 
89   /* update the URI for the preview */
90   uri = gtk_file_chooser_get_preview_uri (chooser);
91   if (G_UNLIKELY (uri == NULL))
92     {
93       /* gee, why is there a get_preview_uri() method if
94        * it doesn't work in several cases? did anybody ever
95        * test this method prior to committing it?
96        */
97       uri = gtk_file_chooser_get_uri (chooser);
98     }
99   _exo_thumbnail_preview_set_uri (thumbnail_preview, uri);
100   g_free (uri);
101 }
102 
103 
104 
105 /**
106  * exo_gtk_file_chooser_add_thumbnail_preview:
107  * @chooser : a #GtkFileChooser.
108  *
109  * This is a convenience function that adds a preview widget to the @chooser,
110  * which displays thumbnails for the selected filenames using the thumbnail
111  * database. The preview widget is also able to generate thumbnails for all
112  * image formats supported by #GdkPixbuf.
113  *
114  * Use this function whenever you display a #GtkFileChooser to ask the user
115  * to select an image file from the file system.
116  *
117  * The preview widget also supports URIs other than file:-URIs to a certain
118  * degree, but this support is rather limited currently, so you may want to
119  * use gtk_file_chooser_set_local_only() to ensure that the user can only
120  * select files from the local file system.
121  *
122  * When @chooser is configured to select multiple image files - using the
123  * gtk_file_chooser_set_select_multiple() method - the behaviour of the
124  * preview widget is currently undefined, in that it is not defined for
125  * which of the selected files the preview will be displayed.
126  *
127  * Since: 0.3.1.9
128  **/
129 void
exo_gtk_file_chooser_add_thumbnail_preview(GtkFileChooser * chooser)130 exo_gtk_file_chooser_add_thumbnail_preview (GtkFileChooser *chooser)
131 {
132   GtkWidget *thumbnail_preview;
133 
134   g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
135 
136   /* add the preview to the file chooser */
137   thumbnail_preview = _exo_thumbnail_preview_new ();
138   gtk_file_chooser_set_preview_widget (chooser, thumbnail_preview);
139   gtk_file_chooser_set_preview_widget_active (chooser, TRUE);
140   gtk_file_chooser_set_use_preview_label (chooser, FALSE);
141   gtk_widget_show (thumbnail_preview);
142 
143   /* update the preview as necessary */
144   g_signal_connect (G_OBJECT (chooser), "update-preview", G_CALLBACK (update_preview), thumbnail_preview);
145 
146   /* initially update the preview, in case the file chooser is already setup */
147   update_preview (chooser, EXO_THUMBNAIL_PREVIEW (thumbnail_preview));
148 }
149 
150 
151 
152 /**
153  * exo_gtk_url_about_dialog_hook:
154  * @about_dialog : the #GtkAboutDialog in which the user activated a link.
155  * @address      : the link, mail or web address, to open.
156  * @user_data    : user data that was passed when the function was
157  *                 registered with gtk_about_dialog_set_email_hook()
158  *                 or gtk_about_dialog_set_url_hook(). This is currently
159  *                 unused within the context of this function, so you
160  *                 can safely pass %NULL when registering this hook
161  *                 with #GtkAboutDialog.
162  *
163  * This is a convenience function, which can be registered with #GtkAboutDialog,
164  * to open links clicked by the user in #GtkAboutDialog<!---->s.
165  *
166  * All you need to do is to register this hook with gtk_about_dialog_set_url_hook()
167  * and gtk_about_dialog_set_email_hook(). This can be done prior to calling
168  * gtk_show_about_dialog(), for example:
169  *
170  * <informalexample><programlisting>
171  * static void show_about_dialog (void)
172  * {
173  *
174  *   gtk_show_about_dialog (.....);
175  * }
176  * </programlisting></informalexample>
177  *
178  * This function is not needed when you use Gtk 2.18 or later, because from
179  * that version this is implemented by default.
180  *
181  * Since: 0.5.0
182  **/
183 void
exo_gtk_url_about_dialog_hook(GtkAboutDialog * about_dialog,const gchar * address,gpointer user_data)184 exo_gtk_url_about_dialog_hook (GtkAboutDialog *about_dialog,
185                                const gchar    *address,
186                                gpointer        user_data)
187 {
188   GtkWidget *message;
189   GError    *error = NULL;
190   gchar     *uri, *escaped;
191 
192   g_return_if_fail (GTK_IS_ABOUT_DIALOG (about_dialog));
193   g_return_if_fail (address != NULL);
194 
195   /* simple check if this is an email address */
196   if (!g_str_has_prefix (address, "mailto:") && strchr (address, '@') != NULL)
197     {
198       escaped = g_uri_escape_string (address, NULL, FALSE);
199       uri = g_strdup_printf ("mailto:%s", escaped);
200       g_free (escaped);
201     }
202   else
203     {
204       uri = g_strdup (address);
205     }
206 
207   /* try to open the url on the given screen */
208   if (!gtk_show_uri_on_window (GTK_WINDOW(about_dialog), uri, gtk_get_current_event_time (), &error))
209     {
210       /* make sure to initialize i18n support first,
211        * so we'll see a translated message.
212        */
213       _exo_i18n_init ();
214 
215       /* display an error message to tell the user that we were unable to open the link */
216       message = gtk_message_dialog_new (GTK_WINDOW (about_dialog),
217                                         GTK_DIALOG_DESTROY_WITH_PARENT,
218                                         GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
219                                         _("Failed to open \"%s\"."), uri);
220       gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message), "%s.", error->message);
221       gtk_dialog_run (GTK_DIALOG (message));
222       gtk_widget_destroy (message);
223       g_error_free (error);
224     }
225 
226   /* cleanup */
227   g_free (uri);
228 }
229 
230 
231 
232 /**
233  * exo_gtk_dialog_get_action_area:
234  * @dialog : a #GtkDialog.
235  *
236  * Returns the action area of a #GtkDialog. The internal function has been
237  * deprecated in GTK+, so this wraps and dispels the deprecation warning.
238  *
239  * Returns: the action area.
240  *
241  * Since: 0.11.4
242  **/
243 GtkWidget *
exo_gtk_dialog_get_action_area(GtkDialog * dialog)244 exo_gtk_dialog_get_action_area (GtkDialog *dialog)
245 {
246 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
247     return gtk_dialog_get_action_area (dialog);
248 G_GNUC_END_IGNORE_DEPRECATIONS
249 }
250 
251 
252 
253 /**
254  * exo_gtk_dialog_add_secondary_button:
255  * @dialog : a #GtkDialog.
256  * @button : a #GtkButton to add and mark as secondary.
257  *
258  * Convenience function to add a secondary button to a #GtkDialog.
259  *
260  * Since: 0.11.4
261  **/
262 void
exo_gtk_dialog_add_secondary_button(GtkDialog * dialog,GtkWidget * button)263 exo_gtk_dialog_add_secondary_button (GtkDialog *dialog,
264                                      GtkWidget *button)
265 {
266     GtkWidget *button_box;
267 
268     button_box = exo_gtk_dialog_get_action_area (dialog);
269     gtk_box_pack_start (GTK_BOX (button_box), button, FALSE, FALSE, 0);
270     gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (button_box), button, TRUE);
271 }
272 
273 
274 
275 #define __EXO_GTK_EXTENSIONS_C__
276 #include <exo/exo-aliasdef.c>
277