source: trunk/third/evolution/shell/evolution-folder-selector-button.c @ 18142

Revision 18142, 12.2 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18141, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/* evolution-folder-selector-button.c
3 *
4 * Copyright (C) 2002 Ximian, Inc.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 */
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
25#include "evolution-folder-selector-button.h"
26#include <bonobo/bonobo-ui-toolbar-icon.h>
27#include <gal/util/e-util.h>
28#include <gal/widgets/e-unicode.h>
29#include <gtk/gtkhbox.h>
30#include <gtk/gtklabel.h>
31#include <libgnome/gnome-i18n.h>
32
33
34struct _EvolutionFolderSelectorButtonPrivate {
35        EvolutionShellClient *shell_client;
36        GNOME_Evolution_StorageRegistry corba_storage_registry;
37        GNOME_Evolution_Folder *selected_folder;
38        GtkWidget *icon, *label;
39        char *title, **possible_types;
40};
41
42enum {
43        POPPED_UP,
44        SELECTED,
45        CANCELED,
46        LAST_SIGNAL
47};
48static guint signals[LAST_SIGNAL] = { 0 };
49
50#define PARENT_TYPE gtk_button_get_type ()
51static GtkButtonClass *parent_class = NULL;
52
53
54static GNOME_Evolution_Folder *
55get_folder_for_uri (EvolutionFolderSelectorButton *folder_selector_button,
56                    const char *uri)
57{
58        EvolutionFolderSelectorButtonPrivate *priv = folder_selector_button->priv;
59        CORBA_Environment ev;
60        GNOME_Evolution_Folder *folder;
61
62        if (!uri)
63                return NULL;
64
65        CORBA_exception_init (&ev);
66        folder = GNOME_Evolution_StorageRegistry_getFolderByUri (
67                priv->corba_storage_registry, uri, &ev);
68        if (ev._major != CORBA_NO_EXCEPTION)
69                folder = CORBA_OBJECT_NIL;
70        CORBA_exception_free (&ev);
71
72        return folder;
73}
74
75static void
76set_folder (EvolutionFolderSelectorButton *folder_selector_button,
77            GNOME_Evolution_Folder *folder)
78{
79        GtkWidget *w = GTK_WIDGET (folder_selector_button);
80        EvolutionFolderSelectorButtonPrivate *priv;
81        GdkPixbuf *pixbuf;
82        char *folder_lname, *storage_lname, *label_text;
83        const char *p;
84
85        priv = folder_selector_button->priv;
86
87        if (priv->selected_folder)
88                CORBA_free (priv->selected_folder);
89        priv->selected_folder = folder;
90
91        if (!folder) {
92                bonobo_ui_toolbar_icon_clear (BONOBO_UI_TOOLBAR_ICON (priv->icon));
93                gtk_label_set_text (GTK_LABEL (priv->label),
94                                    _("<click here to select a folder>"));
95                return;
96        }
97
98        pixbuf = evolution_shell_client_get_pixbuf_for_type (priv->shell_client, folder->type, TRUE);
99        bonobo_ui_toolbar_icon_set_pixbuf (BONOBO_UI_TOOLBAR_ICON (priv->icon), pixbuf);
100        gdk_pixbuf_unref (pixbuf);
101
102        folder_lname = e_utf8_to_gtk_string (w, folder->displayName);
103        storage_lname = NULL;
104        p = strchr (folder->evolutionUri, '/');
105        if (p) {
106                p = strchr (p + 1, '/');
107                if (p) {
108                        GNOME_Evolution_Folder *storage_folder;
109                        char *storage_uri;
110
111                        storage_uri = g_strndup (folder->evolutionUri,
112                                                 p - folder->evolutionUri);
113                        storage_folder = get_folder_for_uri (folder_selector_button, storage_uri);
114                        storage_lname = e_utf8_to_gtk_string (w, storage_folder->displayName);
115                        CORBA_free (storage_folder);
116                        g_free (storage_uri);
117                }
118        }
119
120        if (storage_lname) {
121                label_text = g_strdup_printf (_("\"%s\" in \"%s\""), folder_lname,
122                                              storage_lname);
123                g_free (storage_lname);
124        } else
125                label_text = g_strdup_printf ("\"%s\"", folder_lname);
126
127        gtk_label_set_text (GTK_LABEL (priv->label), label_text);
128        g_free (label_text);
129        g_free (folder_lname);
130}
131
132static void
133clicked (GtkButton *button)
134{
135        EvolutionFolderSelectorButton *folder_selector_button;
136        EvolutionFolderSelectorButtonPrivate *priv;
137        GNOME_Evolution_Folder *return_folder;
138        GtkWindow *parent_window;
139        char *initial_uri;
140
141        parent_window = (GtkWindow *)
142                gtk_widget_get_ancestor (GTK_WIDGET (button),
143                                         GTK_TYPE_WINDOW);
144
145        gtk_widget_set_sensitive (GTK_WIDGET (parent_window), FALSE);
146        gtk_object_ref (GTK_OBJECT (parent_window));
147
148        folder_selector_button = EVOLUTION_FOLDER_SELECTOR_BUTTON (button);
149        priv = folder_selector_button->priv;
150
151        if (priv->selected_folder)
152                initial_uri = priv->selected_folder->evolutionUri;
153        else
154                initial_uri = "";
155
156        gtk_signal_emit (GTK_OBJECT (folder_selector_button),
157                         signals[POPPED_UP]);
158
159        evolution_shell_client_user_select_folder (priv->shell_client,
160                                                   parent_window,
161                                                   priv->title,
162                                                   initial_uri,
163                                                   (const char **)priv->possible_types,
164                                                   &return_folder);
165
166        /* If the parent gets destroyed despite our best efforts (eg,
167         * because its own parent got destroyed), then the folder
168         * selector button will have been destroyed too and we need
169         * to just bail out here.
170         */
171        if (GTK_OBJECT_DESTROYED (parent_window)) {
172                gtk_object_unref (GTK_OBJECT (parent_window));
173                return;
174        }
175
176        gtk_widget_set_sensitive (GTK_WIDGET (parent_window), TRUE);
177        gtk_object_unref (GTK_OBJECT (parent_window));
178
179        if (!return_folder) {
180                gtk_signal_emit (GTK_OBJECT (folder_selector_button),
181                                signals[CANCELED]);
182                return;
183        }
184
185        set_folder (folder_selector_button, return_folder);
186
187        gtk_signal_emit (GTK_OBJECT (folder_selector_button),
188                         signals[SELECTED], return_folder);
189}
190
191
192/* GtkObject methods.  */
193
194static void
195destroy (GtkObject *object)
196{
197        EvolutionFolderSelectorButton *folder_selector_button;
198        EvolutionFolderSelectorButtonPrivate *priv;
199        int i;
200
201        folder_selector_button = EVOLUTION_FOLDER_SELECTOR_BUTTON (object);
202        priv = folder_selector_button->priv;
203
204        bonobo_object_unref (BONOBO_OBJECT (priv->shell_client));
205        g_free (priv->title);
206        for (i = 0; priv->possible_types[i]; i++)
207                g_free (priv->possible_types[i]);
208        g_free (priv->possible_types);
209
210        if (priv->selected_folder)
211                CORBA_free (priv->selected_folder);
212
213        g_free (priv);
214
215        (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
216}
217
218
219static void
220class_init (EvolutionFolderSelectorButtonClass *klass)
221{
222        GtkObjectClass *object_class;
223        GtkButtonClass *button_class;
224
225        parent_class = gtk_type_class (PARENT_TYPE);
226
227        object_class = GTK_OBJECT_CLASS (klass);
228        button_class = GTK_BUTTON_CLASS (klass);
229
230        button_class->clicked = clicked;
231        object_class->destroy = destroy;
232
233        signals[POPPED_UP] = gtk_signal_new ("popped_up",
234                                            GTK_RUN_FIRST,
235                                            object_class->type,
236                                            GTK_SIGNAL_OFFSET (EvolutionFolderSelectorButtonClass, popped_up),
237                                            gtk_marshal_NONE__NONE,
238                                            GTK_TYPE_NONE, 0);
239        signals[SELECTED] = gtk_signal_new ("selected",
240                                            GTK_RUN_FIRST,
241                                            object_class->type,
242                                            GTK_SIGNAL_OFFSET (EvolutionFolderSelectorButtonClass, selected),
243                                            gtk_marshal_NONE__POINTER,
244                                            GTK_TYPE_NONE, 1,
245                                            GTK_TYPE_POINTER);
246        signals[CANCELED] = gtk_signal_new ("canceled",
247                                            GTK_RUN_FIRST,
248                                            object_class->type,
249                                            GTK_SIGNAL_OFFSET (EvolutionFolderSelectorButtonClass, canceled),
250                                            gtk_marshal_NONE__NONE,
251                                            GTK_TYPE_NONE, 0);
252        gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
253}
254
255static void
256init (EvolutionFolderSelectorButton *folder_selector_button)
257{
258        EvolutionFolderSelectorButtonPrivate *priv;
259        GtkWidget *box;
260
261        priv = g_new0 (EvolutionFolderSelectorButtonPrivate, 1);
262
263        priv->icon = bonobo_ui_toolbar_icon_new ();
264        priv->label = gtk_label_new ("");
265        gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_LEFT);
266        gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.0);
267        box = gtk_hbox_new (FALSE, 4);
268        gtk_box_pack_start (GTK_BOX (box), priv->icon, FALSE, TRUE, 0);
269        gtk_box_pack_start (GTK_BOX (box), priv->label, TRUE, TRUE, 0);
270        gtk_widget_show_all (GTK_WIDGET (box));
271        gtk_container_add (GTK_CONTAINER (folder_selector_button), box);
272
273        folder_selector_button->priv = priv;
274}
275
276
277
278/**
279 * evolution_folder_selector_button_construct:
280 * @folder_selector_button:
281 * @shell_client: the shell client that will be used for folder selection
282 * @title: the title to use for the selection dialog
283 * @initial_uri: the URI (evolution: or physical) of the
284 * initially-selected folder
285 * @possible_types: a %NULL-terminated array of selectable types.
286 *
287 * Construct @folder_selector_button.
288 **/
289void
290evolution_folder_selector_button_construct (EvolutionFolderSelectorButton *folder_selector_button,
291                                            EvolutionShellClient *shell_client,
292                                            const char *title,
293                                            const char *initial_uri,
294                                            const char *possible_types[])
295{
296        EvolutionFolderSelectorButtonPrivate *priv;
297        GNOME_Evolution_Folder *folder;
298        int count;
299
300        g_return_if_fail (EVOLUTION_IS_FOLDER_SELECTOR_BUTTON (folder_selector_button));
301        g_return_if_fail (EVOLUTION_IS_SHELL_CLIENT (shell_client));
302        g_return_if_fail (possible_types != NULL);
303
304        priv = folder_selector_button->priv;
305
306        priv->shell_client = shell_client;
307        bonobo_object_ref (BONOBO_OBJECT (shell_client));
308        priv->corba_storage_registry = evolution_shell_client_get_storage_registry_interface (shell_client);
309
310        priv->title = g_strdup (title);
311
312        folder = get_folder_for_uri (folder_selector_button, initial_uri);
313        set_folder (folder_selector_button, folder);
314
315        for (count = 0; possible_types[count]; count++)
316                ;
317        priv->possible_types = g_new (char *, count + 1);
318        for (count = 0; possible_types[count]; count++)
319                priv->possible_types[count] = g_strdup (possible_types[count]);
320        priv->possible_types[count] = NULL;
321}
322
323/**
324 * evolution_folder_selector_button_new:
325 * @shell_client: the shell client that will be used for folder selection
326 * @title: the title to use for the selection dialog
327 * @initial_uri: the URI (evolution: or physical) of the
328 * initially-selected folder
329 * @possible_types: a %NULL-terminated array of selectable types.
330 *
331 * Return value: a new folder selector button.
332 **/
333GtkWidget *
334evolution_folder_selector_button_new (EvolutionShellClient *shell_client,
335                                      const char *title,
336                                      const char *initial_uri,
337                                      const char *possible_types[])
338{
339        EvolutionFolderSelectorButton *folder_selector_button;
340
341        folder_selector_button = gtk_type_new (evolution_folder_selector_button_get_type ());
342
343        evolution_folder_selector_button_construct (folder_selector_button,
344                                                    shell_client,
345                                                    title,
346                                                    initial_uri,
347                                                    possible_types);
348        return (GtkWidget *)folder_selector_button;
349}
350
351/**
352 * evolution_folder_selector_button_set_uri:
353 * @folder_selector_button:
354 * @uri: the URI (evolution: or physical) to select, or %NULL
355 *
356 * Attempts to make @folder_selector_button select @uri. If @uri
357 * doesn't point to a folder, or points to a folder of an incorrect
358 * type for this button, then the selected URI will be unchanged.
359 *
360 * If @uri is %NULL, the button will be returned to an unselected
361 * state.
362 *
363 * Return value: whether or not the URI was successfully set.
364 **/
365gboolean
366evolution_folder_selector_button_set_uri (EvolutionFolderSelectorButton *folder_selector_button,
367                                          const char *uri)
368{
369        EvolutionFolderSelectorButtonPrivate *priv;
370        GNOME_Evolution_Folder *folder;
371        char *slash;
372        int i;
373
374        g_return_val_if_fail (EVOLUTION_IS_FOLDER_SELECTOR_BUTTON (folder_selector_button), FALSE);
375        g_return_val_if_fail (uri != NULL, FALSE);
376
377        priv = folder_selector_button->priv;
378
379        if (!uri) {
380                set_folder (folder_selector_button, NULL);
381                return TRUE;
382        }
383
384        folder = get_folder_for_uri (folder_selector_button, uri);
385        if (!folder)
386                return FALSE;
387
388        for (i = 0; priv->possible_types[i]; i++) {
389                if (!strcmp (folder->type, priv->possible_types[i])) {
390                        set_folder (folder_selector_button, folder);
391                        return TRUE;
392                }
393                slash = strchr (priv->possible_types[i], '/');
394                if (slash && slash[1] == '*' &&
395                    !strncmp (folder->type, priv->possible_types[i],
396                              slash - priv->possible_types[i])) {
397                        set_folder (folder_selector_button, folder);
398                        return TRUE;
399                }
400        }
401
402        CORBA_free (folder);
403        return FALSE;
404}
405
406/**
407 * evolution_folder_selector_button_get_folder:
408 * @folder_selector_button:
409 *
410 * Return value: the currently-selected folder, or %NULL
411 **/
412GNOME_Evolution_Folder *
413evolution_folder_selector_button_get_folder (EvolutionFolderSelectorButton *folder_selector_button)
414{
415        g_return_val_if_fail (EVOLUTION_IS_FOLDER_SELECTOR_BUTTON (folder_selector_button), NULL);
416
417        return folder_selector_button->priv->selected_folder;
418}
419
420
421E_MAKE_TYPE (evolution_folder_selector_button, "EvolutionFolderSelectorButton", EvolutionFolderSelectorButton, class_init, init, PARENT_TYPE)
Note: See TracBrowser for help on using the repository browser.