Implemented an Evolution::Activity interface for keeping track of

background tasks.  The Activity interface is added to the shell, and
the status of the various tasks is now displayed in a task bar widget
at the bottom of the EShellView.

I also implemented a simple test component to test all this stuff.

svn path=/trunk/; revision=10434
This commit is contained in:
Ettore Perazzoli
2001-06-23 06:46:13 +00:00
parent 72ca61d74b
commit b106b13525
19 changed files with 2133 additions and 87 deletions

View File

@ -1,3 +1,61 @@
2001-06-23 Ettore Perazzoli <ettore@ximian.com>
* Makefile.am: Add rules to build the test component and an
`install-test-component' target to install it.
* GNOME_Evolution_TestComponent.oafinfo: New OAF file for the test
component.
* evolution-test-component.c: New component, currently to test the
activity interfaces. We will be able use it for testing more
things in the future.
* e-shell.c: New member `activity_handler' in `EShellViewPrivate'.
(init): Init here.
(class_init): Unref.
(setup_activity_interface): New helper function to create an
`EActivityHandler' object and aggregate it to the `EShell'.
(e_shell_construct): Call here.
(e_shell_new_view): Attach the task bar of the newly created view
to the activity handler by using
`e_activity_handler_attach_task_bar()'.
* e-shell-view.c: Removed old progress bar code. New members
`status_bar' and `task_bar' in EShellViewPrivagte; removed member
`progress_bar'.
(init): Initialize the new fields; remove initialization for
`progress_bar'.
(impl_destroy): Handle the new fields here too.
(setup_task_bar): New helper function to set up an ETaskBar.
(create_status_bar): New helper function to create the status bar
with an ETaskBar in it.
(ui_engine_add_hint_callback): New callback for the "add_int"
BonoboUIEngine signal.
(setup_statusbar_hints): New helper function to set up the menu
hints for the status bar; connect `ui_engine_add_hint_callback()'
here.
(setup_widgets): Call `create_status_bar()' and
`setup_statusbar_hints()'; pack the status bar in a vbox instead
of using the Bonobo status bar stuff, which is kinda broken.
(e_shell_view_get_task_bar): New.
(get_type_for_folder): No use to get the EFolderTypeRegistry here.
* Evolution.idl: #include <Evolution-Activity.idl> and
<Evolution-Icon.idl>.
* Evolution-Activity.idl: New.
* Evolution-Icon.idl: New.
* e-activity-handler.c: New.
* e-activity-handler.h: New.
* e-task-bar.c: New.
* e-task-bar.h: New.
* e-task-widget.c: New.
* e-task-widget.h: New.
2001-06-21 Jason Leach <jleach@ximian.com>
* evolution-storage.c (evolution_storage_deregister_on_shell): New

View File

@ -0,0 +1,108 @@
/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Activity management for Evolution.
*
* Authors:
* Ettore Perazzoli <ettore@ximian.com>
*
* Copyright (C) 2000, 2001 Ximian, Inc.
*/
module GNOME {
module Evolution {
interface Activity : Bonobo::Unknown {
typedef long ActivityID;
enum DialogType {
DIALOG_TYPE_NONE,
DIALOG_TYPE_MESSAGE,
DIALOG_TYPE_WARNING,
DIALOG_TYPE_INPUT,
DIALOG_TYPE_ERROR
};
enum DialogAction {
DIALOG_ACTION_DISPLAY,
DIALOG_ACTION_POSTPONE
};
exception InvalidIcon {};
exception IdNotFound {};
/* Events propagated through the listener:
- "Clicked": The status widget has been clicked on.
- "DisplayProgress": Display a nice progress dialog for this
operation.
- "DisplayDialog": The dialog that the component has requested
through ::requestDialog() can now be safely displayed.
- "Cancelled": The user wants the operation to be cancelled.
*/
/**
* operationStarted:
* @component_id: ID of the component starting the operation.
* @information: Informative string about the operation being performed.
* @cancellable: Whether this operation should be cancellable by
* the user from the shell view.
* @event_listener: Listener which the events for the activity
* widget will be passed to.
* @activity_id: A unique ID for the activity, to be used to update the
* status of the operation.
* @suggest_display: Whether displaying the dialog might be a nice idea.
*/
void operationStarted (in string component_id,
in AnimatedIcon icon,
in string information,
in boolean cancellable,
in Bonobo::Listener event_listener,
out ActivityID activity_id,
out boolean suggest_display)
raises (InvalidIcon);
/**
* operationProgressing:
* @activity: The unique ID for the activity whose status we want to update.
* @information: New informative string. If empty, the informative string
* isn't changed.
* @progress: A float from 0.0 to 1.0 indicating the status of completion.
*
* Update the status of the specified @activity.
*/
void operationProgressing (in ActivityID activity,
in string information,
in float progress)
raises (IdNotFound);
/**
* operationFinished:
* @activity: The unique ID for the activity that has been completed.
*
* Report that the specified @activity has been completed. After this
* method is invoked, @activity is not considered to be a valid ID
* anymore.
*/
void operationFinished (in ActivityID activity);
/**
* requestDialog:
*
* Inform the shell that the specified @activity requires user input
* from a dialog. The returned value specifies whether the shell wants
* the dialog to be shown now (%DIALOG_ACTION_DISPLAY) or postponed
* (%DIALOG_ACTION_POSTPONE). If the return value is
* %DIALOG_ACTION_POSTPONE, the component should wait for the
* "DisplayDialog" event before proceeding further. In that case, the
* shell will flash the label related to this activity, and emit
* "DisplayDialog" through the event source when the user clicks on it.
*/
DialogAction requestDialog (in ActivityID activity,
in DialogType dialog_type);
};
};
};

23
shell/Evolution-Icon.idl Normal file
View File

@ -0,0 +1,23 @@
/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Icon definition.
*
* Authors:
* Ettore Perazzoli <ettore@ximian.com>
*
* Copyright (C) 2000, 2001 Ximian, Inc.
*/
module GNOME {
module Evolution {
struct Icon {
short width, height;
boolean hasAlpha;
sequence <octet> rgba_data; // Row-by-row, left-to-right, top-to-bottom RGBA bytes
};
typedef sequence <Icon> AnimatedIcon;
};
};

View File

@ -10,6 +10,8 @@
#include <Bonobo.idl>
#include <Evolution-Icon.idl>
#include <Evolution-Activity.idl>
#include <Evolution-Session.idl>
#include <Evolution-ShellComponent.idl>
#include <Evolution-ShellComponentDnd.idl>

View File

@ -0,0 +1,27 @@
<oaf_info>
<oaf_server iid="OAFIID:GNOME_Evolution_TestComponent_ShellComponentFactory"
type="exe"
location="evolution-test-component">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:GNOME/ObjectFactory:1.0"/>
</oaf_attribute>
<oaf_attribute name="description" type="string"
value="Factory for the Evolution test component."/>
</oaf_server>
<oaf_server iid="OAFIID:GNOME_Evolution_TestComponent_ShellComponent"
type="factory"
location="OAFIID:GNOME_Evolution_TestComponent_ShellComponentFactory">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:GNOME/Evolution/ShellComponent:1.0"/>
</oaf_attribute>
<oaf_attribute name="description" type="string"
value="Evolution test component."/>
</oaf_server>
</oaf_info>

View File

@ -1,6 +1,6 @@
SUBDIRS = glade importer
INCLUDES = \
INCLUDES = -O \
-I$(top_srcdir)/widgets \
-I$(top_srcdir)/widgets/misc \
-I$(top_srcdir) \
@ -16,15 +16,17 @@ INCLUDES = \
# CORBA stuff
IDLS = \
Evolution-LocalStorage.idl \
Evolution-Offline.idl \
Evolution-Session.idl \
Evolution-Shell.idl \
Evolution-ShellComponent.idl \
Evolution-ShellComponentDnd.idl \
Evolution-ShellView.idl \
Evolution-Storage.idl \
Evolution-StorageSetView.idl \
Evolution-Activity.idl \
Evolution-Icon.idl \
Evolution-LocalStorage.idl \
Evolution-Offline.idl \
Evolution-Session.idl \
Evolution-Shell.idl \
Evolution-ShellComponent.idl \
Evolution-ShellComponentDnd.idl \
Evolution-ShellView.idl \
Evolution-Storage.idl \
Evolution-StorageSetView.idl \
Evolution.idl
IDL_GENERATED = \
@ -88,6 +90,8 @@ libeshell_la_SOURCES = \
bin_PROGRAMS = evolution
evolution_SOURCES = \
e-activity-handler.c \
e-activity-handler.h \
e-component-registry.c \
e-component-registry.h \
e-corba-storage-registry.c \
@ -139,6 +143,10 @@ evolution_SOURCES = \
e-storage-set.h \
e-storage.c \
e-storage.h \
e-task-bar.c \
e-task-bar.h \
e-task-widget.c \
e-task-widget.h \
evolution-storage-set-view.c \
evolution-storage-set-view.h \
evolution-storage-set-view-factory.c \
@ -155,6 +163,29 @@ evolution_LDADD = \
$(GTKHTML_LIBS) \
$(BONOBO_GNOME_LIBS)
# Test component
noinst_PROGRAMS = \
evolution-test-component
evolution_test_component_SOURCES = \
evolution-test-component.c
evolution_test_component_LDADD = \
libeshell.la \
$(EXTRA_GNOME_LIBS) \
$(GNOME_PRINT_LIBS) \
$(GTKHTML_LIBS) \
$(BONOBO_GNOME_LIBS)
install-test-component: evolution-test-component
$(mkinstalldirs) $(DESTDIR)$(bindir)
$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) evolution-test-component $(DESTDIR)$(bindir)/evolution-test-component
$(mkinstalldirs) $(DESTDIR)$(oafdir)
$(INSTALL_DATA) $(srcdir)/GNOME_Evolution_TestComponent.oafinfo $(DESTDIR)$(oafdir)/GNOME_Evolution_TestComponent.oafinfo
# Misc stuff
oafdir = $(datadir)/oaf
oaf_in_files = GNOME_Evolution_Shell.oaf.in
oaf_DATA = $(oaf_in_files:.oaf.in=.oaf)
@ -164,7 +195,12 @@ etspec_DATA = e-storage-set-view.etspec
@XML_I18N_MERGE_OAF_RULE@
EXTRA_DIST = $(IDLS) $(oaf_in_files) $(oaf_DATA) $(etspec_DATA)
EXTRA_DIST = \
$(IDLS) \
$(oaf_in_files) \
$(oaf_DATA) \
$(etspec_DATA) \
GNOME_Evolution_TestComponent.oafinfo
# Purify support

459
shell/e-activity-handler.c Normal file
View File

@ -0,0 +1,459 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* e-activity-handler.c
*
* Copyright (C) 2001 Ximian, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ettore Perazzoli <ettore@ximian.com>
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "e-activity-handler.h"
#include <gtk/gtksignal.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gal/util/e-util.h>
#define PARENT_TYPE bonobo_x_object_get_type ()
static BonoboXObjectClass *parent_class = NULL;
#define ICON_SIZE 16
struct _ActivityInfo {
GdkPixbuf *icon_pixbuf;
GNOME_Evolution_Activity_ActivityID id;
CORBA_char *information;
CORBA_boolean cancellable;
Bonobo_Listener event_listener;
CORBA_float progress;
};
typedef struct _ActivityInfo ActivityInfo;
struct _EActivityHandlerPrivate {
GNOME_Evolution_Activity_ActivityID next_activity_id;
GList *activity_infos;
GSList *task_bars;
};
/* Utility functions. */
static GdkPixbuf *
create_gdk_pixbuf_from_corba_icon (const GNOME_Evolution_Icon *icon)
{
GdkPixbuf *pixbuf;
GdkPixbuf *scaled_pixbuf;
unsigned char *p;
int src_offset;
int i, j;
int rowstride;
int total_width;
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, icon->hasAlpha, 8, icon->width, icon->height);
if (icon->hasAlpha)
total_width = 4 * icon->width;
else
total_width = 3 * icon->width;
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
src_offset = 0;
p = gdk_pixbuf_get_pixels (pixbuf);
for (i = 0; i < icon->height; i++) {
for (j = 0; j < total_width; j++)
p[j] = icon->rgba_data._buffer[src_offset ++];
p += rowstride;
}
if (icon->width == ICON_SIZE && icon->height == ICON_SIZE)
return pixbuf;
scaled_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, icon->hasAlpha, 8, ICON_SIZE, ICON_SIZE);
gdk_pixbuf_scale (pixbuf, scaled_pixbuf,
0, 0, ICON_SIZE, ICON_SIZE,
0, 0, (double) ICON_SIZE / icon->width, (double) ICON_SIZE / icon->height,
GDK_INTERP_HYPER);
gdk_pixbuf_unref (pixbuf);
return scaled_pixbuf;
}
static unsigned int
get_new_activity_id (EActivityHandler *activity_handler)
{
EActivityHandlerPrivate *priv;
priv = activity_handler->priv;
return priv->next_activity_id ++;
}
static GList *
lookup_activity (GList *list,
GNOME_Evolution_Activity_ActivityID activity_id,
int *order_number_return)
{
GList *p;
int i;
for (p = list, i = 0; p != NULL; p = p->next, i ++) {
ActivityInfo *activity_info;
activity_info = (ActivityInfo *) p->data;
if (activity_info->id == activity_id) {
*order_number_return = i;
return p;
}
}
*order_number_return = -1;
return NULL;
}
/* Creating and destroying ActivityInfos. */
static ActivityInfo *
activity_info_new (GNOME_Evolution_Activity_ActivityID id,
GdkPixbuf *icon,
const CORBA_char *information,
CORBA_boolean cancellable,
const Bonobo_Listener event_listener)
{
ActivityInfo *info;
CORBA_Environment ev;
CORBA_exception_init (&ev);
info = g_new (ActivityInfo, 1);
info->id = id;
info->icon_pixbuf = gdk_pixbuf_ref (icon);
info->information = CORBA_string_dup (information);
info->cancellable = cancellable;
info->event_listener = CORBA_Object_duplicate (event_listener, &ev);
info->progress = -1.0; /* (Unknown) */
CORBA_exception_free (&ev);
return info;
}
static void
activity_info_free (ActivityInfo *info)
{
CORBA_Environment ev;
CORBA_exception_init (&ev);
CORBA_free (info->information);
CORBA_Object_release (info->event_listener, &ev);
g_free (info);
CORBA_exception_free (&ev);
}
static ETaskWidget *
task_widget_new_from_activity_info (ActivityInfo *activity_info)
{
GtkWidget *widget;
widget = e_task_widget_new (activity_info->icon_pixbuf, activity_info->information);
gtk_widget_show (widget);
return E_TASK_WIDGET (widget);
}
/* Task Bar handling. */
static void
setup_task_bar (EActivityHandler *activity_handler,
ETaskBar *task_bar)
{
EActivityHandlerPrivate *priv;
GList *p;
priv = activity_handler->priv;
for (p = g_list_last (priv->activity_infos); p != NULL; p = p->prev) {
e_task_bar_prepend_task (task_bar,
task_widget_new_from_activity_info ((ActivityInfo *) p->data));
}
}
static void
task_bar_destroy_callback (GtkObject *task_bar_object,
void *data)
{
ETaskBar *task_bar;
EActivityHandler *activity_handler;
EActivityHandlerPrivate *priv;
task_bar = E_TASK_BAR (task_bar_object);
activity_handler = E_ACTIVITY_HANDLER (data);
priv = activity_handler->priv;
priv->task_bars = g_slist_remove (priv->task_bars, task_bar);
}
/* GtkObject methods. */
static void
impl_destroy (GtkObject *object)
{
EActivityHandler *handler;
EActivityHandlerPrivate *priv;
GList *p;
handler = E_ACTIVITY_HANDLER (object);
priv = handler->priv;
for (p = priv->activity_infos; p != NULL; p = p->next) {
ActivityInfo *info;
info = (ActivityInfo *) p->data;
activity_info_free (info);
}
g_free (priv);
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
/* CORBA methods. */
static void
impl_operationStarted (PortableServer_Servant servant,
const CORBA_char *component_id,
const GNOME_Evolution_AnimatedIcon *icon,
const CORBA_char *information,
const CORBA_boolean cancellable,
const Bonobo_Listener event_listener,
GNOME_Evolution_Activity_ActivityID *activity_id_return,
CORBA_boolean *suggest_display_return,
CORBA_Environment *ev)
{
EActivityHandler *activity_handler;
EActivityHandlerPrivate *priv;
ActivityInfo *activity_info;
GdkPixbuf *icon_pixbuf;
unsigned int activity_id;
GSList *p;
activity_handler = E_ACTIVITY_HANDLER (bonobo_object_from_servant (servant));
priv = activity_handler->priv;
if (icon->_length == 0) {
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_GNOME_Evolution_Activity_InvalidIcon, NULL);
return;
}
if (icon->_length > 1)
g_warning ("Animated icons are not supported for activities (yet).");
icon_pixbuf = create_gdk_pixbuf_from_corba_icon (icon->_buffer);
activity_id = get_new_activity_id (activity_handler);
activity_info = activity_info_new (activity_id, icon_pixbuf, information, cancellable, event_listener);
for (p = priv->task_bars; p != NULL; p = p->next)
e_task_bar_prepend_task (E_TASK_BAR (p->data),
task_widget_new_from_activity_info (activity_info));
priv->activity_infos = g_list_prepend (priv->activity_infos, activity_info);
*activity_id_return = activity_id;
}
static void
impl_operationProgressing (PortableServer_Servant servant,
const GNOME_Evolution_Activity_ActivityID activity_id,
const CORBA_char *information,
const CORBA_float progress,
CORBA_Environment *ev)
{
EActivityHandler *activity_handler;
EActivityHandlerPrivate *priv;
ActivityInfo *activity_info;
GList *p;
GSList *sp;
int order_number;
/* FIXME? The complexity in this function sucks. */
activity_handler = E_ACTIVITY_HANDLER (bonobo_object_from_servant (servant));
priv = activity_handler->priv;
p = lookup_activity (priv->activity_infos, activity_id, &order_number);
if (p == NULL) {
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_GNOME_Evolution_Activity_IdNotFound, NULL);
return;
}
activity_info = (ActivityInfo *) p->data;
CORBA_free (activity_info->information);
activity_info->information = CORBA_string_dup (information);
activity_info->progress = progress;
for (sp = priv->task_bars; sp != NULL; sp = sp->next) {
ETaskBar *task_bar;
ETaskWidget *task_widget;
task_bar = E_TASK_BAR (sp->data);
task_widget = e_task_bar_get_task_widget (task_bar, order_number);
e_task_widget_update (task_widget, information, progress);
}
}
static void
impl_operationFinished (PortableServer_Servant servant,
const GNOME_Evolution_Activity_ActivityID activity_id,
CORBA_Environment *ev)
{
EActivityHandler *activity_handler;
EActivityHandlerPrivate *priv;
GList *p;
GSList *sp;
int order_number;
activity_handler = E_ACTIVITY_HANDLER (bonobo_object_from_servant (servant));
priv = activity_handler->priv;
p = lookup_activity (priv->activity_infos, activity_id, &order_number);
activity_info_free ((ActivityInfo *) p->data);
priv->activity_infos = g_list_remove_link (priv->activity_infos, p);
for (sp = priv->task_bars; sp != NULL; sp = sp->next) {
ETaskBar *task_bar;
task_bar = E_TASK_BAR (sp->data);
e_task_bar_remove_task (task_bar, order_number);
}
}
static GNOME_Evolution_Activity_DialogAction
impl_requestDialog (PortableServer_Servant servant,
const GNOME_Evolution_Activity_ActivityID activity_id,
const GNOME_Evolution_Activity_DialogType dialog_type,
CORBA_Environment *ev)
{
/* FIXME implement. */
g_warning ("Evolution::Activity::requestDialog not implemented");
return GNOME_Evolution_Activity_DIALOG_ACTION_DISPLAY;
}
/* GTK+ type stuff. */
static void
class_init (GtkObjectClass *object_class)
{
EActivityHandlerClass *handler_class;
parent_class = gtk_type_class (PARENT_TYPE);
object_class->destroy = impl_destroy;
handler_class = E_ACTIVITY_HANDLER_CLASS (object_class);
handler_class->epv.operationStarted = impl_operationStarted;
handler_class->epv.operationProgressing = impl_operationProgressing;
handler_class->epv.operationFinished = impl_operationFinished;
handler_class->epv.requestDialog = impl_requestDialog;
}
static void
init (EActivityHandler *activity_handler)
{
EActivityHandlerPrivate *priv;
priv = g_new (EActivityHandlerPrivate, 1);
priv->next_activity_id = 0;
priv->activity_infos = NULL;
priv->task_bars = NULL;
activity_handler->priv = priv;
}
void
e_activity_handler_construct (EActivityHandler *activity_handler)
{
g_return_if_fail (activity_handler != NULL);
g_return_if_fail (E_IS_ACTIVITY_HANDLER (activity_handler));
/* Nothing to do here. */
}
EActivityHandler *
e_activity_handler_new (void)
{
EActivityHandler *activity_handler;
activity_handler = gtk_type_new (e_activity_handler_get_type ());
e_activity_handler_construct (activity_handler);
return activity_handler;
}
void
e_activity_handler_attach_task_bar (EActivityHandler *activity_handler,
ETaskBar *task_bar)
{
EActivityHandlerPrivate *priv;
g_return_if_fail (activity_handler != NULL);
g_return_if_fail (E_IS_ACTIVITY_HANDLER (activity_handler));
g_return_if_fail (task_bar != NULL);
g_return_if_fail (E_IS_TASK_BAR (task_bar));
priv = activity_handler->priv;
gtk_signal_connect_while_alive (GTK_OBJECT (task_bar), "destroy",
GTK_SIGNAL_FUNC (task_bar_destroy_callback), activity_handler,
GTK_OBJECT (activity_handler));
priv->task_bars = g_slist_prepend (priv->task_bars, task_bar);
setup_task_bar (activity_handler, task_bar);
}
E_MAKE_X_TYPE (e_activity_handler, "EActivityHandler", EActivityHandler, class_init, init, PARENT_TYPE,
POA_GNOME_Evolution_Activity__init,
GTK_STRUCT_OFFSET (EActivityHandlerClass, epv))

View File

@ -0,0 +1,73 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* e-activity-handler.h
*
* Copyright (C) 2001 Ximian, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ettore Perazzoli <ettore@ximian.com>
*/
#ifndef _E_ACTIVITY_HANDLER_H_
#define _E_ACTIVITY_HANDLER_H_
#include "Evolution.h"
#include "e-task-bar.h"
#include <bonobo/bonobo-xobject.h>
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus */
#define E_TYPE_ACTIVITY_HANDLER (e_activity_handler_get_type ())
#define E_ACTIVITY_HANDLER(obj) (GTK_CHECK_CAST ((obj), E_TYPE_ACTIVITY_HANDLER, EActivityHandler))
#define E_ACTIVITY_HANDLER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_ACTIVITY_HANDLER, EActivityHandlerClass))
#define E_IS_ACTIVITY_HANDLER(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_ACTIVITY_HANDLER))
#define E_IS_ACTIVITY_HANDLER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_ACTIVITY_HANDLER))
typedef struct _EActivityHandler EActivityHandler;
typedef struct _EActivityHandlerPrivate EActivityHandlerPrivate;
typedef struct _EActivityHandlerClass EActivityHandlerClass;
struct _EActivityHandler {
BonoboXObject parent;
EActivityHandlerPrivate *priv;
};
struct _EActivityHandlerClass {
BonoboXObjectClass parent_class;
POA_GNOME_Evolution_Activity__epv epv;
};
GtkType e_activity_handler_get_type (void);
void e_activity_handler_construct (EActivityHandler *activity_hanlder);
EActivityHandler *e_activity_handler_new (void);
void e_activity_handler_attach_task_bar (EActivityHandler *activity_hanlder,
ETaskBar *task_bar);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _E_ACTIVITY_HANDLER_H_ */

View File

@ -60,11 +60,142 @@ static EFolderClass *parent_class = NULL;
#define URI_PREFIX "file://"
#define URI_PREFIX_LEN 7
/* This provides the name and the description for a specific locale. */
struct _I18nInfo {
char *language_id;
char *name;
char *description;
};
typedef struct _I18nInfo I18nInfo;
struct _ELocalFolderPrivate {
int dummy;
GHashTable *language_id_to_i18n_info;
};
/* Locale information. */
static char *global_language_id = NULL;
/* I18nInfo handling. */
static I18nInfo *
i18n_info_new (const char *language_id,
const char *name,
const char *description)
{
I18nInfo *info;
info = g_new (I18nInfo, 1);
info->language_id = g_strdup (language_id);
info->name = g_strdup (name);
info->description = g_strdup (description);
return info;
}
static void
i18n_info_free (I18nInfo *info)
{
g_free (info->language_id);
g_free (info->name);
g_free (info->description);
g_free (info);
}
/* Language ID -> I18nInfo hash table handling. */
static void
add_i18n_info_to_hash (GHashTable *language_id_to_i18n_info_hash,
I18nInfo *i18n_info)
{
I18nInfo *existing_i18n_info;
existing_i18n_info = (I18nInfo *) g_hash_table_lookup (language_id_to_i18n_info_hash,
i18n_info->language_id);
if (existing_i18n_info != NULL) {
g_hash_table_remove (language_id_to_i18n_info_hash,
i18n_info->language_id);
i18n_info_free (existing_i18n_info);
}
g_hash_table_insert (language_id_to_i18n_info_hash, i18n_info->language_id, i18n_info);
}
static void
language_id_to_i18n_info_hash_foreach_free (void *key,
void *value,
void *data)
{
i18n_info_free ((I18nInfo *) value);
}
static I18nInfo *
get_i18n_info_for_language (ELocalFolder *local_folder,
const char *language_id)
{
ELocalFolderPrivate *priv;
I18nInfo *i18n_info;
priv = local_folder->priv;
if (language_id == NULL)
language_id = global_language_id;
i18n_info = g_hash_table_lookup (priv->language_id_to_i18n_info, language_id);
/* For locale info like `en_UK@yadda', we try to use `en' as a backup. */
/* Note: this is exactly the same thing that gnome-config does with the
I18N value handling. I hope it works. */
if (i18n_info == NULL) {
size_t n;
n = strcspn (language_id, "@_");
if (language_id[n] != '\0') {
char *simplified_language_id;
simplified_language_id = g_strndup (language_id, n);
i18n_info = g_hash_table_lookup (priv->language_id_to_i18n_info,
simplified_language_id);
}
}
return i18n_info;
}
/* Locale handling. */
static void
setup_global_language_id (void)
{
/* FIXME: Implement. */
global_language_id = "C";
}
/* Update the EFolder attributes according to the current locale. */
static void
update_for_global_locale (ELocalFolder *local_folder)
{
I18nInfo *i18n_info;
i18n_info = get_i18n_info_for_language (local_folder, NULL);
if (i18n_info == NULL)
i18n_info = get_i18n_info_for_language (local_folder, "C");
g_assert (i18n_info != NULL);
e_folder_set_name (E_FOLDER (local_folder), i18n_info->name);
e_folder_set_description (E_FOLDER (local_folder), i18n_info->description);
}
/* XML tree handling. */
static char *
get_string_value (xmlNode *node,
const char *name)
@ -81,13 +212,51 @@ get_string_value (xmlNode *node,
if (p == NULL)
return NULL;
xml_string = xmlNodeListGetString (node->doc, p, 1);
xml_string = xmlNodeListGetString (node->doc, p, TRUE);
retval = g_strdup ((char *) xml_string);
xmlFree (xml_string);
return retval;
}
static void
retrieve_info_item (ELocalFolder *local_folder,
xmlNode *node)
{
xmlChar *lang;
char *name;
char *description;
lang = xmlGetProp (node, "lang");
name = get_string_value (node, "name");
description = get_string_value (node, "description");
if (lang == NULL) {
e_local_folder_add_i18n_info (local_folder, "C", name, description);
} else {
e_local_folder_add_i18n_info (local_folder, lang, name, description);
xmlFree (lang);
}
g_free (name);
g_free (description);
}
static void
retrieve_info (ELocalFolder *local_folder,
xmlNode *root_xml_node)
{
ELocalFolderPrivate *priv;
xmlNode *p;
priv = local_folder->priv;
for (p = root_xml_node->childs; p != NULL; p = p->next) {
if (xmlStrcmp (p->name, "info") == 0)
retrieve_info_item (local_folder, p);
}
}
static gboolean
construct_loading_metadata (ELocalFolder *local_folder,
const char *path)
@ -96,7 +265,6 @@ construct_loading_metadata (ELocalFolder *local_folder,
xmlDoc *doc;
xmlNode *root;
char *type;
char *description;
char *metadata_path;
char *physical_uri;
@ -118,12 +286,16 @@ construct_loading_metadata (ELocalFolder *local_folder,
}
type = get_string_value (root, "type");
description = get_string_value (root, "description");
e_folder_construct (folder, g_basename (path), type, description);
if (type == NULL) {
g_free (metadata_path);
xmlFreeDoc (doc);
return FALSE;
}
e_local_folder_construct (local_folder, g_basename (path), type, NULL);
g_free (type);
g_free (description);
retrieve_info (local_folder, root);
xmlFreeDoc (doc);
@ -180,7 +352,18 @@ save_metadata (ELocalFolder *local_folder)
static void
destroy (GtkObject *object)
{
/* No ELocalFolder-specific data to free. */
ELocalFolder *local_folder;
ELocalFolderPrivate *priv;
local_folder = E_LOCAL_FOLDER (object);
priv = local_folder->priv;
g_hash_table_foreach (priv->language_id_to_i18n_info,
language_id_to_i18n_info_hash_foreach_free,
NULL);
g_hash_table_destroy (priv->language_id_to_i18n_info);
g_free (priv);
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
@ -195,11 +378,19 @@ class_init (ELocalFolderClass *klass)
object_class = GTK_OBJECT_CLASS (klass);
object_class->destroy = destroy;
setup_global_language_id ();
}
static void
init (ELocalFolder *local_folder)
{
ELocalFolderPrivate *priv;
priv = g_new (ELocalFolderPrivate, 1);
priv->language_id_to_i18n_info = g_hash_table_new (g_str_hash, g_str_equal);
local_folder->priv = priv;
}
@ -209,12 +400,20 @@ e_local_folder_construct (ELocalFolder *local_folder,
const char *type,
const char *description)
{
ELocalFolderPrivate *priv;
I18nInfo *i18n_info;
g_return_if_fail (local_folder != NULL);
g_return_if_fail (E_IS_LOCAL_FOLDER (local_folder));
g_return_if_fail (name != NULL);
g_return_if_fail (type != NULL);
priv = local_folder->priv;
e_folder_construct (E_FOLDER (local_folder), name, type, description);
i18n_info = i18n_info_new ("C", name, description);
add_i18n_info_to_hash (priv->language_id_to_i18n_info, i18n_info);
}
EFolder *
@ -261,5 +460,94 @@ e_local_folder_save (ELocalFolder *local_folder)
return save_metadata (local_folder);
}
/**
* e_local_folder_add_i18n_info:
* @local_folder: A pointer to an ELocalFolder object
* @language_id: An I1I8N locale ID
* @name: Name for @local_folder in the specified @language_id
* @description: Description for @local_folder in the specified @language_id
*
* Set the @name and @description for the specified @language_id locale.
**/
void
e_local_folder_add_i18n_info (ELocalFolder *local_folder,
const char *language_id,
const char *name,
const char *description)
{
ELocalFolderPrivate *priv;
I18nInfo *info;
g_return_if_fail (local_folder != NULL);
g_return_if_fail (E_IS_LOCAL_FOLDER (local_folder));
g_return_if_fail (language_id != NULL);
g_return_if_fail (name != NULL || description != NULL);
priv = local_folder->priv;
info = i18n_info_new (language_id, name, description);
add_i18n_info_to_hash (priv->language_id_to_i18n_info, info);
update_for_global_locale (local_folder);
}
/**
* e_local_folder_get_i18n_info:
* @local_folder: A pointer to an ELocalFolder object
* @language_id: The ID of the language whose locale we want to retrieve name
* and description for
* @language_id_return: The actual locale ID that the name and description are
* saved under (e.g. if you ask for an "en_UK@yadda", we might give you the
* info for just "en")
* @name_return: A pointer to a pointer that will point to the i18nized name on
* return. Can be NULL.
* @description_return: A pointer to a pointer that will point to the i18n
* description on return. Can be NULL.
*
* Retrieve the name and description for @local_folder in the specified locale.
*
* Return value: %TRUE if some info is found for that @language_id, %FALSE
* otherwise.
**/
gboolean
e_local_folder_get_i18n_info (ELocalFolder *local_folder,
const char *language_id,
const char **language_id_return,
const char **name_return,
const char **description_return)
{
ELocalFolderPrivate *priv;
I18nInfo *i18n_info;
g_return_val_if_fail (local_folder != NULL, FALSE);
g_return_val_if_fail (E_IS_LOCAL_FOLDER (local_folder), FALSE);
g_return_val_if_fail (language_id != NULL, FALSE);
priv = local_folder->priv;
i18n_info = get_i18n_info_for_language (local_folder, language_id);
if (i18n_info == NULL) {
if (language_id_return != NULL)
*language_id_return = NULL;
if (name_return != NULL)
*name_return = NULL;
if (description_return != NULL)
*description_return = NULL;
return FALSE;
}
if (language_id_return != NULL)
*language_id_return = i18n_info->language_id;
if (name_return != NULL)
*name_return = i18n_info->name;
if (description_return != NULL)
*description_return = i18n_info->description;
return TRUE;
}
E_MAKE_TYPE (e_local_folder, "ELocalFolder", ELocalFolder, class_init, init, PARENT_TYPE)

View File

@ -44,9 +44,12 @@ extern "C" {
typedef struct _ELocalFolder ELocalFolder;
typedef struct _ELocalFolderClass ELocalFolderClass;
typedef struct _ELocalFolderPrivate ELocalFolderPrivate;
struct _ELocalFolder {
EFolder parent;
ELocalFolderPrivate *priv;
};
struct _ELocalFolderClass {
@ -55,15 +58,25 @@ struct _ELocalFolderClass {
GtkType e_local_folder_get_type (void);
void e_local_folder_construct (ELocalFolder *local_folder,
const char *name,
const char *type,
const char *description);
EFolder *e_local_folder_new (const char *name,
const char *type,
const char *description);
EFolder *e_local_folder_new_from_path (const char *physical_path);
gboolean e_local_folder_save (ELocalFolder *local_folder);
void e_local_folder_construct (ELocalFolder *local_folder,
const char *name,
const char *type,
const char *description);
EFolder *e_local_folder_new (const char *name,
const char *type,
const char *description);
EFolder *e_local_folder_new_from_path (const char *physical_path);
gboolean e_local_folder_save (ELocalFolder *local_folder);
void e_local_folder_add_i18n_info (ELocalFolder *local_folder,
const char *language_id,
const char *name,
const char *description);
gboolean e_local_folder_get_i18n_info (ELocalFolder *local_folder,
const char *language_id,
const char **language_id_return,
const char **name_return,
const char **description_return);
#ifdef __cplusplus
}

View File

@ -34,6 +34,7 @@
#include <libgnome/gnome-i18n.h>
#include <libgnomeui/gnome-window.h>
#include <libgnomeui/gnome-window-icon.h>
#include <libgnomeui/gnome-app.h>
#include <bonobo/bonobo-socket.h>
#include <bonobo/bonobo-ui-util.h>
#include <bonobo/bonobo-widget.h>
@ -100,9 +101,10 @@ struct _EShellViewPrivate {
GtkWidget *storage_set_view_box;
/* The status bar widgetry. */
GtkWidget *status_bar;
GtkWidget *offline_toggle;
GtkWidget *offline_toggle_pixmap;
GtkWidget *progress_bar;
GtkWidget *task_bar;
/* The view we have already open. */
GHashTable *uri_to_control;
@ -116,12 +118,6 @@ struct _EShellViewPrivate {
EShellViewSubwindowMode shortcut_bar_mode;
EShellViewSubwindowMode folder_bar_mode;
/* Timeout ID for the progress bar. */
int progress_bar_timeout_id;
/* Status of the progress bar. */
int progress_bar_value;
/* List of sockets we created. */
GList *sockets;
};
@ -617,7 +613,6 @@ static void
setup_offline_toggle (EShellView *shell_view)
{
EShellViewPrivate *priv;
BonoboControl *control;
GtkWidget *toggle;
GtkWidget *pixmap;
@ -637,46 +632,78 @@ setup_offline_toggle (EShellView *shell_view)
gtk_widget_show (toggle);
gtk_widget_show (pixmap);
control = bonobo_control_new (toggle);
g_return_if_fail (control != NULL);
bonobo_ui_component_object_set (priv->ui_component, "/status/OfflineToggle",
BONOBO_OBJREF (control),
NULL);
bonobo_object_unref (BONOBO_OBJECT (control));
priv->offline_toggle = toggle;
priv->offline_toggle_pixmap = pixmap;
update_offline_toggle_status (shell_view);
g_assert (priv->status_bar != NULL);
gtk_box_pack_start (GTK_BOX (priv->status_bar), priv->offline_toggle, FALSE, TRUE, 0);
}
static void
setup_progress_bar (EShellView *shell_view)
setup_task_bar (EShellView *task_bar)
{
EShellViewPrivate *priv;
priv = task_bar->priv;
priv->task_bar = e_task_bar_new ();
g_assert (priv->status_bar != NULL);
gtk_box_pack_start (GTK_BOX (priv->status_bar), priv->task_bar, TRUE, TRUE, 0);
gtk_widget_show (priv->task_bar);
}
static void
create_status_bar (EShellView *shell_view)
{
EShellViewPrivate *priv;
GtkProgressBar *progress_bar;
BonoboControl *control;
priv = shell_view->priv;
progress_bar = (GTK_PROGRESS_BAR (gtk_progress_bar_new ()));
priv->status_bar = gtk_hbox_new (FALSE, 2);
gtk_widget_show (priv->status_bar);
gtk_progress_bar_set_orientation (progress_bar, GTK_PROGRESS_LEFT_TO_RIGHT);
gtk_progress_bar_set_bar_style (progress_bar, GTK_PROGRESS_CONTINUOUS);
priv->progress_bar = GTK_WIDGET (progress_bar);
gtk_widget_show (priv->progress_bar);
control = bonobo_control_new (priv->progress_bar);
g_return_if_fail (control != NULL);
bonobo_ui_component_object_set (priv->ui_component, "/status/Progress",
BONOBO_OBJREF (control),
NULL);
bonobo_object_unref (BONOBO_OBJECT (control));
setup_offline_toggle (shell_view);
setup_task_bar (shell_view);
}
/* Menu hints for the status bar. */
static void
ui_engine_add_hint_callback (BonoboUIEngine *engine,
const char *str,
void *data)
{
EShellView *shell_view;
EShellViewPrivate *priv;
shell_view = E_SHELL_VIEW (data);
priv = shell_view->priv;
g_print ("Hint -- %s\n", str);
/* FIXME: Implement me. */
}
static void
setup_statusbar_hints (EShellView *shell_view)
{
EShellViewPrivate *priv;
priv = shell_view->priv;
g_assert (priv->status_bar != NULL);
gtk_signal_connect (GTK_OBJECT (bonobo_window_get_ui_engine (BONOBO_WINDOW (shell_view))), "add_hint",
GTK_SIGNAL_FUNC (ui_engine_add_hint_callback), shell_view);
}
void
e_shell_view_set_current_shortcuts_group_num (EShellView *shell_view, int group_num)
{
@ -711,17 +738,10 @@ static void
setup_widgets (EShellView *shell_view)
{
EShellViewPrivate *priv;
GtkWidget *contents_vbox;
priv = shell_view->priv;
/* The offline/online button toggle. */
setup_offline_toggle (shell_view);
/* The progress bar. */
setup_progress_bar (shell_view);
/* The shortcut bar. */
priv->shortcut_bar = e_shortcuts_new_view (e_shell_get_shortcuts (priv->shell));
@ -773,7 +793,19 @@ setup_widgets (EShellView *shell_view)
e_paned_pack2 (E_PANED (priv->hpaned), priv->view_vbox, TRUE, FALSE);
e_paned_set_position (E_PANED (priv->hpaned), DEFAULT_SHORTCUT_BAR_WIDTH);
bonobo_window_set_contents (BONOBO_WINDOW (shell_view), priv->hpaned);
/* The status bar. */
create_status_bar (shell_view);
setup_statusbar_hints (shell_view);
/* The contents. */
contents_vbox = gtk_vbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (contents_vbox), priv->hpaned, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (contents_vbox), priv->status_bar, FALSE, TRUE, 0);
gtk_widget_show (contents_vbox);
bonobo_window_set_contents (BONOBO_WINDOW (shell_view), contents_vbox);
/* Show stuff. */
@ -786,6 +818,7 @@ setup_widgets (EShellView *shell_view)
gtk_widget_show (priv->view_hpaned);
gtk_widget_show (priv->view_vbox);
gtk_widget_show (priv->view_title_bar);
gtk_widget_show (priv->status_bar);
/* By default, both the folder bar and shortcut bar are visible. */
priv->shortcut_bar_mode = E_SHELL_VIEW_SUBWINDOW_STICKY;
@ -839,16 +872,10 @@ destroy (GtkObject *object)
g_hash_table_foreach (priv->uri_to_control, hash_forall_destroy_control, NULL);
g_hash_table_destroy (priv->uri_to_control);
gtk_widget_destroy (priv->offline_toggle);
gtk_widget_destroy (priv->progress_bar);
bonobo_object_unref (BONOBO_OBJECT (priv->ui_component));
g_free (priv->uri);
if (priv->progress_bar_timeout_id != 0)
gtk_timeout_remove (priv->progress_bar_timeout_id);
g_free (priv);
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
@ -929,9 +956,10 @@ init (EShellView *shell_view)
priv->storage_set_view_box = NULL;
priv->shortcut_bar = NULL;
priv->progress_bar = NULL;
priv->status_bar = NULL;
priv->offline_toggle = NULL;
priv->offline_toggle_pixmap = NULL;
priv->task_bar = NULL;
priv->shortcut_bar_mode = E_SHELL_VIEW_SUBWINDOW_HIDDEN;
priv->folder_bar_mode = E_SHELL_VIEW_SUBWINDOW_HIDDEN;
@ -941,14 +969,13 @@ init (EShellView *shell_view)
priv->uri_to_control = g_hash_table_new (g_str_hash, g_str_equal);
priv->progress_bar_timeout_id = 0;
priv->progress_bar_value = 0;
priv->sockets = NULL;
shell_view->priv = priv;
}
#if 0
/* Progress bar handling. */
#define PROGRESS_BAR_TIMEOUT 80
@ -1013,6 +1040,8 @@ stop_progress_bar (EShellView *shell_view)
gtk_progress_set_value (GTK_PROGRESS (progress_bar), 0);
}
#endif
/* EvolutionShellView interface callbacks. */
@ -1045,10 +1074,12 @@ corba_interface_set_message_cb (EvolutionShellView *shell_view,
g_free (status);
#if 0
if (busy)
start_progress_bar (E_SHELL_VIEW (data));
else
stop_progress_bar (E_SHELL_VIEW (data));
#endif
}
static void
@ -1063,7 +1094,9 @@ corba_interface_unset_message_cb (EvolutionShellView *shell_view,
bonobo_ui_component_set_status (view->priv->ui_component, "", NULL);
#if 0
stop_progress_bar (E_SHELL_VIEW (data));
#endif
}
static void
@ -1222,6 +1255,11 @@ e_shell_view_construct (EShellView *shell_view,
return view;
}
/* WARNING: Don't use `e_shell_view_new()' to create new views for the shell
unless you know what you are doing; this is just the standard GTK+
constructor thing and it won't allow the shell to do the required
bookkeeping for the created views. Instead, the right way to create a new
view is calling `e_shell_new_view()'. */
EShellView *
e_shell_view_new (EShell *shell)
{
@ -1644,7 +1682,6 @@ get_type_for_folder (EShellView *shell_view,
{
EShellViewPrivate *priv;
EStorageSet *storage_set;
EFolderTypeRegistry *folder_type_registry;
EFolder *folder;
priv = shell_view->priv;
@ -1656,8 +1693,6 @@ get_type_for_folder (EShellView *shell_view,
*physical_uri_return = e_folder_get_physical_uri (folder);
folder_type_registry = e_shell_get_folder_type_registry (e_shell_view_get_shell (shell_view));
return e_folder_get_type_string (folder);
}
@ -1989,6 +2024,15 @@ e_shell_view_get_folder_bar_mode (EShellView *shell_view)
}
ETaskBar *
e_shell_view_get_task_bar (EShellView *shell_view)
{
g_return_val_if_fail (shell_view != NULL, NULL);
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
return E_TASK_BAR (shell_view->priv->task_bar);
}
EShell *
e_shell_view_get_shell (EShellView *shell_view)
{

View File

@ -24,9 +24,9 @@
#ifndef _E_SHELL_VIEW_H_
#define _E_SHELL_VIEW_H_
#include <bonobo/bonobo-win.h>
#include "e-task-bar.h"
#include "e-shell.h"
#include <bonobo/bonobo-win.h>
#ifdef __cplusplus
extern "C" {
@ -44,6 +44,8 @@ typedef struct _EShellView EShellView;
typedef struct _EShellViewPrivate EShellViewPrivate;
typedef struct _EShellViewClass EShellViewClass;
#include "e-shell.h"
enum _EShellViewSubwindowMode {
E_SHELL_VIEW_SUBWINDOW_HIDDEN,
E_SHELL_VIEW_SUBWINDOW_TRANSIENT,
@ -66,6 +68,12 @@ struct _EShellViewClass {
};
/* WARNING: Don't use `e_shell_view_new()' to create new views for the shell
unless you know what you are doing; this is just the standard GTK+
constructor thing and it won't allow the shell to do the required
bookkeeping for the created views. Instead, the right way to create a new
view is calling `e_shell_new_view()'. */
GtkType e_shell_view_get_type (void);
EShellView *e_shell_view_construct (EShellView *shell_view,
EShell *shell);
@ -84,7 +92,7 @@ void e_shell_view_set_folder_bar_mode (EShellView
EShellViewSubwindowMode mode);
EShellViewSubwindowMode e_shell_view_get_folder_bar_mode (EShellView *shell_view);
ETaskBar *e_shell_view_get_task_bar (EShellView *shell_view);
EShell *e_shell_view_get_shell (EShellView *shell_view);
BonoboUIComponent *e_shell_view_get_bonobo_ui_component (EShellView *shell_view);
BonoboUIContainer *e_shell_view_get_bonobo_ui_container (EShellView *shell_view);

View File

@ -38,6 +38,7 @@
#include "Evolution.h"
#include "e-activity-handler.h"
#include "e-component-registry.h"
#include "e-corba-storage-registry.h"
#include "e-folder-type-registry.h"
@ -75,6 +76,9 @@ struct _EShellPrivate {
ECorbaStorageRegistry *corba_storage_registry;
/* ::Activity interface handler. */
EActivityHandler *activity_handler;
/* This object handles going off-line. If the pointer is not NULL, it
means we have a going-off-line process in progress. */
EShellOfflineHandler *offline_handler;
@ -344,6 +348,26 @@ register_shell (EShell *shell,
return oaf_active_server_register (iid, corba_object);
}
/* Set up the ::Activity interface. */
static void
setup_activity_interface (EShell *shell)
{
EActivityHandler *activity_handler;
EShellPrivate *priv;
priv = shell->priv;
activity_handler = e_activity_handler_new ();
bonobo_object_add_interface (BONOBO_OBJECT (shell),
BONOBO_OBJECT (activity_handler));
bonobo_object_ref (BONOBO_OBJECT (activity_handler));
priv->activity_handler = activity_handler;
}
/* Initialization of the storages. */
@ -618,6 +642,9 @@ destroy (GtkObject *object)
if (priv->corba_storage_registry != NULL)
bonobo_object_unref (BONOBO_OBJECT (priv->corba_storage_registry));
if (priv->activity_handler != NULL)
bonobo_object_unref (BONOBO_OBJECT (priv->activity_handler));
/* FIXME. Maybe we should do something special here. */
if (priv->offline_handler != NULL)
gtk_object_unref (GTK_OBJECT (priv->offline_handler));
@ -705,6 +732,7 @@ init (EShell *shell)
priv->component_registry = NULL;
priv->folder_type_registry = NULL;
priv->corba_storage_registry = NULL;
priv->activity_handler = NULL;
priv->offline_handler = NULL;
priv->crash_type_names = NULL;
priv->line_status = E_SHELL_LINE_STATUS_ONLINE;
@ -775,7 +803,12 @@ e_shell_construct (EShell *shell,
/* The local storage depends on the component registry. */
setup_local_storage (shell);
/* Now that we have a local storage, we can tell the components we are here. */
/* Set up the ::Activity interface. This must be done before we notify
the components, as they might want to use it. */
setup_activity_interface (shell);
/* Now that we have a local storage and an ::Activity interface, we can
tell the components we are here. */
set_owner_on_components (shell);
/* Run the intelligent importers to find see if any data needs
@ -858,10 +891,14 @@ e_shell_new_view (EShell *shell,
const char *uri)
{
EShellView *view;
EShellPrivate *priv;
ETaskBar *task_bar;
g_return_val_if_fail (shell != NULL, NULL);
g_return_val_if_fail (E_IS_SHELL (shell), NULL);
priv = shell->priv;
view = e_shell_view_new (shell);
gtk_widget_show (GTK_WIDGET (view));
@ -875,6 +912,9 @@ e_shell_new_view (EShell *shell,
shell->priv->views = g_list_prepend (shell->priv->views, view);
task_bar = e_shell_view_get_task_bar (view);
e_activity_handler_attach_task_bar (priv->activity_handler, task_bar);
return view;
}
@ -1130,7 +1170,7 @@ e_shell_restore_from_settings (EShell *shell)
EShellView *view;
/* FIXME: restore the URI here. There should be an
e_shell_view_new_from_configuration() thingie. */
e_shell_new_view_from_configuration() thingie. */
view = e_shell_new_view (shell, NULL);
if (! e_shell_view_load_settings (view, i))

View File

@ -37,6 +37,7 @@ typedef struct _EShellPrivate EShellPrivate;
typedef struct _EShellClass EShellClass;
#include "Evolution.h"
#include "e-shortcuts.h"
#include "e-shell-view.h"
#include "e-local-storage.h"

154
shell/e-task-bar.c Normal file
View File

@ -0,0 +1,154 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* e-task-bar.c
*
* Copyright (C) 2001 Ximian, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ettore Perazzoli <ettore@ximian.com>
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "e-task-bar.h"
#include <gal/util/e-util.h>
#define PARENT_TYPE gtk_hbox_get_type ()
static GtkHBoxClass *parent_class = NULL;
/* GtkObject methods. */
static void
impl_destroy (GtkObject *object)
{
ETaskBar *task_bar;
task_bar = E_TASK_BAR (object);
/* Nothing to do here. */
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
static void
class_init (GtkObjectClass *object_class)
{
parent_class = gtk_type_class (PARENT_TYPE);
object_class->destroy = impl_destroy;
}
static void
init (ETaskBar *task_bar)
{
/* Nothing to do here. */
}
void
e_task_bar_construct (ETaskBar *task_bar)
{
g_return_if_fail (task_bar != NULL);
g_return_if_fail (E_IS_TASK_BAR (task_bar));
/* Nothing to do here. */
}
GtkWidget *
e_task_bar_new (void)
{
ETaskBar *task_bar;
task_bar = gtk_type_new (e_task_bar_get_type ());
e_task_bar_construct (task_bar);
return GTK_WIDGET (task_bar);
}
void
e_task_bar_prepend_task (ETaskBar *task_bar,
ETaskWidget *task_widget)
{
GtkBoxChild *child_info;
GtkBox *box;
g_return_if_fail (task_bar != NULL);
g_return_if_fail (E_IS_TASK_BAR (task_bar));
g_return_if_fail (task_widget != NULL);
g_return_if_fail (E_IS_TASK_WIDGET (task_widget));
/* Hah hah. GTK+ sucks. This is adapted from `gtkhbox.c'. */
child_info = g_new (GtkBoxChild, 1);
child_info->widget = GTK_WIDGET (task_widget);
child_info->padding = 0;
child_info->expand = TRUE;
child_info->fill = TRUE;
child_info->pack = GTK_PACK_START;
box = GTK_BOX (task_bar);
box->children = g_list_append (box->children, child_info);
gtk_widget_set_parent (GTK_WIDGET (task_widget), GTK_WIDGET (task_bar));
if (GTK_WIDGET_REALIZED (task_bar))
gtk_widget_realize (GTK_WIDGET (task_widget));
if (GTK_WIDGET_VISIBLE (task_bar) && GTK_WIDGET_VISIBLE (task_widget)) {
if (GTK_WIDGET_MAPPED (task_bar))
gtk_widget_map (GTK_WIDGET (task_widget));
gtk_widget_queue_resize (GTK_WIDGET (task_widget));
}
}
void
e_task_bar_remove_task (ETaskBar *task_bar,
int n)
{
ETaskWidget *task_widget;
g_return_if_fail (task_bar != NULL);
g_return_if_fail (E_IS_TASK_BAR (task_bar));
g_return_if_fail (n >= 0);
task_widget = e_task_bar_get_task_widget (task_bar, n);
gtk_container_remove (GTK_CONTAINER (task_bar), GTK_WIDGET (task_widget));
}
ETaskWidget *
e_task_bar_get_task_widget (ETaskBar *task_bar,
int n)
{
GtkBoxChild *child_info;
g_return_val_if_fail (task_bar != NULL, NULL);
g_return_val_if_fail (E_IS_TASK_BAR (task_bar), NULL);
child_info = (GtkBoxChild *) g_list_nth (GTK_BOX (task_bar)->children, n)->data;
return E_TASK_WIDGET (child_info->widget);
}
E_MAKE_TYPE (e_task_bar, "ETaskBar", ETaskBar, class_init, init, PARENT_TYPE)

72
shell/e-task-bar.h Normal file
View File

@ -0,0 +1,72 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* e-task-bar.h
*
* Copyright (C) 2001 Ximian, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ettore Perazzoli <ettore@ximian.com>
*/
#ifndef _E_TASK_BAR_H_
#define _E_TASK_BAR_H_
#include "e-task-widget.h"
#include <gtk/gtkhbox.h>
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus */
#define E_TYPE_TASK_BAR (e_task_bar_get_type ())
#define E_TASK_BAR(obj) (GTK_CHECK_CAST ((obj), E_TYPE_TASK_BAR, ETaskBar))
#define E_TASK_BAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_TASK_BAR, ETaskBarClass))
#define E_IS_TASK_BAR(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_TASK_BAR))
#define E_IS_TASK_BAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_TASK_BAR))
typedef struct _ETaskBar ETaskBar;
typedef struct _ETaskBarPrivate ETaskBarPrivate;
typedef struct _ETaskBarClass ETaskBarClass;
struct _ETaskBar {
GtkHBox parent;
};
struct _ETaskBarClass {
GtkHBoxClass parent_class;
};
GtkType e_task_bar_get_type (void);
void e_task_bar_construct (ETaskBar *task_bar);
GtkWidget *e_task_bar_new (void);
void e_task_bar_prepend_task (ETaskBar *task_bar,
ETaskWidget *task_widget);
void e_task_bar_remove_task (ETaskBar *task_bar,
int n);
ETaskWidget *e_task_bar_get_task_widget (ETaskBar *task_bar,
int n);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _E_TASK_BAR_H_ */

190
shell/e-task-widget.c Normal file
View File

@ -0,0 +1,190 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* e-task-widget.c
*
* Copyright (C) 2001 Ximian, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ettore Perazzoli <ettore@ximian.com>
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "e-task-widget.h"
#include <gtk/gtkhbox.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkpixmap.h>
/* HA HA. Just #including <libgnome/gnome-i18n.h> doesn't seem to work, so
I'll have to include the full thing. */
#include <libgnome/libgnome.h>
#include <gal/util/e-util.h>
#define SPACING 2
#define PARENT_TYPE (gtk_frame_get_type ())
static GtkFrameClass *parent_class = NULL;
struct _ETaskWidgetPrivate {
GdkPixbuf *icon_pixbuf;
GtkWidget *label;
GtkWidget *pixmap;
};
/* GtkObject methods. */
static void
impl_destroy (GtkObject *object)
{
ETaskWidget *task_widget;
ETaskWidgetPrivate *priv;
task_widget = E_TASK_WIDGET (object);
priv = task_widget->priv;
gdk_pixbuf_unref (priv->icon_pixbuf);
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
static void
class_init (GtkObjectClass *object_class)
{
parent_class = gtk_type_class (PARENT_TYPE);
object_class->destroy = impl_destroy;
}
static void
init (ETaskWidget *task_widget)
{
ETaskWidgetPrivate *priv;
priv = g_new (ETaskWidgetPrivate, 1);
task_widget->priv = priv;
}
void
e_task_widget_construct (ETaskWidget *task_widget,
GdkPixbuf *icon_pixbuf,
const char *information)
{
ETaskWidgetPrivate *priv;
GdkPixmap *pixmap;
GdkBitmap *mask;
GtkWidget *box;
g_return_if_fail (task_widget != NULL);
g_return_if_fail (E_IS_TASK_WIDGET (task_widget));
g_return_if_fail (icon_pixbuf != NULL);
g_return_if_fail (information != NULL);
priv = task_widget->priv;
gtk_frame_set_shadow_type (GTK_FRAME (task_widget), GTK_SHADOW_IN);
box = gtk_hbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (task_widget), box);
gtk_widget_show (box);
priv->icon_pixbuf = gdk_pixbuf_ref (icon_pixbuf);
gdk_pixbuf_render_pixmap_and_mask (icon_pixbuf, &pixmap, &mask, 128);
priv->pixmap = gtk_pixmap_new (pixmap, mask);
gtk_widget_show (priv->pixmap);
gtk_box_pack_start (GTK_BOX (box), priv->pixmap, FALSE, TRUE, 0);
priv->label = gtk_label_new ("");
gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.5);
gtk_widget_show (priv->label);
gtk_box_pack_start (GTK_BOX (box), priv->label, TRUE, TRUE, 0);
gdk_pixmap_unref (pixmap);
gdk_bitmap_unref (mask);
e_task_widget_update (task_widget, information, -1.0);
}
GtkWidget *
e_task_widget_new (GdkPixbuf *icon_pixbuf,
const char *information)
{
ETaskWidget *task_widget;
g_return_val_if_fail (icon_pixbuf != NULL, NULL);
g_return_val_if_fail (information != NULL, NULL);
task_widget = gtk_type_new (e_task_widget_get_type ());
e_task_widget_construct (task_widget, icon_pixbuf, information);
return GTK_WIDGET (task_widget);
}
void
e_task_widget_update (ETaskWidget *task_widget,
const char *information,
double completion)
{
ETaskWidgetPrivate *priv;
char *text;
g_return_if_fail (task_widget != NULL);
g_return_if_fail (E_IS_TASK_WIDGET (task_widget));
g_return_if_fail (information != NULL);
priv = task_widget->priv;
if (completion < 0.0) {
text = g_strdup_printf (_("%s (...)"), information);
} else {
int percent_complete;
percent_complete = (int) (completion * 100.0 + .5);
text = g_strdup_printf (_("%s (%d%% complete)"), information, percent_complete);
}
gtk_label_set_text (GTK_LABEL (priv->label), text);
g_free (text);
}
void
e_task_wiget_alert (ETaskWidget *task_widget)
{
g_return_if_fail (task_widget != NULL);
g_return_if_fail (E_IS_TASK_WIDGET (task_widget));
}
void
e_task_wiget_unalert (ETaskWidget *task_widget)
{
g_return_if_fail (task_widget != NULL);
g_return_if_fail (E_IS_TASK_WIDGET (task_widget));
}
E_MAKE_TYPE (e_task_widget, "ETaskWidget", ETaskWidget, class_init, init, PARENT_TYPE)

75
shell/e-task-widget.h Normal file
View File

@ -0,0 +1,75 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* e-task-widget.h
*
* Copyright (C) 2001 Ximian, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ettore Perazzoli <ettore@ximian.com>
*/
#ifndef _E_TASK_WIDGET_H_
#define _E_TASK_WIDGET_H_
#include <gtk/gtkframe.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus */
#define E_TYPE_TASK_WIDGET (e_task_widget_get_type ())
#define E_TASK_WIDGET(obj) (GTK_CHECK_CAST ((obj), E_TYPE_TASK_WIDGET, ETaskWidget))
#define E_TASK_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_TASK_WIDGET, ETaskWidgetClass))
#define E_IS_TASK_WIDGET(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_TASK_WIDGET))
#define E_IS_TASK_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_TASK_WIDGET))
typedef struct _ETaskWidget ETaskWidget;
typedef struct _ETaskWidgetPrivate ETaskWidgetPrivate;
typedef struct _ETaskWidgetClass ETaskWidgetClass;
struct _ETaskWidget {
GtkFrame parent;
ETaskWidgetPrivate *priv;
};
struct _ETaskWidgetClass {
GtkFrameClass parent_class;
};
GtkType e_task_widget_get_type (void);
void e_task_widget_construct (ETaskWidget *task_widget,
GdkPixbuf *icon_pixbuf,
const char *information);
GtkWidget *e_task_widget_new (GdkPixbuf *icon_pixbuf,
const char *information);
void e_task_widget_update (ETaskWidget *task_widget,
const char *information,
double completion);
void e_task_wiget_alert (ETaskWidget *task_widget);
void e_task_wiget_unalert (ETaskWidget *task_widget);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _E_TASK_WIDGET_H_ */

View File

@ -0,0 +1,375 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* evolution-test-component.c
*
* Copyright (C) 2001 Ximian, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ettore Perazzoli
*/
/* Simple test component for the Evolution shell. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "evolution-shell-component.h"
#include <bonobo/bonobo-generic-factory.h>
#include <bonobo/bonobo-main.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#define COMPONENT_FACTORY_ID "OAFIID:GNOME_Evolution_TestComponent_ShellComponentFactory"
#define COMPONENT_ID "OAFIID:GNOME_Evolution_TestComponent_ShellComponent"
static const EvolutionShellComponentFolderType folder_types[] = {
{ "test", "/usr/share/pixmaps/gnome-money.png", NULL, NULL },
{ NULL }
};
static EvolutionShellClient *parent_shell = NULL;
static GNOME_Evolution_Activity activity_interface = CORBA_OBJECT_NIL;
static CORBA_long activity_id = 0;
static BonoboListener *task_bar_event_listener;
static int timeout_id = 0;
static int progress = -1;
static void
create_icon_from_pixbuf (GdkPixbuf *pixbuf,
GNOME_Evolution_Icon *frame_return)
{
const char *sp;
CORBA_octet *dp;
int width, height, total_width, rowstride;
int i, j;
gboolean has_alpha;
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
if (has_alpha)
total_width = 4 * width;
else
total_width = 3 * width;
frame_return->width = width;
frame_return->height = height;
frame_return->hasAlpha = has_alpha;
frame_return->rgba_data._length = frame_return->height * total_width;
frame_return->rgba_data._maximum = frame_return->rgba_data._length;
frame_return->rgba_data._buffer = CORBA_sequence_CORBA_octet_allocbuf (frame_return->rgba_data._maximum);
sp = gdk_pixbuf_get_pixels (pixbuf);
dp = frame_return->rgba_data._buffer;
for (i = 0; i < height; i ++) {
for (j = 0; j < total_width; j++) {
*(dp ++) = sp[j];
}
sp += rowstride;
}
}
static GNOME_Evolution_AnimatedIcon *
create_animated_icon (void)
{
GNOME_Evolution_AnimatedIcon *animated_icon;
GdkPixbuf *pixbuf;
animated_icon = GNOME_Evolution_AnimatedIcon__alloc ();
animated_icon->_length = 1;
animated_icon->_maximum = 1;
animated_icon->_buffer = CORBA_sequence_GNOME_Evolution_Icon_allocbuf (animated_icon->_maximum);
pixbuf = gdk_pixbuf_new_from_file (gnome_pixmap_file ("gnome-money.png"));
create_icon_from_pixbuf (pixbuf, &animated_icon->_buffer[0]);
gdk_pixbuf_unref (pixbuf);
CORBA_sequence_set_release (animated_icon, TRUE);
return animated_icon;
}
static void
task_bar_event_listener_callback (BonoboListener *listener,
char *event_name,
CORBA_any *any,
CORBA_Environment *ev,
void *data)
{
g_print ("Taskbar event -- %s\n", event_name);
}
/* Timeout #3: We are done. */
static int
timeout_callback_3 (void *data)
{
CORBA_Environment ev;
CORBA_exception_init (&ev);
GNOME_Evolution_Activity_operationFinished (activity_interface,
activity_id,
&ev);
if (ev._major != CORBA_NO_EXCEPTION) {
g_warning ("Cannot report operation as finished; exception returned -- %s\n",
ev._repo_id);
CORBA_exception_free (&ev);
return FALSE;
}
CORBA_exception_free (&ev);
return FALSE;
}
/* Timeout #2: Update the progress until it reaches 100%. */
static int
timeout_callback_2 (void *data)
{
CORBA_Environment ev;
if (progress < 0)
progress = 0;
CORBA_exception_init (&ev);
GNOME_Evolution_Activity_operationProgressing (activity_interface,
activity_id,
"Operation Foo in progress",
(CORBA_float) progress / 100.0,
&ev);
if (ev._major != CORBA_NO_EXCEPTION) {
g_warning ("Cannot update operation; exception returned -- %s\n",
ev._repo_id);
CORBA_exception_free (&ev);
return FALSE;
}
CORBA_exception_free (&ev);
progress += 10;
if (progress > 100) {
gtk_timeout_add (1000, timeout_callback_3, NULL);
return FALSE;
}
return TRUE;
}
/* Timeout #1: Set busy. */
static int
timeout_callback_1 (void *data)
{
CORBA_boolean suggest_display;
CORBA_Environment ev;
GNOME_Evolution_AnimatedIcon *animated_icon;
CORBA_exception_init (&ev);
if (CORBA_Object_is_nil (activity_interface, &ev)) {
CORBA_exception_free (&ev);
return FALSE;
}
g_print ("Component becoming busy -- %s\n", COMPONENT_ID);
task_bar_event_listener = bonobo_listener_new (task_bar_event_listener_callback, NULL);
animated_icon = create_animated_icon ();
GNOME_Evolution_Activity_operationStarted (activity_interface,
COMPONENT_ID,
animated_icon,
"Operation Foo started!",
FALSE,
bonobo_object_corba_objref (BONOBO_OBJECT (task_bar_event_listener)),
&activity_id,
&suggest_display,
&ev);
CORBA_free (animated_icon);
if (ev._major != CORBA_NO_EXCEPTION) {
g_warning ("Cannot start an operation; exception returned -- %s\n",
ev._repo_id);
CORBA_exception_free (&ev);
return FALSE;
}
g_print (" --> Activity ID: %ld\n", (long) activity_id);
if (suggest_display)
g_print (" --> Could display dialog box.\n");
CORBA_exception_free (&ev);
gtk_timeout_add (3000, timeout_callback_2, NULL);
return FALSE;
}
static EvolutionShellComponentResult
create_view_fn (EvolutionShellComponent *shell_component,
const char *physical_uri,
const char *folder_type,
BonoboControl **control_return,
void *closure)
{
GtkWidget *vbox;
GtkWidget *label_1, *label_2;
GtkWidget *event_box_1, *event_box_2;
label_1 = gtk_label_new ("This is just a test component, displaying the following URI:");
label_2 = gtk_label_new (physical_uri);
event_box_1 = gtk_event_box_new ();
event_box_2 = gtk_event_box_new ();
vbox = gtk_vbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), event_box_1, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), label_1, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), label_2, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), event_box_2, TRUE, TRUE, 0);
gtk_widget_show (label_1);
gtk_widget_show (label_2);
gtk_widget_show (event_box_1);
gtk_widget_show (event_box_2);
gtk_widget_show (vbox);
*control_return = bonobo_control_new (vbox);
g_assert (timeout_id == 0);
timeout_id = gtk_timeout_add (2000, timeout_callback_1, NULL);
return EVOLUTION_SHELL_COMPONENT_OK;
}
/* Callbacks. */
static void
owner_set_callback (EvolutionShellComponent *shell_component,
EvolutionShellClient *shell_client,
const char *evolution_homedir)
{
CORBA_Environment ev;
g_assert (parent_shell == NULL);
g_print ("We have an owner -- home directory is `%s'\n", evolution_homedir);
parent_shell = shell_client;
CORBA_exception_init (&ev);
activity_interface = Bonobo_Unknown_queryInterface (bonobo_object_corba_objref (BONOBO_OBJECT (shell_client)),
"IDL:GNOME/Evolution/Activity:1.0",
&ev);
if (ev._major != CORBA_NO_EXCEPTION)
activity_interface = CORBA_OBJECT_NIL;
if (CORBA_Object_is_nil (activity_interface, &ev))
g_warning ("Shell doesn't have a ::Activity interface -- weird!");
CORBA_exception_free (&ev);
}
static int
owner_unset_idle_callback (void *data)
{
gtk_main_quit ();
return FALSE;
}
static void
owner_unset_callback (EvolutionShellComponent *shell_component,
void *data)
{
g_idle_add_full (G_PRIORITY_LOW, owner_unset_idle_callback, NULL, NULL);
}
static BonoboObject *
factory_fn (BonoboGenericFactory *factory,
void *closure)
{
EvolutionShellComponent *shell_component;
shell_component = evolution_shell_component_new (folder_types,
create_view_fn,
NULL, NULL, NULL, NULL, NULL, NULL);
gtk_signal_connect (GTK_OBJECT (shell_component), "owner_set",
GTK_SIGNAL_FUNC (owner_set_callback), NULL);
gtk_signal_connect (GTK_OBJECT (shell_component), "owner_unset",
GTK_SIGNAL_FUNC (owner_unset_callback), NULL);
return BONOBO_OBJECT (shell_component);
}
static void
component_factory_init (void)
{
BonoboGenericFactory *factory;
factory = bonobo_generic_factory_new (COMPONENT_FACTORY_ID, factory_fn, NULL);
if (factory == NULL)
g_error ("Cannot initialize test component.");
}
int
main (int argc, char **argv)
{
CORBA_ORB orb;
bindtextdomain (PACKAGE, EVOLUTION_LOCALEDIR);
textdomain (PACKAGE);
gnome_init_with_popt_table ("evolution-test-component", VERSION,
argc, argv, oaf_popt_options, 0, NULL);
orb = oaf_init (argc, argv);
if (bonobo_init (orb, CORBA_OBJECT_NIL, CORBA_OBJECT_NIL) == FALSE)
g_error ("Cannot initialize the test component.");
component_factory_init ();
bonobo_main ();
return 0;
}