source: trunk/third/evolution/shell/e-shell-shared-folder-picker-dialog.c @ 18142

Revision 18142, 14.3 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/* e-shell-shared-folder-picker-dialog.c - Implementation for the shared folder
3 * picker dialog.
4 *
5 * Copyright (C) 2002 Ximian, Inc.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU General Public
9 * License as published by the Free Software Foundation.
10 *
11 * This program 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 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 *
21 * Author: Ettore Perazzoli <ettore@ximian.com>
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include "e-shell-shared-folder-picker-dialog.h"
29
30#include "e-corba-storage.h"
31#include "e-shell-constants.h"
32#include "evolution-storage-listener.h"
33
34#include "Evolution-Addressbook-SelectNames.h"
35
36#include <gal/widgets/e-gui-utils.h>
37#include <gal/widgets/e-unicode.h>
38
39#include <libgnomeui/gnome-stock.h>
40#include <libgnomeui/gnome-dialog.h>
41#include <libgnome/gnome-i18n.h>
42#include <glade/glade.h>
43
44#include <bonobo/bonobo-exception.h>
45#include <bonobo/bonobo-listener.h>
46#include <bonobo/bonobo-widget.h>
47
48#include <gtk/gtk.h>
49
50
51/* Timeout for showing the progress dialog (msecs).  */
52
53#define PROGRESS_DIALOG_DELAY 500
54
55
56/* Dialog creation and handling.  */
57
58static void
59setup_folder_name_combo (GladeXML *glade_xml)
60{
61        GtkWidget *combo;
62        GList *string_list;
63        char *strings[] = {
64                "Calendar",
65                "Inbox",
66                "Contacts",
67                NULL
68                /* FIXME: Should these be translated?  */
69        };
70        int i;
71
72        combo = glade_xml_get_widget (glade_xml, "folder-name-combo");
73        g_assert (GTK_IS_COMBO (combo));
74
75        string_list = NULL;
76        for (i = 0; strings[i] != NULL; i ++)
77                string_list = g_list_append (string_list, strings[i]);
78        gtk_combo_set_popdown_strings (GTK_COMBO (combo), string_list);
79        g_list_free (string_list);
80
81        gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo)->entry), "Calendar");
82}
83
84static void
85user_clicked (GtkWidget *button, GNOME_Evolution_Addressbook_SelectNames corba_iface)
86{
87        CORBA_Environment ev;
88       
89        CORBA_exception_init (&ev);
90        GNOME_Evolution_Addressbook_SelectNames_activateDialog (corba_iface, "User", &ev);
91
92        if (BONOBO_EX (&ev)) {
93                g_warning ("Cannot activate SelectNames dialog -- %s", BONOBO_EX_ID (&ev));
94        }
95        CORBA_exception_free (&ev);
96}
97
98static GtkWidget *
99setup_name_selector (GladeXML *glade_xml)
100{
101        GNOME_Evolution_Addressbook_SelectNames corba_iface;
102        Bonobo_Control control;
103        CORBA_Environment ev;
104        GtkWidget *placeholder;
105        GtkWidget *control_widget;
106        GtkWidget *button;
107
108        placeholder = glade_xml_get_widget (glade_xml, "user-picker-placeholder");
109        g_assert (GTK_IS_CONTAINER (placeholder));
110
111        CORBA_exception_init (&ev);
112
113        corba_iface = oaf_activate_from_id ("OAFIID:GNOME_Evolution_Addressbook_SelectNames",
114                                            0, NULL, &ev);
115        if (corba_iface == CORBA_OBJECT_NIL || BONOBO_EX (&ev)) {
116                g_warning ("Cannot activate SelectNames -- %s", BONOBO_EX_ID (&ev));
117                CORBA_exception_free (&ev);
118                return CORBA_OBJECT_NIL;
119        }
120
121        GNOME_Evolution_Addressbook_SelectNames_addSectionWithLimit (corba_iface, "User", "User", 1, &ev);
122        if (BONOBO_EX (&ev)) {
123                g_warning ("Cannot add SelectNames section -- %s", BONOBO_EX_ID (&ev));
124                goto err;
125        }
126
127        control = GNOME_Evolution_Addressbook_SelectNames_getEntryBySection (corba_iface, "User", &ev);
128        if (BONOBO_EX (&ev)) {
129                g_warning ("Cannot get SelectNames section -- %s", BONOBO_EX_ID (&ev));
130                goto err;
131        }
132
133        control_widget = bonobo_widget_new_control_from_objref (control, CORBA_OBJECT_NIL);
134        gtk_container_add (GTK_CONTAINER (placeholder), control_widget);
135        gtk_widget_show (control_widget);
136
137        button = glade_xml_get_widget (glade_xml, "button-user");
138        gtk_signal_connect (GTK_OBJECT (button), "clicked",
139                            user_clicked, corba_iface);
140
141        CORBA_exception_free (&ev);
142        return control_widget;
143
144 err:
145        Bonobo_Unknown_unref (corba_iface, &ev);
146        CORBA_exception_free (&ev);
147        return NULL;
148}
149
150static void
151server_option_menu_item_activate_callback (GtkMenuItem *menu_item,
152                                           void *data)
153{
154        char **storage_name_return;
155
156        storage_name_return = (char **) data;
157        if (*storage_name_return != NULL)
158                g_free (*storage_name_return);
159
160        *storage_name_return = g_strdup ((const char *) gtk_object_get_data (GTK_OBJECT (menu_item),
161                                                                             "storage_name"));
162}
163
164static void
165setup_server_option_menu (EShell *shell,
166                          GladeXML *glade_xml,
167                          char **storage_name_return)
168{
169        GList *storages;
170        GList *p;
171        GtkWidget *widget;
172        GtkWidget *menu;
173
174        widget = glade_xml_get_widget (glade_xml, "server-option-menu");
175        g_assert (GTK_IS_OPTION_MENU (widget));
176
177        menu = gtk_menu_new ();
178        gtk_widget_show (menu);
179
180        *storage_name_return = NULL;
181        storages = e_storage_set_get_storage_list (e_shell_get_storage_set (shell));
182        for (p = storages; p != NULL; p = p->next) {
183                GtkWidget *menu_item;
184                const char *storage_name;
185
186                if (!e_storage_supports_shared_folders (p->data))
187                        continue;
188
189                storage_name = e_storage_get_name (E_STORAGE (p->data));
190
191                menu_item = e_utf8_gtk_menu_item_new_with_label (GTK_MENU (menu), storage_name);
192                gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
193                                    GTK_SIGNAL_FUNC (server_option_menu_item_activate_callback),
194                                    storage_name_return);
195                gtk_object_set_data_full (GTK_OBJECT (menu_item), "storage_name",
196                                          g_strdup (storage_name), g_free);
197
198                gtk_widget_show (menu_item);
199                gtk_menu_append (GTK_MENU (menu), menu_item);
200
201                if (*storage_name_return == NULL)
202                        *storage_name_return = g_strdup (storage_name);
203        }
204
205        gtk_option_menu_set_menu (GTK_OPTION_MENU (widget), menu);
206
207        /* FIXME: Default to the current storage in the shell view.  */
208}
209
210static gboolean
211show_dialog (EShell *shell,
212             EShellView *parent,
213             char **user_email_address_return,
214             char **storage_name_return,
215             char **folder_name_return)
216{
217        GladeXML *glade_xml;
218        GtkWidget *dialog;
219        GtkWidget *name_selector_widget;
220        GtkWidget *folder_name_entry;
221        int button_num;
222
223        glade_xml = glade_xml_new (EVOLUTION_GLADEDIR "/e-shell-shared-folder-picker-dialog.glade",
224                                   NULL);
225        g_assert (glade_xml != NULL);
226
227        name_selector_widget = setup_name_selector (glade_xml);
228        if (name_selector_widget == NULL)
229                return FALSE;
230
231        setup_server_option_menu (shell, glade_xml, storage_name_return);
232        setup_folder_name_combo (glade_xml);
233
234        dialog = glade_xml_get_widget (glade_xml, "dialog");
235        g_assert (dialog != NULL);
236
237        gnome_dialog_close_hides (GNOME_DIALOG (dialog), TRUE);
238
239        button_num = gnome_dialog_run_and_close (GNOME_DIALOG (dialog));
240        if (button_num == 1) {  /* Cancel */
241                g_free (*storage_name_return);
242                *storage_name_return = NULL;
243                gtk_widget_destroy (dialog);
244                return FALSE;
245        }
246
247        bonobo_widget_get_property (BONOBO_WIDGET (name_selector_widget),
248                                    "addresses", user_email_address_return,
249                                    NULL);
250
251        folder_name_entry = glade_xml_get_widget (glade_xml, "folder-name-entry");
252        *folder_name_return = g_strdup (gtk_entry_get_text (GTK_ENTRY (folder_name_entry)));
253
254        gtk_widget_destroy (dialog);
255        return TRUE;
256}
257
258
259/* Discovery process.  */
260
261struct _DiscoveryData {
262        EShell *shell;
263        EShellView *parent;
264        GtkWidget *dialog;
265        char *user_email_address;
266        char *folder_name;
267        EStorage *storage;
268};
269typedef struct _DiscoveryData DiscoveryData;
270
271static void
272cleanup_discovery (DiscoveryData *discovery_data)
273{
274        if (discovery_data->dialog != NULL)
275                gtk_widget_destroy (discovery_data->dialog);
276
277        g_free (discovery_data->user_email_address);
278        g_free (discovery_data->folder_name);
279        gtk_object_unref (GTK_OBJECT (discovery_data->storage));
280        g_free (discovery_data);
281}
282
283static int
284progress_bar_timeout_callback (void *data)
285{
286        GtkAdjustment *adjustment;
287        float value;
288
289        adjustment = GTK_PROGRESS (data)->adjustment;
290        value = adjustment->value + 1;
291        if (value > adjustment->upper)
292                value = adjustment->lower;
293
294        gtk_progress_set_value (GTK_PROGRESS (data), value);
295
296        return TRUE;
297}
298
299static void
300progress_bar_destroy_callback (GtkObject *object,
301                               void *data)
302{
303        int timeout_id;
304
305        timeout_id = GPOINTER_TO_INT (data);
306        g_source_remove (timeout_id);
307}
308
309static int
310progress_dialog_close_callback (GnomeDialog *dialog,
311                                void *data)
312{
313        /* Don't allow the dialog to be closed through the window manager close
314           command.  */
315        return TRUE;
316}
317
318/* This is invoked if the "Cancel" button is clicked.  */
319static void
320progress_dialog_clicked_callback (GnomeDialog *dialog,
321                                  int button_number,
322                                  void *data)
323{
324        DiscoveryData *discovery_data;
325
326        discovery_data = (DiscoveryData *) data;
327
328        e_storage_cancel_discover_shared_folder (discovery_data->storage,
329                                                 discovery_data->user_email_address,
330                                                 discovery_data->folder_name);
331
332        cleanup_discovery (discovery_data);
333}
334
335static int
336progress_dialog_show_timeout_callback (void *data)
337{
338        GtkWidget *dialog;
339
340        dialog = GTK_WIDGET (data);
341        gtk_widget_show_all (dialog);
342        return FALSE;
343}
344
345static GtkWidget *
346create_progress_dialog (EShell *shell,
347                        EStorage *storage,
348                        const char *user_email_address,
349                        const char *folder_name)
350{
351        GtkWidget *dialog;
352        GtkWidget *label;
353        GtkWidget *progress_bar;
354        int timeout_id;
355        char *text;
356
357        dialog = gnome_dialog_new (_("Opening Folder"), GNOME_STOCK_BUTTON_CANCEL, NULL);
358        gtk_widget_set_usize (dialog, 300, -1);
359        gtk_window_set_policy (GTK_WINDOW (dialog), FALSE, FALSE, FALSE);
360
361        gtk_signal_connect (GTK_OBJECT (dialog), "close",
362                            GTK_SIGNAL_FUNC (progress_dialog_close_callback), NULL);
363
364        text = g_strdup_printf (_("Opening Folder \"%s\""), folder_name);
365        label = gtk_label_new (text);
366        gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label, FALSE, TRUE, 0);
367        g_free (text);
368
369        text = g_strdup_printf (_("in \"%s\" ..."), e_storage_get_name (storage));
370        label = gtk_label_new (text);
371        gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label, FALSE, TRUE, 0);
372        g_free (text);
373
374        progress_bar = gtk_progress_bar_new ();
375        gtk_progress_set_activity_mode (GTK_PROGRESS (progress_bar), TRUE);
376        gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), progress_bar, FALSE, TRUE, 0);
377
378        timeout_id = g_timeout_add (50, progress_bar_timeout_callback, progress_bar);
379        gtk_signal_connect (GTK_OBJECT (progress_bar), "destroy",
380                            GTK_SIGNAL_FUNC (progress_bar_destroy_callback),
381                            GINT_TO_POINTER (timeout_id));
382
383        timeout_id = g_timeout_add (PROGRESS_DIALOG_DELAY, progress_dialog_show_timeout_callback, dialog);
384        gtk_signal_connect (GTK_OBJECT (progress_bar), "destroy",
385                            GTK_SIGNAL_FUNC (progress_bar_destroy_callback),
386                            GINT_TO_POINTER (timeout_id));
387
388        return dialog;
389}
390
391static void
392shell_destroy_callback (GtkObject *object,
393                        void *data)
394{
395        DiscoveryData *discovery_data;
396
397        discovery_data = (DiscoveryData *) data;
398        cleanup_discovery (discovery_data);
399}
400
401static void
402shell_view_destroy_callback (GtkObject *object,
403                             void *data)
404{
405        DiscoveryData *discovery_data;
406
407        discovery_data = (DiscoveryData *) data;
408        discovery_data->parent = NULL;
409}
410
411static void
412storage_destroy_callback (GtkObject *object,
413                          void *data)
414{
415        DiscoveryData *discovery_data;
416
417        discovery_data = (DiscoveryData *) data;
418        cleanup_discovery (discovery_data);
419
420        /* FIXME: Should we signal the user when this happens?  I.e. when the
421           storage dies for some reason before the folder is discovered.  */
422}
423
424static void
425shared_folder_discovery_callback (EStorage *storage,
426                                  EStorageResult result,
427                                  const char *path,
428                                  void *data)
429{
430        DiscoveryData *discovery_data;
431        EShell *shell;
432        EShellView *parent;
433
434        discovery_data = (DiscoveryData *) data;
435        shell = discovery_data->shell;
436        parent = discovery_data->parent;
437
438        /* Make sure the progress dialog doesn't show up now. */
439        cleanup_discovery (discovery_data);
440
441        if (result == E_STORAGE_OK) {
442                char *uri;
443
444                uri = g_strconcat (E_SHELL_URI_PREFIX, "/",
445                                   e_storage_get_name (storage),
446                                   path, NULL);
447
448                if (discovery_data->parent != NULL)
449                        e_shell_view_display_uri (parent, uri, TRUE);
450                else
451                        e_shell_create_view (shell, uri, NULL);
452        } else {
453                e_notice (parent ? GTK_WINDOW (parent) : NULL,
454                          GNOME_MESSAGE_BOX_ERROR,
455                          _("Could not open shared folder: %s."),
456                          e_storage_result_to_string (result));
457        }
458}
459
460static void
461discover_folder (EShell *shell,
462                 EShellView *parent,
463                 const char *user_email_address,
464                 const char *storage_name,
465                 const char *folder_name)
466{
467        EStorageSet *storage_set;
468        EStorage *storage;
469        GtkWidget *dialog;
470        DiscoveryData *discovery_data;
471
472        storage_set = e_shell_get_storage_set (shell);
473        if (storage_set == NULL)
474                goto error;
475
476        storage = e_storage_set_get_storage (storage_set, storage_name);
477        if (storage == NULL || ! e_storage_supports_shared_folders (storage))
478                goto error;
479
480        dialog = create_progress_dialog (shell, storage, user_email_address, folder_name);
481
482        discovery_data = g_new (DiscoveryData, 1);
483        discovery_data->dialog             = dialog;
484        discovery_data->shell              = shell;
485        discovery_data->parent             = parent;
486        discovery_data->user_email_address = g_strdup (user_email_address);
487        discovery_data->folder_name        = g_strdup (folder_name);
488        discovery_data->storage            = storage;
489        gtk_object_ref (GTK_OBJECT (storage));
490
491        gtk_signal_connect (GTK_OBJECT (shell), "destroy",
492                            GTK_SIGNAL_FUNC (shell_destroy_callback), discovery_data);
493
494        gtk_signal_connect (GTK_OBJECT (parent), "destroy",
495                            GTK_SIGNAL_FUNC (shell_view_destroy_callback), discovery_data);
496
497        gtk_signal_connect (GTK_OBJECT (storage), "destroy",
498                            GTK_SIGNAL_FUNC (storage_destroy_callback), discovery_data);
499
500        gtk_signal_connect (GTK_OBJECT (dialog), "clicked",
501                            GTK_SIGNAL_FUNC (progress_dialog_clicked_callback), discovery_data);
502
503        e_storage_async_discover_shared_folder (storage,
504                                                user_email_address,
505                                                folder_name,
506                                                shared_folder_discovery_callback,
507                                                discovery_data);
508        return;
509
510 error:
511        /* FIXME: Be more verbose?  */
512        e_notice (GTK_WINDOW (parent), GNOME_MESSAGE_BOX_ERROR,
513                  _("Cannot find the specified shared folder."));
514}
515
516
517void
518e_shell_show_shared_folder_picker_dialog (EShell *shell,
519                                          EShellView *parent)
520{
521        char *user_email_address;
522        char *storage_name;
523        char *folder_name;
524
525        g_return_if_fail (E_IS_SHELL (shell));
526
527        if (! show_dialog (shell, parent, &user_email_address, &storage_name, &folder_name))
528                return;
529
530        discover_folder (shell, parent, user_email_address, storage_name, folder_name);
531
532        g_free (user_email_address);
533        g_free (storage_name);
534        g_free (folder_name);
535}
Note: See TracBrowser for help on using the repository browser.