source: trunk/third/evolution/shell/e-activity-handler.c @ 18142

Revision 18142, 14.1 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-activity-handler.c
3 *
4 * Copyright (C) 2001  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 * Author: Ettore Perazzoli <ettore@ximian.com>
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include "e-activity-handler.h"
28
29#include "e-shell-corba-icon-utils.h"
30
31#include <gtk/gtksignal.h>
32#include <gdk-pixbuf/gdk-pixbuf.h>
33
34#include <libgnome/gnome-i18n.h>
35#include <libgnomeui/gnome-popup-menu.h>
36
37#include <gal/util/e-util.h>
38#include <gal/widgets/e-popup-menu.h>
39
40
41#define PARENT_TYPE bonobo_x_object_get_type ()
42static BonoboXObjectClass *parent_class = NULL;
43
44
45#define ICON_SIZE 16
46
47
48struct _ActivityInfo {
49        char *component_id;
50        GdkPixbuf *icon_pixbuf;
51        GNOME_Evolution_Activity_ActivityId id;
52        CORBA_char *information;
53        CORBA_boolean cancellable;
54        Bonobo_Listener event_listener;
55        CORBA_float progress;
56        GtkWidget *menu;
57};
58typedef struct _ActivityInfo ActivityInfo;
59
60struct _EActivityHandlerPrivate {
61        GNOME_Evolution_Activity_ActivityId next_activity_id;
62        GList *activity_infos;
63        GSList *task_bars;
64};
65
66
67/* Utility functions.  */
68
69static unsigned int
70get_new_activity_id (EActivityHandler *activity_handler)
71{
72        EActivityHandlerPrivate *priv;
73
74        priv = activity_handler->priv;
75
76        return priv->next_activity_id ++;
77}
78
79static GList *
80lookup_activity (GList *list,
81                 GNOME_Evolution_Activity_ActivityId activity_id,
82                 int *order_number_return)
83{
84        GList *p;
85        int i;
86
87        for (p = list, i = 0; p != NULL; p = p->next, i ++) {
88                ActivityInfo *activity_info;
89
90                activity_info = (ActivityInfo *) p->data;
91                if (activity_info->id == activity_id) {
92                        *order_number_return = i;
93                        return p;
94                }
95        }
96
97        *order_number_return = -1;
98        return NULL;
99}
100
101#if 0
102static const CORBA_any *
103get_corba_null_value (void)
104{
105        static CORBA_any *null_value = NULL;
106
107        if (null_value == NULL) {
108                null_value = CORBA_any__alloc ();
109                null_value->_type = TC_null;
110        }
111
112        return null_value;
113}
114
115static void
116report_task_event (ActivityInfo *activity_info,
117                   const char *event_name)
118{
119        CORBA_Environment ev;
120
121        CORBA_exception_init (&ev);
122
123        Bonobo_Listener_event (activity_info->event_listener, event_name, get_corba_null_value (), &ev);
124        if (ev._major != CORBA_NO_EXCEPTION)
125                g_warning ("EActivityHandler: Cannot event `%s' -- %s", event_name, ev._repo_id);
126
127        CORBA_exception_free (&ev);
128}
129#endif
130
131
132/* ETaskWidget actions.  */
133
134#if 0
135static void
136task_widget_cancel_callback (GtkWidget *widget,
137                             void *data)
138{
139        ActivityInfo *activity_info;
140
141        activity_info = (ActivityInfo *) data;
142        report_task_event (activity_info, "Cancel");
143}
144
145static void
146task_widget_show_details_callback (GtkWidget *widget,
147                                   void *data)
148{
149        ActivityInfo *activity_info;
150
151        activity_info = (ActivityInfo *) data;
152        report_task_event (activity_info, "ShowDetails");
153}
154
155static void
156show_cancellation_popup (ActivityInfo *activity_info,
157                         GtkWidget *task_widget,
158                         GdkEventButton *button_event)
159{
160        GtkMenu *popup;
161        EPopupMenu items[] = {
162                E_POPUP_MENU (N_("Show Details"), task_widget_show_details_callback, 0),
163                E_POPUP_SEPARATOR,
164                E_POPUP_MENU (N_("Cancel Operation"), task_widget_cancel_callback, 0),
165                E_POPUP_TERMINATOR
166        };
167
168        /* FIXME: We should gray out things properly here.  */
169        popup = e_popup_menu_create (items, 0, 0, activity_info);
170
171        g_assert (activity_info->menu == NULL);
172        activity_info->menu = GTK_WIDGET (popup);
173
174        gnome_popup_menu_do_popup_modal (GTK_WIDGET (popup), NULL, NULL, button_event, activity_info);
175
176        activity_info->menu = NULL;
177}
178#endif
179
180static int
181task_widget_button_press_event_callback (GtkWidget *widget,
182                                         GdkEventButton *button_event,
183                                         void *data)
184{
185        CORBA_Environment ev;
186        ActivityInfo *activity_info;
187        CORBA_any *null_value;
188
189        activity_info = (ActivityInfo *) data;
190
191        if (button_event->button == 3) {
192                if (! activity_info->cancellable) {
193                        return FALSE;
194                } else {
195                        /* show_cancellation_popup (activity_info, widget, button_event); */
196                        /* return TRUE; */
197                        return TRUE;
198                }
199        }
200
201        if (button_event->button != 1)
202                return FALSE;
203
204        CORBA_exception_init (&ev);
205
206        null_value = CORBA_any__alloc ();
207        null_value->_type = TC_null;
208
209        Bonobo_Listener_event (activity_info->event_listener, "Clicked", null_value, &ev);
210        if (ev._major != CORBA_NO_EXCEPTION)
211                g_warning ("EActivityHandler: Cannot report `Clicked' event -- %s",
212                           ev._repo_id);
213
214        CORBA_free (null_value);
215 
216        CORBA_exception_free (&ev);
217
218        return TRUE;
219}
220
221
222/* Creating and destroying ActivityInfos.  */
223
224static ActivityInfo *
225activity_info_new (const char *component_id,
226                   GNOME_Evolution_Activity_ActivityId id,
227                   GdkPixbuf *icon,
228                   const CORBA_char *information,
229                   CORBA_boolean cancellable,
230                   const Bonobo_Listener event_listener)
231{
232        ActivityInfo *info;
233        CORBA_Environment ev;
234
235        CORBA_exception_init (&ev);
236
237        info = g_new (ActivityInfo, 1);
238        info->component_id   = g_strdup (component_id);
239        info->id             = id;
240        info->icon_pixbuf    = gdk_pixbuf_ref (icon);
241        info->information    = CORBA_string_dup (information);
242        info->cancellable    = cancellable;
243        info->event_listener = CORBA_Object_duplicate (event_listener, &ev);
244        info->progress       = -1.0; /* (Unknown) */
245        info->menu           = NULL;
246
247        CORBA_exception_free (&ev);
248
249        return info;
250}
251
252static void
253activity_info_free (ActivityInfo *info)
254{
255        CORBA_Environment ev;
256
257        CORBA_exception_init (&ev);
258
259        g_free (info->component_id);
260
261        gdk_pixbuf_unref (info->icon_pixbuf);
262        CORBA_free (info->information);
263        CORBA_Object_release (info->event_listener, &ev);
264
265        if (info->menu != NULL)
266                gtk_widget_destroy (info->menu);
267
268        g_free (info);
269
270        CORBA_exception_free (&ev);
271}
272
273static ETaskWidget *
274task_widget_new_from_activity_info (ActivityInfo *activity_info)
275{
276        GtkWidget *widget;
277
278        widget = e_task_widget_new (activity_info->icon_pixbuf,
279                                    activity_info->component_id,
280                                    activity_info->information);
281        gtk_widget_show (widget);
282
283        gtk_signal_connect (GTK_OBJECT (widget), "button_press_event",
284                            GTK_SIGNAL_FUNC (task_widget_button_press_event_callback), activity_info);
285
286        return E_TASK_WIDGET (widget);
287}
288
289
290/* Task Bar handling.  */
291
292static void
293setup_task_bar (EActivityHandler *activity_handler,
294                ETaskBar *task_bar)
295{
296        EActivityHandlerPrivate *priv;
297        GList *p;
298
299        priv = activity_handler->priv;
300
301        for (p = g_list_last (priv->activity_infos); p != NULL; p = p->prev) {
302                e_task_bar_prepend_task (task_bar,
303                                         task_widget_new_from_activity_info ((ActivityInfo *) p->data));
304        }
305}
306
307static void
308task_bar_destroy_callback (GtkObject *task_bar_object,
309                           void *data)
310{
311        ETaskBar *task_bar;
312        EActivityHandler *activity_handler;
313        EActivityHandlerPrivate *priv;
314
315        task_bar = E_TASK_BAR (task_bar_object);
316
317        activity_handler = E_ACTIVITY_HANDLER (data);
318        priv = activity_handler->priv;
319
320        priv->task_bars = g_slist_remove (priv->task_bars, task_bar);
321}
322
323
324/* GtkObject methods.  */
325
326static void
327impl_destroy (GtkObject *object)
328{
329        EActivityHandler *handler;
330        EActivityHandlerPrivate *priv;
331        GList *p;
332
333        handler = E_ACTIVITY_HANDLER (object);
334        priv = handler->priv;
335
336        for (p = priv->activity_infos; p != NULL; p = p->next) {
337                ActivityInfo *info;
338
339                info = (ActivityInfo *) p->data;
340                activity_info_free (info);
341        }
342
343        g_free (priv);
344        handler->priv = NULL;
345
346        (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
347}
348
349
350/* CORBA methods.  */
351
352static void
353impl_operationStarted (PortableServer_Servant servant,
354                       const CORBA_char *component_id,
355                       const GNOME_Evolution_AnimatedIcon *icon,
356                       const CORBA_char *information,
357                       const CORBA_boolean cancellable,
358                       const Bonobo_Listener event_listener,
359                       GNOME_Evolution_Activity_ActivityId *activity_id_return,
360                       CORBA_boolean *suggest_display_return,
361                       CORBA_Environment *ev)
362{
363        EActivityHandler *activity_handler;
364        EActivityHandlerPrivate *priv;
365        ActivityInfo *activity_info;
366        GdkPixbuf *icon_pixbuf;
367        unsigned int activity_id;
368        GSList *p;
369
370        activity_handler = E_ACTIVITY_HANDLER (bonobo_object_from_servant (servant));
371
372        if (GTK_OBJECT_DESTROYED (activity_handler) || activity_handler->priv == NULL)
373                return;
374
375        priv = activity_handler->priv;
376
377        if (icon->_length == 0) {
378                CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
379                                     ex_GNOME_Evolution_Activity_InvalidIcon, NULL);
380                return;
381        }
382
383        if (icon->_length > 1)
384                g_warning ("Animated icons are not supported for activities (yet).");
385
386        icon_pixbuf = e_new_gdk_pixbuf_from_corba_icon (icon->_buffer, ICON_SIZE, ICON_SIZE);
387
388        activity_id = get_new_activity_id (activity_handler);
389
390        activity_info = activity_info_new (component_id, activity_id, icon_pixbuf, information,
391                                           cancellable, event_listener);
392
393        for (p = priv->task_bars; p != NULL; p = p->next)
394                e_task_bar_prepend_task (E_TASK_BAR (p->data),
395                                         task_widget_new_from_activity_info (activity_info));
396
397        gdk_pixbuf_unref (icon_pixbuf);
398
399        priv->activity_infos = g_list_prepend (priv->activity_infos, activity_info);
400
401        *activity_id_return = activity_id;
402}
403
404static void
405impl_operationProgressing (PortableServer_Servant servant,
406                           const GNOME_Evolution_Activity_ActivityId activity_id,
407                           const CORBA_char *information,
408                           const CORBA_float progress,
409                           CORBA_Environment *ev)
410{
411        EActivityHandler *activity_handler;
412        EActivityHandlerPrivate *priv;
413        ActivityInfo *activity_info;
414        GList *p;
415        GSList *sp;
416        int order_number;
417
418        /* FIXME?  The complexity in this function sucks.  */
419
420        activity_handler = E_ACTIVITY_HANDLER (bonobo_object_from_servant (servant));
421
422        if (GTK_OBJECT_DESTROYED (activity_handler) || activity_handler->priv == NULL)
423                return;
424
425        priv = activity_handler->priv;
426
427        p = lookup_activity (priv->activity_infos, activity_id, &order_number);
428        if (p == NULL) {
429                CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
430                                     ex_GNOME_Evolution_Activity_IdNotFound, NULL);
431                return;
432        }
433
434        activity_info = (ActivityInfo *) p->data;
435
436        CORBA_free (activity_info->information);
437        activity_info->information = CORBA_string_dup (information);
438
439        activity_info->progress = progress;
440
441        for (sp = priv->task_bars; sp != NULL; sp = sp->next) {
442                ETaskBar *task_bar;
443                ETaskWidget *task_widget;
444
445                task_bar = E_TASK_BAR (sp->data);
446                task_widget = e_task_bar_get_task_widget (task_bar, order_number);
447
448                e_task_widget_update (task_widget, information, progress);
449        }
450}
451
452static void
453impl_operationFinished (PortableServer_Servant servant,
454                        const GNOME_Evolution_Activity_ActivityId activity_id,
455                        CORBA_Environment *ev)
456{
457        EActivityHandler *activity_handler;
458        EActivityHandlerPrivate *priv;
459        GList *p;
460        GSList *sp;
461        int order_number;
462
463        activity_handler = E_ACTIVITY_HANDLER (bonobo_object_from_servant (servant));
464
465        if (GTK_OBJECT_DESTROYED (activity_handler) || activity_handler->priv == NULL)
466                return;
467
468        priv = activity_handler->priv;
469
470        p = lookup_activity (priv->activity_infos, activity_id, &order_number);
471
472        activity_info_free ((ActivityInfo *) p->data);
473        priv->activity_infos = g_list_remove_link (priv->activity_infos, p);
474
475        for (sp = priv->task_bars; sp != NULL; sp = sp->next) {
476                ETaskBar *task_bar;
477
478                task_bar = E_TASK_BAR (sp->data);
479                e_task_bar_remove_task (task_bar, order_number);
480        }
481}
482
483static GNOME_Evolution_Activity_DialogAction
484impl_requestDialog (PortableServer_Servant servant,
485                    const GNOME_Evolution_Activity_ActivityId activity_id,
486                    const GNOME_Evolution_Activity_DialogType dialog_type,
487                    CORBA_Environment *ev)
488{
489        EActivityHandler *activity_handler;
490
491        activity_handler = E_ACTIVITY_HANDLER (bonobo_object_from_servant (servant));
492
493        if (GTK_OBJECT_DESTROYED (activity_handler) || activity_handler->priv == NULL)
494                return GNOME_Evolution_Activity_DIALOG_ACTION_ERROR;
495
496        /* FIXME implement.  */
497        g_warning ("Evolution::Activity::requestDialog not implemented");
498
499        return GNOME_Evolution_Activity_DIALOG_ACTION_DISPLAY;
500}
501
502
503/* GTK+ type stuff.  */
504
505static void
506class_init (GtkObjectClass *object_class)
507{
508        EActivityHandlerClass *handler_class;
509
510        parent_class = gtk_type_class (PARENT_TYPE);
511
512        object_class->destroy = impl_destroy;
513
514        handler_class = E_ACTIVITY_HANDLER_CLASS (object_class);
515        handler_class->epv.operationStarted     = impl_operationStarted;
516        handler_class->epv.operationProgressing = impl_operationProgressing;
517        handler_class->epv.operationFinished    = impl_operationFinished;
518        handler_class->epv.requestDialog        = impl_requestDialog;
519}
520
521static void
522init (EActivityHandler *activity_handler)
523{
524        EActivityHandlerPrivate *priv;
525
526        priv = g_new (EActivityHandlerPrivate, 1);
527        priv->next_activity_id = 0;
528        priv->activity_infos   = NULL;
529        priv->task_bars        = NULL;
530
531        activity_handler->priv = priv;
532}
533
534
535void
536e_activity_handler_construct (EActivityHandler *activity_handler)
537{
538        g_return_if_fail (activity_handler != NULL);
539        g_return_if_fail (E_IS_ACTIVITY_HANDLER (activity_handler));
540
541        /* Nothing to do here.  */
542}
543
544EActivityHandler *
545e_activity_handler_new (void)
546{
547        EActivityHandler *activity_handler;
548
549        activity_handler = gtk_type_new (e_activity_handler_get_type ());
550        e_activity_handler_construct (activity_handler);
551
552        return activity_handler;
553}
554
555
556void
557e_activity_handler_attach_task_bar (EActivityHandler *activity_handler,
558                                    ETaskBar *task_bar)
559{
560        EActivityHandlerPrivate *priv;
561
562        g_return_if_fail (activity_handler != NULL);
563        g_return_if_fail (E_IS_ACTIVITY_HANDLER (activity_handler));
564        g_return_if_fail (task_bar != NULL);
565        g_return_if_fail (E_IS_TASK_BAR (task_bar));
566
567        priv = activity_handler->priv;
568
569        gtk_signal_connect_while_alive (GTK_OBJECT (task_bar), "destroy",
570                                        GTK_SIGNAL_FUNC (task_bar_destroy_callback), activity_handler,
571                                        GTK_OBJECT (activity_handler));
572
573        priv->task_bars = g_slist_prepend (priv->task_bars, task_bar);
574
575        setup_task_bar (activity_handler, task_bar);
576}
577
578
579E_MAKE_X_TYPE (e_activity_handler, "EActivityHandler", EActivityHandler, class_init, init, PARENT_TYPE,
580               POA_GNOME_Evolution_Activity__init,
581               GTK_STRUCT_OFFSET (EActivityHandlerClass, epv))
Note: See TracBrowser for help on using the repository browser.